ich entwickle aufm ARM mit dem GCC und der hat nen absoluten Horror-Optimierungsbug für volatile-Lesezugriffe von Datentypen kleiner der nativen Bitanzahl.
Sprich: alles was kleiner ist als volatile unsigned int dauert doppelt so lange im Zugriff.
Szenario: ich toiggle ein Bit in einem Memory mapped Register:
Code: Alles auswählen
GPIOA->ODR ^= 1<<Pin;
Beim Lesezugriff geschieht nun folgendes:
Code: Alles auswählen
Laden eines 16bit Wertes
zero-extent 16 bit auf 32 bit weil Register nunmal 32bit groß sind
XOR (auf die unteren 16bit btw)
Speichern des 16 bit wertes.
Mich interessiert an diesem Punkt der workaround:
Code: Alles auswählen
GPIOA->ODR = (*const_cast<unsigned short*>(&GPIOA->ODR)) ^ (1u<<Pin);
Also das volatile wieder hinmachen:
Code: Alles auswählen
GPIOA->ODR = ((volatile unsigned int)*const_cast<unsigned short*>(&GPIOA->ODR)) ^ (1u<<Pin);
Frage an die Experten:
a) ist das volatile jetzt immernoch volatile? (oder mach ich das durch weg- und wieder hin casten irgendwie immernoch kaputt?)
b) geht das nich (abgesehen von Makros) einfacher -.- Das ist doch ein Witz.
Irgendwie will ich grade den Lade-Operator für unsigned short und unsigned char überladen... wenn es sowas gäbe :lol:
Derzeitiges Makro:
Code: Alles auswählen
#define IO_READ(x) ( static_cast<decltype(x)>(*const_cast< std::remove_volatile<decltype(x)>::type*>(&(x))) )