记一次非原子运算引起的软件复位
背景:
最近软件团队在做压测的时候发现,某个温度数据会偶现为复位值(原始值),此行为表示软件产生了复位。
通过检查canoe的trace发现确实产生了复位,trace的报文如下所示,能清楚的看到复位丢失了30ms左右的报文,复位的时间在50ms以内。
过程:
通过NVM记录所有的复位源并通过DID读取存储的值最终确定复位点。
复位语句展开成汇编表示如下,很明显的能看到CMP的代码会最终通过汇编存储在两个不同的寄存器中,最后去做一个比较。那么在存储寄存器的这个过程中我们发现每次存储需要6个指令周期,如果高优先级的任务中断此行为并更新if语句中的变量,那么就会出现比较不一致的行为产生,从而导致软件复位。
if(DPR_as32xxxxxxxx != ~DPR_as32xxxxxxxx_copy)
0x2f7ec: 0x4824 LDR.N R0, ??DataTable6_5
0x2f7ee:~ MOVS R1, R4
0x2f7f0:~ UXTB R1, R1
0x2f7f2:~ MOVS R3, #4
0x2f7f4:~ MULS R1, R3, R1
0x2f7f6:~ LDR R1, [R0, R1]
0x2f7f8:~
0x2f7fa:~
0x2f7fc:~
0x2f7fe:~
0x2f800:~
0x2f802:~
0x2f804:~
0x2f806:~ CMP R1, R5
结论:
这种数据取反是为防止数据异常篡改,但是针对单片机这种时分复用的场景没有考虑中断优先级等行为,因此引入了偶发的软件复位。
顶层设计一定要谨慎谨慎再谨慎。