Go Down

Topic: Interrupt contemporanei (Read 7452 times) previous topic - next topic

psoftware

Salve gente... durante l'ideazione di un progetto da realizzare con Arduino UNO (o eventualmente MEGA), sono sorte nella mia mente alcune problematiche a cui ho trovato solo parziale soluzione. Ho già iniziato a scrivere un po' di codice, con cui sono in grado di generare alcuni segnali PWM con frequenza prestabilita e sfasati fra di loro, facendo uso degli interrupt generati dal Timer1, configurato appositamente per le mie necessità. Il problema sorgerebbe quando dovrei sfruttare anche l'interfaccia seriale di Arduino UNO per trasmettere e ricevere dati con dispositivi esterni (probabilmente una Rasp), proprio perchè HardwareSerial sfrutta degli interrupt per la ricezione dei dati e a quanto pare anche per trasmetterne. Ora mi chiedo:

1) Che succede se vengono liberati due interrupt contemporaneamente o ne viene generato uno mentre una funzione eseguita a causa dell'altro è ancora in esecuzione?
2) Ho fatto le giuste considerazioni su HardwareSerial in termini di interrupt?
3) Rinunciando alla ricezione di dati sull'interfaccia seriale , posso fare in modo di sfruttare solo la trasmissione senza scatenare interrupt? (considerando che ci sia il problema)

Ovviamente già ho letto vari articoli nel Playground, quindi ho una mezza base teorica sugli interrupt e i timer, prescaler e altro, ma non ho trovato risoluzione a questi problemi... vi ringrazio in anticipo :)

Maurotec

1) L'esecuzione di codice interno a una ISR avviene per default con gli interrupt globali disabilitati.
Terminata la ISR vengono riabilitati gli interrupt.
In sostanza e come eseguire cli() all'ingresso e sei() alla fine della ISR.

2) Si

3) No

Per la (3) se scrivessi del codice per gestire la seriale senza interrupt dovresti anche verificare se gli interrupt della seriale sono disabilitati e se non lo sono provare a vedere cosa succede disabilitandoli.
Temo però che si incasinino un bel poco di cose, ma per saperlo con certezza bisognerebbe analizzare il codice
di Arduino core oppure provare e vedere cosa accade.

Ciao.



cyberhs

La risposta l'hai già data tu stesso: usa un MEGA che ha altre tre UART a disposizione.
Come alternativa altrettanto valida potresti usare un LEONARDO od un MICRO: hanno entrambi una porta seriale USB (virtuale) per il Serial Monitor e lasciano libera la porta seriale (pin 0 ed 1) per altri scopi. 

PaoloP

Inoltre gli interrupt non sono tutti uguali ma vengono eseguiti in base ad una scala di priorità: trovi l'ordine nel datasheet del micro.
Se due interrupt vengono richiamati contemporaneamente sarà eseguito quello con priorità maggiore e il secondo messo in coda ed eseguito al termine del primo.

icio

   Karma++;   //PaopoP

psoftware

Perfetto ragazzi! MauroTec e PaoloP siete stai molto chiari... cyberhs forse non hai colto la questione, per ora non mi servono più UART fisiche, più che altro volevo capire come gli interrupt generati dall'acquisizione dei dati in seriale potrebbe inibire la generazione del mio segnale PWM o la sua distorsione. Ora però mi sorge solo un'altra domanda:

- considerando che l'esecuzione di una ISR disabilita durante l'esecuzione altri interrupt... questi altri vengono accodati in qualche modo oppure l'esecuzione della ISR a cui sono legati viene inibita temporaneamente?

Dopo di questa penso che avrò le idee abbastanza chiare!

icio

Vengono accodati,  ogni interrupt setta un bit di flag nel registo apposito e quando è finita la risposta il rispettivo bit ritorna a 0, il controllo ritorna alla task interrotta ma se nel frattempo un'altro flag di interrupt è stato settato và subito alla sua risposta all'interrupt,  esiste una priorità che avviene nel caso di interrupt contemporanei.

Esiste anche un'altra situazione, non molto usata a dire il vero: l'interruzione di una risposta all'interrupt, cioè se l'interrupt viene riabilitato molto prima della fine della risposta può essere interrotto DURANTE LA STESSA RISPOSTA, è molto delicato in quanto l'ultima interruzione deve durare molto meno della prima e usare variabili non più usate nella prima interruzione altrimenti il programma si "autoinchiappetta" scusate il termine... :smiley-mr-green:

PaoloP


il programma si "autoinchiappetta" scusate il termine... :smiley-mr-green:


:smiley-mr-green: :smiley-mr-green: :smiley-mr-green:

Maurotec

@psoftware
I dettagli li puoi cogliere studiando il datasheet del microcontroller, tutti gli ATmega di base si comportano allo stesso modo.
Quote
- considerando che l'esecuzione di una ISR disabilita durante l'esecuzione altri interrupt... questi altri vengono accodati in qualche modo oppure l'esecuzione della ISR a cui sono legati viene inibita temporaneamente?

Anche se ci fosse un buffer che tiene conto di IRQ non soddisfatte, il problema rimane. Prima che la ISR del timer venga eseguita deve terminare la ISR corrente e se questa monopolizza il micro per 100ms, la ISR del timer sarebbe eseguita con un ritardo di almeno 100ms.
Si pensa che un IRQ non possa essere persa e che comunque sarà eseguita prima o poi, invece ciò può accadere più spesso di quanto non si pensi.

Se ci illustri per cosa usi il timer e come forse si può trovare una soluzione.
Ricorda che il PWM una volta impostato viene generato dal timer in modo indipendente dalle altre operazioni
eseguite. La tua applicazione potrebbe rientrare tra quelle dette mission-critical o soft-realtime o altro, riuscire a categorizzare la tua applicazione ti permette di decidere se ti serve un RTOS e il tipo di scheduler ecc.

Esempio, cosa accade se c'è uno slittamento dei tempi occasionale, se dei vincoli temporali occasionalmente
non vengono rispettati?
lo puoi accettare o e un disastro di proporzioni bibliche? :D

Ciao.

icio


Si pensa che un IRQ non possa essere persa e che comunque sarà eseguita prima o poi, invece ciò può accadere più spesso di quanto non si pensi.


Accade PER ESEMPIO in questa situazione:
il Timer0 produce un interrupt periodico a 10msec....risponde all'interrupt
durante la risposta a Timer0  accade un interrupt della rs232, arriva il carattere "A" , non si risponde ad essa perchè la risposta a Timer0 deve ancora terminare, ACCADE UN'ALTRA RICHIESTA DI INTERRUZIONE SEMPRE DA RS232,  arriva il carattere "B",   al termine della richesta di timer0 risponde anche a alla rs232 ma prenderà solo il carattere "B" , il carattere "A" è perso con guai  seri

tutto questo è reso possibile perchè la risposta al timer0 è durata più del tempo della ricezione tra i caratteri A e B
è possibile parlare della soluzione per questo esempio che ho citato ma non è il caso

Maurotec

@icio
Sintesi ottima.
In molti casi ci viene in aiuto il buffer presente nel convertitore seriale, e il meccanismo busy della seriale, sempre
se presenti in HardwareSerial.

Credo anche io che non sia il caso di approfondire principalmente perché ci sono molte possibili soluzione.

Ciao.

gpb01


Accade PER ESEMPIO in questa situazione:
il Timer0 produce un interrupt periodico a 10msec. ...........


... non per nulla le ISR dovrebbero essere ridotte veramente ai minimi termini, facendo il minimo indispensabile e tornando immediatamente indietro ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

icio

Penso che ora la richiesta di psoftware è stata esaudita,
tutti gli atmel90 a 8 bit funzionano così

psoftware

E' una discussione davvero interessante, spero riuscirò ad approfondire per bene tutti questi argomenti... ma ora ho le idee molto più chiare. Intanto ringrazio tutti i partecipanti per il contributo, poi vi spiego meglio cosa sto per fare.

In pratica sfruttando il Timer1 riesco a generare tre segnali PWM (usando dei semplici DigitalWrite nella ISR e una struttura if) a 50hz "sfasati" tra di loro con cui, tramite un circuito di potenza, andrò a controllare dispositivi a tensione molto più alta (230-400v). Facendo le vostre considerazioni, rischio che questo "conflitto" di interrupt possa far si che i miei segnali non vengano generati nel modo che ho prestabilito, e vengano distorti in qualche modo...provocando qualche problema con i dispositivi che controllerò.

Contemporaneamente rischio che pure il trasferimento di dati in seriale, via UART, sia intaccato in qualche modo, causando come mi avete descritto perdita di caratteri e successivi problemi. Probabilmente mi proporrete di generare quei segnali con qualche circuito elettronico a sè, ma vorrei farlo direttamente con Arduino...

Da quello che dite si evince che dovrei trovare un modo per gestire in modo diverso trasmissione e ricezione dei dati via seriale. A questo punto ritorno alla terza domanda che avevo fatto nel post di introduzione a questa discussione: rinunciando alla ricezione di dati su Arduino, posso sfruttare solo la trasmissione evitando il liberarsi di interrupt diversi da quelli del timer1? Non capisco se la trasmissione via seriale implichi la generazione di qualche interrupt. Per la ricezione ormai è certo, se ci fosse una soluzione anche per questa sarebbe ben accolta.

In ogni caso vorrei capire bene la "teoria" prima di arrivare alla pratica, non c'è miglior modo :)

PaoloP

Ecco....
Non usare digitalWrite dentro l'interrupt ma i registri del micro per cambiare stato al pin.
La DW è troppo lenta.

Go Up