2014-10-20 21 views
6

Ich habe ein Interrupt-Service-Routing auf dem AVR32. Ich muss aus dem Interrupt-Status-Register lesen, um den Interrupt abzubrechen. Allerdings verwende ich das Ergebnis des Lesens nicht. Ich würde lieber keine asm-Anweisung verwenden, aber ich bin besorgt, dass gcc ein Lesen in eine Dummy-Variable optimieren wird. Was ist der richtige Weg?Wie liest man aus einem peripheren IO-Register mit C/gcc?

Zur Zeit habe ich:

uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

Sollte tmp auch flüchtig sein? Ich mache mir Sorgen, dass gcc das Lesen einfach überspringt, wenn tmp nicht benutzt wird.

+0

Ich kenne AVR32 nicht, aber sind Sie sicher, dass Sie das Interrupt-Statusregister lesen müssen? Aus meiner Erfahrung sollten Sie nur ein einzelnes Interrupt-Flag innerhalb des entsprechenden Registers löschen müssen (oft durch Schreiben einer 1 in das entsprechende Bit). Was ist Ihr Anwendungsfall dafür? –

+0

Ja, es ist nur ein Lesen des PWM-Vergleichs-Statusregisters, um den IRQ zu löschen. 'uint32_t temp = AVR32_PWM.isr2;' – Robotbugs

Antwort

6

Interrupt-Status durch Zeiger cast (volatile uint32_t *) registrieren Lese sagt Compiler, der diesen Ausdruck (Variable an bestimmten Adresse) Lesen Nebenwirkungen hervorruft, so braucht es immer diesen Ausdruck auszuwerten.

Da Ihre tmp-Variable nicht flüchtig ist, kann der Compiler den Wert Ihres Registers als Variable speichern.

Ich denke Kapitel 5.1.2.3 von C Standard (see here) ist relevant genug.

Zusätzlich Kapitel 6.7.3 erklärt:

Ein Objekt, die flüchtige qualifizierten Typen hat, kann in einer Weise, unbekannt, die Implementierung modifiziert werden, oder haben andere unbekannte Nebenwirkungen. Daher muss jeder Ausdruck, der sich auf ein solches Objekt bezieht, streng nach den Regeln der abstrakten Maschine , wie in 5.1.2.3 beschrieben, bewertet werden. Darüber hinaus muss an jedem Sequenzpunkt der Wert, der zuletzt im Objekt gespeichert wurde, mit dem von der abstrakten Maschine vorgeschriebenen Wert übereinstimmen, mit Ausnahme der durch die zuvor genannten unbekannten Faktoren modifizierten . 116) Was einen Zugriff auf ein Objekt darstellt, das über den Typ "Volatile-qualified" verfügt, ist implementierungsdefiniert.

Sie können tatsächlich tmp weglassen und nur schreiben:

*(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

Dies wird einfach lesen uint32_t bei INTERRUPT_STATUS_REG_ADDRESS befindet Register;

+0

Danke, das ist seltsam, ein Stück Code zu sehen, der nichts dergleichen zu tun scheint. Ich war wirklich nicht sicher, dass so etwas funktionieren könnte. – Robotbugs

+1

Ja, es sieht komisch aus, also ist es wahrscheinlich gut, zumindest ein Makro oder eine Funktion mit erklärendem Namen zu schreiben, um periphere Register zu lesen. – dbrank0