跳转到APP的跳转函数详解~"/>
BOOT跳转到APP的跳转函数详解~
2022-9-26,一个灰蒙蒙的阴雨天,工作学习有感记录。
文章目录
- 要记录什么?
- 一、展示代码
- 二、细节解释
- 1.描述边界
- 2.首地址内容
- 3.函数指针
- 4.设置MSP
- 总结
要记录什么?
没有提示~
解决完BOOT往APP下载内容与跳转后,需要将他的实现原理进行记录。这也是写这篇blog的初衷。
一、展示代码
HAL_StatusTypeDef mdl_flash_jump2app(uint32_t app_addr)
{if (app_addr < APP_SECTOR || app_addr > APP_SECTOR + APP_SIZE_MAX) //检查app地址的合法性,有无超出边界{return HAL_ERROR;}p_function jump_to_app_func; uint32_t jump_addr;/* 判断检查栈顶地址是否合法的语句Test if user code is programmed starting from address "ApplicationAddress测试用户代码是否从地址“应用地址”开始编程" */if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000) == 0x20000000) //app首地址指向栈顶指针 0x20000000-0x2001FFFF MSP=ram堆栈内存末地址+1{/* Jump to user application */ jump_addr = *(__IO uint32_t*) (app_addr + 4); //app+4地址里面的内容为jump_addrjump_to_app_func = (p_function) jump_addr; //jump_addr 变为 函数指针 然后赋值给func函数指针/* Initialize user application's Stack Pointer初始化用户应用程序的堆栈指针 */__set_MSP(*(__IO uint32_t*)app_addr); //设置栈顶指针指向的地址,然后设置MSPjump_to_app_func(); //跳转的函数指针}else{return HAL_ERROR;}return HAL_OK;
}
二、细节解释
1.描述边界
代码如下:
if (app_addr < APP_SECTOR || app_addr > APP_SECTOR + APP_SIZE_MAX) //检查app地址的合法性,有无超出边界{return HAL_ERROR;}
首先判断实参放入FLASH扇区SECTOR地址的合法性。
2.首地址内容
代码如下:
if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000) == 0x20000000) {}
其作用是判断APP起始地址内的数值是否在0x20000000~0x2001FFFF之间。
其存储的是RAM栈顶的首地址(STM32的RAM中栈区为满减栈,需要从顶部往下存入)。
3.函数指针
代码如下:
typedef void (*p_function)(void); //函数指针类型定义p_function jump_to_app_func; uint32_t jump_addr;jump_addr = *(__IO uint32_t*) (app_addr + 4); //app+4地址里面的内容为jump_addrjump_to_app_func = (p_function) jump_addr; jump_to_app_func(); //跳转的函数指针
首先定义一个函数指针类型,用此类型定义一个函数指针变量,将此变量作为跳转到PC程序指针指向地址的跳转函数,其中*(__IO uint32_t*) (app_addr + 4),的目的是将app_addr+4内部存放的复位向量程序指针的地址读取出来赋值给jump_to_app_func ,以供该函数完成程序的跳转。
4.设置MSP
代码如下:
__set_MSP(*(__IO uint32_t*)app_addr); //设置栈顶指针指向的地址,然后设置MSP}
这是较为底层的API,目的是设置主堆栈指针。MSP全称为:Main Stack Pointer。放入的参数需要是主堆栈指针的栈顶地址。一定要是堆栈的栈顶指针。
总结
嵌入式人必经的过程,你我共勉~再接再厉!
更多推荐
BOOT跳转到APP的跳转函数详解~
发布评论