STM32如何启动

谈及如何启动,首先得看看 启动文件 了,STM32启动文件由汇编了语言编写,很多小伙伴使用stm32单片机很久了也对其不是很了解,在此做了一下整理,顺便分析给大家。


了解stm32启动文件有助于大家对其运行状态的理解,其中主要的三件事就是,栈和堆的初始化、定位中断向量表、调用Reset Handler
1、上电后的运行顺序(为什么不从main函数开始执行?)
2、向量表中定义了哪些中断,是如何处理的?
……
首先来看看启动文件相关指令

指令指令功能
EQU给数字常量取一个符号名,相当于C语言中的define
IF,ELSE,ENDIF汇编条件分支语句,跟C语言的if else类似
SPACE分配内存空间
AREA汇编一个新的代码段或者数据段
PRESERVE8当前文件堆栈需按照8字节对齐
EXPORT声明一个标号具有全局属性,可被外部的文件使用
DCD以字为单位分配内存,要求4字节对齐,并要求初始化这些内存
PROC定义子程序,与ENDP成对使用,表示子程序结束
IMPORT声明标号来自外部文件,跟C语言中的EXTERN关键字类似
B无条件跳转到一个标号
END到达文件的末尾,文件结束
LDR从存储器中加载字到一个寄存器中
BL跳转到由寄存器/标号给出的地址,并把跳转前的下条指令地址保存到LR
BLX跳转到由寄存器给出的地址,并根据寄存器的LSE确定处理器的状态,还要把跳转前的下条指令地址保存到LR
BX跳转到由寄存器/标号给出的地址,不用返回
ALIGN编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示4字节对齐。
WEAK弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不出错。

更多相关指令参考①更多相关指令参考②

启动文件代码如下,做了详细的注释
1、栈——Stack

; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x00000400                          ;宏定义的伪指令,相当于等于,类似与C中的define;定义栈(Stack_Size )的大小,1024Byte,1K
                                                            
                AREA    STACK, NOINIT, READWRITE, ALIGN=3   ;定义一块的数据段或代码段,段名为STACK,不初始化,可读可写,82^3)字节对齐
Stack_Mem       SPACE   Stack_Size                          ;分配一块名叫Stack_Mem空间,单位为字节,大小为Stack_Size(1KB),并初始化
__initial_sp                                                ;标号__initial_sp紧挨着SPACE语句放置,表示栈的结束地址,即栈顶地址,栈是由高向低生长的。

栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM的大小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。当程序出现了莫名奇怪的错误,并进入了硬fault的时候,这时你就要考虑下是不是栈不够大,溢出了。
2、堆——Heap

; <h> Heap Configuration                                    
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>            
; </h>                                                      
                                                            
Heap_Size       EQU     0x00000200                          ;定义堆(Heap_Siz)的大小为512Byte
                                                            
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3    ;定义一块的数据段或代码段,段名为HEAP,不初始化,可读可写,82^3)字节对齐
__heap_base                                                 ;堆的起始地址
Heap_Mem        SPACE   Heap_Size                           ;分配一块名叫Heap_Mem空间,单位为字节,大小为Heap_Size(1KB),并初始化
__heap_limit                                                ;堆的结束地址                                               

堆是由低向高生长的,跟栈的生长方向相反。堆主要用来动态内存的分配,像malloc()函数申请的内存就在堆上面。

                PRESERVE8                                   ;当前堆栈需要按8字节对齐
                THUMB                                       ;兼容THUMB指令

THUBM是ARM以前的指令集,只兼容16位,而ARM指令兼容32位,但现在Cortex-M系列的都使用THUMB-2指令集,THUMB-2是32位的,兼容16位和32位的指令。
3、向量表

; Vector Table Mapped to Address 0 at Reset                 
                AREA    RESET, DATA, READONLY               ;定义一块的数据段,段名为RESET,只读
                EXPORT  __Vectors                           ;用EXPORT在程序中声明一个全局的标号,声明全局变量__Vectors
                EXPORT  __Vectors_End                       ;声明全局变量__Vectors_End
                EXPORT  __Vectors_Size                      ;声明全局变量__Vectors_Size

声明__Vectors、__Vectors_End和__Vectors_Size这三个标号具有全局属性,可供外部的文件调用。

当内核响应了一个发生的异常后,对应的异常服务就会执行。为了决定异常服务的入口地址,内核使用了"向量表查表机制"。这里使用一张向量表。向量表其实是一个WORD(32 位)的数组,就像一个指针数组,每个下标表示一个异常,里面的值就是异常服务程序地址。向量表在地址空间中的位置是可以设置的,通过NVIC 中的一个重定位寄存器来指出向量表的地址。在复位后,该寄存器的值为0。因此,在地址0 (即FLASH 地址0)处必须包含一张向量表,用于初始时的异常分配,决定程序下一步的跳转,所以该表映射在0x0000 0000地址上。

DCD指令以字为单位分配内存,伪指令,用于分配一段字内存单元,并用伪指令中的expr初始化,分配的内存需要字对齐,一般可用来定义数据表格或其它常数。在向量表中,DCD分配了一堆内存,并且以ISR的入口地址,当内核响应了一个发生的异常后,对应的异常服务程序就会被执行。

;中断向量表
__Vectors       DCD     __initial_sp               ; Top of Stack                       ;栈顶地址
                DCD     Reset_Handler              ; Reset Handler                      ;默认程序上电复位从这里开始执行
                DCD     NMI_Handler                ; NMI Handler                        ;不可屏蔽中断。 RCC 时钟安全系统(CSS) 连接到 NMI 向量
                DCD     HardFault_Handler          ; Hard Fault Handler                 ;
                DCD     MemManage_Handler          ; MPU Fault Handler                  ;
                DCD     BusFault_Handler           ; Bus Fault Handler                  ;
                DCD     UsageFault_Handler         ; Usage Fault Handler                ;
                DCD     0                          ; Reserved                           ;
                DCD     0                          ; Reserved                           ;
                DCD     0                          ; Reserved                           ;
                DCD     0                          ; Reserved                           ;
                DCD     SVC_Handler                ; SVCall Handler                     ;
                DCD     DebugMon_Handler           ; Debug Monitor Handler              ;
                DCD     0                          ; Reserved                           ;
                DCD     PendSV_Handler             ; PendSV Handler                     ;
                DCD     SysTick_Handler            ; SysTick Handler                    ;
                                                                                        ;
                ; External Interrupts                                                   ;
                DCD     WWDG_IRQHandler            ; Window Watchdog                    ;
                DCD     PVD_IRQHandler             ; PVD through EXTI Line detect       ;
                DCD     TAMPER_IRQHandler          ; Tamper                             ;
                DCD     RTC_IRQHandler             ; RTC                                ;
                DCD     FLASH_IRQHandler           ; Flash                              ;
                DCD     RCC_IRQHandler             ; RCC                                ;
                DCD     EXTI0_IRQHandler           ; EXTI Line 0                        ;
                DCD     EXTI1_IRQHandler           ; EXTI Line 1                        ;
                DCD     EXTI2_IRQHandler           ; EXTI Line 2                        ;
                DCD     EXTI3_IRQHandler           ; EXTI Line 3                        ;
                DCD     EXTI4_IRQHandler           ; EXTI Line 4                        ;
                DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1                     ;
                DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2                     ;
                DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3                     ;
                DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4                     ;
                DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5                     ;
                DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6                     ;
                DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7                     ;
                DCD     ADC1_2_IRQHandler          ; ADC1 & ADC2                        ;
                DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX       ;
                DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0      ;
                DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1                           ;
                DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE                           ;
                DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5                     ;
                DCD     TIM1_BRK_IRQHandler        ; TIM1 Break                         ;
                DCD     TIM1_UP_IRQHandler         ; TIM1 Update                        ;
                DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation       ;
                DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare               ;
                DCD     TIM2_IRQHandler            ; TIM2                               ;
                DCD     TIM3_IRQHandler            ; TIM3                               ;
                DCD     TIM4_IRQHandler            ; TIM4                               ;
                DCD     I2C1_EV_IRQHandler         ; I2C1 Event                         ;
                DCD     I2C1_ER_IRQHandler         ; I2C1 Error                         ;
                DCD     I2C2_EV_IRQHandler         ; I2C2 Event                         ;
                DCD     I2C2_ER_IRQHandler         ; I2C2 Error                         ;
                DCD     SPI1_IRQHandler            ; SPI1                               ;
                DCD     SPI2_IRQHandler            ; SPI2                               ;
                DCD     USART1_IRQHandler          ; USART1                             ;
                DCD     USART2_IRQHandler          ; USART2                             ;
                DCD     USART3_IRQHandler          ; USART3                             ;
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10                   ;
                DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line        ;
                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend            ;
                DCD     TIM8_BRK_IRQHandler        ; TIM8 Break                         ;
                DCD     TIM8_UP_IRQHandler         ; TIM8 Update                        ;
                DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation       ;
                DCD     TIM8_CC_IRQHandler         ; TIM8 Capture Compare               ;
                DCD     ADC3_IRQHandler            ; ADC3                               ;
                DCD     FSMC_IRQHandler            ; FSMC                               ;
                DCD     SDIO_IRQHandler            ; SDIO                               ;
                DCD     TIM5_IRQHandler            ; TIM5                               ;
                DCD     SPI3_IRQHandler            ; SPI3                               ;
                DCD     UART4_IRQHandler           ; UART4                              ;
                DCD     UART5_IRQHandler           ; UART5                              ;
                DCD     TIM6_IRQHandler            ; TIM6                               ;
                DCD     TIM7_IRQHandler            ; TIM7                               ;
                DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1                      ;
                DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2                      ;
                DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3                      ;
                DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5           ;
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors               ;向量表的长度或大小

向量表从FLASH的0地址开始放置,以4个字节为一个单位,地址0存放的是栈顶地址,0X04存放的是复位程序的地址,以此类推。从代码上看,向量表中存放的都是中断服务函数的函数名,可我们知道C语言中的函数名就是一个地址。

3、复位程序
复位子程序是系统上电后第一个执行的程序 ,调用SystemInit函数初始化系统时钟,然后调用C库函数_mian,最终调用main函数
在这里插入图片描述

                AREA    |.text|, CODE, READONLY              ;定义一个只读的代码段,放在Flash中.text,一般代表代码
                                                             
; Reset handler                                             
;PROC ENDP:定义子程序的伪指令,分别表示子程序定义的开始和结束两者必须成对出现。类似于C语言的{}
;IMPORT:伪指令,指示编译器当前的符号不是在本文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号。类似于C语言的外部声明extern
;WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。这里表示复位子程序可以由用户在其他文件重新实现,这里并不是唯一的。
Reset_Handler   PROC                                         ;PROC是子程序定义的伪指令,与后面的ENDP结合相当与一个子函数
                EXPORT  Reset_Handler             [WEAK]     ;可以在其他地方重写Reset_Handler这个函数(如其他地方有定义,则不执行这个)
                IMPORT  __main                               ;IMPORT表明其后面内容是从其他地方定义的,告诉编译器,外部定义了这个__main
                IMPORT  SystemInit                           ;告诉编译器,外部定义了这个SystemInit,即系统初始化函数,是系统上电之后执行的第一个函数,主要初始化系统时钟
                LDR     R0, =SystemInit                      ;加载SystemInit程序地址到R0寄存器
                BLX     R0                                   ;跳转到R0寄存器去执行系统初始化代码,同时保存返回当前函数并执行下一条指令的地址,即下一行指令
                LDR     R0, =__main                          ;加载main程序地址到R0寄存器
                BX      R0                                   ;执行__main函数(即标准C的库函数)主要作用是初始化用户堆栈并且在最后调用main函数,并且不用返回到当前函数
                ENDP                                         ;子函数结束

4、 中断服务程序
在启动文件里面已经帮我们写好所有中断的中断服务函数,跟我们平时写的中断服务函数不一样的就是这些函数都是空的,真正的中断复服务程序需要我们在外部的C文件里面重新实现,这里只是提前占了一个位置而已。如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务程序或者函数名写错,那当中断来临的时,程序就会跳转到启动文件预先写好的空的中断服务程序中,并且在这个空函数中无线循环,即程序就死在这里。

; Dummy Exception Handlers (infinite loops which can be modified)  
;中断向量表其他函数

;和复位程序相比,可知启动文件里面的这些中断复位程序都是空的,而真正相关的中断复位程序是需要我们在外部C文件编写
;实现的,如果外部没有实现相应的中断复位,发生了相关中断就会跳转这些空程序,循环死在这里
NMI_Handler     PROC                                          ;同上解释
                EXPORT  NMI_Handler                [WEAK]     ;可以在其他的地方定义该函数,当发生该中断时就会进入重定义的函数
                B       .                                     ;无条件跳转到此处,即在这里无 限循环,卡死程序
                ENDP                                          ;结束该函数
                    
;下面函数同上
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler          [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler           [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler         [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler                [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler           [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler             [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WWDG_IRQHandler            [WEAK]
                EXPORT  PVD_IRQHandler             [WEAK]
                EXPORT  TAMPER_IRQHandler          [WEAK]
                EXPORT  RTC_IRQHandler             [WEAK]
                EXPORT  FLASH_IRQHandler           [WEAK]
                EXPORT  RCC_IRQHandler             [WEAK]
                EXPORT  EXTI0_IRQHandler           [WEAK]
                EXPORT  EXTI1_IRQHandler           [WEAK]
                EXPORT  EXTI2_IRQHandler           [WEAK]
                EXPORT  EXTI3_IRQHandler           [WEAK]
                EXPORT  EXTI4_IRQHandler           [WEAK]
                EXPORT  DMA1_Channel1_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel2_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel3_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel4_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel5_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel6_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel7_IRQHandler   [WEAK]
                EXPORT  ADC1_2_IRQHandler          [WEAK]
                EXPORT  USB_HP_CAN1_TX_IRQHandler  [WEAK]
                EXPORT  USB_LP_CAN1_RX0_IRQHandler [WEAK]
                EXPORT  CAN1_RX1_IRQHandler        [WEAK]
                EXPORT  CAN1_SCE_IRQHandler        [WEAK]
                EXPORT  EXTI9_5_IRQHandler         [WEAK]
                EXPORT  TIM1_BRK_IRQHandler        [WEAK]
                EXPORT  TIM1_UP_IRQHandler         [WEAK]
                EXPORT  TIM1_TRG_COM_IRQHandler    [WEAK]
                EXPORT  TIM1_CC_IRQHandler         [WEAK]
                EXPORT  TIM2_IRQHandler            [WEAK]
                EXPORT  TIM3_IRQHandler            [WEAK]
                EXPORT  TIM4_IRQHandler            [WEAK]
                EXPORT  I2C1_EV_IRQHandler         [WEAK]
                EXPORT  I2C1_ER_IRQHandler         [WEAK]
                EXPORT  I2C2_EV_IRQHandler         [WEAK]
                EXPORT  I2C2_ER_IRQHandler         [WEAK]
                EXPORT  SPI1_IRQHandler            [WEAK]
                EXPORT  SPI2_IRQHandler            [WEAK]
                EXPORT  USART1_IRQHandler          [WEAK]
                EXPORT  USART2_IRQHandler          [WEAK]
                EXPORT  USART3_IRQHandler          [WEAK]
                EXPORT  EXTI15_10_IRQHandler       [WEAK]
                EXPORT  RTCAlarm_IRQHandler        [WEAK]
                EXPORT  USBWakeUp_IRQHandler       [WEAK]
                EXPORT  TIM8_BRK_IRQHandler        [WEAK]
                EXPORT  TIM8_UP_IRQHandler         [WEAK]
                EXPORT  TIM8_TRG_COM_IRQHandler    [WEAK]
                EXPORT  TIM8_CC_IRQHandler         [WEAK]
                EXPORT  ADC3_IRQHandler            [WEAK]
                EXPORT  FSMC_IRQHandler            [WEAK]
                EXPORT  SDIO_IRQHandler            [WEAK]
                EXPORT  TIM5_IRQHandler            [WEAK]
                EXPORT  SPI3_IRQHandler            [WEAK]
                EXPORT  UART4_IRQHandler           [WEAK]
                EXPORT  UART5_IRQHandler           [WEAK]
                EXPORT  TIM6_IRQHandler            [WEAK]
                EXPORT  TIM7_IRQHandler            [WEAK]
                EXPORT  DMA2_Channel1_IRQHandler   [WEAK]
                EXPORT  DMA2_Channel2_IRQHandler   [WEAK]
                EXPORT  DMA2_Channel3_IRQHandler   [WEAK]
                EXPORT  DMA2_Channel4_5_IRQHandler [WEAK]

WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
RTC_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_IRQHandler
DMA1_Channel3_IRQHandler
DMA1_Channel4_IRQHandler
DMA1_Channel5_IRQHandler
DMA1_Channel6_IRQHandler
DMA1_Channel7_IRQHandler
ADC1_2_IRQHandler
USB_HP_CAN1_TX_IRQHandler
USB_LP_CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler
CAN1_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTCAlarm_IRQHandler
USBWakeUp_IRQHandler
TIM8_BRK_IRQHandler
TIM8_UP_IRQHandler
TIM8_TRG_COM_IRQHandler
TIM8_CC_IRQHandler
ADC3_IRQHandler
FSMC_IRQHandler
SDIO_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
UART5_IRQHandler
TIM6_IRQHandler
TIM7_IRQHandler
DMA2_Channel1_IRQHandler
DMA2_Channel2_IRQHandler
DMA2_Channel3_IRQHandler
DMA2_Channel4_5_IRQHandler
                B       .

                ENDP
                
;ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示 4 字节对齐
                ALIGN                                                 ;对齐

5、用户堆栈初始化
用户栈和堆初始化,由 C 库函数_main 来完成,首先判断是否定义了__MICROLIB ,如果定义了这个宏则赋予标号__initial_sp(栈顶地址)、 __heap_base(堆起始地址)、__heap_limit(堆结束地址)全局属性,可供外部文件调用。有关这个宏我们在 KEIL 里面配置。
在这里插入图片描述
然后堆栈的初始化就由 C 库函数_main 来完成。如 果没 有 定 义 __MICROLIB , 则 才 用 双 段 存 储 器 模 式 , 且 声 明 标 号__user_initial_stackheap 具有全局属性,让用户自己来初始化堆栈。IF,ELSE,ENDIF:汇编的条件分支语句,跟 C 语言的 if ,else 类似 ,END:文件结束。

; User Stack and Heap initialization

                 IF      :DEF:__MICROLIB                              ;同C语言的if
                                                                      
                 EXPORT  __initial_sp                                 ;声明全局变量__initial_sp
                 EXPORT  __heap_base                                  ;声明全局变量__heap_base
                 EXPORT  __heap_limit                                 ;声明全局变量__heap_limit
                                                                      
                 ELSE                                                 ;同C语言的else
                                                                      
                 IMPORT  __use_two_region_memory                      ;外部定义__use_two_region_memory
                 EXPORT  __user_initial_stackheap                     ;声明全局变量__user_initial_stackheap
                                                                      
__user_initial_stackheap                                              ;标号
                                                                      
                 LDR     R0, =  Heap_Mem                              ;加载Heap_Mem到R0
                 LDR     R1, =(Stack_Mem + Stack_Size)                ;加载(Stack_Mem + Stack_Size)到R1
                 LDR     R2, = (Heap_Mem +  Heap_Size)                ;加载(Heap_Mem +  Heap_Size)到R2
                 LDR     R3, = Stack_Mem                              ;加载Stack_Mem到R3
                 BX      LR                                           ;跳转到LR寄存器
                                                                      
                 ALIGN                                                ;对齐
                                                                      
                 ENDIF                                                ;同C语言的endif
                                                                      
                 END                                                  ;伪指令表示汇编源文件已结束
                                                                      

STM32的堆栈是存放在SRAM中的,分配堆栈大小需要考虑SRAM容量,堆在使用时会从低地址往上加,而栈是从__initial_sp开始往下减。可以通过修改startup.s文件来设置堆栈大小,只需要修改startup.s文件中的Stack_Size和Heap_Size即可。

同时支持三种启动方式,如下图:
STM32启动方式 在CortexM3中规定上电后CPU是从0地址开始执行,但是中断向量表却被烧写在0x0800 0000地址里(第一种启动方式,即Flash memory启动方式),因此当选择从主Flash启动模式时,芯片一上电,Flash的0x0800 0000地址被映射到0地址处,不影响CortexM3内核的读取,所以这时的CortexM3内核既可以在0地址处访问中断向量表,也可以在0x08000000地址处访问中断向量表,而代码还是在0x08000000地址处存储的。
启动方式相关内容可以参考一下这位博主

完结

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

画凉ZL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值