一.分析JumpToApp函数
点击查看代码
void JumpToApp(uint32_t addr)
{
__disable_irq();//这个函数调用会禁用中断。在跳转到新的应用程序之前,通常需要确保当前的中断状态不会干扰跳转过程。
uint32_t sp = *((volatile uint32_t *)(addr));//从addr指定的地址读取栈指针(Stack Pointer,SP)的值。volatile关键字告诉编译器不要优化这部分代码,因为它可能会在程序执行过程中改变。
uint32_t pc = *((volatile uint32_t *)(addr + 4));//从addr + 4的地址读取程序计数器(Program Counter,PC)的值,这是新应用程序的入口地址。
typedef void (*Func_void_void)(void);
Func_void_void ResetHandler = (Func_void_void)pc;//将pc的值转换为Func_void_void类型的函数指针,并将其赋值给ResetHandler变量。
SCB->VTOR = addr;//设置向量表偏移寄存器(Vector Table Offset Register,VTOR)的值为addr。这个寄存器定义了中断向量表的起始地址。在跳转到新应用程序时,需要更新这个寄存器,以便中断能够正确地跳转到新应用程序的中断处理函数。
__set_MSP(sp);//设置主堆栈指针(Main Stack Pointer,MSP)为从addr读取的栈指针值。这是为了确保新应用程序能够使用正确的堆栈。
ResetHandler();//调用ResetHandler函数,这实际上是跳转到新应用程序的入口点。
while(1) __NOP();//在跳转到新应用程序后,如果函数返回,这将导致程序进入一个无限循环,执行空操作(No Operation,NOP)。这通常是为了防止程序返回到旧的上下文中。
}
#define FLASH_APP1_ADDR 0x00008000
JumpToApp(FLASH_APP1_ADDR);
二.3个核心寄存器
-
1.三级流水线
ARM-CPU属于属于精简指令集,三级流水线。取指、译指、执行。
ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4(ARM RISC指令集,通常一个基础指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。
当突然发生中断的时候,保存的是PC的地址,如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq -
2.寄存器介绍
SP寄存器(R13):堆栈指针,SP总是指向栈顶。
LR寄存器(R14):LR寄存器存的是,执行子函数后,PC指针应该跳转回去的地方。
PC寄存器(R15): 程序计数器,内部存的值是当前执行到了哪个地址;PC 总是指向“正在取指”的指令