首先一些背景。當出於任何原因的固件崩潰(例如堆棧溢出,損壞的函數指針...)時,它可能發生,它跳到某處並開始執行一些代碼。這遲早會導致看門狗復位。 MCU將重置,我們回到正軌。除非......避免意外的固件覆蓋
什麼,當我們有一個寫入閃存(例如引導程序)代碼?現在可能會發生我們不小心直接跳入閃存編寫代碼 - 跳過所有檢查。在監督人員咆哮之前,最終會損壞固件。這正是我發生的事情。
現在,有些人可能會說 - 解決導致我們甚至跳進寫代碼的根本錯誤。那麼,當你正在開發時,你會不斷地改變代碼。即使目前在那裏沒有這樣的錯誤,明天可能會有。此外,沒有代碼是無bug的 - 或者至少不是我的。
所以現在我正在做一些交叉檢查。我有一個名爲'wen'的變量,我在通常的檢查之前將其設置爲0xa5(例如,檢查以確保目標有效)。然後在做實際的擦除或寫之前,我檢查'wen'是否真的被設置爲0xa5。否則這意味着我們不小心跳進了寫作代碼。成功寫入'文'後清除。我已經在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"
);
還沒有試過的代碼呢,明天就會那樣做。你有沒有看到任何問題?你如何解決這個問題?
是的,成功寫入後會清除wen。 這個對__assert的調用實際上觸發了看門狗復位(加上它記錄了關於觸發它的一些信息)。 很高興聽到人們實際上使用這種方法:) – Stefan 2012-02-17 07:01:47