2014-10-20 27 views
6

Ho un routing del servizio di interrupt su AVR32. Ho bisogno di leggere dal registro di stato degli interrupt per cancellare l'interruzione. Comunque non uso il risultato della lettura. Preferisco non usare un'istruzione ASM, ma sono preoccupato che gcc ottimizzerà una lettura in una variabile fittizia. Qual è la strada giusta?Come si legge da un registro IO periferico usando C/gcc?

Attualmente ho:

uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

caso TMP anche essere volatile? Sono preoccupato che gcc salterà la lettura se tmp non viene utilizzato.

+0

Non ho familiarità con AVR32, ma sei sicuro di aver letto il registro dello stato di interruzione? Dalla mia esperienza, dovresti semplicemente cancellare un singolo flag di interrupt all'interno del rispettivo registro (spesso compiuto scrivendo un 1 nel rispettivo bit). Inoltre, qual è il tuo caso d'uso per questo? –

+0

Sì, è solo una lettura del registro di stato di confronto PWM per cancellare l'IRQ. 'uint32_t temp = AVR32_PWM.isr2;' – Robotbugs

risposta

6

La lettura dello stato di interruzione tramite il cast del puntatore su (voluminoso uint32_t *) indica al compilatore che la lettura di questa espressione (variabile all'indirizzo specificato) produce effetti collaterali, quindi è sempre necessario valutare questa espressione.

Poiché la variabile tmp non è volatile, il compilatore è libero di ottimizzare la memorizzazione del valore del registro su variabile.

Penso che il capitolo 5.1.2.3 dello standard C (see here) sia sufficientemente pertinente.

Inoltre capitolo 6.7.3 spiega:

Un oggetto che ha tipo di volatili-qualificati possono essere modificati in modi sconosciuti al realizzazione o avere altri effetti collaterali sconosciuti. Pertanto qualsiasi espressione che faccia riferimento a a tale oggetto deve essere valutata rigorosamente secondo le regole della macchina astratta, come descritto in 5.1.2.3. Inoltre, in ogni punto di sequenza il valore memorizzato per ultimo nell'oggetto deve concordare con quello prescritto dalla macchina astratta, ad eccezione di quanto modificato dai fattori sconosciuti menzionati in precedenza. 116) Ciò che costituisce un accesso a un oggetto che ha un tipo volatile qualificato è definito dall'implementazione.

Si può effettivamente omettere tmp e basta scrivere:

*(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

Questo sarà semplicemente leggere uint32_t register situato a INTERRUPT_STATUS_REG_ADDRESS;

+0

Grazie, è bizzarro vedere un pezzo di codice che sembra non fare nulla del genere. Non ero sicuro che una cosa del genere potesse funzionare. – Robotbugs

+1

Sì, sembra strano, quindi probabilmente è bene scrivere almeno una macro o una funzione con un nome esplicativo per leggere i registri delle periferiche. – dbrank0