Sistemi operativi in tempo reale (RTOS) e loro applicazioni
Contributo di Editori nordamericani di DigiKey
2021-02-25
Cos'è l'RTOS
Un sistema operativo in tempo reale (RTOS) è un sistema operativo leggero utilizzato per facilitare il multitasking e l'integrazione delle attività in progetti con risorse e tempo limitati, tipico dei sistemi embedded. Inoltre, il termine "tempo reale" indica la prevedibilità/il determinismo del tempo di esecuzione e non la velocità pura, quindi un RTOS di solito può dimostrarsi di soddisfare i rigido requisiti di tempo reale grazie al suo determinismo.
I concetti chiave di RTOS sono:
Attività
Le attività (potrebbero anche essere chiamate processi/thread) sono funzioni indipendenti che si eseguono a cicli infiniti, di solito ognuna responsabile di una funzione. Le attività sono eseguite indipendentemente nel proprio tempo (isolamento temporale) e nel proprio stack di memoria (isolamento spaziale). L'isolamento spaziale tra le attività può essere garantito con l'uso di un'unità di protezione di memoria (MPU) hardware, che limita la regione di memoria accessibile e innesca eccezioni di errore alla violazione dell'accesso. Normalmente, le periferiche interne sono mappate in memoria, quindi una MPU può essere utilizzata per limitare l'accesso alle periferiche.
Le attività possono essere in diversi stati:
- Bloccata - l'attività è in attesa di un evento (es. timeout del ritardo, disponibilità di dati/risorse)
- Pronta - l'attività è pronta per essere eseguita sulla CPU ma non è in esecuzione perché la CPU è in uso da parte di un'altra attività
- In esecuzione - l'attività è assegnata all'esecuzione sulla CPU
Utilità di pianificazione
Le utilità di pianificazione in RTOS controllano quale attività eseguire sulla CPU e sono disponibili diversi algoritmi di pianificazione. Normalmente sono:
- Prelazionale - l'esecuzione dell'attività può essere interrotta se un'altra con priorità più alta è pronta
- Cooperativa - il cambio di attività avverrà solo se l'attività attualmente in esecuzione lo concede
Le utilità di pianificazione prelazionali permettono alle attività dalla priorità più alta di interrompere altre inferiori per soddisfare i vincoli del tempo reale, ma a discapito di un maggiore costo in termini di commutazione contestuale.
Comunicazione tra attività (ITC)
Più attività avranno normalmente bisogno di condividere informazioni o eventi tra di loro. Il modo di condivisione più semplice è di leggere/scrivere direttamente le variabili globali condivise nella RAM, ma questo comporta rischi legati al danneggiamento dei dati causato da una condizione di competizione. Un modo migliore è quello di leggere/scrivere le variabili statiche accessibili dalle funzioni setter e getter e prevenire condizioni di competizione disabilitando gli interrupt o mediante un oggetto di mutua esclusione (mutex) all'interno della funzione setter/getter. Il modo più pulito è usare oggetti RTOS thread-safe come la coda di messaggi per passare informazioni tra le attività.
Oltre alla condivisione delle informazioni, gli oggetti RTOS sono anche in grado di sincronizzare l'esecuzione delle attività, perché le attività possono essere bloccate mentre attendono che gli oggetti RTOS si rendano disponibili. La maggior parte degli RTOS ha oggetti come:
- Coda di messaggi
- Coda FIFO (first-in-first-out) per passare i dati
- I dati possono essere inviati per copia o per riferimento (puntatore)
- Utilizzato per inviare dati tra le attività o tra l'interrupt e l'attività
- Semaforo
- Può essere considerato un contatore di riferimento per registrare la disponibilità di una particolare risorsa
- Può essere un semaforo binario o di conteggio
- Utilizzato per sorvegliare l'uso delle risorse o sincronizzare l'esecuzione delle attività
- Mutex
- Simile al semaforo binario, generalmente usato per custodire l'uso di una singola risorsa (MUTual EXclusion)
- Il mutex FreeRTOS è dotato di un meccanismo di ereditarietà della priorità per evitare il problema dell'inversione di priorità (condizione in cui un'attività ad alta priorità finisce per aspettare un'attività a bassa priorità).
- Casella postale
- Luogo di memorizzazione semplice per condividere una singola variabile
- Può essere considerata una coda di elementi singoli
- Gruppo di eventi
- Gruppo di condizioni (disponibilità di semaforo, coda, indicatore eventi, ecc.)
- L'attività può essere bloccata e può aspettare che sia soddisfatta una specifica condizione di combinazione
- Disponibile in Zephyr come API di polling, in FreeRTOS come QueueSet
Tick di sistema
Gli RTOS hanno bisogno di una base temporale per misurare il tempo, normalmente sotto forma di una variabile del contatore di tick di sistema incrementata in un interrupt periodico del timer hardware. Con il tick di sistema, un'applicazione può mantenere più servizi basati sul tempo (intervallo di esecuzione delle attività, timeout di attesa, suddivisione temporale) usando solo un singolo timer hardware. Tuttavia, una frequenza di tick più alta aumenterà solo la risoluzione della base temporale dell'RTOS, non renderà il software più veloce.
Perché usare RTOS
Organizzazione
Le applicazioni possono sempre essere scritte in modo "bare-metal", ma quando la complessità del codice aumenta, una certa struttura aiuterà a gestire le diverse parti dell'applicazione, tenendole separate. Inoltre, con un modo strutturato di sviluppo e un linguaggio di progettazione familiare, un nuovo membro del team può leggere il codice e iniziare a fornire il suo contributo più velocemente. RFCOM Technologies ha sviluppato applicazioni utilizzando diversi microcontroller come Hercules di Texas Instruments, RL78 e RX di Renesas e STM32 di STMicroelectronics su un diverso RTOS. Modelli di progettazione simili ci permettono di sviluppare applicazioni su diversi microcontroller e persino su un diverso RTOS.
Modularità
Divide et impera. Separando le funzioni in diverse attività, si possono aggiungere facilmente nuove funzioni senza problemi; a condizione che la nuova funzioni non sovraccarichi le risorse condivise come la CPU e le periferiche. Lo sviluppo senza RTOS avverrà normalmente in un grande ciclo infinito in cui tutte le funzioni fanno parte del ciclo. Un cambiamento a qualsiasi funzione all'interno del ciclo avrà un impatto sulle altre, rendendo il software difficile da modificare e mantenere.
Stack di comunicazione e driver
Molti driver o stack supplementari come TCP/IP, USB, stack BLE e librerie grafiche sono sviluppati per RTOS esistenti. Uno sviluppatore di applicazioni può concentrarsi su un livello applicativo del software e abbattere significativamente il time-to-market.
Suggerimenti
Allocazione statica
L'uso dell'allocazione statica della memoria per gli oggetti RTOS significa riservare lo stack di memoria nella RAM per ogni oggetto RTOS durante la compilazione. Un esempio di una funzione di allocazione statica in FreeRTOS è xTaskCreateStatic(). Questo assicura la creazione corretta di un oggetto RTOS, risparmiando il fastidio di gestire possibili errori nell'allocazione e rendendo l'applicazione più deterministica.
Per quanto riguarda il decidere la dimensione dello stack per un'attività, l'attività può essere eseguita con uno stack più grande (più che sufficiente) e poi l'utilizzo dello stack può essere controllato in runtime per determinare il punto di massimo livello. Esiste anche uno strumento di analisi statica dello stack.
Livello di astrazione del sistema operativo (OSAL) e astrazione significativa
Proprio come il livello di astrazione hardware (HAL), l'uso del livello di astrazione RTOS permette al software applicativo di migrare facilmente verso altri RTOS. Le caratteristiche degli RTOS sono abbastanza simili, quindi creare OSAL non dovrebbe essere troppo complicato. Ad esempio:
Utilizzando direttamente l'API FreeRTOS:
if( xSemaphoreTake( spiMutex, ( TickType_t ) 10 ) == pdTRUE ) { //dosomething }
Includendo l'API RTOS in OSAL:
if( osalSemTake( spiMutex, 10 ) == true) { //dosomething }
usando il livello di astrazione sulla comunicazione tra attività per rendere il codice più leggibile e minimizzare l'ambito applicativo di un oggetto RTOS:
if( isSpiReadyWithinMs( 10 ) ) { //doSomething }
Inoltre, l'astrazione permette anche a un programmatore di cambiare l'oggetto RTOS soggiacente utilizzato (es., da mutex a semaforo di conteggio) se vi sono più moduli SPI disponibili. OSAL e altri livelli di astrazione aiutano anche nei test software, semplificando l'inserimento di funzioni "mock" durante i test unitari.
Selezione dell'intervallo di tick
Idealmente, una frequenza di tick più bassa è meglio perché causa un sovraccarico minore. Per selezionare una frequenza di tick adatta, lo sviluppatore può elencare i vincoli temporali dei moduli in un'applicazione (intervallo di ripetizione, durata del timeout, ecc.) Se alcuni moduli outlier hanno bisogno di un intervallo piccolo, si può considerare un interrupt timer dedicato per questi moduli piuttosto che aumentare la frequenza di tick dell'RTOS. Se la funzione ad alta frequenza è molto breve (ad esempio, scrivere al registro di accendere/spegnere un LED), può essere fatto all'interno di una routine di servizio interrupt (ISR), altrimenti si può usare la gestione differita degli interrupt. La gestione differita degli interrupt è una tecnica di rinvio del calcolo degli interrupt in un attività RTOS, l'ISR genererà solo un evento attraverso l'oggetto RTOS, poi l'attività RTOS sarà sbloccata dall'evento ed eseguirà il calcolo.
Soppressione dei tick per applicazioni a bassa potenza
"Tickless idle" disabilita l'interrupt tick quando il sistema è inattivo per un tempo più lungo. Un modo significativo per i firmware embedded di ridurre il consumo di energia è quello di portare il sistema in modalità a basso consumo il più a lungo possibile. Tickless idle viene implementato disabilitando l'interrupt periodico del tick e quindi impostando un timer per il conto alla rovescia dell'interrupt quando un'attività bloccata deve essere eseguita. Se non vi è alcuna attività in attesa di un timeout, l'interrupt tick può essere disabilitato indefinitamente fino a quando non si verifica un altro interrupt (es., pulsante premuto). Ad esempio, nel caso di un radiofaro Bluetooth Low Energy (BLE), l'MCU può essere portato in modalità di sospensione profonda tra l'intervallo di advertising. Come mostra la Figura 1, il radiofaro è in modalità di sospensione profonda per la maggior parte del tempo, consumando energia nell'ordine delle decine di µA.
Figura 1: Consumo di corrente di un radiofaro BLE (Immagine per gentile concessione di RFCOM)
Conclusione
Un RTOS fornisce funzioni come le utilità di pianificazione, le attività e gli oggetti RTOS di comunicazione tra attività, così come gli stack di comunicazione e i driver. Permette agli sviluppatori di concentrarsi sul livello applicativo del software embedded e di progettare software multitasking velocemente e in modo semplice. Tuttavia, proprio come qualsiasi altro strumento, deve essere usato correttamente per sfruttarne tutte le potenzialità. Per creare un software embedded sicuro ed efficiente, gli sviluppatori devono sapere quando usare le funzioni RTOS e anche come configurare RTOS.
Esonero della responsabilità: le opinioni, le convinzioni e i punti di vista espressi dai vari autori e/o dai partecipanti al forum su questo sito Web non riflettono necessariamente le opinioni, le convinzioni e i punti di vista di DigiKey o le sue politiche.



