2012-02-16 14 views
5

Prima alcuni background. Quando il firmware per qualsiasi motivo si blocca (ad esempio overflow dello stack, puntatore a funzione corrotta ...) può accadere che salti da qualche parte e inizi ad eseguire del codice. Questo prima o poi porterà al reset del watchdog. MCU verrà ripristinato e siamo di nuovo in pista. A meno che ...Evitare la sovrascrittura del firmware accidentale

Che dire quando abbiamo il codice che scrive in flash (ad esempio bootloader)? Ora può succedere che salteremo accidentalmente direttamente nel codice di scrittura flash, saltando tutti i controlli. Prima che il cane da guardia abbaia, finirai con il firmware corrotto. Questo è esattamente quello che mi stava succedendo.

Ora alcuni potrebbero dire: risolvere il bug di root che ha causato il passaggio al codice di scrittura. Bene, quando stai sviluppando cambi continuamente il codice. Anche se al momento non ci sono bug di questo tipo, potrebbe esserci domani. Inoltre, nessun codice è privo di bug - o almeno non mio.

Quindi ora sto facendo una specie di controllo incrociato. Ho una variabile denominata "wen" che ho impostato su 0xa5 prima dei soliti controlli (ad esempio per verificare che la destinazione sia valida). Quindi, prima di eseguire la cancellazione o la scrittura effettiva, controllo che "wen" sia impostato su 0xa5. Altrimenti ciò significa che in qualche modo siamo saltati accidentalmente nel codice di scrittura. Dopo aver scritto con successo "wen" viene cancellato. Ho fatto questo in C e ha funzionato bene. Ma c'è ancora una leggera possibilità teorica di corruzione, perché ci sono poche istruzioni da questo controllo finale di "wen" fino a scrivere nel registro SPMCR.

Ora voglio migliorare questo mettendo questo controllo in assembly, tra le istruzioni di scrittura su SPMCR e 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" 
); 

Non ho ancora provato il codice, lo farò domani. Vedi qualche problema? Come/vuoi risolvere questo problema?

risposta

3

Una tecnica che ho visto è quella di verificare i byte immediatamente prima che le routine di scrittura flash attivino una sorta di timeout del watchdog o reimpostino il processore. In questo modo, non è possibile eseguire dati casuali che portano alla funzione di scrittura flash e semplicemente "ricadere" nella funzione.

Potrebbe essere necessario disporre di alcuni NOP prima del ripristino per garantire che le istruzioni vengano interpretate correttamente.

La tecnica per verificare che la funzione sia stata eseguita dall'inizio, sembra buona, supponendo di aver cancellato la variabile wen una volta terminata la scrittura.

+0

Sì, wen viene cancellato dopo una scrittura riuscita. Questa chiamata a __assert attiva effettivamente il reset del watchdog (in più registra alcune informazioni su cosa lo ha attivato). Felice di sentire che la gente usa effettivamente questi approcci :) – Stefan

2

Non sono sicuro del motivo per cui è necessario avere la possibilità di scrivere sul flash nel proprio bootloader. Il nostro bootloader lo fa, perché può aggiornare il programma applicativo tramite porta seriale. Quindi eliminiamo il potenziale di scrittura involontaria assicurandoci che il caricatore non contenga alcun codice che scrive sul flash. Il codice scaricato è un'intestazione nello stesso pacchetto che contiene l'immagine da scrivere. L'immagine di bordo ha memorizzato il checksum della programmazione e lo verifica prima di eseguirlo.

Se si scrivono elementi generati internamente, si esamineranno gli interblocchi correlati all'hardware. Consenti solo le scritture se in precedenza è stato impostato un particolare pin di uscita discreto su ON. Per rispondere al problema di "cosa succede se l'IP supera i controlli"? puoi farlo in 2 parti. Prima imposta alcune variabili critiche per l'algoritmo. (l'indirizzo in cui scrivere, ad esempio, mantiene quella inizializzata nella memoria non valida e la imposta solo correttamente in una chiamata separata prima della scrittura, quindi verifica la funzione di scrittura dell'interblocco HW. Esegui una delle fasi di abilitazione in un interrupt, o in risposta a un timer, qualcosa che è improbabile che venga colpito nella sequenza corretta se si dispone di un IP canaglia.

Se il tuo IP può davvero saltare ovunque, potrebbe essere impossibile impedire una scrittura involontaria. Il meglio che puoi sperare è che ti assicuri che l'unica strada da percorrere sia anche quella che serve per scrivere con successo.

+0

Sto facendo la stessa cosa (aggiornamento via UART). C'è un codice di scrittura nell'applicazione e nel bootloader. In questo modo possono aggiornarsi a vicenda e anche memorizzare alcune configurazioni in flash. Non so cosa tu abbia, ma quello che ho non può eseguire codice dalla RAM, quindi caricare un codice per scrivere non è un'opzione. Attualmente sto usando una procedura simile a quella descritta con l'interblocco HW. Questo è quello che ho cercato di spiegare quando ho impostato la domanda ... sembra che abbia fatto un brutto lavoro :) – Stefan

+0

@Stefan: fai attenzione quando aggiorni il tuo bootloader dalla tua applicazione. Cosa succede sulla perdita di potenza tra la cancellazione e la scrittura? Oops, il tuo bootloader è sparito e hai messo in pausa il tuo dispositivo. Un progetto Freescale HCS08, il bootloader in realtà imposta i registri della CPU per proteggerlo dalla sovrascrittura, ed è impossibile che l'applicazione scriva su quelle pagine nel flash. Stai attento. – tomlogic

+0

@tomlogic: ho 2 codici di scrittura - in aplication e in bootloader - e possono attraversare l'aggiornamento a vicenda. uC per impostazione predefinita si attiva nel codice dell'applicazione. Se non riesco ad aggiornare il bootloader, mi sveglio ancora nell'applicazione e posso riprovare. E il bootloader usa un trucco. Scrive il codice dell'applicazione dalla pagina più in alto al più basso. Prima che scriva la prima pagina (che è effettivamente la più alta), scrive 'jump to bootloader' nella pagina 0. Ora l'unica preoccupazione è che non debba fallire scrivere l'ultima pagina (pagina 0). Quindi le possibilità sono estremamente piccole per finire con un flash non recuperabile. – Stefan

Problemi correlati