IAP在线升级二

一.分析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属于属于精简指令集,三级流水线。取指、译指、执行。
    理想的情况下,保证了每个CPU-Cycle都有一个指令被执行。

    ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址。在地址为m的指令时,PC值为m+4,所以PC值总是当前正在执行的指令地址加4。

    (注意:当突然发生中断的时候,保存的是PC的地址,如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq )

    1. SP寄存器(R13):
      堆栈指针,SP总是指向栈顶。
      SP寄存器分为MSP和PSP。(MSP---主栈指针、默认栈指针;PSP---中断栈指针、进程栈寄存器)。
      在裸机模式下,通常只使用MSP,而在操作系统环境下,MSP和PSP会根据任务切换和异常处理动态切换。
    1. LR寄存器(R14):
      LR寄存器保存的是,执行子函数、中断、任务切换(中断包括任务切换:xPortPendSVHandler),PC指针应该跳转回去的地方。
    1. PC寄存器(R15):
      程序计数器,内部存的值是当前执行到了哪个地址;PC 总是指向“正在取指”的指令,即“PC+4”。
      在《Cortex™-M3 Devices Generic User Guide》中关于SP和LR的描述如下图:

三 PC值分析

1.指令集

  • ARM指令集:一条指令为4个字节。
  • Thumb指令集:一条指令为2个字节。
  • Thumb2指令集:中的大部分指令仍然是16位的Thumb指令,但引入了一些额外的32位指令,以提供更高级别的功能和更灵活的操作数寻址模式。
    注:cotex-m3、m4都采用thum2指令集

2.PC值
无论处理器处于何种状态,程序计数器R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或者正在“译码”的指令。
将正在执行的指令作为参考点,即当前第1条指令。所以,PC总是指向第3条指令,或者说PC总是指向当前正在执行的指令地址再加2条指令的地址。

处理器处于ARM状态时,每条指令为4个字节,所以PC值为正在执行的指令地址加8字节,即是:
PC值 = 当前程序执行位置 + 8字节

处理器处于Thumb状态时,每条指令为2字节,所以PC值为正在执行的指令地址加4字节,即是:
PC值 = 当前程序执行位置 + 4字节

posted @   Charles_hui  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示