fromelf --bin --output=STM32F103.bin ../Output/STM32F103.axffromelf --text -a -c --output=STM32F103.dis ../Output/STM32F103.axf
然后重新编译,即可得到二进制文件STM32F103.bin(以后会分析)、反汇编文件STM32F103.dis。如下图所示:3.3 设置系统时钟细心的朋友可能发现,PC=0x08000145的地址是没有对齐的。然后在反汇编文件中却是这样的:这里是硬件自动对齐到 0x08000145,并执行SystemInit函数初始化系统时钟。当然也可通过硬件调试来确认上面的分析:接下来就会进入SystemInit函数中。SystemInit函数内容如下:/ @brief Setup the microcontroller system Initialize the Embedded Flash Interface, the PLL and update the SystemCoreClock variable. @note This function should be used only after reset. @param None @retval None /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 }
前面部分是配置时钟的,具体参考手册吧。SetSysClock()函数主要配置的时钟系数,笔者使用的MCU是STM32F103ZE,因此对应的时钟配置参数如下。/ @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. @note This function should be used only after reset. @param None @retval None /static void SetSysClockTo72(void){ __IO uint32_t StartUpCounter = 0, HSEStatus = 0; / SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------/ / Enable HSE / RCC->CR |= ((uint32_t)RCC_CR_HSEON); / Wait till HSE is ready and if Time out is reached exit / do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_HSERDY) != RESET) { HSEStatus = (uint32_t)0x01; } else { HSEStatus = (uint32_t)0x00; } if (HSEStatus == (uint32_t)0x01) { / Enable Prefetch Buffer / FLASH->ACR |= FLASH_ACR_PRFTBE; / Flash 2 wait state / FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; / HCLK = SYSCLK / RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; / PCLK2 = HCLK / RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; / PCLK1 = HCLK / RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;#ifdef STM32F10X_CL / Configure PLLs ------------------------------------------------------/ / PLL2 configuration: PLL2CLK = (HSE / 5) 8 = 40 MHz / / PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz / RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); / Enable PLL2 / RCC->CR |= RCC_CR_PLL2ON; / Wait till PLL2 is ready / while((RCC->CR & RCC_CR_PLL2RDY) == 0) { } / PLL configuration: PLLCLK = PREDIV1 9 = 72 MHz / RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); #else / PLL configuration: PLLCLK = HSE 9 = 72 MHz / RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);#endif / STM32F10X_CL / / Enable PLL / RCC->CR |= RCC_CR_PLLON; / Wait till PLL is ready / while((RCC->CR & RCC_CR_PLLRDY) == 0) { } / Select PLL as system clock source / RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; / Wait till PLL is used as system clock source / while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { } } else { / If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error / }}
SetSysClockTo72()函数配置了各个参数,最终PLL的时钟位72MHz。这里还需要注意以下代码:#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
默认是没有开启VECT_TAB_SRAM,则从FLASH中启动,VTOR 寄存器存放的是中断向量表的起始地址,在IAP升级会修改这里的偏移量,后面讲解IAP升级在细讲吧。3.4 初始化堆栈并进入main执行指令LDR R0, =__main,然后就跳转到__main程序段运行,当然这里指标准库的__main函数。这中间初始化了栈区。这段代码是个循环(BCC 0x0800016e),实际运行时候循环了两次。第一次运行的时候,读取“加载数据段的函数”的地址并跳转到该函数处运行(注意加载已初始化数据段和未初始化数据段用的是同一个函数);第二次运行的时候,读取“初始化栈的函数”的地址并跳转到该函数处运行。最后就进入C文件的main函数中,至此,启动过程到此结束。最后,总结下STM32 从flash的启动流程。MCU上电后从0x0800 0000处读取栈顶地址并保存,然后从0x0800 0004读取中断向量表的起始地址,这就是复位程序的入口地址,接着跳转到复位程序入口处,初始向量表,然后设置时钟,设置堆栈,最后跳转到C空间的main函数,即进入用户程序。(图片来源网络,侵删)
0 评论