STM32启动文件
一、复位电路
在了解启动文件之前需要明白STM32的复位中断流程,STM32的复位分为上电复位和手动复位,复位的电路图如下所示:
注意: 图中的复位电路是低电平复位,有的MCU是高电平复位。
上电复位:顾名思义,上电复位就是STM32通电时,硬件自动复位的过程。从复位电路中可知,当芯片刚通电时电容两端没离子存在,所以处于充电过程,此时复位引脚等同于接地,这一过程成为上电复位。
手动复位:手动复位是通过按键强行将复位引脚拉低,使芯片产生复位中断。
二、启动文件分析准备
STM32的启动文件后缀是".s"的文件,打开项目是可以看到项目中有一个startup_stm32f103xb.s的文件,如下图所示:
打开文件后可以很清晰的看到STM32的启动流程,不过这里需要一些简单的汇编知识。没学过汇编的小伙伴也不用怕,我们只需要简单的分析即可,这里只分析流程不进行汇编指令的编写。
启动文件中常用的汇编指令
指令 作用 EQU 定义字符常量,相当于C语言的 define AREA 汇编一个新的代码段或数据段 SPACE 分配内存空间 PRESERVE8 当前文件堆栈需按照 8 字节对其 EXPORT 声明全局属性,可被外部文件使用 DCD 以字为单位分配内存,要求4字节对齐,并初始化这些内存 PROC 定义子程序,与 ENOP 成对使用,表示子程序结束 WEAK 弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义,则使用当前位置的标号 IMPORT 声明标号来自外部文件,跟 C 语言中的 EXTERN 关键字类似 B 跳转到一个标号 END 到达文件的末尾,文件结束 IF,ELSE,ENDIF 汇编条件分支语句 LDR 从存储器中加载字到一个寄存器中 BL 跳转到由寄存器/标号给出的地址,并把跳转前的下条指令地址保存到 LR BLX 跳转到由寄存器给出的地址,并根据寄存器的LSE确定处理器的状态,还要把跳转前的下条指令地址保存到LR BX 跳转到由寄存器/标号给出的地址,不用返回 注意: ALIGN是编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示 4 字节对齐。需要注意的是:这个不是ARM的指令,是编译器的
启动流程
(1) 硬件上电复位。
(2) 初始化指针 SP=_initial_sp 和 PC == Reset_Handler。
(3) 执行复位中断服务程序。
三、启动文件的作用
- 初始化堆栈指针SP;
- 初始化程序计数器指针 PC;
- 设置堆、栈的大小;
- 设置异常向量表的入口;
- 配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板没有外部SRAM)
- 设置C库的分支入口__main(最终调用mian函数)
- 使用库函数项目时,启动文件还调用了SystemInit函数配置系统时钟。
四、启动代码详解
开辟栈(stack)空间,用于局部变量、函数调用、函数的参数等使用。栈的大小不能超过内部SRAM大小。
Stack_Size EQU 0x400 AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
- EQU:表示宏定义的伪指令,伪指令并不会生成二进制程序代码,也不会引起变量空间分配。0x400表示栈大小,注意这里是以字节为单位。
- AREA:开辟一段可读写的数据空间,段名为stack,按照 8 字节对齐。AREA后面的关键字表示这个段的属性。
(1) STACK:表示这个段的名字,可以任意命名。
(2) NOINIT:表示此数据段不需要填入初始化数据。
(3) READWRITE:表示此段可读写。
(4) ALIGN=3:表示首地址按照 2 的 3次方对齐,也就是按照8字节对齐。 - SPACE 这行指令告诉汇编器给STACK段分配0x400字节的连续内存空间。
- __initial_sp紧挨SPACE放置,表示栈的结束机制,栈是从高往低使用,所以结束地址就是栈顶地址。
开辟堆(heap)空间,主要用于动态内存分配,也就是malloc、calloc、realloc等函数分配的变量空间是在堆上。
Heap_Size EQU 0x200 AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
- __heap_base:表示堆的开始地址
- __heap_limit:表示堆的结束地址
文件属性定义
PRESERVE8
THUMB ; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
- PRESERVE8:指定当前文件保持堆栈 8 字节对齐
- THUMB:表示后面的指令是 THUMB 指令集,CM4 采用的是 THUMB - 2指令集
- AREA:定义一块代码段,只读,段名是RESET。READONLY表示只读,缺省就表示代码段了
- 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 ; 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
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
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_2
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 RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
- __Vectors:为向量表其实地址
- __Vectors_End:为向量表结束地址
- __Vectors_Size:为向量表的大小。
- DCD:表示分配1个4字节的空间。每行DCD都会生成一个4字节的二进制代码。中断向量表存放的实际上是中断服务程序的入口地址,当异常(也就是中断实践)发生时,CPU的中断系统会将相应的入口地址赋值给PC程序计数器,之后就开始执行中断服务程序。
定义可读代码段
AREA |.text|, CODE, READONLY
- AREA:定义一个名为.test的可读代码段
复位程序
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
- 复位子程序是系统上电后第一个执行的程序,调用SystemInit()函数初始化系统时钟,然后调用C库函数__main。
中断复位子程序
; Dummy Exception Handlers (infinite loops which can be modified) 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 RTC_Alarm_IRQHandler [WEAK]
EXPORT USBWakeUp_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
RTC_Alarm_IRQHandler
USBWakeUp_IRQHandler B . ENDP- WEAK:如果外部文件中定义了此中断函数,优先使用外部文件中的中断函数,反之使用当前中断函数。
- ".":表示无限循环
- 如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务程序需或者函数名写错时,当相应的中断产生时,程序就会跳转到启动文件预先写好的空中断函数中,并且在这个空函数中无限循环,即程序就死在这里。
用户堆栈初始化
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
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR ALIGN ENDIF END
- ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示4字节对齐。
- __user_initial_stackheap:初始化栈和堆(使用默认C库时,由__main函数进行调用)
- 如果使用微库时,调用__MICROLIB部分的程序,反之使用默认的C库,然后初始化用户堆栈大小。微库的使用如下图所示:
参考文献
STM32启动文件————startup_stm32f10x_hd.s:https://wenku.baidu.com/view/3275eee00ba1284ac850ad02de80d4d8d15a0198.html
STM32启动文件的更多相关文章
- STM32启动文件的选择
移植了同事一个程序,然后死活不能用,发现启动文件错了,明天继续调.真把人折腾死了. stm32给的库文件太琐碎了,正如它的芯片型号一样繁多,例如启动文件: 网上查到的各个文件的解释是: startup ...
- 2.STM32启动文件
一.概念声明 中断向量:由硬件产生的中断标识码,一般用于存放中断服务程序的跳转指令.根据硬件产生的中断号查找中断向量表来确定对应的中断向量.CM3内核有15个异常 和240个中断源. 程序的内 ...
- stm32启动文件ld md hd cl vl xl分析及选择
startup_stm32f10x_cl.s互联型的STM32F105xx,STM32F107xxstartup_stm32f10x_hd.s 大容量的STM32F101xx,STM32F102xx, ...
- (转)stm32启动文件详解
在<<STM32不完全手册里面>>,用的是STM32F103RBT6,所有的例程都采用了一个叫STM32F10x.s的启动文件,里面定义了STM32的堆栈大小以及各种中断的名字 ...
- STM32启动文件深度解析
STM32启动过程全面解析,包括启动过程的介绍.启动代码的陈列以及深入解析.相对于ARM上一代的主流ARM7/ARM9内核架构,新一代Cortex内核架构的启动方式有了比较大的变化.ARM7/ARM9 ...
- STM32启动文件:startup_stm32f10x_hd.s等启动文件的简单描述
在官方的库文件中,分别有如下文件: startup │ │ │ ├─arm │ │ │ │ startup_stm32f10x_cl.s │ │ │ │ startup_stm32f10x_hd.s ...
- STM32启动文件详解
启动文件使用的 ARM 汇编指令汇总 启动程序源码注释(点此下载) 1. Stack—栈 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE ...
- STM32启动文件详细解析(V3.5.0) 以:startup_stm32f10x_hd.s为例
我用的是IAR,这个貌似是MDK的,不过很有用,大家可以看一下 ;* 文件名 : startup_stm32f10x_hd.s ;* 库版本 : V3.5.0 ;* 说明: 此文件为STM32F10x ...
- stm32启动文件 startup_stm32f10x_hd.s
;* 文件名 : startup_stm32f10x_hd.s;* 库版本 : V3.5.0;* 说明: 此文件为STM32F10x高密度 ...
随机推荐
- linux vim编辑器使用
小i 在光标所在行位置停止不动开始写入内容 大I 在光标所在行行首开始写入内容 小a 在光标所在行当前字符后开始写入内容 大A 在光标所在行行尾开始写入内容 小o 在光标所在行下一行开始写入内容 大O ...
- EMS设置发送连接器和接收连接器邮件大小
任务:通过EMS命令设置发送接收连接器和接收连接器的邮件大小限制值为50MB. 以Exchange管理员身份打开EMS控制台.在PowerShell命令提示符下. 键入以下命令设置接收-连接器的最大邮 ...
- Java报错:Injection of resource dependencies failed
在学习springMVC+Mabatis的时候,添加注解@Resource报错 Injection of resource dependencies failed de完bug后发现有几个点注意一下, ...
- print,printf,println的区别,以及\r,\n,\r\n的区别
1.常用的是println,就是换行输出 2.print,不换行输出 3.printf常使用于格式转化 public class Print { public static void main(Str ...
- 自己写的一个Hash文件校验软件
原因 学校网络安全课讲到了Hash函数,老师提了一句上机操作的时候可以用自己的写的文件校验软件,所以我干脆就自己写一个. 说明 支持算法 MD5 SHA1 SHA256 SHA512 SHA384 为 ...
- JavaWeb入门day10-JSP
JSP 什么是JSP Java Server Pages:Java服务器端页面,也和Servlet一样,用于动态Web技术 最大特点: 写JSP就像在写HTML 区别 HTML只给用户提供静态数据 J ...
- line-height: 1; line-height: 100%;是什么意思
先简单看个例子: css 页面: 应该猜测出来了: line-height: 1; = line-height: 100%; = font-size: 50px; 把哪一个放到最后都是一样的.我理解的 ...
- 翻译《Mastering ABP Framework》
前言 大家好,我是张飞洪,谢谢你阅读我的文章. 自从土牛Halil ibrahim Kalkan的<Mastering ABP Framework>出版之后,我就开始马不停蹄进行学习阅读和 ...
- Day 005:PAT练习--1047. 编程团体赛(20)
编程团体赛的规则为:每个参赛队由若干队员组成:所有队员独立比赛:参赛队的成绩为所有队员的成绩和:成绩最高的队获胜.现给定所有队员的比赛成绩,请你编写程序找出冠军队. 输入格式: 输入第一行给出一个正整 ...
- Python 查找算法_众里寻他千百度,蓦然回首那人却在灯火阑珊处(线性、二分,分块、插值查找算法)
查找算法是用来检索序列数据(群体)中是否存在给定的数据(关键字),常用查找算法有: 线性查找: 线性查找也称为顺序查找,用于在无序数列中查找. 二分查找: 二分查找也称为折半查找,其算法用于有序数列. ...