Un bootloader è un programma che viene eseguito nel microcontrollore da programmare. Riceve nuove informazioni sul programma esternamente tramite alcuni mezzi di comunicazione e scrive tali informazioni nella memoria del programma del processore.
Ciò è in contrasto con il modo normale di inserire il programma nel microcontrollore, che è tramite hardware speciale incorporato nel micro a tale scopo. Sui PIC, questa è un'interfaccia simile a SPI. Se ricordo bene, gli AVR usano Jtag, o almeno alcuni di loro. Ad ogni modo, ciò richiede dell'hardware esterno che fa oscillare i pin di programmazione proprio per scrivere le informazioni nella memoria del programma. Il file HEX che descrive il contenuto della memoria del programma ha origine su un computer per uso generale, quindi questo hardware si collega al computer da un lato e agli speciali pin di programmazione del micro dall'altro. La mia azienda crea programmatori PIC tra le altre cose come una linea laterale, quindi ho abbastanza familiarità con questo processo sui PIC.
Il punto importante della programmazione esterna tramite hardware specializzato è che funziona indipendentemente dal contenuto esistente della memoria del programma. I microcontrollori iniziano con la memoria del programma cancellata o in uno stato sconosciuto, quindi la programmazione esterna è l'unico mezzo per inserire il primo programma in un micro.
Se sei sicuro del programma che desideri caricare nel tuo prodotto e i tuoi volumi sono abbastanza alti, puoi avere i chip del programma del produttore o del distributore per te. Il chip viene saldato alla scheda come qualsiasi altro chip e l'unità è pronta per partire. Questo può essere appropriato per qualcosa come un giocattolo, per esempio. Una volta che il firmware è finito, è praticamente fatto e sarà prodotto in grandi volumi.
Se i tuoi volumi sono più bassi o, cosa più importante, ti aspetti uno sviluppo del firmware e correzioni di bug in corso, non vuoi acquistare chip pre-programmati. In questo caso, sulla scheda vengono montati chip vuoti e il firmware deve essere caricato sul chip come parte del processo di produzione. In tal caso, le linee di programmazione hardware devono essere rese disponibili in qualche modo. Questo può avvenire tramite un connettore esplicito o pad pogo se si è disposti a creare un dispositivo di prova di produzione. Spesso tali prodotti devono essere testati e magari calibrati comunque, quindi il costo aggiuntivo di scrivere il programma sul processore è generalmente minimo. A volte, quando vengono utilizzati piccoli processori, nel processore viene caricato per la prima volta un firmware di test di produzione speciale. Questo è usato per facilitare il test e la calibrazione dell'unità, quindi il firmware reale viene caricato dopo che l'hardware è noto per essere buono. In questo caso ci sono alcune considerazioni sulla progettazione del circuito per consentire l'accesso alle linee di programmazione in modo sufficiente per il funzionamento del processo di programmazione, ma anche per non disturbare troppo il circuito. Per maggiori dettagli su questo, vedi il mioscrittura di programmazione in-circuit .
Fin qui tutto bene, e non è necessario alcun bootloader. Tuttavia, considerare un prodotto con firmware relativamente complesso che si desidera aggiornare sul campo o addirittura consentire al cliente finale di aggiornare. Non puoi aspettarti che il cliente finale disponga di un gadget programmatore o sapere come utilizzarlo correttamente anche se ne hai fornito uno. In realtà uno dei miei clienti lo fa. Se acquisti l'opzione di personalizzazione del campo speciale, ricevi uno dei miei programmatori con il prodotto.
Tuttavia, nella maggior parte dei casi si desidera solo che il cliente esegua un programma su un PC e che il firmware venga aggiornato magicamente. È qui che entra in gioco un bootloader, soprattutto se il tuo prodotto ha già una porta di comunicazione che può facilmente interfacciarsi con un PC, come USB, RS-232 o Ethernet. Il cliente esegue un programma per PC che parla con il bootloader già nel micro. Questo invia il nuovo binario al bootloader, che lo scrive nella memoria del programma e quindi fa eseguire il nuovo codice.
Sembra semplice, ma non lo è, almeno non se si desidera che questo processo sia solido. Cosa succede se si verifica un errore di comunicazione e il nuovo firmware è corrotto quando arriva al bootloader? Cosa succede se l'alimentazione viene interrotta durante il processo di avvio? Cosa succede se il bootloader ha un bug e craps su se stesso?
Uno scenario semplicistico è che il bootloader viene sempre eseguito dal ripristino. Prova a comunicare con l'host. Se l'host risponde, allora comunica al bootloader che non ha nulla di nuovo o gli invia un nuovo codice. All'arrivo del nuovo codice, il vecchio codice viene sovrascritto. Includi sempre un checksum con il codice caricato, in modo che il bootloader possa dire se la nuova app è intatta. In caso contrario, rimane nel bootloader richiedendo costantemente un caricamento fino a quando qualcosa con un checksum valido viene caricato in memoria. Ciò potrebbe essere accettabile per un dispositivo sempre connesso e possibilmente in cui viene eseguita un'attività in background sull'host che risponde alle richieste del bootloader. Questo schema non è utile per le unità che sono in gran parte autonome e solo occasionalmente si connettono a un computer host.
Di solito il semplice bootloader come descritto sopra non è accettabile poiché non esiste un fail-safe. Se una nuova immagine dell'app non viene ricevuta intatta, si desidera che il dispositivo continui a eseguire la vecchia immagine, non rimanga morto fino a quando non viene eseguito correttamente il caricamento. Per questo motivo, di solito ci sono due moduli speciali nel firmware, un uploader e un bootloader. L'autore del caricamento fa parte dell'app principale. Come parte delle comunicazioni regolari con l'host, è possibile caricare una nuova immagine dell'app. Ciò richiede memoria separata dall'immagine dell'app principale, come una EEPROM esterna o utilizzare un processore più grande in modo che metà dello spazio di memoria del programma possa essere allocato per l'archiviazione della nuova immagine dell'app. L'autore del caricamento scrive semplicemente l'immagine della nuova app ricevuta da qualche parte, ma non la esegue. Quando il processore viene ripristinato, il che potrebbe accadere su comando dall'host dopo un caricamento, il bootloader viene eseguito. Questo è ora un programma totalmente autonomo che non necessita di capacità di comunicazione esterna. Confronta le versioni di app correnti e caricate, controlla i loro checksum e copia la nuova immagine nell'area dell'app se le versioni differiscono e il nuovo checksum delle immagini verifica. Se la nuova immagine è corrotta, esegue semplicemente la vecchia app come prima.
Ho fatto molti bootloader e non ce ne sono due uguali. Non esiste un bootloader generico, nonostante ciò che alcune aziende di microcontrollori vogliono farti credere. Ogni dispositivo ha i propri requisiti e circostanze speciali nei rapporti con l'host. Ecco solo alcune delle configurazioni di bootloader e talvolta uploader che ho usato:
- Bootloader di base. Questo dispositivo aveva una linea seriale e sarebbe stato collegato a un host e acceso come necessario. Il bootloader è stato eseguito dalla reimpostazione e ha inviato all'host alcune risposte alla richiesta di caricamento. Se il programma di caricamento era in esecuzione, risponderebbe e invierebbe una nuova immagine dell'app. Se non rispondesse entro 500 ms, il bootloader avrebbe rinunciato ed eseguito l'app esistente. Pertanto, per aggiornare il firmware, è stato necessario eseguire prima l'app di aggiornamento sull'host, quindi connettersi e accendere il dispositivo.
- Programma di caricamento della memoria. Qui abbiamo usato il PIC di dimensioni successive che aveva il doppio della memoria del programma. La memoria del programma è stata approssimativamente divisa in 49% app principale, 49% nuova immagine app e 2% bootloader. Il bootloader verrebbe eseguito dal ripristino e copierebbe la nuova immagine dell'app sull'immagine corrente dell'app nelle giuste condizioni.
- Immagine EEPROM esterna. Come il n. 2, tranne per il fatto che è stata utilizzata una EEPROM esterna per memorizzare la nuova immagine dell'app. In questo caso il processore con più memoria sarebbe stato anche fisicamente più grande e in una sottofamiglia diversa che non aveva il mix di periferiche di cui avevamo bisogno.
- Bootloader TCP. Questo è stato il più complesso di tutti. È stato utilizzato un grande PIC 18F. L'ultimo 1/4 di memoria conteneva circa il bootloader, che aveva la propria copia completa di uno stack di rete TCP. Il bootloader è stato eseguito dal ripristino e ha tentato di connettersi a un server di caricamento speciale in una porta nota a un indirizzo IP precedentemente configurato. Questo era per grandi installazioni dove c'era sempre una macchina server dedicata per l'intero sistema. Ogni piccolo dispositivo effettuerà il check-in con il server di caricamento dopo il ripristino e riceverà una nuova copia dell'app, a seconda dei casi. Il bootloader sovrascriverà l'app esistente con la nuova copia, ma la eseguirà solo se il checksum è selezionato. In caso contrario, tornerebbe al server di caricamento e riproverebbe.
Poiché il bootloader era esso stesso un pezzo complicato di codice contenente uno stack di rete TCP completo, doveva essere aggiornabile anche sul campo. Il modo in cui lo abbiamo fatto è stato quello di fare in modo che il server di caricamento gli fornisse un'app speciale il cui unico scopo era quello di sovrascrivere il bootloader una volta eseguito, quindi ripristinare la macchina in modo che il nuovo bootloader fosse in esecuzione, il che avrebbe causato al server di upload di inviare il ultima immagine dell'app principale. Tecnicamente, un errore tecnico durante i pochi millisecondi necessari all'app speciale per copiare una nuova immagine sul bootloader sarebbe un errore irrecuperabile. In pratica questo non è mai successo. Eravamo d'accordo con la probabilità molto improbabile di ciò dal momento che questi dispositivi facevano parte di grandi installazioni in cui c'erano già persone che avrebbero fatto manutenzione sul sistema, il che a volte significava sostituire i dispositivi integrati per altri motivi comunque.
Spero che tu possa vedere che ci sono molte altre possibilità, ognuna con i suoi compromessi di rischio, velocità, costo, facilità d'uso, tempi di inattività, ecc.