之前一直是用STM32CubeMX自动生成的,没有深入理解STM32的启动过程。今天研究了下stm32的启动代码,记录一下,希望给初学带来一点帮助吧。
1)堆和栈的初始化
; 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 0x500
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x400
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
Stack_Size EQU 0x500
Heap_Size EQU 0x400
定义堆(heap)栈(stack)的大小
AREA STACK, NOINIT, READWRITE, ALIGN=3
AREA HEAP, NOINIT, READWRITE, ALIGN=3
AREA 伪指令用于定义一个段,如代码段、数据段或者堆栈段。(注意:段是汇编语言中非常重要的一个概念,可以去详细了解一下) ;STACK表示我们定义的是栈,其实这里仅仅是一个便于人理解的一个单词啦;NOINIT指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0;READWRITE属性,指定本段为可读可写;ALIGN属性,用来指定数据对齐的方式,为2的ALIGN次方,这是ALIGN=3,也就是按照字节对齐。
Stack_Mem SPACE Stack_Size
Heap_Mem SPACE Heap_Size
分配连续的空间给栈和堆
2)中断向量表
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
。。。。。。。。
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
__initial_sp是初始栈地址,剩下的都是中断注册函数入口地址
3)中断处理函数
AREA |.text|, CODE, READONLY
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]。。。。
ENDP
这是复位后调用的函数。
[WEAK],如果外部有此函数的定义就调用ben函数。
LDR R0, =SystemInit
BLX R0
调用系统初始化函数,由STM32CubMx生成,主要是时钟的初始化。
LDR R0, =__main
BX R0
从此进入用户程序。
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
其它的中断基本上都是这样的函数, " B . "跳转到本行,也就是在没有定义外部中断处理程序时,一旦发生中断就死循环在这里了。
3)其它
汇编中定义了stack的位置__initial_sp,但编译器ARMCC怎么知道呢,见下面