Oggi sempre più dispositivi embedded supportano aggiornamenti automatici da remoto senza la necessità di downloader, rendendo la manutenzione del dispositivo estremamente comoda. Per abilitare gli aggiornamenti da remoto per un dispositivo, è necessario scrivere codice di programma che supporti il processo di aggiornamento. Questo programma è comunemente chiamato BootLoader.
In sostanza, il codice del programma del dispositivo è diviso in due parti: il BootLoader e l’APP. Il BootLoader è responsabile dell’aggiornamento dell’APP e dell’avvio della sua esecuzione. L’APP, d’altra parte, è responsabile dell’implementazione delle funzioni operative del dispositivo, ospitando essenzialmente la funzionalità principale del dispositivo.
Per i microcontrollori della serie Cortex-M, ottenere una transizione sicura dal BootLoader all’APP richiede determinate configurazioni. Questo articolo prende come esempio i microcontrollori STM32 per delineare i passaggi di configurazione chiave necessari per implementare una transizione di successo dal BootLoader all’APP.
BootLoader Jump to APP
Passaggio 1: Partizionamento Flash
Durante la fase di programmazione e progettazione, è importante partizionare la memoria Flash in base ai requisiti specifici dell’applicazione. Ciò comporta la determinazione di dove verranno archiviati il BootLoader e l’APP, nonché lo spazio allocato a ciascuno. Questo posizionamento dello storage influisce direttamente sull’esecuzione e sulle transizioni del programma.
Una delle strategie di aggiornamento più semplici prevede un BootLoader e un’APP. Il BootLoader gestisce le transizioni e facilita gli aggiornamenti dell’APP. Questo articolo utilizza questa strategia di aggiornamento come esempio per la spiegazione.
Per i microcontrollori STM32, l’indirizzo mappato per l’avvio del programma è 0x8000000.
Il BootLoader può essere archiviato all’indirizzo 0x8000000 e lo spazio allocato può essere regolato in base alle dimensioni specifiche della Flash del chip, ad esempio 0x10000 o 64KB.
L’indirizzo di archiviazione dell’APP è posizionato dopo il BootLoader, specificamente all’indirizzo 0x8010000. Lo spazio rimanente nella Flash può essere allocato all’APP.
Passaggio 2: Configurazione del progetto BootLoader
La configurazione del progetto BootLoader prevede alcuni passaggi. Utilizzando MDK come esempio, il programma BootLoader viene archiviato nella memoria FLASH all’indirizzo 0x8000000 con una dimensione di 0x10000.

Quando si passa all’APP utilizzando il codice del programma, considerare i seguenti punti:
- Verificare la validità dell’indirizzo di cima dello stack, ovvero se l’indirizzo di partenza dell’APP è valido.
if(((*(__IO uint32_t *)APP_FLASH_ADDR) & 0x2FFE0000) == 0x20000000)
- Disabilitare tutte le interruzioni per prevenire disturbi durante la transizione che potrebbero causare eccezioni.
- Ottenere l’indirizzo di partenza del programma APP, che è memorizzato come seconda parola (indirizzo di partenza + 4, dati memorizzati in Flash).
- Inizializzare il puntatore dello stack (la prima parola nell’area del codice utente contiene l’indirizzo di cima dello stack).
- Convertire l’indirizzo di partenza dell’APP in un tipo di puntatore a funzione ed eseguire la transizione.
Il codice specifico per la transizione è il seguente:
/* Define type */
typedef void (*pFunction)(void);
/* APP flash address */
#define APP_FLASH_ADDR (0x8010000)
void jump_to_app(void)
{
uint32_t JumpAddress;
pFunction Jump_To_Application;
/* Check if the stack top address is valid */
if(((*(__IO uint32_t *)APP_FLASH_ADDR) & 0x2FFE0000) == 0x20000000)
{
/* Disable all interrupts to prevent disturbances during transition */
__disable_irq();
/* The second word in the user code area is the program's start address (reset address) */
JumpAddress = *(__IO uint32_t *) (APP_FLASH_ADDR + 4);
/* Initialize the user application's Stack Pointer */
__set_MSP(*(__IO uint32_t *) APP_FLASH_ADDR);
/* Type conversion */
Jump_To_Application = (pFunction) JumpAddress;
/* Transition to the APP */
Jump_To_Application();
}
}
Passaggio 3: Configurazione del progetto APP
Allo stesso modo, il progetto APP richiede determinate configurazioni. Utilizzando MDK come esempio, il programma APP viene archiviato nella memoria FLASH all’indirizzo 0x8010000 con una dimensione di 0x30000.

La configurazione per il programma APP prevede i seguenti passaggi:
- Rilocare la tabella vettoriale Flash interna nell’APP modificando SCB->VTOR.
- Dopo l’avvio dell’esecuzione dell’APP, è essenziale abilitare le interruzioni nella funzione di inizializzazione per garantire un’esecuzione fluida del programma. In caso contrario, potrebbero verificarsi anomalie del programma.
Normalmente, nel file di avvio, viene chiamata la funzione SystemInit(). Questa funzione configura le informazioni dell’interfaccia della Flash.
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET

Modifica il valore della definizione della macro VECT_TAB_OFFSET a 0x10000.

Dopo l’avvio del programma APP, è fondamentale abilitare le interruzioni globali. Puoi inserire il seguente codice nella sezione di inizializzazione:
/* Enable interrupts */
__enable_irq();
APP Salto a BootLoader
Durante il funzionamento del dispositivo, l’APP è in esecuzione ed elabora le funzioni aziendali. Se desideri aggiornare l’APP, devi passare da APP a BootLoader. Quindi, come realizzare il salto dell’APP a BootLoader? Ci sono due metodi:
- Modalità hardware, riavvio del dispositivo o pulsante di reset
- Modalità software, reset dell’MCU tramite controllo software
Nella modalità software, è possibile aggiungere comandi di controllo al codice APP e quando l’APP riceve il comando di salto (o comando di aggiornamento), l’MCU verrà ripristinato. Il seguente codice può ripristinare l’MCU:
/* reset chip */
HAL_NVIC_SystemReset();




