Go Down

Topic: Dove iniziare per programmare SAM3U (Read 7243 times) previous topic - next topic

lesto

quindi stai dicendo che probabilmente quelle differenze misurate dal tipo del PDF sono semplicemente  l'interferenza degli altri interrupt esterni (vedi Serial)? oppure la INT ha priorità anche su interrupt interni? immagino ci sia tutto sul datasheet ma sono al lavoro e mi interessa
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

leo72

Per "solerzia" non intendevo la celerità delle istruzioni ma proprio ciò che avevo premesso, ossia la priorità. Il concetto di "precedenza". E' come nel traffico quando arriva un'ambulanza a sirene spiegate, che vien fatta passare dal vigile prima delle altre auto.

Janos

Quindi, ricapitolando, va bene anche se si usa attachInterrupt, no? Io ho usato gli ingressi collegati agli INT...

lesto

esatto, se usi ISR forse risparmi qualcosa per via del fatto che non fa il salto alla tua funzione, son pochi cicli ma magari basta. In oltre se postassi il codice si potrebbe vedere di ottimizzare la funzione e farcela stare coi tempi
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

astrobeed


oppure la INT ha priorità anche su interrupt interni? immagino ci sia tutto sul datasheet ma sono al lavoro e mi interessa


La INT0 e INT1 sono i primi due interrupt della lista, quindi hanno maggiore priorità su tutti gli altri, però la questione si pone solo se ci sono interrupt nella stessa finestra temporale di INT0 e INT1, ovvero vengono gestiti solo quando le ISR INTx hanno terminato il loro compito.

leo72

@lesto:
A pag. 57, tab. 11.1, c'è l'elenco per priorità dei vettori di interrupt.

Quote
ehm... ehm ehm....  smiley-roll-sweat smiley-roll-sweat smiley-roll-sweat smiley-roll-sweat
Si perde tanto in prestazioni usando attachInterrupt invece che utilizzare direttamente le ISR? Io pensavo che attachInterrupt non facesse altro che indirizzare un jump alla funzione richiesta...


Scusa al posto di "core" o scritto "cose", cioè XMega a quale core ti riferisci?

ISR(vect) // e una macro
{
    if (qualcosa)
        call function pointer
}

Questa è più o meno come si presenta il vettore di interrupt di arduino, si fa uso di attachInterrupt per registrare un puntatore a funzione utente, che come vedi viene chiamata da dentro la isr, quindi scrivendo direttamente il codice nella isr si risparmia una if e una chiamata a funzione che comporta il salvataggio di SREG e la situazione dello stack. Quindi qualcosa si risparmia.

La situazione di janos è tipica ed è questo il momento per ottimizzare quanto più possibile il codice. Certo ci sarebbe da studiare il codice al fine di capire qual'è la porzione di codice che più necessita di ottimizazione.

Il 2560 mi pare che ha 4 interrupt trigerabili da INT0-INT3, se usi encoder in quadratura sono necesari solo due pin, se gli encoder sono due cominciano i problemi o almeno ci sono maggiori probabilità che i due encoder scatenino eventi che non possono essere gestiti in parallelo, ma in questo caso ti accorgeresti che le isr monopolizzano l'uso del mcu e rimane davvero poco tempo per eseguire altro codice.

In genere nella isr c'è solo un contatore chAcount++; e chBcount-- e quindi più rapido di così non si può, se nelle isr fai altro devi vedere se influisce in modo importante.

Quote
esatto, se usi ISR forse risparmi qualcosa per via del fatto che non fa il salto alla tua funzione, son pochi cicli ma magari basta. In oltre se postassi il codice si potrebbe vedere di ottimizzare la funzione e farcela stare coi tempi

Si ma quanto costa una chiamata a funzione? si tratta di un tempo costante o è variabile?

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Janos

postare tutto il codice non posso, sia per segreto aziendale sia perché sono circa 1500 righe...  :)

L'encoder penso sia la cosa che più ho ottimizzato...

Code: [Select]

#define encInterrA 0
#define encInterrB 1
#define encA 2
#define encB 3

volatile unsigned long contEnc = 0; //Valore del conteggio dell'encoder

void setup() {
  digitalWrite(encA, HIGH);                           //Attivo i pullup degli ingressi dell'encoder
  digitalWrite(encB, HIGH);                           //Attivo i pullup degli ingressi dell'encoder
  attachInterrupt(encInterrA, encoderA, CHANGE);      //Attivo il gestore di interrupt per gli ingressi dell'encoder
  attachInterrupt(encInterrB, encoderB, CHANGE);      //Attivo il gestore di interrupt per gli ingressi dell'encoder
};

void encoderA() {
  unsigned char i = PINE;                   //Leggo il valore di PINE
  unsigned char a = i & (1 << PE4);         //Maschero gli altri bit per isolare quello corrisp. alla fase A
  unsigned char b = i & (1 << PE5);         //Maschero gli altri bit per isolare quello corrisp. alla fase B
  if (a == (1 << PE4)) {                    //Se A è alto
    if (b == 0) contEnc++;                  //e B è basso incrementa
    else contEnc--;                         //altrimenti decrementa
  }
  else {                                    //Se A è basso
    if (b == (1 << PE5)) contEnc++;         //e B è alto incrementa
    else contEnc--;                         //Altrimenti decrementa
  }
};

void encoderB() {
  unsigned char i = PINE;                   //Leggo il valore di PINE
  unsigned char a = i & (1 << PE4);         //Maschero gli altri bit per isolare quello corrisp. alla fase A
  unsigned char b = i & (1 << PE5);         //Maschero gli altri bit per isolare quello corrisp. alla fase B
  if (b == (1 << PE5)) {                    //Se B è alto
    if (a == (1 << PE4)) contEnc++;         //e A è alto incrementa
    else contEnc--;                         //altrimenti decrementa
  }
  else {                                    //Se B è basso
    if (a == 0) contEnc++;                  //e A è basso incrementa
    else contEnc--;                         //Altrimenti decrementa
  }
};

lesto

#53
May 10, 2012, 01:56 pm Last Edit: May 10, 2012, 02:03 pm by lesto Reason: 1
la chiamata ha una parte costante, visto che i dati da salvare in stack son sempre quelli, però deve salvare anche le variabili locali (se presenti) ed infine fare il passaggio di parametri
poi considera che finita la funzione chiamanta viene rifatto tutto al contrario.

edit:
@janos: non dichiarare le variabili dentro la funzione, ma falle globali. così risparmi qualche ciclo.

poi (1 << PE5) è una operazione che puoi evitare se PE5 è costante.
per esempio potrebbe diventare da
Code: [Select]
if (b == (1 << PE5))
a (se PE5 valesse 16 per esempio)
Code: [Select]
if (b == B00010000)

ci sono mille altre vie, il fatto di fare (1 << PE5) vuol dire fondentalmente sposta 1 a sinistra di PE5 bit, ma se PE5 è costante, questo valore te lo puoi calcolare a mano e usare come define
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Janos

#54
May 10, 2012, 02:39 pm Last Edit: May 10, 2012, 02:41 pm by Janos Reason: 1
"1 << PE5" non occupa nessun ciclo del processore, è un calcolo che esegue una volta il precompilatore. Attenzione, non prendo una variabile, metto un 1 all'inizio e faccio e ROR (rotate on right) ma è una costante con un 1 nella posizione indicata da PE5. PE5 è una costante che è definita non so dove di preciso ma a partire dal file avr/io.h

La mie isr erano così:

Code: [Select]

unsigned int npulseA = 1;
unsigned int npulseB = 1;
void encoderChA()
{
   if ((PIND & _BV(2)) ^ (PIND & _BV(3)))
   {
       encoderpos++;
   }
   else
   {
       encoderpos--;
   }
}

void encoderChB()
{
 
   if ((PIND & _BV(2)) ^ (PIND & _BV(3)))
   {
       encoderpos--;
   }
   else
   {
       encoderpos++;
   }
}


Codice per la 2009.

Quote

"1 << PE5" non occupa nessun ciclo del processore, è un calcolo che esegue una volta il precompilatore. Attenzione, non prendo una variabile, metto un 1 all'inizio e faccio e ROR (rotate on right) ma è una costante con un 1 nella posizione indicata da PE5. PE5 è una costante che è definita nel file portpins.h


Si, suppongo PE5 e definito per avere "valore" 5 quindi è uno shift << di 5.

Comunque usa direttamente PINE anziche assegnarlo a i;

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Janos


Comunque usa direttamente PINE anziche assegnarlo a i


Effettivamente non è male come idea... =)

lesto


"1 << PE5" non occupa nessun ciclo del processore, è un calcolo che esegue una volta il precompilatore. Attenzione, non prendo una variabile, metto un 1 all'inizio e faccio e ROR (rotate on right) ma è una costante con un 1 nella posizione indicata da PE5. PE5 è una costante che è definita non so dove di preciso ma a partire dal file avr/io.h


sicuramente è un'operazione perchè puoi usare anche valori non costanti, poi non so se il compilatore se ne accorge che usi costanti e la risolve.. dovresti controllare l'assembly
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Janos

Secondo quello che c'hanno spiegato all'università quella non è un'operazione perché è un numero... E' un'operazione che esegue il precompilatore.

leo72


Secondo quello che c'hanno spiegato all'università quella non è un'operazione perché è un numero... E' un'operazione che esegue il precompilatore.

Forse confondi l'operazione di sostituzione di PE5 che il compilatore esegue con il corrispondente valore portato da PE5 con l'operazione di rotazione (o shift), che viene eseguita sul contenuto di una variabile a runtime.

Go Up