STM32启动文件分析(startup_stm32f10x_md.s)

一般而言,系统上电后第一个执行的是由汇编所编写的启动文件,其主要工作为一下五部分

  • 初始化堆栈指针SP=_initial_sp
  • 初始化PC指针,令其=Reset_Handler
  • 初始化中断向量表
  • 配置系统时钟
  • 调用C库函数_main初始化用户堆栈,从而最终调用main函数进入C的世界

初始化堆栈

初始化栈指针(SP)

; Amount of memory (in bytes) allocated for Stack
;为Stack分配的内存量(以字节为单位)
; Tailor this value to your application needs
;根据您的应用需求定制此值
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x800      ;2K

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp

  • EQU 是表示宏定义的伪指令,类似亍 C 诧言中的#define。伪指令的意思是指这个“指令”并丌会生
    成二进制程序代码,也丌会引起变量空间分配。 0x00000800 表示栈大小,注意这里是以字节为单位。

  • 开辟一段数据空间可读可写,段名 STACK,按照 8 字节对齐。 ARER 伪指令表示下面将开始定义一个
    代码段戒者数据段。此处是定义数据段。 ARER 后面的关键字表示这个段的属性。

    1. STACK :表示这个段的名字,可以任意意命名。
    2. NOINIT:表示此数据段不需要填入初始数据。
    3. READWRITE:表示此段可读可写。
    4. ALIGN=3 :表示首地址按照 2 的 3 次方对齐,也就是按照 8 字节对齐(SP mod 8 = 0)。
  • SPACE 这行指令告诉汇编器给 STACK 段分配 0x00000800 字节的连续内存空间

  • __initial_sp 紧接着 SPACE 诧句放置,表示了栈顶地址。 __initial_sp 只是一个标号,标号主要用亍表示
    一片内存空间的某个位置,等价亍 C 诧言中的“地址”概念。地址仅仅表示存储空间的一个位置,从 C 诧言
    的角度来看,变量的地址,数组的地址戒是函数的入口地址在本质上并无区别。

初始化栈指针(SP)

; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x400      ;1K

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit
  • 在栈的代码后面便是初始化堆的代码,其中堆的大小设为0x0000 0200(512B),栈名为HEAP,不初始化,可读可写,8(2^3)字节对齐。而__heap_base为堆的起始地址,__heap_limit为堆的结束地址,因为堆的由低地址向高地址生长。
PRESERVE8
THUMB
  • PRESERVE8 指定当前文件保持堆栈八字节对齐。
  • THUMB 表示后面的指令是 THUMB 指令集 ,CM4 采用的是 THUMB - 2指令集

向量表的设置

; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
  • AREA 定义一块代码段,只读,段名字是 RESET。 READONLY 表示只读,缺省就表示代码段了。
  • 3 行 EXPORT 诧句将 3 个标号申明为可被外部引用, 主要提供给连接器用亍连接库文件戒其他其
    他文件。
__Vectors       DCD     __initial_sp              ; Top of Stack
                DCD     Reset_Handler             ; Reset Handler
                DCD     NMI_Handler               ; NMI Handler
                DCD     HardFault_Handler         ; Hard Fault Handler
                DCD     MemManage_Handler         
   
   
   ;此处省略中间代码,详细参见文末链接中的文件
   
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
                DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors
   
  • 上面的这段代码是建立中断向量表,中断向量表定位在代码段的最前面。具体的物理地址由连接器的
    配置参数(IROM1 的地址)决定。如果程序在 Flash 运行,则中断向量表的起始地址是 0x08000000。
  • DCD 表示分配 1 个 4 字节的空间。每行 DCD 都会生成一个 4 字节的二进制代码。中断向量表存放
    的实际上是中断服务程序的入口地址。当异常(也即是中断事件)发生时,CPU 的中断系统会将相应的入
    口地址赋值给 PC 程序计数器,之后就开始执行中断服务程序。

配置系统时钟进入main

                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
  • AREA 定义一块代码段,只读,段名字是 .text 。 READONLY 表示只读
  • 利用 PROC、 ENDP 这一对伪指令把程序段分为若干个过程,使程序的结构加清晰
  • WEAK 声明其他的同名标号优先亍该标号被引用,就是说如果外面声明了的话会调用外面的。 这个申明很重要,它让我们可
    以在 C 文件中仸意地方放置中断服务程序,只要保证 C 函数的名字和向量表中的名字一致即可。
  • IMPORT:伪指令用亍通知编译器要使用的标号在其他的源文件中定义。但要在当前源文件中引用,而且无论当前源文件是
    否引用该标号,该标号均会被加入到当前源文件的符号表中。
  • SystemInit 函数在文件 system_stm32f4xx.c 里面,这个文件在下期教程有详细讲解。
  • __main 标号表示 C/C++ 标准实时库函数里的一个初始化子程序 __main 的入口地址。该程序的一个主要作用是初始化堆栈
    (跳转__user_initial_stackheap 标号进行初始化堆栈的,下面会讲到这个标号),并初始化映像文件,最后跳转到 C 程序中的 main函
    数。这就解释了为何所有的 C 程序必须有一个 main 函数作为程序的起点。因为这是由 C/C++标准实时库所规,并且不能更改。
NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
;此处省略中间代码,详细参见文末链接中的文件
USBWakeUp_IRQHandler

                B       .

                ENDP

                ALIGN
  • 此处为中断服务程序,如果有在C中定义了中断服务程序,就会使用C中的中断服务车程序。
  • B 是指死循环
;*******************************************************************************
; 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
                 LDR     R1, =(Stack_Mem + Stack_Size)
                 LDR     R2, = (Heap_Mem +  Heap_Size)
                 LDR     R3, = Stack_Mem
                 BX      LR

                 ALIGN

                 ENDIF

                 END
  • 上面代码使用汇编诧言实现了 IF…….ELSE…………诧句。如果定义了 MICROLIB,那么程序是
    丌会 ELSE 分支的代码。
  • __user_initial_stackheap将由__main函数进行调用

参考:

安富莱教程

cnds文章

启动文件地址

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要下载startup_stm32f10x_md.s文件,首先需要找到可靠的下载来源。可以在STMicroelectronics的官方网站或STM32社区论坛上寻找该文件。从中文社区获取该文件也是一个选择。 在搜索引擎上搜索“startup_stm32f10x_md.s中文下载”,可以找到网上许多资源提供商,但是要确保他们是可靠的和合法的。选择一个受信任的源,以确保你下载的是正版的和有效的文件。 一旦找到可靠的来源,点击下载链接。然后,按照提示操作,选择下载文件的位置和文件名。 下载完成后,你将得到一个startup_stm32f10x_md.s文件。这是一个汇编文件,用于启动STM32F10x微控制器的启动代码。 接下来,你可以使用一个适当的集成开发环境(IDE)来打开这个文件。如果你正在使用Keil或者IAR等IDE,可以直接将该文件导入到你的项目中。 打开文件后,你可以编辑和查看其中的代码。startup_stm32f10x_md.s文件包含了初始化寄存器和设置中断向量表等关键功能,用于初始化STM32F10x微控制器的系统。 在编辑完成后,可以将该文件与其他源文件一起编译,生成可执行文件。这个可执行文件可以烧录到STM32F10x微控制器上,以运行你的应用程序。 总之,要下载startup_stm32f10x_md.s文件,首先要从可靠的来源获取该文件,然后使用适当的IDE打开并编辑。完成后,将其与其他源文件一起编译并烧录到STM32F10x微控制器上。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

002237

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

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

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

打赏作者

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

抵扣说明:

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

余额充值