ESP32 (4) – Flash, bootloader e FreeRTOS

luca 22/12/2016 9

Nei precedenti post vi ho introdotto il nuovo chip esp32 e vi ho spiegato come effettuare il setup dell’ambiente di sviluppo, incluso l’utilizzo – opzionale – di un IDE grafico, Eclipse.

Prima di poter iniziare a sviluppare nuovi programmi, è necessario che vi parli ancora di tre elementi fondamentali: la flash, il bootloader e il sistema operativo FreeRTOS. Ma non preoccupatevi! Già alla fine di questo post scriveremo un programma (seppur “minimale”) e dal prossimo tutorial inizieremo con esempi pratici.

Flash

Come detto nel primo post di questa serie, il chip esp32 richiede una memoria flash esterna, nella quale memorizzare software, dati, parametri di configurazione…

Questa memoria esterna viene collegata al chip via bus SPI e può avere una dimensione massima di 16Mb. Il modulo ufficiale Espressif (ESP-WROOM-32) monta un chip da 4Mb prodotto da GigaDevice (GD25Q32):

esp-flash01

La memoria flash può contenere diversi elementi: programmi, dati… per questo viene divisa in sezioni (partizioni). L’elenco delle diverse partizioni, della loro dimensione e della loro posizione all’interno della flash è memorizzato nella flash stessa (all’indirizzo 0x8000) e prende il nome di partition table.

Due tipi di partizioni sono definite di default:

  • app (tipo 0) – partizione che contiene una applicazione
  • data (tipo 1) – partizione che contiene dati

Durante lo sviluppo di un nuovo programma, lo sviluppatore può decidere come organizzare la memoria flash in base alle specifiche esigenze. Il framework di sviluppo offre due configurazioni già pronte, definite all’interno del menu di configurazione:

esp-flash02

E’ inoltre possibile visualizzare la partition table del proprio progetto lanciando il comando make partition_table:

esp-flash03

Nello screenshot sopra si vede la partition table relativa alla configurazione più semplice (Single factory app, no OTA):

  • una partizione data (chiamata “nvs“) da 24Kb all’indirizzo 0x9000
  • una partizione data (chiamata “phy_init“) da 4Kb all’indirizzo 0xf000
  • una partizione app (chiamata “factory“) da 1Mb all’indirizzo 0x10000

Bootloader

Per spiegare il motivo della divisione della memoria flash in più partizioni, dobbiamo comprendere come funziona il bootloader del chip esp32, ovvero come viene avviata la nostra applicazione.

Il chip esp32 ha memorizzato al suo interno (nella memoria ROM) un piccolo programma detto first-stage bootloader. Questo programma viene eseguito ad ogni reset del chip e si occupa di inizializzare l’accesso alla memoria flash e, se richiesto, di memorizzare dei nuovi dati (comando flash). Una volta terminati i propri compiti, questo primo bootloader accede alla memoria flash (indirizzo 0x1000) e carica il second-stage bootloader.

Sebbene il comportamento standard del framework esp-idf sia di utilizzare questo secondo bootloader, è anche possibile sviluppare una applicazione che – memorizzata all’indirizzo 0x8000 della flash – sia eseguita direttamente.

Il second-stage bootloader legge la partition table dall’indirizzo 0x8000 della flash alla ricerca di partizioni di tipo app e decide quale eseguire in base a quanto trovato nella partizione otadata. Se tale partizione è vuota, viene eseguita l’applicazione presente nella partizione factory. In questo modo è possibile implementare un meccanismo di aggiornamento over-the-air (OTA): si invia la nuova versione dell’applicazione al chip esp32 mentre è in funzione; tale versione viene memorizzata in una nuova partizione. Una volta che l’invio è terminato con successo, viene scritto l’id della nuova partizione della otadata e riavviato il chip; in questo modo il bootloader eseguirà la nuova applicazione:

esp-flash04

FreeRTOS

Il framework esp-idf si basa sul Real-Time Operating System FreeRTOS. Può sembrare strano parlare di sistema operativo in esecuzione su un chip quale esp32… non dobbiamo però pensare che FreeRTOS sia un sistema operativo come Windows, Linux o MacOS. Il compito fondamentale di un sistema operativo in ambito embedded è quello di offrire, tramite un proprio schedulatore, il multitasking, ovvero la possibilità di eseguire contemporaneamente più programmi (tasks). In realtà sappiamo che un core di un microprocessore è in grado di eseguire una sola istruzione in una unità di tempo: il sistema operativo da l’impressione che i programmi siano in esecuzione contemporaneamente mandandoli rapidamente in esecuzione uno dopo l’altro.

esp-flash05

passaggi di stato per i tasks in FreeRTOS

Un sistema operativo real-time garantisce che la schedulazione dei vari tasks sia deterministica, ovvero che sia possibile predire il comportamento dello scheduler del sistema operativo. FreeRTOS consente al programmatore di definire delle priorità per i propri tasks; lo scheduler utilizza i valori di priorità per definire la sequenza di esecuzione dei vari tasks.

Il primo programma

Iniziamo ora a scrivere il nostro primo programma che utilizza il framework esp-idf. Questo programma, disponibile nel mio repository Github, sarà la base per i prossimi tutorial.

Per prima cosa dobbiamo includere alcune librerie:

esp-flash07

La libreria stdio.h (Standard I/O) viene utilizzata per le funzioni di stampa a video (printf…) mentre le due librerie freertos servono per definire ed eseguire i vari tasks.

Ogni programma viene eseguito a partire dal metodo app_main():

esp-flash08

All’interno di app_main() viene definito un nuovo task, tramite xTaskCreate. Questo metodo richiede come parametri il puntatore al metodo (&loop_task) che contiene il codice del task, il nome da assegnare al task (“loop_task”)la dimensione in words (512) dello stack in memoria da assegnare al task, eventuali parametri (NULL), la priorità (5) e il puntatore – opzionale – per ottenere un handler (NULL).

Una volta creato il task, lo schedulatore di FreeRTOS lo manda in esecuzione in base alle diverse priorità.

Il task ha il seguente codice:

esp-flash09

è un loop continuo che ogni  secondo stampa a video la scritta “Hello World!”. Il metodo vTaskDelay mette in pausa il task per il numero di ticks specificati come parametro. La costante portTICK_RATE_MS definisce la durata, in millisecondi, di un tick; dividendo quindi 1000 per tale costante si ottiene proprio il numero di ticks in ogni secondo.

Files aggiuntivi

Per poter compilare il progetto, è necessario preparare un paio di files aggiuntivi:

  • un Makefile nella cartella principale che contenga almeno il nome del progetto e il riferimento al makefile principale del framework:

esp-flash10

  • un file component.mk anche vuoto nella cartella dove è presente il codice sorgente per indicare al compilatore che deve processare i files presenti in tale cartella:

esp-flash11

Test

Una volta pronto il programma, possiamo compilarlo e caricarlo come spiegato nel precedente tutorial

make
make flash

Se è tutto ok, collegandoci con un emulatore terminale dovremmo vedere:

esp-flash12

 

9 Comments »

  1. Mauro 24/12/2016 at 18:53 - Reply

    Ottimi articoli (mi riferisco anche alle puntate precedenti) chiaro e coinciso: capito tutto in un baleno–
    Spero nelle prossimi si esamini il framework per accedere ai pin (accendere led e leggere un valore analogico….) e magari usare i due core (esp32 ha 2 core invece di uno del esp8266).
    Comunque grazie e attendo con trepidazione la prossima puntata..Per Ora Buon Natale e Buon Anno

    Mauro

  2. Michele 04/01/2017 at 15:20 - Reply

    Ottimo tutorial!!!!! Complimenti e molto molto interessante!! …. spero in altri articoli su esp32

    • luca 09/01/2017 at 08:27 - Reply

      Ciao Michele e grazie! Ho postato poco fa proprio un nuovo articolo… ho intenzione di approfondire molto l’utilizzo di questo chip quindi segui periodicamente il blog ;)

  3. Roberto 23/01/2017 at 00:56 - Reply

    Ciao, Sto smanettando anche io con l’esp32, sono riuscito a far funzionare il progetto blink in esp-pdf, poi ho provato a creare un progetto nuovo ed ho copiato il tuo sorgente wifi_scanner ma quando assemblo mi da un sacco di errori, nel tuo articolo dici che “In fase di compilazione del programma, è fondamentale attivare il modulo wifi dal menu di configurazione” ora però non sono riuscito a lanciare questo menu di configurazione? dovrebbe apparire quando lancio il make?

    • luca 23/01/2017 at 08:40 - Reply

      Ciao Roberto… si la prima volta che lanci il comando make ti deve apparire il menu; in alternativa puoi lanciare “make menuconfig” per eseguirlo esplicitamente. Ti consiglio di seguire tutti i tutorial dall’inizio: da quello che scrivi sembra che il tuo ambiente di compilazione non sia configurato completamente.

  4. flyword 08/09/2017 at 13:38 - Reply

    hey! once I run the original code, the ESP32 board will get panic,and finally I discovery that the parameter “512” should be set as 1024 or 2048 in the function xCreateTask() ,then the program will run perfectly,why??

    • luca 08/09/2017 at 23:47 - Reply

      Hi, that parameter is the stack size, so it depends on how much memory (= variables…) the task will allocate

Leave A Response »

Questo sito usa i cookie per poterti offrire una migliore esperienza di navigazione maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi