STM32启动流程详解及步骤解析

一、STM32三种启动方式

  1. 常规模式(主闪存存储器)

  2. 这是最常见的启动模式。
  3. 在此模式下,处理器会执行复位向量表中的复位地址,从而启动芯片。
  4. 芯片会执行各种初始化操作,包括时钟初始化、外设初始化等,然后跳转到用户定义的启动代码。
  5. 基地址:0x0800000
  6. Bootloader模式(系统存储器)

  7. 这是一种特殊的启动模式,通常用于更新固件或通过外部接口(如UART或USB)加载新的程序。
  8. 在此模式下,处理器会将启动地址设置为Bootloader的起始地址,而不是复位向量表中的复位地址。
  9. Bootloader负责检查外部接口是否有新的程序,如果有,则加载并启动新程序;否则,它会跳转到复位向量表中的复位地址。
  10. 基地址:0x1FFFF000
  11. 系统内存模式(内置SRAM)

  12. 这种模式通常用于恢复或修复芯片中的固件
  13. 在此模式下,处理器会将启动地址设置为系统内存中的特定地址,而不是复位向量表中的复位地址。
  14. 系统内存包含一个特殊的Bootloader,它可以用于加载新的固件或执行其他恢复操作。
  15. 基地址:0x20000000

这三种启动模式为STM32芯片提供了灵活性和可靠性,使其适用于各种不同的应用场景。开发人员可以根据实际需求选择合适的启动模式来确保系统的正常运行和维护。启动时都会自动把基地址重映射到0x00000000,执行RESET中断。

二、常规启动模式分析

Stack_Size      EQU     0x00000400    ; 定义栈的大小为1024字节(0x400字节)

            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     0x00000200    ; 定义堆的大小为512字节(0x200字节)

            AREA    HEAP, NOINIT, READWRITE, ALIGN=3   ; 定义堆区域,不进行初始化,可读可写,字节对齐
__heap_base                                         ; 堆的起始地址
Heap_Mem    SPACE   Heap_Size                       ; 分配堆的空间
__heap_limit                                        ; 堆的结束地址

            PRESERVE8
            THUMB

; Vector Table Mapped to Address 0 at Reset
            AREA    RESET, DATA, READONLY           ; 定义重置区域,数据区域,只读
            EXPORT  __Vectors                       ; 导出向量表
            EXPORT  __Vectors_End                   ; 导出向量表的结束地址
            EXPORT  __Vectors_Size                  ; 导出向量表的大小

__Vectors   DCD     __initial_sp               ; Top of Stack    栈顶指针
            DCD     Reset_Handler              ; Reset Handler   复位处理函数
            DCD     NMI_Handler                ; NMI Handler     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
            ...
            (其他外部中断处理函数)
            ...

__Vectors_End                                 ; 向量表结束标志
__Vectors_Size  EQU  __Vectors_End - __Vectors  ; 向量表大小

            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]   ; 导出NMI处理函数,标记为弱符号
                B       .                           ; 无限循环
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]   ; 导出硬件故障处理函数,标记为弱符号
                B       .                           ; 无限循环
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler          [WEAK]   ; 导出内存管理单元故障处理函数,标记为弱符号
                B       .                           ; 无限循环
                ENDP
...
(其他异常处理函数)
...

Default_Handler PROC

                EXPORT  WWDG_IRQHandler            [WEAK]   ; 导出默认的外部中断处理函数,标记为弱符号
                EXPORT  PVD_IRQHandler             [WEAK]
                ...
                (其他外部中断处理函数)
                ...

                B       .                            ; 无限循环

                ENDP

                ALIGN

;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
                 IF      :DEF:__MICROLIB           
                
                 EXPORT  __initial_sp               ; 导出栈顶指针
                 EXPORT  __heap_base                ; 导出堆的起始地址
                 EXPORT  __heap_limit               ; 导出堆的结束地址
                
                 ELSE
                
                 IMPORT  __use_two_region_memory
                 EXPORT  __user_initial_stackheap   ; 导出用户栈和堆的初始化函数
                 
__user_initial_stackheap

                 LDR     R0, =  Heap_Mem            ; 将堆的起始地址加载到R0寄存器
                 LDR     R1, =(Stack_Mem + Stack_Size)  ; 将栈的起始地址加上栈的大小加载到R1寄存器
                 LDR     R2, = (Heap_Mem +  Heap_Size)  ; 将堆的起始地址加上堆的大小加载到R2寄存器
                 LDR     R3, = Stack_Mem            ; 将栈的起始地址加载到R3寄存器
                 BX      LR                         ; 返回

                 ALIGN

                 ENDIF

                 END

这段启动代码实现了STM32的启动流程,

  1. 栈和堆的初始化

  2. 定义了栈的大小和堆的大小,并分配了相应的空间。
  3. 在向量表中定义了栈顶指针 __initial_sp、堆的起始地址 __heap_base 和结束地址 __heap_limit
  4. 向量表的定义

  5. 向量表是在芯片复位时会被加载到内存地址0处,用于存放异常处理函数的入口地址。
  6. 向量表中定义了复位、NMI、硬件故障、内存管理单元故障、总线故障、使用错误等异常处理函数的入口地址。
  7. 向量表还包含了外部中断处理函数的入口地址。
  8. Reset_Handler复位处理函数

  9. Reset_Handler 是复位时的处理函数,在芯片复位时会被调用。
  10. 该函数首先调用 SystemInit 完成系统的初始化工作,然后跳转到 __main 函数继续执行用户的主程序。
  11. 异常处理函数的定义

  12. 定义了各种异常处理函数的入口地址,如 NMI、硬件故障、内存管理单元故障、总线故障等。
  13. 这些异常处理函数是无限循环的,表示当对应的异常发生时,系统会停留在该函数处进行处理。
  14. 用户栈和堆的初始化

  15. 如果使用了标准库函数 __MICROLIB,则导出了栈和堆的初始化函数 __user_initial_stackheap
  16. 如果未使用标准库函数,则需要手动定义栈和堆的初始化函数,并在其中设置栈的起始地址、堆的起始地址和结束地址。

STM32的启动流程比较简单,从这个流程可以学习到通用的的ARM系统的启动模式。

作者:石头嵌入式

物联沃分享整理
物联沃-IOTWORD物联网 » STM32启动流程详解及步骤解析

发表评论