1.cortex M3的复位过程(来自官方资料)
上述开机启动流程比较详细,内容较为全面,但部分步骤可以省略(红字可省略标出),因为对于某些初始化,我们可能会在main函数中重新配置。
2.复位程序的详细跟踪分析(重点)
此次分析基于单步跟踪stm32从复位到main()函数的汇编代码。
0.过程补充
中断向量表:
__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
内核设置堆栈从中断向量表偏移量为0的位置,也就是执行__inital_sp,代码如下:
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
伪指令AREA,表示开辟一段内存空间,段名是STACK
NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0
READWRITE可读可写
ALIGN=3-- 2 的3次方表示以8字节对齐
然后设置pc=Rest_handler,执行stm32复位程序。。。。。。。。。
1.stm32复位程序
-
; 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();
__main();
2.SystemInit()
功能:初始化时钟(SYSCLK, HCLK, PCLK2 and PCLK1 prescalers)、配置中断向量表(中断向量表的定位是在flash还是SRAM)。
-
void SystemInit (void)
-
{
-
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
-
/* Set HSION bit */
-
RCC->CR |= (uint32_t)0x00000001;
-
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
-
#ifndef STM32F10X_CL
-
RCC->CFGR &= (uint32_t)0xF8FF0000;
-
#else
-
RCC->CFGR &= (uint32_t)0xF0FF0000;
-
#endif /* STM32F10X_CL */
-
/* Reset HSEON, CSSON and PLLON bits */
-
RCC->CR &= (uint32_t)0xFEF6FFFF;
-
/* Reset HSEBYP bit */
-
RCC->CR &= (uint32_t)0xFFFBFFFF;
-
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
-
RCC->CFGR &= (uint32_t)0xFF80FFFF;
-
#ifdef STM32F10X_CL
-
/* Reset PLL2ON and PLL3ON bits */
-
RCC->CR &= (uint32_t)0xEBFFFFFF;
-
/* Disable all interrupts and clear pending bits */
-
RCC->CIR = 0x00FF0000;
-
/* Reset CFGR2 register */
-
RCC->CFGR2 = 0x00000000;
-
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
-
/* Disable all interrupts and clear pending bits */
-
RCC->CIR = 0x009F0000;
-
/* Reset CFGR2 register */
-
RCC->CFGR2 = 0x00000000;
-
#else
-
/* Disable all interrupts and clear pending bits */
-
RCC->CIR = 0x009F0000;
-
#endif /* STM32F10X_CL */
-
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
-
#ifdef DATA_IN_ExtSRAM
-
SystemInit_ExtMemCtl();
-
#endif /* DATA_IN_ExtSRAM */
-
#endif
-
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
-
/* Configure the Flash Latency cycles and enable prefetch buffer */
-
SetSysClock();
-
#ifdef VECT_TAB_SRAM
-
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
-
#else
-
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
-
#endif
-
}
3.__main();重点
该函数属于C/C++库函数。
该函数的作用是
1.完成全局/静态变量的初始化工作
2.初始化堆栈
3.库函数的初始化
4.程序的跳转,进入main()函数。
1.加载_main()函数的相应汇编代码
2._main()函数的汇编代码
功能:跳转进入__scatterload_rt2函数。
3.__scatterload_rt2函数汇编代码(C库函数)
该函数的作用是设置四个寄存器为后续__scatterload_cpy()函数服务的。
设置待copy内容(静态变量、全局变量、常量)的的加载域和运行域,设置待copy内容的大小,跳转进入__scatterload_cpy函数
4.__scatterload_cpy函数(C库函数)
完成静态变量、全局变量、常量的从flash到SRAM的加载以及程序的跳转进入__scatterload_zeroinit函数
5.__scatterload_zeroinit函数(C库函数)
功能:未初始化的全局变量的初始化,跳转进入__user_steup_stackheap函数
6.__user_steup_stackheap函数(C库函数)
功能:实现用户的堆栈的配置
__user_steup_stackheap函数包含了以下函数的调用:
a.__user_libspace------------------------__user_libspace为C库保持了静态数据。这是一个96字节,0初始化的数据块,该块由C库创建。在C库初始化期间可以用来当做临时栈。
b.__user_initial_stackheap-------------------------------------------------用户的初始化堆栈函数
7._fp_init和__rt_fp_status_addr(C库函数)------------------------------------------------------两个函数调用实现浮点运算的支持
调用结束跳转进入main()函数
8.main()函数