Hallo, ist Schreibzugriff aus IRQ und normalem Code aus auf uint32_t durch __disable_irq und __enable_irq zu schützen oder nicht? Grüsse Entwickler
Das hängt weniger vom Compile als vom konkreten System ab. Ich nehme mal an du hast einen Cortex-M irgendwas mit 32 bit Kern. Hier ist der Zugriff auf uint32_t und kleiner atomar*. * Solange das 32 bit Wort auch an einer 32 bit aligned Adresse liegt. Das sollte bei automatischer Platzierung durch den Linker gegeben sein. Wenn das 32 bit Wort nicht aligned ist, dann kann bspw. ein Cortex M0 gar nicht darauf zugreifen -> HardFault und ein Cortex M4 bspw. wird den Zugriff in zwei Zugriffe spalten, die dann nicht atomar sind.
Ja, das System ist Cortex-M4 und die Variable wird vom Compiler im RAM alloziert. Kein cast von (uint8_t*) nach (uint32_t*) oder ähnliches. Danke
Entwickler schrieb: > ist Schreibzugriff aus IRQ und normalem Code aus auf uint32_t durch > __disable_irq und __enable_irq zu schützen oder nicht? Nicht wenn du zB. auch DMA benutzt.
Read-Modify-Write ist auch nicht atomar, z.B.
1 | count++; |
2 | flags |= FOO; |
selbst wenn es einen Maschinenbefehl INC gäbe, wäre der beim M4 nicht atomar.
:
Bearbeitet durch User
Entwickler schrieb: > ist Schreibzugriff aus IRQ und normalem Code aus auf uint32_t durch > __disable_irq und __enable_irq zu schützen oder nicht? Kannst du vielleicht auch mal nicht mit der Keule programmieren? Bei jeder Gelegenheit mit dis/enable der Interrupts herumzufuchteln scheint mir eine tiefsitzende Unsitte von Leuten zu sein, die vom AVR herkommen. Nein, die Interrupts sollte man in Ruhe lassen und sich Methoden angewöhnen, die ohne solche Keulen auskommen. Insofern kann man deine Frage mit JA oder NEIN beantworten, je nachdem wie du dich beim Programmieren anstellen willst. Aber das ist deine Obliegenheit. W.S.
W.S. schrieb: > Entwickler schrieb: >> ist Schreibzugriff aus IRQ und normalem Code aus auf uint32_t durch >> __disable_irq und __enable_irq zu schützen oder nicht? > > Kannst du vielleicht auch mal nicht mit der Keule programmieren? Was ist dein Problem? Er fragt doch extra nach, ob er das braucht oder nicht.
Bauform B. schrieb: > Read-Modify-Write ist auch nicht atomar, z.B.count++; > flags |= FOO; > selbst wenn es einen Maschinenbefehl INC gäbe, wäre der beim M4 nicht > atomar. In diesem Fall kann mittels der exklusiven load und store Befehle der RMW Vorgang "atomar gekapselt werden". Das erfordert aber etwas Assembler.
M. H. schrieb: > Bauform B. schrieb: >> Read-Modify-Write ist auch nicht atomar, z.B.count++; > > In diesem Fall kann mittels der exklusiven load und store Befehle der > RMW Vorgang "atomar gekapselt werden". Das erfordert aber etwas > Assembler. Hat schon mal jemand gewagt, das zu verwenden? Wie war das, das R in RISC steht für Ridiculous, oder? Es heißt ja nicht, dass es weniger zu lernen gibt.
Beitrag #7317609 wurde vom Autor gelöscht.
Faktisch ist ein uint32_t, wenn er denn aligned, ist, auf einem 32bitter wie ein Cortex-M bis auf weiteres mit gcc atomar. Das ist aber wie ich gelernt habe nicht garantiert. Und zumindest beim Clang hab ich da sehr interessante Optimierungen beobachtet (die ungewöhnlich, aber nicht dem Standard widersprechen). In etwa ging der Code so:
1 | typedef struct { |
2 | uint32_t a; |
3 | uint8_t b; |
4 | } myType_t; |
5 | |
6 | void foo(myType_t * x, myType_t * y) { |
7 | y->a = x->a; |
8 | y->b = x->b; |
9 | }
|
Der Zugriff auf a erfolgte nicht atomar. Stattdessen hat der clang selbstständig die Erlaubnis für nicht alignte Zugriffe angenommen und einen 4 Byte Zugriff gemacht der 3 Byte von a und dann das 1 Byte von b beinhaltet hat. Dann einen 1 Byte Zugriff um das fehlende Byte von a zu kopieren.
M. H. schrieb: > ..."atomar gekapselt werden". > Das erfordert aber etwas Assembler. Diese Arbeit kann man heutzutage durchaus dem Compiler überlassen: - https://en.cppreference.com/w/cpp/atomic/atomic
Das wird regelmäßig hier gefragt (oft auch in Zusammenhang mit volatile): Beitrag "Re: c volatile -> wann bracht mans wirklich?"
Bauform B. schrieb: > Hat schon mal jemand gewagt, das zu verwenden? Was heißt "gewagt"? Die Funktionalität ist weder besonders schwierig zu verstehen noch außergewöhnlich. Hier ist schon in der Frage ein funktionales Beispiel: Beitrag "STM32: LDREX/STREX vs Interruptsperre"
Bauform B. schrieb: > Hat schon mal jemand gewagt, das zu verwenden Das geht sogar ganz einfach, wenn du die Atomic-Library verwendest: https://en.cppreference.com/w/c/language/atomic https://en.cppreference.com/w/cpp/atomic/atomic Wenn ich mich recht erinnere, muss man noch bei Kontextwechseln/Interrupt-Eintritt noch ein CLREX ausführen. Wenn du ein RTOS verwendest, basieren die Synchronisations-Primitive wahrscheinlich auch auf Atomics oder direkt auf den jeweiligen Assembler-Befehlen.
:
Bearbeitet durch User
Rolf M. schrieb: > Was ist dein Problem? Er fragt doch extra nach, ob er das braucht oder > nicht. ICH brauche sowas nicht. Und ich habe auch kein Problem damit. Aber ob der TO bei seiner Programmierweise sowas braucht, kann eigentlich nur er selber sagen. Allenfalls kann er seine Programmierweise ändern - sofern er das will. Das ist der entscheidende Punkt. W.S.
Niklas G. schrieb: > Kontextwechseln/Interrupt-Eintritt noch ein CLREX ausführen. Bei exceptions / Interrupts übernimmt das der Cortex von sich.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.