STM32 CM3/CM4 ------ startup.s 文件分析 ------ IAR 版本

startup.s 功能

不同的开发环境(IAR、KEIL、GCC编译器),startup.s的内容多少有些差别,但是功能基本如下:

设置向量表,包含MSP初值,各中断函数指针

芯片一上电,自动设置SP,PC,然后执行复位中断:

  执行 SystemInit,初始化时钟,设置SCB->VTOR的值为向量表起始地址

  执行 __iar_program_start(根据GCC RT-Thread Studio 版本,里面应该有data段的数据从 flash 拷贝到 SRAM, bss段位于SRAM,初始化为0),在里面跳转到 main() 

 

向量表

在 startup.s 内,定义了一个向量表,不同于GCC编译器由链接脚本决定向量表存储在ROM(flash)的哪个地址,IAR是 .icf 文件内决定存储地址,默认从地址0开始(对于STM32,就是 flash 的起始地址 0x08000000)存每个向量,向量指向的位置就是对应的中断服务函数

向量表的起始处都必须包含以下向量:
  主堆栈指针(MSP)的初始值
  复位向量(根据CM3权威指南,复位向量是PC初始值,也就是说程序是从中断服务函数 Reset_Handler 开始运行的
  NMI
  硬 fault 服务例程
后两者也是必需的,因为有可能在引导过程中发生这两种异常。

 

所以 0x20000D84 就是主堆栈指针的初始值,0x08059545-1就是复位向量,指向中断服务函数 Reset_Handler 

 

startup.s 文件内容

 以下是 IAR 版本的 startup.s

        MODULE  ?cstartup

        ;; Forward declaration of sections.
        SECTION CSTACK:DATA:NOROOT(3)

        SECTION .intvec:CODE:NOROOT(2)

        EXTERN  
        EXTERN  SystemInit        
        PUBLIC  __vector_table

        DATA
__vector_table
        DCD     sfe(CSTACK)
        DCD     Reset_Handler             ; Reset Handler
        DCD     NMI_Handler               ; NMI Handler
        DCD     HardFault_Handler         ; Hard Fault Handler
......



        THUMB

        PUBWEAK Reset_Handler
        SECTION .text:CODE:REORDER(2)
Reset_Handler
        LDR     R0, =SystemInit
        BLX     R0
        LDR     R0, =__iar_program_start
        BX      R0
        
        PUBWEAK NMI_Handler
        SECTION .text:CODE:REORDER(1)
NMI_Handler
        B NMI_Handler

        PUBWEAK HardFault_Handler
        SECTION .text:CODE:REORDER(1)
HardFault_Handler
        B HardFault_Handler
......

除了 Reset_Handler 中断服务函数, 其他中断服务函数都是死循环,B 是跳转指令(即函数调用)。BLX 也是跳转指令。

        DCD     sfe(CSTACK)
        DCD     Reset_Handler             ; Reset Handler
        DCD     NMI_Handler               ; NMI Handler
        DCD     HardFault_Handler         ; Hard Fault Handler

 

 

DCD:数据定义( Data Definition )伪指令
一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。

语法格式:

标号 DCD(或 DCDU) 表达式

DCD(或 DCDU)伪指令用于分配一片连续的字存储单元并用指定的表达式初始化。其中表达式可以为程序标号或数字表达式。 DCD 也可用 “ &” 代替。

用 DCD 分配的字存储单元是字对齐的,而用 DCDU 分配的字存储单元并不严格字对齐。

结合前面的截图,上面几行分析如下:

为 CSTACK 分配存储地址 0x08000000,地址上的内容为 CSTACK 的值是 0x20000D84

为 Reset_Handler 分配存储地址 0x08000004,地址上的内容为中断服务函数指针(0x08059545),指向中断服务函数 Reset_Handler

为 NMI_Handler 分配存储地址 0x08000008,地址上的内容为中断服务函数指针(0x08059591),指向中断服务函数 NMI_Handler

 

posted @ 2021-06-06 22:55  流水灯  阅读(1176)  评论(0编辑  收藏  举报