Tach,
bin vor kurzem von der reinen Assembler-Programmierung (ATMEL) auf C
umgestiegen. C-Kenntnisse sind zwar etwas eingerostet, aber vorhanden.
Bei der Umsetzung einiger Assembler Projekte in C bin ich auf folgendes
Problem gestossen:
Um z.B. am PortA (ist auf Output geschaltet) am Pin 4 ein High-Signal
auszugeben, benutzt man in Assembler die Anweisung:
in C mangels sbi die Anweisung:
Im Prinzip wird nun in beiden Fällen das IO-Bit 4 im PORTA gesetzt.
Schaue ich mir den ASM-Code an, der vom Compiler erzeugt wird:
1 | in r24, 0x1b
|
2 | ori r24, 0xFB
|
3 | out 0x1b, r24
|
Sieht auch OK aus. Doch was passiert im folgenden Fall:
Es existiert eine IRQ-Routine, welche im PortA die Bits 2 und 5 bedient.
Die Bits sind LOW.
Mal angenommen, der IRQ tritt auf, während der ASM-Code abgearbeitet
wird, z.B. während das Portregister (in r24,01xb) eigelesen wird. Das
würde dann folgendes bedeuten.
1.Die in Anweisung wird abgearbeitet, der Zustand des PORTA befindet
sich nun im r24 (0b00000000)
2.Der IRQ wird ausgelöst, im IRQ werden die Bits 2&5 im PORTA gesetzt
(0b00100100)
3. Nach Ende des IRQs gehts im Programm weiter mit "ori", aber in diesem
Augenblick sind die Inhalte von r24 'veraltet', da der Inhalt von r24
den Zustand des PORTA vor dem IRQ reflektiert.
4.Das Bitmuster 0b00010000 wird in den PORTA geschrieben, welches die
Änderungen, welche durch den IRQ verursacht wurden, nicht
berücksichtigt.
Das bedeutet für mich eigentlich, dass die Anweisung
keine geeignete Anweisung darstellt, um irgendwelche Bit-orientierte
Register im ATMEL anzusprechen.
sbi als C-Anweisung wird ja lt. DOKU nicht mehr unterstützt.
Gibt es eine Möglichkeit, dies Sinnvoll in "C" zu erledigen, ohne auf
INLINE ASM zurückzugreifen?
Jürgen