用CMSIS-RTOS做Bootloarder的一些问题及解决方案

使用CMSIS-RTOS有段时间了,产品功能已经基本完成,现在做升级功能,需要做Boot,但在做的过程中遇到了一些问题,耽搁了两天才搞定,因此有必要记录一下。

首先第一个问题是跳转函数的写法。

在程序怎么都无法跳转到APP执行的情况下,我重新建立了两个裸跑的工程,BOOT直接执行跳转,APP只执行灯闪烁,结果还是无法跳转。这里我参考一篇帖子做的跳转程序,跳转函数写法如下:

void (*iapfun)(void);

aipfun = (void (*)(void))(APPSTART + 4);

然后我尝试用正点原子的IAP代码例程里的跳转函数,结果跳转成功,跳转函数写法如下:

typedef void (*appl_func)(void); //定义一个函数类型的参数.
appl_func run_appl;
...
run_appl = (appl_func)*(vu32*)(APPSTART + 4);

解决跳转问题后,修改CMSIS-RTOS的跳转函数后再次测试,发现跳转后会进入HardFault。

尝试过网上说的关所有中断、删除任务(我一个任务都没新建)、重新设置中断向量表等等操作依然无果。

然后我找到一篇文章,写的是如果和RTX做Bootloader,文章链接如下:

ARM: How to Stop CMSIS RTX or RTX5 in Bootloader

这篇文章里说明了做用RTX做Bootloader只需要关闭SysTick中断就可以,在跳转后需要打开SysTick中断,按这个方法尝试后依然进入HardFault。但这个文章提醒了我,还有一个中断我没有关闭。

在做APP时为了系统稳定我设置了任务工作在用户模式,因此使用了SVC中断方式调用操作中断的函数。在做Bootloader时依然是用的这个方式,因此,SVC中断是没有关闭的。

我修改任务为特权模式(修改方式参考这个帖子:SVC中断方式调用用户函数),删除了所有SVC中断操作,然后程序跳转成功。

然后我将所有的关闭所有中断的函数删除,并恢复了之前屏蔽的任务,跳转依然成功。

至此,用RTX做Bootloader的功能完全正常。

总结:

Bootloader跳转APP前不能有任何中断发生,因此最好将所有打开的中断全部关闭。

 

//============================================================================

记录一下后期遇到的一个头疼问题。

做好BOOT后每次跳转后都会将一个全局变量的值修改,追查好久发现居然是在进入中断函数时修改的。一时间不知道是怎么回事。以为是跳转后RTX的任务或信号量没有删除的原因,全部删除后发现也不是这个问题。

后来分析了被修改的变量的地址,发现刚好和堆栈地址相近,因此怀疑是堆栈溢出。追查启动文件,发现自己添加了这么一句。

__initial_sp	EQU 	0x20000000 + Stack_Size

这里将初始化的堆栈地址强制为一个固定地址,而且和变量表里的地址不一致,导致开机运行时,堆栈地址不对,修改了其他的全局变量,将这句后面的“EQU     0x20000000 + Stack_Size”删除后,功能正常。

你可能感兴趣的:(RTX学习)