Möglicherweise wird relais_as beim Anlaufen von der runtime nicht sauber initialisiert? Man könnte mal in den de-assemblierten Code schauen um das zu prüfen.
Nur mal Interesse halber, welcher tiefere Sinn steckt dahinter, die Pinzugriffe derartig zu verschwurbeln.
D.h. wie soll die praktische Anwendung aussehen?
Vermutlich wird der Compiler dadurch gezwungen, die Zugriffe memory mapped zu machen, also nicht einfach über direkte Bitbefehle und auch nicht atomar (mögliche Konflikte beim Setzen in Interrupts).
Vermutlich wird der Compiler dadurch gezwungen, die Zugriffe memory
mapped zu machen, also nicht einfach über direkte Bitbefehle und auch
nicht atomar (mögliche Konflikte beim Setzen in Interrupts).
Vermutlich. Wobei gcc durchaus einige Varianten erkennt und entsprechend sbi oder cbi einsetzt.
Würde hier aber auch empfehlen statt der Maske eher die Pin-Nummer zu speichern und im Code "PORTB |= (1<< x.pin)"... zu nutzen.
Ineffizient. Worst case hast du dann zur Laufzeit eine Schleife nur
dafür, dass du die Bitmaske ausrechnest.
Warum?
Ineeffizient bedeutet unwirtschaftlich oder nicht leistungsfähig.
Aber das gilt im Sinne der Ressourcen nur wenn es von der Geschwindigkeit darauf ankommt. Wenn ich beim Programmieren schnell zum Ziel komme ist das durchaus "effizient"....
Wenn die Pinnummer statt der Maske gespeichert wird, kann man auch direkt die asm Befehle (sbi, cbi ) nutzen. Schneller geht's nicht. Aber das würde ich nur machen wenn es aus Performance Gründen Sinn macht.
Goldene Regel der Softwareprogrammierung:
Nie im Voraus manuell optimieren. Nur wenn eine messbare Verbesserung daraus entsteht. Aktuelle Compiler können es normalerweise besser.
Wenn die Pinnummer statt der Maske gespeichert wird, kann man auch
direkt die asm Befehle (sbi, cbi ) nutzen. Schneller geht's nicht.
Du denkst viel zu sehr in Assembler.
In C gibt es keine Notation für eine Bit-Nummer. Es gibt nur Bitmasken, mit denen man logische Verknüpfungen machen kann. Wenn du die Bitmaske gleich in der Initialisierung erzeugst, dann ist sie zumindest garantiert für den Compiler sichtbar eine Konstante. Erzeugst du sie erst später, weil du nur eine Bit-Nummer hast, dann hängt es vom Kontext ab, ob der Compiler erkennen kann, dass sie konstant ist. Kann er es nicht, läufst du Gefahr, dass dort eine Schleife aus Schiebebefehlen produziert wird.
Die Umwandlung einer konstanten Bitmaske in CBI/SBI (oder SBIS/SBIC) ist ohnehin Aufgabe des Compilers, die kannst du ihm nicht abnehmen, indem du irgendwo nur Bit-Nummern abspeicherst.
In r30:r31 steht (anfangs) die Adresse 0x100 (aus r16:r17 übernommen). Der entsprechende Wert wird zuerst gelesen und auf 0 / !0 verglichen, in Abhhängig davon wird '0' oder '1' in r24 geladen und uart_characterPut() gerufen. Danach wird PORTB eingelesen, der Wert erneut von 0x100 gelesen, mit dem Wert aus PORTB verODERt und auf PORTB geschrieben.
Ups das wollte ich eigentlich nicht. Ich wollte ausdrücken dass man nicht zu schnell optimieren sollte.
Ist schon eine Weile her, dass ich avr programmiert habe. Das meiste wurde mit Bitmasken gemacht. Nur in speziellen Optimierungsfällen (Geschwindigkeit einer Pin Ausgabe) hab ich darauf geachtet, dass sbi/cbi genutzt wurde.
Hatte nicht mehr daran gedacht dass die Pin-Nummer im Opcode des Befehls gespeichert ist. Der Compiler kann es dann nicht in allen Fällen auflösen.
Asche auf mein Haupt.