startup_stm32f10x_hd.s启动文件详解;

一、启动文件介绍

  • 启动文件位于标准库的下面目录中:STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm
    在这里插入图片描述
  • 标准库下载方法,可以参考这篇文章
  • 启动文件有很多个,不同型号的单片机用的启动文件不一样,每个启动文件的详细说明见下图:
    在这里插入图片描述
  • 启动文件由汇编语言编写,是系统上电复位后第一个执行的程序,主要做了一下工作
    1. 初始化SP(Stack Pointer,栈指针);
    2. 初始化PC(Programmer Counter,程序计数器)== Reset_Handler;【程序计数器内核中的一个特殊寄存器,它用于存储即将执行的下一条指令的地址】
    3. 初始化中断向量表;
    4. 配置系统时钟;
    5. 调用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
    
    1. EQU汇编指令用来给数字常量、寄存器相对值、程序计数器相对值命名;【Stack_Size EQU 0x00000400------>即把数字常量0x00000400(4 * 16^2 = 1024 = 1KB)命名为Stack_Size】;
    2. 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表示82^3)字节对齐;
    ;(5)CONST
    ;	表示该段包含常量数据;
    

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

    1. 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(0x00000200512)字节,标签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
      
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值