Go Down

Topic: Sketch controllo encoder con interrupt - ho bisogno di chiarimenti (Read 5550 times) previous topic - next topic

PaoloP

#15
Apr 26, 2014, 10:25 am Last Edit: Apr 26, 2014, 10:27 am by PaoloP Reason: 1
Vi state concentrando su un bit del registro quando gli altri sono più importanti.
E' giusto il discorso di Mauro.
Il datasheet del 328P inoltre dice che in caso di chiamata il registro di stato (tutto, non solo il bit I) DEVE essere salvato.
Questo perché all'interno dell'interrupt potrebbero essere fatti dei calcoli che cambiano la configurazione del registro e tornando da un'interrupt col registro cambiato il flusso di operazioni successive può dare risultati imprevedibili.
Copiare e incollare l'SREG non serve per riabilitare gli interrupt globali ma per salvare lo stato precedente alla chiamata all'interrupt e per me è più importante.
Parlo naturalmente per il solo Arduino, riferendomi al datasheet del 328P.

Inoltre secondo me usare il comando
Code: [Select]
SREG &= ~(1<<SREG_I);
al posto di
Code: [Select]
cli();
esegue l'impostazione di SREG più lentamente.
Cli() viene tradotto in una unica istruzione asm. bisognerebbe vedere in quante istruzioni è tradotto l'assegnamento al registro.  

Maurotec

Come fa notare PaoloP ci possono essere altri motivi che ci portano a salvare SREG. La domanda è:
Siamo davvero così infallibili da ricordarci cosa abbiamo scritto nella funzione x tre mesi fa, io no.
Io l'ho scritta non la guardo da tre mesi e ora mi viene in mente che posso usarla nel codice di esempio.

Code: [Select]

void loop(){
  uint8_t oldSREG = SREG;
  cli();
  fuctionVeryOld();
  Pos = encoderPos;      // ops doveva essere eseguita atomicamente.
  SREG = oldSREG;
  if(Pos != oldPos){
    Serial.println(Pos,DEC);
    oldPos = Pos;
  }
  delay(1000);
}


Se functionVeryOld disabilita con cli() ed esegue codice e poi prima di uscire riabilita gli interrupt con sei()
si verifica il problema. Mi ritrovo ad eseguire codice con gli iterrupt abilitati quando e chiaro che io li ho disabilitati, chi li riabilita?

Qui è semplice capire che fuctionVeryOld() potrebbe essere la causa, e allora vado a vedere il codice sorgente,
nel caso io non l'avessi il codice sorgente quella funzione è da considerare buggata.

Siamo davvero in grado si seguire l'evoluzione del codice a mente e ricordarci tutto?
Io non me la sento di rischiare e allora uso la macro, che salva SREG e lascia l'ambiente nello stesso modo in cui
lo ha ricevuto.

Altro motivo per usare la macro:
Salvo SREG, cli() e mi dimentico di ripristinare lo stato di SREG.
Con la macro la dimenticanza non può proprio verificarsi e al massimo mi scordo a chiudere } e
il compilatore me lo segnala.

Quindi io raccomando di usare la macro anche in ambiente arduino. Come detto nel libro l'esempio è
didattico  e ci sta mostrare i passaggi.

Ciao.

leo72


Vi state concentrando su un bit del registro quando gli altri sono più importanti.

E quali, scusa? Il flag negativo? O quello di riporto? O lo zero? Naaa..  ;)
Di importante per la gestione degli interrupt nel registro di stato c'è solo il bit SREG_I, fidati. Tutto il resto serve alla CPU durante l'esecuzione dei calcoli.

PaoloP


Di importante per la gestione degli interrupt nel registro di stato c'è solo il bit SREG_I, fidati. Tutto il resto serve alla CPU durante l'esecuzione dei calcoli.


E dici niente...
Tu esegui un calcolo in cui parte del risultato è nel registro di stato.
Esegui un interrupt. Il programma principale viene interrotto, viene eseguita una ISR che esegue calcoli che cambia alcuni bit del registro di stato, torni al programma principale con una configurazione diversa del registro di stato.
Il tuo programma prosegue, ma puoi essere sicuro che l'esecuzione e i risultati siano corretti?

Se invece salvi e ripristini il registro alla fine della ISR sai con certezza che il programma prosegue con la stessa configurazione lasciata quando ha dovuto eseguire la ISR.

leo72

Paolo, tu continui a parlare di un problema quando io ho iniziato a discutere di un altro ;) ;)
Io stavo parlando di istruzioni cli() e sei() usate in un programma, tu invece continui a fare l'esempio di una ISR  ;)
Nella ISR ci pensa il codice a salvare lo stato del registro ed a ripristinarlo in uscita. Cli() e sei() sono invece usate per rendere un blocco di codice temporaneamente atomico, e non mi interessa dello stato di quei flag perché non sto andando ad eseguire un task in un ambiente multitasking, sto solo armeggiando con qualcosa che non deve essere interrotta da un interrupt per qualche microsecondo (es. configurare un timer).  ;)

EDIT:
si fa solo per parlare, non voglio che tu pensi che sto criticando tutto quel che dici, mi piace solo scambiare opinioni per capire i pro ed i contro.  ;) ;)

PaoloP


sto solo armeggiando con qualcosa che non deve essere interrotta da un interrupt per qualche microsecondo (es. configurare un timer).


In questo caso sono d'accordo.
Puoi usare anche le macro: nointerrupt() e interrupt().  ;)
Sono degli alias mnemonici meglio identificabili.

Go Up