2014-10-20 40 views
6

Mam routing usługi przerwania na AVR32. Muszę odczytać z rejestru statusu przerwania, aby anulować przerwanie. Jednak nie używam wyniku odczytu. Wolałbym nie używać instrukcji asm, ale obawiam się, że gcc zoptymalizuje odczyt do zmiennej dummy. Jaka jest właściwa droga?Jak można odczytać z peryferyjnego rejestru IO przy użyciu C/gcc?

Obecnie mam:

uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

tmp powinno również być niestabilne? Martwię się, że gcc po prostu pominie odczyt, jeśli tmp nie jest używany.

+0

Nie jestem zaznajomiony z AVR32, ale czy na pewno musisz przeczytać rejestr statusu przerwań? Z mojego doświadczenia, powinieneś po prostu wyczyścić pojedynczą flagę przerwania w odpowiednim rejestrze (często osiągniętą przez napisanie 1 do odpowiedniego bitu). Ponadto, jaki jest twój przypadek użycia? –

+0

Tak, jest to po prostu odczyt rejestru stanu porównywania PWM, aby usunąć przerwanie IRQ. 'uint32_t temp = AVR32_PWM.isr2;' – Robotbugs

Odpowiedz

6

Odczyt stanu przerwania zarejestrować poprzez wskaźnik do obsady (lotnych uint32_t *) informuje kompilator, że czytając ten wyraz (zmienna na podany adres) powoduje skutków ubocznych, dlatego zawsze musi ocenić tego wyrażenia.

Ponieważ zmienna tmp nie jest niestabilna, kompilator może zoptymalizować przechowywanie wartości rejestru w zmiennej.

Myślę, że rozdział 5.1.2.3 normy C (see here) jest wystarczająco istotny.

Dodatkowo rozdział 6.7.3 wyjaśnia:

Obiekt, który ma lotny wykwalifikowaną typu mogą być modyfikowane w sposób nieznanych realizacji lub pełnią inne nieznane skutki uboczne. Dlatego każde wyrażenie odnoszące się do takiego obiektu powinno być ocenione ściśle zgodnie z regułami abstrakcyjnej maszyny, zgodnie z 5.1.2.3. Ponadto, w każdym punkcie sekwencji, wartość ostatnio zapisana w obiekcie musi zgadzać się z wartością opisaną przez abstrakcyjną maszynę, z wyjątkiem zmodyfikowanych przez wymienione wcześniej nieznane czynniki. 116) To, co stanowi dostęp do obiektu, który ma typ o wartościach zmienionych, jest zdefiniowane przez implementację.

Rzeczywiście można pominąć tmp i po prostu napisać:

*(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

To będzie po prostu czytaj uint32_t zarejestruj się na INTERRUPT_STATUS_REG_ADDRESS;

+0

Dzięki, to dziwne, widzieć kod, który wydaje się nie robić nic takiego. Naprawdę nie byłem pewien, czy coś takiego może zadziałać. – Robotbugs

+1

Tak, wygląda to dziwnie, więc dobrze jest przynajmniej napisać makro lub funkcję o nazwie objaśniającej w celu odczytu rejestrów peryferyjnych. – dbrank0