Hallo zusammen, angenommen man habe einen µC auf dem kein OS läuft. Es gibt ein Hauptprogramm welches Berechnungen vornimmt und in bestimmten Variablen abspeichert. Das Programm ist durch Interrupt unterbrechbar. Im Interrupt werden die Variablen gelesen. Auch der Interrupt kann Berechnungen vornehmen, die im Hauptprogramm gelesen werden. Weiterhin nehme man an es gibt keinerlei Synchronisation zwischen Hauptprogramm und Interrupt(Semaphore/Mutexe...) Was ist unter diesen Voraussetzungen das schlimmste was passieren kann? Gruß Kevin
Dazu setzt man sogenannte Flags die anzeigen ob Berechnungen im Gange sind oder abgeschlossen sind. Sonnst : Kevin schrieb: > Was ist unter diesen Voraussetzungen > das schlimmste was passieren kann? Absolutes Chaos und undefinierte Ergebnisse ....;-)
:
Bearbeitet durch User
Patrick L. schrieb: > undefinierte Ergebnisse ... https://www.mikrocontroller.net/articles/Interrupt#Interruptfeste_Programmierung Patrick L. schrieb: > Dazu setzt man sogenannte Flags die anzeigen ob Berechnungen im Gange > sind oder abgeschlossen sind. Meist reicht es, die Unterbrechungen zu unterbinden. Was in der ISR berechnet wird, braucht halt ein Volatile, um nicht versehentlich, veraltete Registerinhalte zu verarbeiten.
Kevin schrieb: > Hallo zusammen, > > angenommen man habe einen µC auf dem kein OS läuft. Es gibt ein > Hauptprogramm welches Berechnungen vornimmt und in bestimmten Variablen > abspeichert. Das Programm ist durch Interrupt unterbrechbar. Im > Interrupt werden die Variablen gelesen. Auch der Interrupt kann > Berechnungen vornehmen, die im Hauptprogramm gelesen werden. Weiterhin > nehme man an es gibt keinerlei Synchronisation zwischen Hauptprogramm > und Interrupt(Semaphore/Mutexe...) Was ist unter diesen Voraussetzungen > das schlimmste was passieren kann? Bei Assemblerprogrammierung einfach inkonsistente Daten. Bei C/C++ bekommst Du UB noch dazu (was in diesem Fall aber mehr ein weiterer formaler Aspekt ist). Da Du ja scheinbar schon etwas von der Thematik verstanden hast, ist mir der Hintergrund der Frage nicht ganz klar ...
Patrick L. schrieb: > Absolutes Chaos und undefinierte Ergebnisse ....;-) Chaos klingt gut. Was ist mit undefiniert gemeint? Was wenn nur jeweils lesend der Zugriff erfolgt? Also nicht auf die gelesene Variable zurückgeschrieben wird. Was wäre hier der Worst Case?
Kevin schrieb: > Was ist unter diesen Voraussetzungen > das schlimmste was passieren kann? Nichts. Außer, das Programm ist fehlerhaft, dann gibts Chaos. Das gilt aber für alle fehlerhaften Programme. Du musst halt selber dafür sorgen, daß sich ISR und Hauptprogramm nicht gegenseitig verheddern. Die Stichworte dazu lauten volatile und atomic. Oliver
Wilhelm M. schrieb: > Da Du ja scheinbar schon etwas von der Thematik verstanden hast, ist mir > der Hintergrund der Frage nicht ganz klar ... Ich möchte verstehen unter welchen Bedingungen man eine Synchronisation braucht und wann nicht, ohne jetzt ins Detail zu gehen wie z.b. so eine Synchronisation aussehen muss.
Kevin schrieb: > Wilhelm M. schrieb: >> Da Du ja scheinbar schon etwas von der Thematik verstanden hast, ist mir >> der Hintergrund der Frage nicht ganz klar ... > > Ich möchte verstehen unter welchen Bedingungen man eine Synchronisation > braucht und wann nicht, ohne jetzt ins Detail zu gehen wie z.b. so eine > Synchronisation aussehen muss. Eine Synchronisation brauchst Du immer bei nebenläufigem Zugriff, wenn mindestens ein Schreiber dabei ist. Je nach eingesetzter Sprache kann das dann unterschiedlich aussehen. Bei C/C++ wurde schon volatile als "Optimierungssperre" genannt. Das hat aber nichts mit Synchronisation zu tun. Weiterhin wird noch wechselseitiger Ausschluss benötigt. Das kannst Du durch atomics oder expliziter Syncho durch bspw. Mutexe erreichen.
Wilhelm M. schrieb: > wechselseitiger Ausschluss benötigt man bei mehr als einen Schreiber, richtig?
Kevin schrieb: > Wilhelm M. schrieb: >> wechselseitiger Ausschluss > > benötigt man bei mehr als einen Schreiber, richtig? Steht doch oben: mindestens einem Schreiber
Kevin schrieb: > Ich möchte verstehen unter welchen Bedingungen man eine Synchronisation > braucht und wann nicht, Immer wenn auf die Daten, aus dem Hautprogramm und einer ISR zugegriffen wird. Das mag sich in einigen (seltenen) Fällen, von ganz alleine ergeben, aber deine Aufmerksamkeit wird hier immer benötigt. Das ganze also mal in ruhe, im Kopf durchspielen.
Kevin schrieb: > Was ist unter diesen Voraussetzungen > das schlimmste was passieren kann? Dass du kaputte Zahlen verarbeitest. Denn bei einem 32 Bit Integer würde ein (8 Bit) Mikrocontroller ganze 4 Scheibzugriffe nacheinander im RAM machen. Wenn du dazwischen liest, bekommst du ein paar alte mit ein paar neuen Bits vermischt.
:
Bearbeitet durch User
Der Interrupt kann über ein Flag signalisieren, daß neue Daten verfügbar sind. Das Main muß sie dann atomar lesen, damit sie konsistent bleiben. Sinnvoll legt man dazu ein Struct an.
Servus, kritisch sind stets Schreib- und Lesezugriffe, welche mehr als einen Assemblerbefehl benötigen. Folgendes Szenario kann das vielleicht beschreiben: Im Hauptprogramm wird eine 16-Bit Variable beschrieben (angenommen das teilt sich 2 Assemblerbefehle auf, High- und Low-Byte schreiben) und diese wird im Interrupt ausgelesen und "verarbeitet". Es könnte folgendes passieren: 1. High-Byte wird geschrieben (Hauptprogramm) 2. Interrupt kommt 2.a. High-Byte (neu) wird im Interrupt gelesen 2.b. Low-Byte (alt) wird im Interrupt gelesen 2.c. Eine Mischung aus alt und neu wird verarbeitet - Möglicherweise Unfug 2.d. Interrupt beendet 3. Low-Byte wird geschrieben (Hauptprogramm) Das gemeine ist, daß dieser Fehler wahrscheinlich nur ab und zu auftritt und dann auch nicht immer zu einem Fehler führt. Die Lösung ist, sich das ganze sehr genau durchdenken. Allgemeine Lösungen wie "immer volatile davorschreiben" helfen da nur sehr bedingt. Es kommt immer auf den konkreten Fall und Architektur an. Viel Erfolg
In dem Zusammenhang haben wir das oben genannte Volatile. Es verhindert aber nicht Konflikte bei gleichzeitigen Zugriff auf Mehr-byte Variablen. Da geht es um was anderes: Man (auch der C Compiler) benutzt CPU Register so oft wie möglich, um langsamere RAM-Zugriffe zu vermeiden. Beispiel:
1 | int zaehler; |
2 | |
3 | void machwas_hundert_mal() |
4 | {
|
5 | for (i:=0; i<100; i++) |
6 | {
|
7 | mach_was(); |
8 | zaehler=zaehler+1; |
9 | }
|
10 | }
|
Hier wird die Variable "zaehler" im RAM nicht hundert mal geändert, sondern nur einmal nach dem Ende der Schleife. Sie wird auch nicht hundert mal gelesen. Wenn du jetzt den "zaehler" in einem anderen Thread (Interrupt) ausliest während die for-Schleife läuft, bekommst du einen veralteten Wert. Wenn du den Zähler im anderen Thread änderst, geht diese Änderung am Ende der for-Schleife verloren, sie wird einfach überschrieben! Volatile verhindert das.
1 | volatile int zaehler; |
Nun wird die Variable innerhalb der for-Schleife tatsächlich immer wieder aus dem RAM gelesen, erhöht und wieder zurück ins RAM geschrieben. Die Schleife läuft nun deutlich langsamer. Dein "Problem" aus der Eingangsfrage ist übrigens weder Mikrocontroller spezifisch noch hängt es von der Programmiersprache ab. Jedes PC Programm ist ebenso betroffen.
:
Bearbeitet durch User
Steve schrieb: > Kevin schrieb: >> Was ist unter diesen Voraussetzungen >> das schlimmste was passieren kann? > > Dass du kaputte Zahlen verarbeitest. > > Denn bei einem 32 Bit Integer würde ein (8 Bit) Mikrocontroller ganze 4 > Scheibzugriffe nacheinander im RAM machen. Wenn du dazwischen liest, > bekommst du ein paar alte mit ein paar neuen Bits vermischt. Das ist interessant. Daran hatte ich nicht gedacht. Kann man annehmen, das auf einem 32Bit Controller der Schreibzugriff auf eine (8/16/32 Bit) Variablen immer atomar erfolgt. Oder kann der Interrupt auch genau im Schreiben erfolgen?
der_eine schrieb: > kritisch sind stets Schreib- und Lesezugriffe, welche mehr als einen > Assemblerbefehl benötigen. Danke, beantwortet meine Frage siehe oben, schon ziemlich gut.
Benutzt man das ATOMIC_BLOCK Macro wird der Zugriff auch nicht wegoptimiert, d.h. volatile mit seinen Nachteilen ist unnötig.
Kevin schrieb: > Kann man annehmen, das auf einem 32Bit Controller der Schreibzugriff > auf eine (8/16/32 Bit) Variablen immer atomar erfolgt. Meistens, aber nicht immer. Denn die meisten 32 Bit CPUs können auch in kleineren Einheiten auf das RAM zugreifen. Ich bin nicht sicher, ob man sich darauf verlassen kann, dass 32 Bit Variablen immer am Stück gelesen und geschrieben werden. Hängt sicher auch vom Compiler und dessen Optionen ab, nicht nur von der CPU.
Peter D. schrieb: > Benutzt man das ATOMIC_BLOCK Macro wird der Zugriff auch nicht > wegoptimiert, d.h. volatile mit seinen Nachteilen ist unnötig. Schaltet nur die Interrupts bei AVR ab. Trotzdem brauchst Du volatile.
Wilhelm M. schrieb: > Schaltet nur die Interrupts bei AVR ab. nicht nur. ATOMIC_BLOCK enthält auch ein _asm_ volatile ("" ::: "memory"); also eine memory barrier. d.H. alle Variablen, die im ATOMIC_BLOCK geändert werden, sind vor dem Re-Aktivieren der ISRs auch wirklich geschrieben.
Steve schrieb: > Kevin schrieb: >> Kann man annehmen, das auf einem 32Bit Controller der Schreibzugriff >> auf eine (8/16/32 Bit) Variablen immer atomar erfolgt. > > Meistens, aber nicht immer. Denn die meisten 32 Bit CPUs können auch in > kleineren Einheiten auf das RAM zugreifen. Ich bin nicht sicher, ob man > sich darauf verlassen kann, dass 32 Bit Variablen immer am Stück gelesen > und geschrieben werden. Hängt sicher auch vom Compiler und dessen > Optionen ab, nicht nur von der CPU. Probleme kann es bei Misaligmment geben, in gepackten Strukturen und in Bitfeldern.
Danke schonmal an alle. Ich habe mal nachgelesen.FreeRtos z.b., nutzt zur Synchronisation zwischen 2 Tasks Mutexe, jedoch zwischen Task und Interrupt Semaphore. Vielleicht kann man sich da was abgucken, wenn es nicht zu komplex implementiert ist.
(prx) A. K. schrieb: > Probleme kann es bei Misaligmment geben, in gepackten Strukturen und in > Bitfeldern. Was meinst du mit Misalignment?
Oje, nu kloppen sich die Spezis die Köppe ein. Dabei will der TO doch nur Fahrradfahren lernen und nicht gleich mit nem Euro-Fighter, auf seine Spatzen losgehen....
Kevin schrieb: > (prx) A. K. schrieb: >> Probleme kann es bei Misaligmment geben, in gepackten Strukturen und in >> Bitfeldern. > > Was meinst du mit Misalignment? Wenn die 4 Bytes nicht an einer Adresse %4==0 liegen, die Maschine einen solchen Zugriff nicht zulässt und der Compiler deshalb daraus mehrere Zugriffe machen muss.
Kevin schrieb: > Danke schonmal an alle. > > Ich habe mal nachgelesen.FreeRtos z.b., nutzt zur Synchronisation > zwischen 2 Tasks Mutexe, jedoch zwischen Task und Interrupt Semaphore. > Vielleicht kann man sich da was abgucken, wenn es nicht zu komplex > implementiert ist. Jetzt doch mit OS? Wenn Du nicht in Assembler programmierst (also etwa C/C++), dann weißt Du nicht, wie ein Objektzugriff gemacht wird. Du musst also vom Schlimmsten ausgehen, und das ist dann eine RMW-Folge. Also etwas nicht-atomares. Daher hast Du zwei Aufgaben: 1) Du musst Atomarität herstellen durch 1a) atomics (s.a. C/C++-Bibliothek), oder 1b) explizite kritische Bereiche mit wechselseitigem Ausschluss und 2) Du musst den Compiler für die gemeinsam genutzten Datenstrukten am Optimieren hindern. Das macht man bei C/C++ durch volatile-Deklaration. Bei den kritichen Bereichen musst Du noch zwischen bedingten und unbedingten KB unterscheiden. Für bedingte KB brauchst Du dann noch Bedingungsvariablen (ich meiner hier das Konzept, keine einfachen Flags oder so).
Teo D. schrieb: > Oje, nu kloppen sich die Spezis die Köppe ein. Dabei will der TO doch > nur Fahrradfahren lernen und nicht gleich mit nem Euro-Fighter, auf > seine Spatzen losgehen.... Seine Fragen sind qualifiziert genug um ihn nicht als Spielkind zu behandeln.
:
Bearbeitet durch User
Wilhelm M. schrieb: > Jetzt doch mit OS? Jetzt doch mit OS? Nein, FreeRtos war in meiner Internetsuche nur recht weit oben ;-). Und es ist recht interessant implementiert. Wilhelm M. schrieb: > Bei den kritichen Bereichen musst Du noch zwischen bedingten und > unbedingten KB unterscheiden. Was ist KB?
Εrnst B. schrieb: > Wilhelm M. schrieb: >> Schaltet nur die Interrupts bei AVR ab. > > nicht nur. ATOMIC_BLOCK enthält auch ein > _asm_ volatile ("" ::: "memory"); > > also eine memory barrier. d.H. alle Variablen, die im ATOMIC_BLOCK > geändert werden, sind vor dem Re-Aktivieren der ISRs auch wirklich > geschrieben. Nö.
1 | static __inline__ uint8_t __iCliRetVal(void) |
2 | {
|
3 | cli(); |
4 | return 1; |
5 | }
|
6 | |
7 | #define ATOMIC_BLOCK(type) for ( type, __ToDo = __iCliRetVal(); \
|
8 | __ToDo ; __ToDo = 0 )
|
Kevin schrieb: > Wilhelm M. schrieb: >> Jetzt doch mit OS? > > Jetzt doch mit OS? > Nein, FreeRtos war in meiner Internetsuche nur recht weit oben ;-). Und > es ist recht interessant implementiert. > > Wilhelm M. schrieb: >> Bei den kritichen Bereichen musst Du noch zwischen bedingten und >> unbedingten KB unterscheiden. > > Was ist KB? Kritischer Bereich: ein Code-Abschnitt, in dem wechselseitiger Ausschluss herrschen soll
Wilhelm M. schrieb: > Nö. Nö.
1 | static __inline__ void __iSeiParam(const uint8_t *__s) |
2 | {
|
3 | __asm__ __volatile__ ("sei" ::: "memory"); |
4 | __asm__ volatile ("" ::: "memory"); |
5 | (void)__s; |
6 | }
|
der Trick liegt im "type", da wird für die sreg-zwischenspeichervariable ein
1 | __attribute__((__cleanup__(__iSeiParam))) |
gesetzt.
:
Bearbeitet durch User
(prx) A. K. schrieb: > Wenn die 4 Bytes nicht an einer Adresse %4==0 liegen, die Maschine einen > solchen Zugriff nicht zulässt und der Compiler deshalb daraus mehrere > Zugriffe machen muss. Danke. Misalignment war mir schon klar, jetzt habe ich auch die Verbindung warum es in meinem betrachteten Fall zum Problem werden kann.
Εrnst B. schrieb: > > der Trick liegt im "type", da wird für die sreg-zwischenspeichervariable > ein >
1 | > __attribute__((__cleanup__(__iSeiParam))) |
2 | >
|
> gesetzt.
Ja, aber nur dafür.
Wilhelm M. schrieb: > Ja, aber nur dafür. Das ist eine "destruktor"-Funktion, die immer ausgeführt wird, wenn die Variable den scope verlässt. Hat den Sinn, dass auch bei einem
1 | ATOMIC_BLOCK(ATOMIC_FORCEON) { |
2 | ...
|
3 | if(x) return; // oder break |
4 | ...
|
5 | }
|
das "return" ein "sei" auslöst. Sonst wären vorzeitigen Verlassen des Blocks die Interrupts immer noch gesperrt. Die darin deklarierte barrier gilt für den gesamten RAM, nicht nur die eine Variable. das cli beim Betreten hat keine solche optimization barrier. d.H. der Compiler könnte zwar Berechnungen vor dem Atomic-Block in diesen hineinziehen, aber nichts aus dem Block herausnehmen. Nach Verlassen des Atomic Blocks ist jedenfalls sichergestellt, dass alle Variablen sauber in den RAM zurückgespeichert wurden.
Εrnst B. schrieb: > Nach Verlassen des Atomic Blocks ist jedenfalls sichergestellt, dass > alle Variablen sauber in den RAM zurückgespeichert wurden. Nö.
1 | #include <stdint.h> |
2 | #include <util/atomic.h> |
3 | |
4 | static /*volatile */ uint8_t x; |
5 | |
6 | int main() { |
7 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { |
8 | x = 0; |
9 | }
|
10 | }
|
ergibt
1 | main:
|
2 | in r24,__SREG__ ; _1, MEM[(volatile uint8_t *)63B] |
3 | cli
|
4 | out __SREG__,r24 ; MEM[(volatile uint8_t *)63B], _1 |
5 | ldi r24,0 ; |
6 | ldi r25,0 ; |
7 | ret
|
Wilhelm M. schrieb: > Nö. Warum Nö? Dein Beispiel bestätigt doch 1:1 was ich geschrieben habe. Nur dass der Compiler "x" eben ganz wegoptimiert hat. Darf er, wird ja nie wieder gelesen. Pack in dein Beispiel ans Ende noch ein "return x", dann siehst du exakt, dass es zuerst in den RAM geschrieben wird, und für's return auch wieder aus dem RAM gelesen wird.
1 | main: |
2 | in r24,__SREG__ |
3 | cli |
4 | sts x,__zero_reg__ |
5 | out __SREG__,r24 |
6 | lds r24,x |
7 | ldi r25,0 |
8 | ret |
Selben Effekt hast du auch, wenn "x" nicht static ist.
:
Bearbeitet durch User
Εrnst B. schrieb: > Warum Nö? Dein Beispiel bestätigt doch 1:1 was ich geschrieben habe. > Nur dass der Compiler "x" eben ganz wegoptimiert hat. Darf er, wird ja > nie wieder gelesen. Du sagst, dass im ATOMIC_BLOCK alle(!) dort zugegriffenen Variablen automatich volatile wären. Wie Du siehst, stimmt diese Aussage nicht! Wenn es volatile wäre, dürfte er den Zugriff auf x nicht wegoptimieren. Du kannst Dich davon leicht überzeugen, indem Du in meinem Beispiel einfach mal die volatile Deklaration einkommentierst.
Wilhelm M. schrieb: > Du sagst, dass im ATOMIC_BLOCK alle(!) dort zugegriffenen Variablen > automatich volatile wären. Wie Du siehst, stimmt diese Aussage nicht! Das habe ich NIE behauptet. Es geht ja gerade darum, dass die Variablen NICHT Volatile werden müssen, weil der Atomic-Block das Rückschreiben erzwingt. Damit ist das übliche Problem von "Variable wird in ISR und main verwendet" in den üblichen Fällen erschlagen, OHNE dass man sich die anderen Nachteile von volatile einfängt.
Εrnst B. schrieb: > Wilhelm M. schrieb: >> Du sagst, dass im ATOMIC_BLOCK alle(!) dort zugegriffenen Variablen >> automatich volatile wären. Wie Du siehst, stimmt diese Aussage nicht! > > Das habe ich NIE behauptet. Es geht ja gerade darum, dass die > Variablen NICHT Volatile werden müssen, weil der Atomic-Block das > Rückschreiben erzwingt. Damit ist das übliche Problem von "Variable wird > in ISR und main verwendet" in den üblichen Fällen erschlagen, *OHNE* > dass man sich die anderen Nachteile von volatile einfängt. Schau Dir folgendes an
1 | #include <stdint.h> |
2 | #include <util/atomic.h> |
3 | |
4 | static /*volatile */ uint8_t x; |
5 | |
6 | ISR( TIMER2_OVF_vect ) { |
7 | uint8_t y = x; |
8 | }
|
9 | |
10 | int main() { |
11 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { |
12 | x = 0; |
13 | }
|
14 | }
|
Ergibt:
1 | __RAMPZ__ = 0x3b |
2 | __CCP__ = 0x34 |
3 | .text |
4 | .type TIMER2_OVF_vect, @function |
5 | TIMER2_OVF_vect: |
6 | __gcc_isr 1 ; |
7 | __gcc_isr 2 ; |
8 | reti
|
9 | __gcc_isr 0,r0 |
10 | .size TIMER2_OVF_vect, .-TIMER2_OVF_vect |
11 | .section .text.startup,"ax",@progbits |
12 | .type main, @function |
13 | main: |
14 | in r24,__SREG__ ; _1, MEM[(volatile uint8_t *)63B] |
15 | cli
|
16 | out __SREG__,r24 ; MEM[(volatile uint8_t *)63B], _1 |
17 | .L3: |
18 | rjmp .L3 ; |
19 | .size main, .-main |
Atomarität und Optimierungssperre (ggf. durch volatile) sind zwei unterschiedliche Dinge.
:
Bearbeitet durch User
Wilhelm M. schrieb: > Wenn es volatile wäre, dürfte er den Zugriff auf x nicht wegoptimieren. Dein Beispiel ist allerdings sehr speziell, da es keine Loop enthält. Typisch wird bei MC-Anwendungen das Main nie verlassen. Ich wüßte jedenfalls nicht, wie dann eine sinnvolle Anwendung zustande kommen soll. Außerdem sagst Du mit dem static, daß die Variable nirgends anders zugegriffen werden kann. Mach ne Loop ins Main, nimm das static weg, dann erfolgt auch die Zuweisung.
Wilhelm M. schrieb: > Schau Dir folgendes an Wieder ein Beispiel, was meine Aussagen belegt bzw. zumindest nicht widerlegt. In dem ASM-Code, den du zeigt, findet keinerlei nicht-synchronisierter Zugriff auf "uint8_t x" statt. Exakt das, was der Atomic_block erreichen soll. QED.
:
Bearbeitet durch User
Man kann aber auch im Main auf volatile casten. Dann wird im Main der Zugriff erzwungen und im Interrupt kann die Variable weiterhin optimiert werden.
1 | #define IVAR(x) (*(volatile typeof(x)*)&(x))
|
Ich würde in der Interruptroutine keine Berechnungen oder andere komplexe Aufgaben durchführen. Die Interruptfunktionen nur füe IO-Operationen verwenden. Z.B. Wert von einem Port abholen und in ein FIFO schreiben und dem Hintergrund mittels Flag signalisieren das etwas im FIFO abholbar ist. Interrupt nur verwenden wenn die Gefahr besteht etwas im Hintergrund zu verpassen. Ist der Hintergrund fertig, dann kann er zum Energiesparen, den Sleepmodus aktivieren. Dieser kann in einer Interruptroutine wieder deaktiviert werden. Kurz eine Bemerkung zum FIFO: Die Interruptroutine hat alleinigen Zugriff zum Schreibzeiger, der Hintergrund alleinigen Zugriff zum Lesezeiger. So kommen sich Interrupt und Hintergrund nicht in die Quere.
:
Bearbeitet durch User
Gerald K. schrieb: > Die Interruptroutine hat alleinigen Zugriff zum Schreibzeiger, der > Hintergrund alleinigen Zugriff zum Lesezeiger. Beim Sende-FIFO dann umgekehrt.
Kevin schrieb: > Kann man annehmen, > das auf einem 32Bit Controller der Schreibzugriff auf eine (8/16/32 Bit) > Variablen immer atomar erfolgt. Nein, das kann man nicht. Es ist zwar der Regelfall, aber, wie bei jeder Regel: es gibt auch viele Ausnahmen. Diese Ausnahmen sind sehr architekturspezifisch. Wobei hier "Architektur" mehr umfasst, als das, was man üblicherweise darunter versteht. Neben der CPU/MCU selber nämlich auch noch die konkrete Schaltung, in der sie steckt.
c-hater schrieb: > Neben der CPU/MCU selber nämlich auch noch die konkrete Schaltung, in > der sie steckt. Wobei eine Aufteilung auf mehrere Zugriffe im Businterface für Interrupts innerhalb eines Cores atomar bleibt.
:
Bearbeitet durch User
(prx) A. K. schrieb: > Wobei eine Aufteilung auf mehrere Zugriffe im Businterface für > Interrupts innerhalb eines Cores atomar bleibt. Das kannst du für jede Architektur garantieren?
c-hater schrieb: > Das kannst du für jede Architektur garantieren? Bei Mikrocontrollern mit einem Core bin ich mir da ziemlicher sicher.
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.