STM32 Bootloader程序中Jump2App函数分析

Jump2App函数代码

#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();
    }
}

用户代码的堆栈地址的判断

if ((((__IO uint32_t)ApplicationAddress) & 0x2FFE0000 ) ==
0x20000000)
{
……
}

其中ApplicationAddress是0x8003000是用户程序Flash的首地址,首地址里面存放的是用户代码的堆栈地址,((__IO uint32_t)ApplicationAddress)这个就是讲用户代码的堆栈地址取出来,堆栈地址指向RAM,而RAM的起始地址是0x20000000,所以(…… & 0x2FFE0000 ) )这个是判断用户代码的堆栈地址是否落在0x20000000~0x2001ffff之间。

启动设置

JumpAddress = (__IO uint32_t) (ApplicationAddress + 4);

在这里插入图片描述

从中断向量表中可以看到,程序代码偏移4个字节是复位地址,所以JumpAddress获取的是复位地址。

Jump_To_Application = (pFunction) JumpAddress;

后面这句则是将复位地址转换成函数指针。

__set_MSP((__IO uint32_t) ApplicationAddress);

这个是把用户代码的栈顶地址设为栈顶指针

Jump_To_Application();

这个是设置PC指针为复位地址。

CORTEX-M3上电后后检测BOOT引脚的电平来决定PC的位置。例:BOOT设置为FLASH启动,启动后CPU会先取两个地址:一个是栈顶地址,另一个是复位地址。

### STM32 Bootloader 跳转到 App 的实现方式及注意事项 #### 1. 配置内存布局 为了确保BootLoader能够顺利跳转至应用程序,需合理规划闪存分配。通常情况下,BootLoader占用前16KB的空间(即0x0800_0000~0x0800_4000),而应用代码则放置于其后的区域,例如从0x0800_4000开始[^1]。 #### 2. 设置启动参数 当准备切换执行流给用户程序时,应先调整栈指针(SP)指向目标位置处定义的新堆栈顶部,并设置PC寄存器等于入口函数地址。这些操作可通过读取位于APP区首部的两个字(word)完成——第一个代表初始SP值;第二个则是RESET_Handler的位置,也就是main()之前的重置处理例程起点。 ```c // 假设APP起始于0x08004000 #define APP_START_ADDRESS ((uint32_t)0x08004000) void JumpToApplication(void){ uint32_t jumpAddress; void (*jumpFunction)(void); /* 获取应用程序的初始SP */ __set_MSP(*(__IO uint32_t*)APP_START_ADDRESS); /* 获取应用程序的Reset Handler地址 */ jumpAddress = *(__IO uint32_t*)(APP_START_ADDRESS + 4); jumpFunction = (void(*)(void))jumpAddress; /* 执行跳转 */ jumpFunction(); } ``` #### 3. 关闭所有外设和中断 在进行实际跳跃之前,建议关闭除必要的UART通信接口之外的所有其他硬件资源和服务,尤其是那些可能触发异常响应机制的部分,比如定时器、DMA控制器等。这一步骤有助于减少潜在冲突并提高稳定性[^3]。 #### 4. 使用开发工具辅助下载 对于采用Keil MDK作为IDE环境的情况来说,在各自独立项目里通过菜单选项“Flash->Download”或者快捷键F8来进行固件刷写是一种简便有效的方法[^2]。不过需要注意的是,如果遇到无法自动转入App的问题,则可能是由于某些特定条件未满足所致,此时可尝试手动控制流程或借助仿真器逐步排查原因所在。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值