mikrocontroller.net

Forum: Compiler & IDEs IO Ports steuern und IRQ = Problem?


Autor: Jürgen W. (coffeejunk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
sbi PORTA,4
in C mangels sbi die  Anweisung:
PORTA |= ~(1 << 4);

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:
in  r24, 0x1b  
ori  r24, 0xFB  
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
PORTA |= ~(1 << 4);
 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aktiviere beim Compiler die Optimierungen (z.B. -Os), dann macht er aus 
der Codezeile oben auch einen einzigen sbi-Befehl.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe atomare Operationen im Artikel Interrupt

MfG
Falk

Autor: Jürgen W. (coffeejunk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Optimierung -0s ist eingeschaltet, Ergebnis bleibt gleich.

Autor: Jürgen W. (coffeejunk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke! Trifft mein Problem zu 100%, nur das dauernde Ab/Anschalten des 
Globalen IRQ-Flag ist für mich nicht unbedingt die optimale Lösung, nur 
um ein IO-Bit zu ändern.

Werde wohl in diesem Fall nicht um ein selbst gestricktes sbi, welches 
wirklich nur ein einzelnes Bit bearbeitet (mit einer 
ASM-Anweisung)herumkommen.

Jürgen

Falk Brunner wrote:
> Siehe atomare Operationen im Artikel Interrupt

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen W. wrote:
> Die Optimierung -0s ist eingeschaltet, Ergebnis bleibt gleich.

Richtig, weil diese Codezeile
PORTA |= ~(1 << 4);
gar nicht in ein sbi übersetzt werden kann. Dort wird nämlich nicht 1 
Bit gesetzt, sondern 7 Bits.

PORTA |= (1 << 4);
Das ist das Äquivalent zu deiner ASM-Zeile.

Autor: Jürgen W. (coffeejunk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
> Jürgen W. wrote:
>> Die Optimierung -0s ist eingeschaltet, Ergebnis bleibt gleich.
>
> Richtig, weil diese Codezeile
>
PORTA |= ~(1 << 4);
> gar nicht in ein sbi übersetzt werden kann. Dort wird nämlich nicht 1
> Bit gesetzt, sondern 7 Bits.
>
>
>
PORTA |= (1 << 4);
> Das ist das Äquivalent zu deiner ASM-Zeile.

Autsch! Stimmt! Vielen Dank! Kleiner aber feiner Unterschied!

Jürgen

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.