Note that there are some explanatory texts on larger screens.

plurals
  1. POAvoiding accidental firmware overwrite
    text
    copied!<p>First some background. When firmware for whatever reason crashes (e.g. stack overflow, corrupted function pointer...) it may happen, that it jumps somewhere and starts executing some code. This will sooner or later result in watchdog reset. MCU will reset and we are back on track. Unless...</p> <p>What about when we have code that writes to flash (e.g. bootloader)? Now it can happen that we will accidentally jump directly into the flash write code - skipping all the checks. Before watchdog will bark you will end up with corrupted firmware. This is exactly what was happening to me.</p> <p>Now some might say - fix the root bug that caused that we even jumped into write code. Well, when you are developing you are constantly changing the code. Even if there is no such bug in there at the moment, there might be tomorrow. Besides, no code is bug free - or at least not mine.</p> <p>So now I am doing some kind of cross checking. I have a variable named 'wen' which I set to 0xa5 before the usual checks (e.g. check to make sure that destination is valid). Then just before doing the actual erase or write I check if 'wen' is really set to 0xa5. Otherwise this means that we somehow accidentally jumped into the writing code. After successful write 'wen' is cleared. I have done this in C and it worked well. But there is still slight theoretical chance corruption will happen, cause there are few instructions from this final check of 'wen' till write to SPMCR register.</p> <p>Now I want to improve this by putting this check into assembly, between the write to SPMCR and spm instruction.</p> <pre><code>__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)(&amp;wen)), "I" (_SFR_IO_ADDR(__SPM_REG)), "r" ((uint8_t)(__BOOT_PAGE_ERASE)), "M" ((uint8_t)(-ACK)), "z" ((uint16_t)(adr)) : "r25" ); </code></pre> <p>Haven't tried the code yet, will do that tomorrow. Do you see any problems? How do/would you solve such problem?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload