首先是一些背景.当固件因任何原因崩溃(例如堆栈溢出,损坏的函数指针......)时,它可能会发生,它跳转到某处并开始执行某些代码.这迟早会导致看门狗复位.MCU将重置,我们将重新回到正轨.除非...
当我们有写入闪存的代码(例如bootloader)时呢?现在我们可能会意外地直接跳转到flash写代码 - 跳过所有检查.在看门狗吠叫之前,你最终会遇到损坏的固件.这正是发生在我身上的事情.
现在有人可能会说 - 修复导致我们甚至跳进编写代码的根错误.好吧,当你开发时,你不断改变代码.即使此刻没有这样的错误,明天也许会有.此外,没有代码是没有错误的 - 或者至少不是我的.
所以现在我正在进行某种交叉检查.我有一个名为'wen'的变量,在常规检查之前我将其设置为0xa5(例如,检查以确保目标有效).然后在进行实际擦除或写入之前,我检查'wen'是否真的设置为0xa5.否则这意味着我们不知何故意外地跳进了编写代码.成功后写'wen'被清除.我用C做了这个,效果很好.但是仍然存在轻微的理论上的机会腐败会发生,因为从最后检查'wen'到指向SPMCR寄存器的指令很少.
现在我想通过将此检查放入汇编,在写入SPMCR和spm指令之间来改进这一点.
__asm__ __volatile__
(
"lds __zero_reg__, %0\n\t"
"out %1, %2\n\t"
"ldi r25, %3\n\t"
"add __zero_reg__, r25\n\t"
"brne spm_fail\n\t"
"spm\n\t"
"rjmp spm_done\n\t"
"spm_fail: clr __zero_reg__\n\t"
"call __assert\n\t"
"spm_done:"
:
: "i" ((uint16_t)(&wen)),
"I" (_SFR_IO_ADDR(__SPM_REG)),
"r" ((uint8_t)(__BOOT_PAGE_ERASE)),
"M" ((uint8_t)(-ACK)),
"z" ((uint16_t)(adr))
: "r25"
);
Run Code Online (Sandbox Code Playgroud)
尚未尝试过代码,明天会这样做.你看到有什么问题吗?你怎么解决这个问题?