AVR-Bitmanipulationskompilierung in GCC: SEI kann nicht anstelle von Lesen-Ändern-Schreiben abgerufen werden

Ich versuche, Bit 2 im TIMSK-Register zu setzen und verwende den folgenden C-Code:

TIMSK |= (1<<2);

Compiler macht den folgenden Code:

TIMSK |= (1<<TOIE1);
108:    89 b7           in  r24, 0x39   ; 57
10a:    84 60           ori r24, 0x04   ; 4
10c:    89 bf           out 0x39, r24   ; 57

Es handelt sich also um eine Read-Modify-Write-Operation, die a) langsam und b) nicht sehr konsistent ist, da es manchmal besser ist, keine überschüssigen Bits zu stören.

Wenn ich jedoch TIMSK durch, sagen wir, PORTA ersetzen würde, bekomme ich SEIwie erwartet:

PORTA |= (1<<2);
108:    da 9a           sbi 0x1b, 2 ; 27

Wie zwinge ich also den Compiler, die obige Anweisung als Bit-Anweisung anstelle von RMW zu kompilieren?

Oder ist dieses ( TIMSK) Register nicht bitzugänglich?

Der resultierende Code stört keine überschüssigen Bits. Es liest das Register, führt das OR aus und schreibt das Ergebnis, es ist genau das OR-IS, das Sie in C-Code eingegeben haben. Außerdem ist SEI der globale Interrupt-Aktivierungsbefehl (Bruder von CLI), Sie meinen SBI wie in Ihrem zweiten Codeblock.

Antworten (1)

Ich habe es gefunden:

Zitat aus Originaldatenblatt (Seite 20):

E/A-Register innerhalb des Adressbereichs 0x00 - 0x1F sind unter Verwendung der SBI- und CBI-Befehle direkt bitweise zugänglich

Daher sind nur die ersten 32 Register bitweise zugänglich. TIMSK hat die Adresse 0x39 - also ziemlich hoch über dem Bereich :(

Exakt. Es ist ein Kompromiss für die Entscheidungen, die sie vor langer Zeit getroffen haben, als die Dinge in den meisten Anwendungssituationen rationalisiert bleiben sollten. Sie versuchen jedoch, die wahrscheinlichsten Kandidaten in die unteren 32 zu bringen. Wie oft schreibst du TIMSK? Wie oft PortA/B/C?