一,网上下载的例程,跳转部分的代码有差异,尤其是用的汇编那句 eg: ①Jump_To_Application = (pFunction)(*(vu32*) (IAPSTART + 4)); 跟踪__MSR_MSP(一般这个函数都在库文件里有,跟踪不到就用搜索找)找到汇编函数为 __MSR_MSP
②//跳转到应用程序段 跟踪MSR_MSP找到函数为 //设置栈顶地址
③ //判断用户是否已经下载程序,因为正常情况下此地址是栈地址。 跟踪__set_MSP找到函数为 __ASM void __set_MSP(uint32_t mainStackPointer) 总结以上发现都是操作ARM的R0跟R14(LR)寄存器。 还有一种不太一样的,就是stm32F4的库函数中的跳转,如下所示 ④ //测试用户app地址是不是在APPLICATION_ADDRESS位置。检测栈顶的地址,来检验app是否下载成功 跟踪__set_MSP找到函数为 static __INLINE void __set_MSP(uint32_t topOfMainStack) 对于M4的这个库函数我也不太懂,感觉最终的操作应该跟其他的一样吧 二,关于跳转部分的代码的理解(转)
这里重点说一下几句经典且非常重要的代码: 第一句: if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) //判断栈定地址值是否在0x2000 0000 - 0x 2000 2000之间 怎么理解呢? (1),在程序里#define ApplicationAddress 0x8003000 ,*(__IO uint32_t*)ApplicationAddress) 即取0x8003000开始到0x8003003 的4个字节的值, 因为我们的应用程序APP中设置把 中断向量表 放置在0x08003000 开始的位置;而中断向量表里第一个放的就是栈顶地址的值 也就是说,这句话即通过判断栈顶地址值是否正确(是否在0x2000 0000 - 0x 2000 2000之间) 来判断是否应用程序已经下载了,因为应用程序的启动文件刚开始就去初始化化栈空间,如果栈顶值对了,说应用程已经下载了启动文件的初始化也执行了;
第二句: JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); [ common.c文件第18行定义了: pFunction Jump_To_Application;] ApplicationAddress + 4 即为0x0800 3004 ,里面放的是中断向量表的第二项“复位地址” JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); 之后此时JumpAddress
第三句: Jump_To_Application = (pFunction) JumpAddress;
void (*pFunction)(void); 是声明一个函数指针,加上一个typedef 之后 pFunction只不过是类型 void (*)(void) 的一个别名;例如:
[cpp] view
plaincopy
所以,Jump_To_Application = (pFunction) JumpAddress; 此时Jump_To_Application指向了复位函数所在的地址;
第四 、五句: __set_MSP(*(__IO uint32_t*) ApplicationAddress); \\设置主函数栈指针
Jump_To_Application()是把用户代码的复位地址付给PC指针,我看到Jump_To_Application()这句代码debug的时候对应的汇编代码是
LDR
r0,[pc,#12] ;相对PC的数据加载,去函数指针的地址 我们看一下启动文件startup_stm32f10x_md_vl.s 中的启动代码,更容易理解
三,关于跳转时能否不用按键,用软件标志位以及APP与IAP之间的互跳 完全可以不用按键,可以模拟一个按键信号,或者用软件的一个标志位来判断是否更新。。我设计的在flash中中存储一个值,当APP运行中需要更新时串口发来更新命令,然后在flash中存一个值之后跳到IAP部分,来读取flash中存储的那个值,如果是需要更新则更新,如果不是需要跟新标志位就直接跳转到APP部分。。。这样也不用重复上电,断电。
四,关于APP与IAP互跳之间的中断处理问题 跳转时中断问题还是一个比较棘手的问题。。经常跳转之后无法进入中断,然后百度了一下,自己理解大概是,跳转时只是强制改变了PC指正的位置,但是里面的中断寄存器什么的都没有变,这样中断存在,但是中断函数什么的都没有了,造成程序死掉。。我在写的过程中也遇到了问题,第一次从iap跳到app正常,但是从app跳回iap的时候由于残留的中断太多,在iap中程序死了。我的处理方式是把app中的跳转命令换成了系统复位NVIC_SystemReset();(不同的固件库可能函数名不同)其他的处理理的方式据我所知还有有①跳转之前复位或者关闭所有打开的中断②跳转后在初始化时加入RCC_DeInit();,,NVIC_DeInit ();等让中断恢复默认值。。具体可参考下面这篇文章http://dzdesigned80.blog.163.com/blog/static/203259238201272425313152/ 关于stm32的软件复位: STM32软件复位(基于库文件V3.5) ,对于STM32来说软件复位有两种方式: 1)采用官方自带的软件库 static __INLINE void NVIC_SystemReset(void) { (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ } { register uint32_t __regFaultMask __ASM("faultmask"); __regFaultMask = (faultMask & 1); } void SoftReset(void) { NVIC_SystemReset();// 复位 }
|
|
来自: goodwangLib > 《STM32》