Domanda sugli ATmega, bit di interrupt

Una domandina: perché, a livello di programmazione lavorando direttamente con i registri dell'ATmega, per resettare un flag di interrupt ci devo scrivere 1 anziché 0? Mi ricordo che il professore all'università, quando ci spiegò gli interrupt, ci disse il motivo ma non me lo ricordo...

Non mi risulta. Se devo attivare un interrupt io ci scrivo 1, non 0: questo lo uso per disattivarlo.
Esempio:
TIMSK &= ~(1<<TOIE2)
Disattivo l'interrupt sull'overflow del registro TCR2 del timer 2.
Mi dici dove hai trovato il comportamento invertito? L'unico "posto" dove la logica è invertita è nei fuse, dove 0 significa "programmato" e 1 significa "non programmato".

Non mi riferisco al bit per abilitare gli interrupt ma al flag che mi indica che l'interrupt deve essere processato. Un esempio è il bit ACI del registri ACRS, il quale viene portato a uno quando l'interrupt deve essere gestito. Riporto quanto dice il datasheet:

Bit 4 – ACI: Analog Comparator Interrupt Flag
This bit is set by hardware when a comparator output event triggers the interrupt mode defined by ACIS1 and ACIS0. The Analog Comparator interrupt routine is executed if the ACIE bit is set and the I-bit in SREG is set. ACI is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, ACI is cleared by writing a logic one to the flag.

Janos:
Una domandina: perché, a livello di programmazione lavorando direttamente con i registri dell'ATmega, per resettare un flag di interrupt ci devo scrivere 1 anziché 0?

Non c'è una regola universale, ovvero a seconda del micro e del registro coinvolto lo stato attivo del flag di interrupt attivo può essere sia 0 che 1, il solo modo per saperlo è consultare il datasheet.
Attenzione che a seconda delle periferiche il clear del flag, può valere sia 0 che 1, può essere sia automatico quando vai a leggere un certo registo oppure solo manuale, ovvero se non resetti il flag il micro comincia a richiamare in eterno quella ISR con il conseguente blocco del normale funzionamento.

Mi sembrava di ricordarmi che il professore ci disse che c'era un motivo perché viene fatto così, tipo per evitare una qualche situazione strana, ma non me lo ricordo...

Ma relativamente agli Atmega? O in generale?

leo72:
Ma relativamente agli Atmega? O in generale?

In generale, ma sicuramente si applica anche agli ATmega.

Parlavamo degli ATmega, penso riferito a quelli, solo che mi ricordassi il motivo magari ti potrei dire se è una cosa generale o meno... :wink:

Janos:
Mi sembrava di ricordarmi che il professore ci disse che c'era un motivo perché viene fatto così,

Sarebbe interessante sapere quale visto che poi i produttori fanno come gli pare :slight_smile:

Anche qui ne parla:

There are basically two types of interrupts. The first type is triggered by an event that sets the
Interrupt Flag. For these interrupts, the Program Counter is vectored to the actual Interrupt Vector
in order to execute the interrupt handling routine, and hardware clears the corresponding
Interrupt Flag. Interrupt Flags can also be cleared by writing a logic one to the flag bit position(s)
to be cleared. If an interrupt condition occurs while the corresponding interrupt enable bit is
cleared, the Interrupt Flag will be set and remembered until the interrupt is enabled, or the flag is
cleared by software. Similarly, if one or more interrupt conditions occur while the Global Interrupt
Enable bit is cleared, the corresponding Interrupt Flag(s) will be set and remembered until the
Global Interrupt Enable bit is set, and will then be executed by order of priority.

Pag. 19 del datasheet del ATmega2560

Mi sa che stai facendo un po' di confusione con la traduzione :wink:
Lì si para del comportamento inerente la gestione degli interrupt ma non dice che "set" equivale a 1. Normalmente, a meno che non sia diversamente specificato (vedi fuse), "set" vuol dire messo ad 1.

leo72:
Mi sa che stai facendo un po' di confusione con la traduzione :wink:
Lì si para del comportamento inerente la gestione degli interrupt ma non dice che "set" equivale a 1. Normalmente, a meno che non sia diversamente specificato (vedi fuse), "set" vuol dire messo ad 1.

....Interrupt Flags can also be cleared by writing a logic one to the flag bit position(s) to be cleared....

Io lo leggo così: I flag di interrupt posso essere resettati anche scrivendo un uno logico nella posizione del flag da cancellare...

Sì, è vero. Mi era sfuggito questo punto.
Se ti può interessare, ho letto questo modo di fare anche da altre parti.
Ad esempio, datasheet del 328, pag. 74:

Bit 1 – INTF1: External Interrupt Flag 1
When an edge or logic change on the INT1 pin triggers an interrupt request, INTF1 becomes set
(one). If the I-bit in SREG and the INT1 bit in EIMSK are set (one), the MCU will jump to the cor-
responding Interrupt Vector. The flag is cleared when the interrupt routine is executed.
Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared
when INT1 is configured as a level interrupt.

• Bit 0 – INTF0: External Interrupt Flag 0
When an edge or logic change on the INT0 pin triggers an interrupt request, INTF0 becomes set
(one). If the I-bit in SREG and the INT0 bit in EIMSK are set (one), the MCU will jump to the cor-
responding Interrupt Vector. The flag is cleared when the interrupt routine is executed.
Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared
when INT0 is configured as a level interrupt.

Ed è scritto anche in tutte le pagine seguenti.
Mi viene da pensare che la scrittura non sia diretta ma che venga fatto uno XOR col valore precedentemente contenuto nel bit. Per attivare il flag, se fai lo XOR fra il contenuto 0 ed il valore 1 ottieni 1: 0 XOR 1 = 1.
Se però rifai lo XOR con 1, ottieni 0: 1 XOR 1 = 0. Quindi forse per evitare più operazioni per modificare il bit, venga fatto uno XOR senza controllare il suo stato.
Senza, per attivare il flag, si dovrebbe fare:

  1. carica il valore del registro
  2. if bit è a 0? sì: mettilo a 1;
  3. no: mettilo a 0.
  4. riscrivi il resistro.
    Con lo XOR, i punti 2 e 3 diventano uno solo:
  5. carica il valore del registro
  6. fai lo XOR con 1 del bit corrispondente
  7. riscrivi il registro

So che può essere una motivazione del ca@@o ma io non ho fatto l'uni e ragiono solo per "logica", cercando di pensare ad un motivo plausibile per questo comportamento.

Mah, non saprei. Non so se passa dentro uno XOR ma me lo ero immaginato anche io che la scrittura passasse da un altro registro di appoggio...

State facendo delle vere e proprie contorsioni mentali, detto in gergo nerd "pippe mentali" :D.
In assembly AVR esiste la SBR e CBR, ovvero Set/Clear Bit Register, cioè permettono di porre a 1 o 0 un qualunque bit di un registro della cpu con una sola istruzione e un solo ciclo macchina, queste istruzioni vengono invocate quando usate le macro CBI e SBI in C.
Non c'è nessun XOR nascosto, i vari flag degli interrupt altro non sono che normalissimi bit di un registro macchina, il set, non importa se a 0 o 1, avviene in hardware tramite porte logiche, il reset può essere sia in automatico da hardware, sempre tramite porte logiche, oppure manualmente, e/o obbligatoriamente, da software utente.

ma perché ci rovini tutta la poesia delle nostre elucubrazioni mentali? :stuck_out_tongue_closed_eyes:

ok, quindi è solo che questi bit vengono gestiti a logica invertita (1=off - 0=on). Tutto qui.

leo72:
ma perché ci rovini tutta la poesia delle nostre elucubrazioni mentali? :stuck_out_tongue_closed_eyes:

Perché il gusto che ci provo non ha prezzo :smiley: :grin: :smiley:

ok, quindi è solo che questi bit vengono gestiti a logica invertita (1=off - 0=on). Tutto qui.

Si, comunque tocca sempre fare riferimento al datasheet perché a seconda dei casi possono essere sia attivi a 1 che a 0, credo dipenda dalla configurazione possibile della glue logic interna al micro che a seconda dei casi gli fa optare, in fase di progetto, per lo 0 o 1.