单⽚机启动过程:main之前⼲了啥
Version S Description Date By V1C First Version2020-12-19AYZP
C―― Create,
A—— Add,
M—— Modify,
D—— Delete。
前⾔
单⽚机在执⾏main函数之前,都⼲了什么呢?都做了什么准备呢?来总结⼀下。
⼀准备
⽤KEIL学STM32单⽚机编程的时候,按下其仿真按钮
再按下RST按钮
会发现进⼊到⼀个启动⽂件startup_stm32f10x_md.s,运⾏指⽰光标,会停在⼀个位置上:
详细代码见附录A,这块代码前⾯是栈⼤⼩设置stack size、堆⼤⼩设置heap size、⼀堆中断向量表Vector Table 可以看到,我们的运⾏光标停在Reset_Handler处。在我们执⾏__main之前,还要执⾏SystemInit,这个SystemInit包括什么呢,打开看看。我们会发现这个SystemInit在⽂件system_stm32f10x.c⽂件中,是⼀个函数,⾥⾯的动作包括很多,详细代码放在附录B,有兴趣看看。
⼆分析
分析全是看别⼈的,链接见参考⽂献
MCU上电(复位)时,从固定的地址启动,⼀般是地址0x00000000,如ARM7;个别特殊的如STM32默认启动地址为 0x8000000(flash区启动)。
STM32的内部闪存地址起始于0x8000000,⼀般情况下,程序⽂件就从此地址开始写⼊。此外STM32是基于Cortex-M3内核的微控制器,其内部通过⼀张“中断向量表”来响应中断,程序启动后,将⾸先从“中断向量表”取出复位中断向量(上⾯的Reset_Handler)执⾏复位中断程序完成启动。 程序执⾏过程如下图:
1、STM32复位后,会从地址为0x8000004处取出复位中断向量的地址,并跳转执⾏复位中断服务程序,如图1中标号1 所⽰。
2、复位中断服务程序执⾏的最终结果是跳转⾄C程序的main函数,如上图中标号2 所⽰,⽽main函数应该是⼀个死循环,是⼀个永不返回的函数。(我们这篇⽂章主要就是这⾥了,跳到main函数前,程序⼲了啥,见下⼀节)
3、在main函数执⾏的过程中,发⽣了⼀个中断请求,此时STM32的硬件机制会将PC指针强制指回中断向量表处,如图中标号3 所⽰。
4、根据中断源进⼊相应的中断服务程序,如图1中标号5 所⽰。
5、中断服务程序执⾏完毕后,程序再度返回⾄main函数中执⾏,如图中标号6 所⽰。
STM32的内部闪存地址起始于0x8000000,⼀般情况下,程序⽂件就从此地址开始写⼊。此外STM32是基于Cortex-M3内核的微控制器,其内部通过⼀张“中断向量表”来响应中断,程序启动后,将⾸先从“中断向量表”取出复位中断向量执⾏复位中断程序完成启动。⽽这张“中断向量表”的起始地址是0x8000004,当中断来临,STM32的内部硬件机制亦会⾃动将PC指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执⾏中断服务程序。最后还需要知道关键的⼀点,通过修改STM32⼯程的链接脚本可以修改程序⽂件写⼊闪存的起始地址。
2.2 main 之前⼲了啥
启动过程主要完成两部分⼯作,⼀个是硬件执⾏环境,如中断向量表、寄存器、看门狗等,另⼀个是软件环境,如C库环境、ZI(未初始化的内存变量)等。
2.2.1 硬件执⾏环境
纳米氧化铋1.初始时钟
初始化内核时钟,主时钟,各个外设的时钟。
2.关闭看门狗
看门狗是⽤来监控应⽤程序的异常跑飞⽽复位CPU,在初始化阶段,由于没有“喂狗”这⼀动作,有可能导致CPU不断复位,因此,⾸先会关闭看门狗,初始化完,再开启。
3.建⽴中断向量表
中断向量表,中断源的识别标志,可⽤来形成相应的中断服务程序的⼊⼝地址,或者中断服务程序⼊⼝地址的偏移量和段基值。CPU利⽤中断向量表转⼊中断服务程序处理相关事务。
4.初始化堆栈寄存器
堆栈的作⽤⼀个就是保存现场(上下⽂),如函数调⽤或者中断发送时,将当前执⾏地址压栈,调⽤完成再返回此处执⾏程序。另⼀个作⽤就是保存参数,如临时变量。因此,在启动阶段需初始化堆栈寄存器、堆栈的⼤⼩、起始地址等。
5.内存初始化
选择内部或者外部RAM。
2.2.2 软件环境
1.把RO,RW从它们的加载域复制到它们的运⾏域中去。
2.初始化(清零)ZI域。
mlssa3.初始化堆栈指针
4.初始化C库环境
包括C库所需的内存空间、程序执⾏所需资源、C库初始化。
2.2.3 CortexM3启动
CortexM3有3种启动⽅式
1、BOOT1=1BOOT0=1,中断向量表定位于SRAM区,即起始地址为0x2000000,同时复位后PC指针位于0x2000000处。
2、BOOT1=xBOOT0=0,中断向量表定位于FLASH区,即起始地址为0x8000000,同时复位后PC指针位于0x8000000处。
3、BOOT1=0BOOT0=1,中断向量表定位于内置Bootloader区,此时可通过串⼝下载程序的⼆进制⽂件到flash区。
⽽Cortex-M3内核规定,起始地址必须存放堆顶指针,⽽第⼆个地址则必须存放复位中断⼊⼝向量地址,这样在Cortex-M3内核复位后,会⾃动从起始地址的下⼀个32位空间取出复位中断⼊⼝向量,跳转执⾏复位中断服务程序。对⽐ARM7/ARM9内核,Cortex-M3内核则是固定了中断向量表的位置⽽起始地址是可变化的。即是对于flash启动来说(正常⼯作也是flash启动),0x8000000地址存放的是栈顶地址__initial_sp,0x8000004地址存放的是复位中断向量Reset_Handler⼊⼝地址(STM32使⽤32位总线,存储空间为4字节对齐);在编写多段程序时,偏移地址空间需注意,如编写⼀个BootLoader,从BootLoader到应⽤程序段的相互跳转。
2.3 流程
关于STM32上电启动的流程,我理解的是这样:
根据boot引脚的电平,确定程序起始地址,同时PC指针指向该地址。(假设从内部flash启动,起始地址0x08000000);
从0x08000000取出MSP栈顶指针;(设置堆栈)
从0x08000004取出值赋给PC,即reset_handler的地址,然后执⾏reset_handler程序。(想想2.1的那张图)。在reset_handler中完成功能:
时钟初始化、看门狗、中断向量表、内存初始化、堆栈初始化、初始化运⾏环境(⼀些库)等。(此处顺序如何⽬前2020-12-19还不知道)
执⾏main
参考⽂献
附录A
启动⽂件startup_stm32f10x_md.s
;********************(C) COPYRIGHT 2011 STMicroelectronics ********************
;
人体结构学* File Name : startup_stm32f10x_md.s
;* Author : MCD Application Team
;* Version : V3.5.0
;* Date :11-March-2011
;* Description : STM32F10x Medium Density Devices vector table for MDK-ARM
;* toolchain.
;* This module performs:
;*- Set the initial SP
;*- Set the initial PC == Reset_Handler
;*- Set the vector table entries with the exceptions ISR address
;*- Configure the clock system
;
*- Branches to __main in the C library (which eventually
;* calls main()).
;* After Reset the CortexM3 processor is in Thread mode,
;* priority is Privileged, and the Stack is set to Main.
;*<<< Use Configuration Wizard in Context Menu >>>
;*******************************************************************************
; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. ; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
;*******************************************************************************
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
;<h> Stack Configuration
;<o> Stack Size (in Bytes)<0x0-0xFFFFFFFF:8>
;</h>
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
;<h> Heap Configuration
;<o> Heap Size (in Bytes)<0x0-0xFFFFFFFF:8>
;</h>
Heap_Size EQU 0x00000200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB
;
Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__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 RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
;
Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
影子价格
IMPORT SystemInit
LDR R0,=SystemInit