打印
[应用相关]

startup_stm32f10x_hd.s启动文件详解

[复制链接]
34|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-12-12 08:12 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、启动文件介绍
启动文件位于标准库的下面目录中:STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm



标准库下载方法,可以参考这篇文章
启动文件有很多个,不同型号的单片机用的启动文件不一样,每个启动文件的详细说明见下图:



启动文件由汇编语言编写,是系统上电复位后第一个执行的程序,主要做了一下工作:
初始化SP(Stack Pointer,栈指针);
初始化PC(Programmer Counter,程序计数器)== Reset_Handler;【程序计数器内核中的一个特殊寄存器,它用于存储即将执行的下一条指令的地址】
初始化中断向量表;
配置系统时钟;
调用C库函数_main初始化用户堆栈,最终调用main函数;



启动代码中涉及到ARM汇编指令和Cortex内核的指令;
ARM汇编指令可以在Keil MDK—>Help—>Uvison Help中搜索到(太官方,可读性比较差):





二、启动文件详解
汇编语言的注释符号为 ;

Stack Configuration 栈配置

Stack_Size      EQU     0x00000400

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


EQU汇编指令用来给数字常量、寄存器相对值、程序计数器相对值命名;【Stack_Size EQU 0x00000400------>即把数字常量0x00000400(4 * 16^2 = 1024 = 1KB)命名为Stack_Size】;
AREA汇编指令用来汇编一个新的代码段或数据段。AREA定义的作用范围会持续到下一个AREA伪指令出现,或者直到源文件结束。
;使用方法
AREA segment_name, attributes
;segment_name        段的名称,用户可以自定义。例如:STACK、TEXT、CODE、DATA等;
;attributes        描述端属性的关键字,可以有多个属性,以逗号分隔;
;常见属性:
;(1)CODE或DATA
;        CODE                表示该段含可执行代码;
;        DATA                表示该段含初始化的数据;
;(2)READONLY或READWRITE
;        READONLY         表示该段的内容只能读取,通常用于代码段;
;        READWRITE        表示该段的内容可以被修改,通常用于数据段;
;(3)NOINIT
;        表示该段中的数据不会在程序启动时被初始化;
;(4)ALIGN=n
;        表示段内数据的对其方式。n的值决定了对齐到2的多少次幂。例如ALIGN=3表示8(2^3)字节对齐;
;(5)CONST
;        表示该段包含常量数据;



【AREA STACK, NOINIT, READWRITE, ALIGN=3------>即定义一个代码段,段名为STACK,不初始化,可读可写,8字节对齐】;

SPACE汇编指令用于在内存中预留一块指定大小的空间,并将其初始化为零;
;预留一段内存并初始化为0,大小为Stack_Size(1024)字节,标签Stack_Mem指向这段内存的开头,标签__initial_sp指向这段内存的结尾;
Stack_Mem       SPACE   Stack_Size
__initial_sp


注意:栈的生长方向是从栈底(高地址)向栈顶生长(低地址)

Heap Configuration 堆配置

Heap_Size       EQU     0x00000200                                                        ;数字常量0x00000200命名为Heap_Size

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3        ;汇编一个代码段,命名为HEAP,不初始化,可读可写,8字节对齐
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit                                                                                                ;预留一段内存并初始化为0,大小为Heap_Size(0x00000200,512)字节,标签Heap_Mem指向这段内存的起始地址,标签__heap_limit指向这段内存的结束地址


PRESERVE8:指定当前文件的堆栈按照8字节对齐;

THUMB:表示后面指令兼容THUMB指令。THUMB是arm以前的指令集,每个指令的大小为16位;现在Cortex-M系列都是用THUMB-2指令集,THUMB-2是32位的,兼容16位和32位的指令,即是THUMB的超集;

Vector Table Mapped to Address 0 at Reset 复位时的向量表映射

当内核响应了一个发生的异常后,对应的异常服务例程(ESR,Exception Service Routine)就会执行;
内核通过查询向量表来找到ESR的入口地址;
向量表就是一个WORD(32位)数组,每个下标对应一种异常,下标元素的值则是该ESR的入口地址。
向量表的地址存储在NVIC的一个重定位寄存器中。复位后,该寄存器的值为0,因此,地址0处必须包含一张向量表,用于初始时的异常分配。
EXPORT:声明一个标签可以被外部文件使用;
DCD:分配一个或多个内存字,按四字节边界对齐,并定义内存的初始运行时内容。
                        AREA    RESET, DATA, READONLY                  ;定义一个数据段,命名为RESET,只读;
            EXPORT  __Vectors                                        ;声明标签__Vectors,使其可以被外部文件使用
            EXPORT  __Vectors_End                                ;声明标签__Vectors_End,使其可以被外部文件使用
            EXPORT  __Vectors_Size                                ;声明标签__Vectors_Size,使其可以被外部文件使用

__Vectors   DCD     __initial_sp               ; Top of Stack--->分配一个字(4字节)的内存,内存中存储__initial_sp的值;标签__Vectors指向该内存的起始地址;
            DCD     Reset_Handler              ; Reset Handler--->分配一个字(4字节)的内存,内存中存储Reset_Handler(复位处理程序)的地址;
            DCD     NMI_Handler                ; NMI Handler--->分配一个字(4字节)的内存,内存中存储NMI_Handler(NMI,None-Maskable Interrupt,不可屏蔽中断处理程序)的地址;
            DCD     HardFault_Handler          ; Hard Fault Handler--->分配一个字(4字节)的内存,内存中存储HardFault_Handler(硬错误处理程序,指非常严重的错误)的地址;
            DCD     MemManage_Handler          ; MPU Fault Handler--->分配一个字(4字节)的内存,内存中存储MemManage_Handler(内存管理处理程序)的地址;
            DCD     BusFault_Handler           ; Bus Fault Handler--->分配一个字(4字节)的内存,内存中存储BusFault_Handler(总线错误处理程序)的地址;
            DCD     UsageFault_Handler         ; Usage Fault Handler--->分配一个字(4字节)的内存,内存中存储UsageFault_Handler(用法错误处理程序)的地址;
            DCD     0                          ; Reserved
            DCD     0                          ; Reserved
            DCD     0                          ; Reserved
            DCD     0                          ; Reserved
            DCD     SVC_Handler                ; SVCall Handler--->分配一个字(4字节)的内存,内存中存储SVC_Handler(Supervisor Call管理程序调用处理程序)的地址;
            DCD     DebugMon_Handler           ; Debug Monitor Handler--->分配一个字(4字节)的内存,内存中存储DebugMon_Handler(Debug Monitor调试监视器处理程序)的地址;
            DCD     0                          ; Reserved
            DCD     PendSV_Handler             ; PendSV Handler--->分配一个字(4字节)的内存,内存中存储PendSV_Handler(Pendable Service Call,可挂起系统服务处理程序)的地址;
            DCD     SysTick_Handler            ; SysTick Handler--->分配一个字(4字节)的内存,内存中存储SysTick_Handler(系统定时器处理程序)的地址;

            ; External Interrupts
            DCD     WWDG_IRQHandler            ; Window Watchdog
            DCD     PVD_IRQHandler             ; PVD through EXTI Line detect--->分配一个字(4字节)的内存,内存中存储PVD_IRQHandler(电源电压检测中断请求处理程序)的地址;
            DCD     TAMPER_IRQHandler          ; Tamper--->分配一个字(4字节)的内存,内存中存储TAMPER_IRQHandler(入侵中断请求处理程序)的地址;
            DCD     RTC_IRQHandler             ; RTC
            DCD     FLASH_IRQHandler           ; Flash
            DCD     RCC_IRQHandler             ; RCC--->分配一个字(4字节)的内存,内存中存储RCC_IRQHandler(复位时钟控制中断请求处理程序)的地址;
            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_End指向向量表的末尾地址

__Vectors_Size  EQU  __Vectors_End - __Vectors                ;标签__Vectors_Size表示向量表的大小,末尾地址-初始地址



复位程序

lable PROC…ENDP:函数的定义。
WEAK:弱定义。如果外部文件中有定义则使用外部定义,如果没有则使用该定义。
IMPORT:表示该定义来自外部文件,类似C语言中的extern.
LDR:从内存加载数据到寄存器;
BLX:内核指令,跳转到目标地址执行代码,并把下一条指令的地址保存到链接寄存器LR中,这样目标地址代码执行结束后还可以返回原始地址并继续执行;
BX:内核指令, 只是简单地将程序计数器(PC)设置为目标地址,不会保存任何返回地址。
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                ENDP


中断处理程序定义
启动文件中已经写好了所有的中断处理程序,但这些处理程序中都是空的,真正的中断处理程序需要我们在外部的C文件中重新实现。
如果我们在使用某个外设的时候,开启了某个中断,但没编写配套的中断处理程序或中断处理程序的名字写错。那么当中断来临的时候,程序就会跳转到启动文件预先写好的中断处理程序中,并在这个空程序中无限循环。

B . 指令会让程序不断跳转回当前指令,形成一个无法退出的循环。
ALIGN:伪指令确保接下来的数据或代码对齐。正确的内存对齐可以提高访问速度,尤其是在处理多字节数据(如32位整数、浮点数等)时,未对齐的访问可能会导致性能下降甚至硬件异常。后面会跟一个参数,参数必须是2的幂次方(如2、4、8、16等),表示对齐的字节数。如果没有跟参数,则默认4字节对齐
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



用户堆栈初始化
IF,ELSE,ENDIF:汇编的条件分支语句,与C语言的if, else类似;
END:文件结束;
**该部分汇编程序首选判断了是否定义了宏__MIRCOLIB,如果定义了这个宏,则把标签__init_sp(栈顶地址)、__heap_base(堆起始地址)、__heap_limit(堆结束地址)全局化,可供外部文件调用,之后堆栈的初始化就由C库函数_main来完成。我们一般使用这种方式。 **__MICROLIB这个宏我们在Keil的魔术棒中可以配置,具体配置方法如下图:



如果没有定义 __MICROLIB,则插入标号 __use_two_region_memory,这个函数需要用户自己实现,具体要如何实现,可在 KEIL 的帮助文档里面查询到,具体见图 use_two_region_memory函数。



                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


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_61470035/article/details/144255912

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2010

主题

15843

帖子

13

粉丝