Interrupt nei microcontrollori - interrupt GPIO con STM32
Un'interruzione, nel lessico informatico interrupt, è un segnale inviato al processore che sospende temporaneamente l'esecuzione del programma principale per eseguire una routine di servizio dell'interruzione (ISR, Interrupt Service Routine). L’operazione può essere definita internamente alla memoria oppure definita dal programmatore.
Le interruzioni possono essere generate da diverse sorgenti, come temporizzatori, periferiche hardware (ad esempio, UART, ADC), o eventi esterni, come la pressione di un pulsante o il segnale di un sensore.
In questo articolo ci si occupa delle interrupt da GPIO ossia interruzioni generate da un segnale connesso a un pin di GPIO in input. Vengono definite EXTI, External interrupts, per la ragione di generare un interrupt da un segnale esterno.
Il compito del programmatore scrivere alcune righe di codice firmware in un'apposita funzione, nella quale si dichiara ciò che deve accadere alla generazione dell'interrupt. In sintesi, il programmatore deve definire il gestore dell'interruzione, ISR (interrupt service routine).
Inoltre, l'interrupt può essere generata sul fronte di salita o di discesa del segnale, a seconda delle necessità. La prima viene generata subito alla pressione del pulsante, mentre la seconda al rilascio dello stesso (figura 1).
Figura 1: Interrupt request (IR) al fronte di salita (in alto) o al fronte di discesa (in basso). |
La scrittura di un'interruzione per microcontrollori ST può essere così fatta:
- Aprire il software STM32CubeIDE e creare un nuovo progetto, attenendosi al proprio microcontrollore in possesso;
- Configurare il clock a dovere, attenendosi sempre alle specifiche del proprio microcontrollore;
- Nella finestra principale, il file .ioc, scegliere un pin disponibile e cliccare sopra con il tasto sinistro. Tra le diverse funzioni che può assumere, presenti nel menù a tendina, impostare GPIO_EXTIx. Nel caso in esame, ho scelto il pin PC13 (bottone blu a bordo della scheda) e il suo interrupt sarà GPIO_EXTI13 (figura 2);
Figura 2: settaggio dell'interruzione sul pin PC13. - Recarsi sulla sinistra della finestra e aprire System Core -> NVIC e attivare la linea di interruzioni EXTI (figura 3). NVIC è il Nested Vectored Interrupt Controller, e ha il compito di gestire le interruzioni all'interno del MCU.
Figura 3: attivazione della linea di interruzioni EXTI. - Dopo aver attivato la linea delle interruzioni, è necessario impostare il fronte su cui inviare la richiesta di interruzione (IR) al MCU. Nella sezione System Core recarsi su GPIO e cliccare sul pin scelto come interrupt. Nel caso in esempio PC13 (figura 4).
Figura 4: selezione del pin di interrupt PC13.
Nella paste inferiore della finestra compare l'area PC13-... configuration. Il primo menù disponibile è la scelta della modalità del GPIO GPIO Mode. Aprire il menù a tendina e scegliere, nel caso di interrupt lanciata dal fronte di salita, External Interrupt Mode with Rising edge trigger detection (figura 5). Ovviamente è possibile scegliere anche il fronte di discesa, cliccando su External Interrupt Mode with Falling edge trigger detection.Figura 5: selezione interrupt sul fronte di salita.
Arrivati a questo punto, occorre scrivere nel programma ciò che la MCU deve fare alla ricezione dell'interruzione legata alla pressione del pulsante. Il fulcro di questa azione sta nella scrittura del corpo di una funzione già disponibile all'interno del programma. Si tratta della funzione Callback, definita void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){...}. Non va dichiarata all'interno del main() e nemmeno del while(1) !! All'interno della funzione Callback, è buona pratica fare una verifica del PIN (e non della porta) tramite un if( GPIO_Pin == GPIO_PIN_13), così da evitare ambiguità nel caso fossero attivi più pulsanti di interrupt, e infine scrivere la routine ISR.
Interrupt - interruttore per led
Figura 7: dichiarazione della ISR. |
Come mostrato in figura 7, è stato preso come riferimento per la locazione della funzione Callback all'interno del codice la sezione USER CODE BEGIN 4. Se fosse stata dichiarata all'interno del main() o del while(1), avrebbe perso il suo significato.
Interrupt - modifica di variabili
Figura 8: variabile globale dichiarata nella sezione Private variables. |
Figura 9: ISR di incremento della variabile. |
Commenti
Posta un commento