网上直接复制的jumpToApp()代码,跳转后程序时好时坏
App单独调试没有问题,经过Bootloader一跳就宕机
设备升级直接“变砖”,不得不求客户把设备邮寄回来
像这类问题绝大多数都可以归于跳转后外设“不干净”,导致App异常或宕机。比如,在Bootloader中配置了串口接收中断,但App中又计划使用DMA方式。这里矛盾与不匹配就出现了!以致于App中如果串口接收到了数据,需要去猜MCU要如何处理了!——程序运行状态未知,这个从系统稳定性的角度考量肯定是不被允许了。问题已经提出来了?那么要怎么办呢?
能少用外设就少用
Bootloader的程序体积很少,功能也有限。Bootloader的核心作用仍然是跳转App,所以,硬件外设能少用就少用。什么意思呢?具体来说,比如延时1ms。我们可以使用Systick来实现,也可以使用Timer来实现。但基于“能少就少用”的原则,我建议类似的延时直接使用nop()方式的阻塞方式实现。Bootloader没有复杂的功能,阻塞式的延时完全可以胜利。同理串口接收,可以使用中断方式接收数据,但也可以使用查询方式接收数据。
再来说为什么要少用硬件外设呢?因为我们必须要在Bootloader跳转前手动将外设deinit。这个deinit操作相对复杂,并且容易遗漏。这也是App偶尔出现宕机的原因。因为,有的时候在Bootloader跳转之后,部分外设功能与API函数是有效的。在App中其实是可以直接调用和使用的。
能不用中断就不用
我们编写Bootloader和App是分为两个工程来实现的,但对于MCU来说,最后执行的时候其实是一个程序,只是在不同阶段执行而已,但MCU并不知道这其实是两个程序。基于ARM Cortex-M系列的MCU的中断Vector表是采用查询的方式,即在固定地址的表查询方式。又因为Bootloader和App是分形的两个工程,故它们俩是有各自的中断Vector的表基地址,如果在Bootloader中开启的中断触发的时间在App运行期间,则响应的中断函数则为App的中断函数,这时,你的App的中断函数是否还能满足Bootloader的需求呢?如果一旦不满足,MCU的程序会不会宕机呢?所以,还是能不用中断就不用中断吧!
总结
Bootloader的功能强烈建议以小而美,以少而美,以稳定为核心。
我要赚赏金
