【STM32】IAP下载程序分析

您所在的位置:网站首页 stm32启动流程分析gcc 【STM32】IAP下载程序分析

【STM32】IAP下载程序分析

2023-12-17 00:23| 来源: 网络整理| 查看: 265

IAP下载程序分析 IAP基本原理STM32启动流程程序跳转代码实现总结

IAP基本原理

要实现STM32的IAP(在应用编程),需要分别建立bootloader和app工程。这里的bootloader程序是用户自己实现的,与STM32内置的bootloader无关。例如,我们可以把bootloader程序放在0x8000000处,把app程序放在0x80001000处,上电时首先进入bootloader程序执行,检查是否需要更新app,执行完毕后再跳转到app程序处执行。

STM32启动流程

为了实现bootLoader到app的跳转,首先需要弄清楚STM32程序执行的流程。 STM32 flash程序执行通常由地址0x8000000开始。首4个字节存放主栈顶指针MSP地址,其值是由编译器编译后决定的。比如用户用到了多少全局变量以及静态变量,在RAM中就需要预留出相应的空间,从而影响栈顶指针的位置,而局部变量在RAM中的存取就需要栈顶指针和栈大小来约束。上电时STM32的MSP寄存器即被初始化。

__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

在栈顶指针地址后面紧接着是以Reset_Handler开始的中断向量表,该表一一指向了对应的中断函数地址。 上电或复位后,STM32的PC被赋予0x8000000+4的值,也就是跳转到中断向量表中Reset_Handler向量指向的中断程序 Reset_Handler所指向的程序如下,可以看出此处执行了SystemInit和main两个函数,也就是说通过复位中断后程序最终流向了main函数的while(1)死循环,从而执行用户代码。

Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP

在执行main函数的过程中,每当有中断发生时,程序就会跳转到中断向量表中搜索对应的中断程序,然后跳转至中断函数处执行,最后返回main函数继续执行。

程序跳转代码实现

通过上面的分析可知,STM32在上电或复位后把0x8000000处的值赋给了MSP寄存器来初始化主堆栈指针地址,把0x8000000+4处的值赋给了PC寄存器使程序进入复位中断从而顺利执行。 所以,要实现bootloader到app的跳转,需要我们需要改变MSP和PC这两个寄存器。bootloader中跳转代码的实现如下:

#define __IO volatile /*!< defines 'read / write' permissions */ #define ApplicationAddress 0x8003000 pFunction Jump_To_Application; uint32_t JumpAddress; typedef void (*pFunction)(void); /** * @brief Set the Main Stack Pointer * * @param topOfMainStack Main Stack Pointer * * Assign the value mainStackPointer to the MSP * (main stack pointer) Cortex processor register */ __ASM void __set_MSP(uint32_t mainStackPointer) { msr msp, r0 bx lr } void Jump2App(void) { /* Test if user code is programmed starting from address "ApplicationAddress" */ if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) { /* Jump to user application */ JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) ApplicationAddress); Jump_To_Application(); } }

ApplicationAddress是用户定义的app程序首地址,如0x8000000+0x1000。通过if条件来判断该地址中的值是否在指定的RAM空间范围内,如果是则从0x8000000+0x1000+4地址(即app程序的Reset_Handler向量)中取出要跳转的地址JumpAddress,并通过空函数指针Jump_To_Application指向该地址。 完成好准备工作后,接下来就是最重要的一步。通过__set_MSP()函数设置MSP寄存器,通过调用空函数指针Jump_To_Application使得PC跳转至地址JumpAddress。如此一来,MSP和PC的值由bootloader空间更新为app空间,转而运行app部分的代码。 但是,配置工作还没有结束。上面提到了当执行main函数发生中断时,会跳转至中断向量表,由于我们没有修改中断向量表,中断向量表指向的仍是bootloader空间的中断函数,所以最后中断返回bootloader的main函数执行。而我们希望映射的中断向量表是app空间的中断向量表,因此,需要在app的main函数开头添加重映射语句:

SCB->VTOR = ApplicationAddress; 总结

1.要实现IAP功能,需要建立bootloader和app两个工程,bootloader地址从0x8000000开始,而app地址由用户指定(不能与bootloader冲突),编译好工程后分别下载到STM32; 2.在bootloader中设置MSP和PC以跳转至app执行,进入app后首先要重映射中断向量表,使得中断执行app空间的中断函数。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3