static void Boot_vJumpToApp(uint32_t u32_appAddress)
{
uint32_t u32_jumpAddress;
pFunction JumpToApp;
if (((*(__IO uint32_t*)u32_appAddress) & 0x2FFE0000 ) == 0x20000000)
{
u32_jumpAddress = *(__IO uint32_t*) (u32_appAddress + 4);
JumpToApp = (pFunction)u32_jumpAddress;
__set_MSP(*(__IO uint32_t*)u32_appAddress);
JumpToApp();
}
}
这是一段从Boot跳转到App的代码。
1. ARM Cortex-M 处理器的启动机制
在 ARM Cortex-M 系列处理器中,向量表(Vector Table)是程序启动的核心数据结构。向量表的前两个条目分别是:
- 初始主栈指针(MSP):处理器上电后,第一个从向量表加载的值,用于初始化栈顶地址。
- 复位向量(Reset Handler):第二个值,指向应用程序的入口函数(即
main
函数之前的初始化代码)。
当处理器复位或跳转到应用程序时,硬件会自动完成以下操作:
- 将向量表的第一个值(MSP)加载到栈指针寄存器(SP)。
- 将第二个值(复位向量)加载到程序计数器(PC),开始执行应用程序。
2. 代码逻辑分析
-
条件检查:
if (((*(__IO uint32_t*)u32_appAddress) & 0x2FFE0000 ) == 0x20000000)
- 目的:验证应用程序的初始栈指针(MSP)是否有效。
- 操作:
u32_appAddress
是应用程序的起始地址,通常指向应用程序的向量表。- 读取
u32_appAddress
处的第一个32位值(即应用程序的初始栈指针,这里取出的数值是应用程序的MSP初始值)。 - 使用掩码
0x2FFE0000
过滤无关位,检查结果是否为0x20000000
(典型RAM起始地址)。
- 意义:确保栈指针指向有效的RAM区域,避免跳转到非法地址。
-
获取应用程序入口地址:
u32_jumpAddress = *(__IO uint32_t*) (u32_appAddress + 4);
- 目的:获取应用程序的复位向量(Reset Handler)。
- 操作:
u32_appAddress + 4
是向量表的第二个条目,存储应用程序的入口地址。- 读取该地址的值,即应用程序的入口函数指针。
-
函数指针转换:
JumpToApp = (pFunction)u32_jumpAddress;
- 目的:将入口地址转换为可调用的函数指针。
- 说明:
pFunction
通常定义为typedef void (*pFunction)(void)
,即无参数无返回的函数指针类型。
-
设置主栈指针(MSP):
__set_MSP(*(__IO uint32_t*)u32_appAddress);
- 目的:将栈指针切换到应用程序的初始栈。
- 操作:通过
__set_MSP
函数(通常为内联汇编或CMSIS函数)设置MSP为应用程序的栈顶。
-
跳转到应用程序:
JumpToApp();
- 目的:执行应用程序的入口函数。
- 效果:程序计数器(PC)指向应用程序的复位处理函数,完成控制权转移。