Hi
Gibt es eine komfortable Möglichkeit auf einzelne Bytes in einem
größerem Datentyp zuzugreifen?
Folgendes habe ich zuerst probiert (x ist als volatile uint32_t
definiert, a als uint8_t).
1
x=(x&~(uint32_t)0xFF)|a;
Hier wird jedoch das ganze Byte aus dem SRAM geladen wieder gespeichert.
Über Pointer (-Pfusch) funktioniert es, allerdings unschön, da es nur
auf Littleendian-Systemen funktionieren würde:
Samuel K. schrieb:> Geht das schöner?
wenn du schreibst eine stuktur dann ist es erstmal egal ob Littleendian
oder big. Denn eine Struktur ist nie irgendwie ausgerichtet. Und damit
ist deine zeiger lösung schon ok
uint8t_t r = ((uint8_t*)&x)[0...x];
Wenn es um eine zahl geht, dann geht es so
uint8t_t r = (x>>x)&0xff;
Samuel K. schrieb:> x ist als volatile uint32_t definiert> Hier wird jedoch das ganze Byte aus dem SRAM geladen wieder gespeichert.
Ich vermute, du meinst die ganzen 32 Bit von x. Aber x ist volatile, da
bleibt dem Compiler so oder so keine andere Wahl.
Samuel K. schrieb:> Hi>> Gibt es eine komfortable Möglichkeit auf einzelne Bytes in einem> größerem Datentyp zuzugreifen?
Das hat alles nix mit avr-gcc zu tun.
Du kannst alles machen, was auch in C geht.
Was in C nicht geht, geht auch mit avr-gcc nicht.
Andreas B. schrieb:> Ich vermute, du meinst die ganzen 32 Bit von x.
Ja ich meinte die 32bit.
Andreas B. schrieb:> Aber x ist volatile, da> bleibt dem Compiler so oder so keine andere Wahl.
Das volatile muss leider bleiben, da der Wert in einem Interrupt
gebraucht wird, allerdings ist der Interrupt diesem Zugriff sicher
ausgeschaltet. Aber das lässt sich dem Compiler wohl nicht mitteilen.
Johann L. schrieb:> Das hat alles nix mit avr-gcc zu tun.> Du kannst alles machen, was auch in C geht.> Was in C nicht geht, geht auch mit avr-gcc nicht.
Naja, avrgcc bietet schon ein paar Funktionen, die z.B. auf einem PC
recht sinnfrei wären. Und das Problem hier ist auch ziemlich spezifisch,
da der Avr als 8-bit µC viele Instruktionen braucht, um irgendetwas mit
einem uint32_t zu machen.
Ganz sauber finde ich die Pointerlösung nicht, aber wenn es nichts
besseres gibt...
Hallo,
du könntest auch ein Union, bestehend aus einem uint_32 und einem char
array, definieren. Dann kannst dann entweder auf die ganze Zahl oder auf
jedes einzelne Byte der Zahl zugreifen.
Grüße,
Florian
Samuel K. schrieb:> Das volatile muss leider bleiben, da der Wert in einem Interrupt> gebraucht wird, allerdings ist der Interrupt diesem Zugriff sicher> ausgeschaltet. Aber das lässt sich dem Compiler wohl nicht mitteilen.
Doch, man kann einen Zeiger auf die Variable auf einen Zeiger ohne
volatile casten. Oder umgekehrt die Variable nur nach volatile casten
wenn nötig. Oder statt volatile ein memory barrier Makro verwenden.
Ich hab es mal mit einem avr-gcc 4.5.3 ausprobiert und der würde
trotzdem die ganzen 32 Bit laden. Bei der Und-Verknüpfung erkennt er,
dass die 0xff Bytes keinen Einfluss haben, aber beim erweiterten uint8_t
erkennt er nicht, dass alle oberen Bytes gleich 0 sind und führt alle 4
or-Instruktionen aus.
Samuel K. schrieb:> Johann L. schrieb:>> Das hat alles nix mit avr-gcc zu tun.>> Du kannst alles machen, was auch in C geht.>> Was in C nicht geht, geht auch mit avr-gcc nicht.>> Naja, avrgcc bietet schon ein paar Funktionen, die z.B. auf einem PC> recht sinnfrei wären. Und das Problem hier ist auch ziemlich spezifisch,> da der Avr als 8-bit µC viele Instruktionen braucht, um irgendetwas mit> einem uint32_t zu machen.
So ist das eben, wenn man 32-Bit Arithmetik auf einem 8-Bit auf einem
8-Bit µC macht.
Und wenn das Ding volatile ist, muss es komplett geladen werden. Alles
andere wäre ein Compilerbug.
> Ganz sauber finde ich die Pointerlösung nicht, aber wenn es nichts> besseres gibt...
Das Thema wurde schon 100* durchgekaut.
Neben der fehlenden Portirebarkeit und Hack durch verkorksen der
Poointer, ist ein weiteres Probleme die Verletzung der Aliasing-Regeln
von C.
Wozu wird der Hack überhapt gebraucht?
Reine Kosmethik im erzeugten Code?
Oder gibt's wirklich ein Performance-Problem?