Forum: Mikrocontroller und Digitale Elektronik Variabel nicht in ISR Routine?


von Tom (Gast)


Lesenswert?

Hallo,
teste gerade mit Timer0 in der Arduino Umgebung (Servo bewegen). Wegen 
Doppelnutzung des Timers (Stichwort delay und millis()) löse ich mich 
teilweise vom Arduino Framework - die Software soll später auf einen 
Tiny85 portiert werden.
Ziel ist mit dem Timer0 125µs Raster zu erzeugen; nach einer Anzahl von 
n Pulsen (Übergeben in pulsWeite) wird der Pin wieder abgeschalten.
Als Nebenkriegsschauplatz habe ich nun folgenden Effekt:obwohl die 
Variable pulsWeite definiert ist, wird der Wert nicht in die ISR Routine 
übergeben.
Schreibe ich den Wert fest in der ISR Routine rein (statt in Variable) 
funktioniert's prinzipiell
liegt das an der Art der Definition der Variable oder habe ich ein 
Verständnisproblem?


1
// Arduino NANO
2
3
#define PIN_OUTPUT 4
4
int pulsCounter;
5
int pulsWeite;
6
int wartePuls;
7
8
int main() {
9
10
  pinMode(PIN_OUTPUT, OUTPUT);
11
12
  // put your setup code here, to run once:
13
  Serial.begin(38400);
14
  TCCR0A = 0x00; //Normal mode
15
  TCCR0B = 0x00;
16
  TCCR0B |= (0 << CS02) | (1 << CS01) | (0 << CS00); //prescaling with 1024
17
18
  TCNT0 = 0x00;
19
  TIMSK0 |= (1 << TOIE0); //enabling timer0 interrupt
20
  sei(); //enabling global interrupt
21
22
23
  while (1) {
24
25
    wartePuls = 0;
26
    pulsWeite = 8;
27
    while (wartePuls << 4000) {}
28
29
30
  }
31
}
32
33
ISR(TIMER0_OVF_vect) { //125µs Raster
34
  pulsCounter++;
35
  wartePuls++;
36
  if (pulsCounter > (8 * 20)) {
37
    pulsCounter = 0;
38
  }
39
40
  if (pulsCounter == 0) {
41
    digitalWrite(PIN_OUTPUT, HIGH);
42
  }
43
  //if (pulsCounter == pulsWeite) {
44
  if (pulsCounter == pulsWeite) {
45
    digitalWrite(PIN_OUTPUT, LOW);
46
  }
47
  // digitalWrite(PIN_OUTPUT,!digitalRead(PIN_OUTPUT)); //erzeugt 125µSs Puls
48
49
}

von Walter T. (nicolas)


Lesenswert?

Lerne die Magie von "volatile"!

(Mit dem Stichwort findest Du alles, was Du dazu wissen musst.)

von Tom (Gast)


Lesenswert?

Walter T. schrieb:
> Lerne die Magie von "volatile"!

Magie! Danke, läuft!!

An der richtigen Stelle nachgelesen ist zu finden:
"[...]Eine Variable sollte immer dann als „volatile“ deklariert werden, 
wenn ihr Wert durch ein Ereignis
beeinflusst werden kann, welches außerhalb des Codes stattfindet, in dem 
sie sich befindet. Das kann z.B.
eine gleichzeitig aufgerufene Funktion sein. Im ARDUINO – die einzige 
Funktion, die so etwas kann, ist
eine Interrupt-Funktion, genannt Interrupt Service Routine [..]" 
(Quelle: Arduino Befehlsübersicht, A.Nagel 2020)

von c-hater (Gast)


Lesenswert?

Tom schrieb:

> "[...]Eine Variable sollte immer dann als „volatile“ deklariert werden,
> wenn ihr Wert durch ein Ereignis
> beeinflusst werden kann, welches außerhalb des Codes stattfindet, in dem
> sie sich befindet. Das kann z.B.
> eine gleichzeitig aufgerufene Funktion sein. Im ARDUINO – die einzige
> Funktion, die so etwas kann, ist
> eine Interrupt-Funktion, genannt Interrupt Service Routine [..]"

Wie jede Vereinfachung, so stößt auch diese irgendwann auf ihre Grenzen.

So, wie es geschrieben ist, passt es auschließlich auf die 
"Ur-Arduinos", also AVR8-MCUs. Im konkreten Fall ist sowas tatsächlich 
das Target, deshalb passt es hier.

Aber schon seit sehr langer Zeit gibt es auch Arduinos mit mehr 
Hardware-Power. Sei es nur durch DMA oder (in etwas neuerer Zeit auch 
durch Multi-Core-MCUs).

Da passt das dann schon nicht mehr. Da hat man einerseits Sachen, wo 
"volatile" auch nötig wird, ohne dass eine ISR beteiligt ist, 
andererseits aber auch Sachen, wo "volatile" allein noch nicht genügt.

Reine Arduidioten sind hier völlig überfordert. Das ist so und das wird 
voraussichtlich auch so bleiben. Die begreifen die dahinter steckenden 
Probleme schon nicht, geschweige denn das völlig abstruse 
Syntax-Geschwalle von C/C++ zu deren Lösung. Mein Gott, letzteres fällt 
ja sogar Leuten schwer, die mit dem Verständnis der Hardware keinerlei 
Probleme haben...

C/C++ als Sprache für erwartete Nicht-Programmierer zu wählen, war wohl 
sicher nicht die weiseste Wahl der Arduino-System-Erfinder...

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> völlig überfordert... Mein Gott

Überall um dich herum sind Geisterfahrer.

von Heiner (Gast)


Lesenswert?

c-hater schrieb:

> Reine Arduidioten sind hier völlig überfordert.

Hallo c-hater

Was Du an fachlicher Kompetenz hast, fehlt Dir an zwischenmenschlicher.
Schade.

von c-hater (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> c-hater schrieb:
>> völlig überfordert... Mein Gott
>
> Überall um dich herum sind Geisterfahrer.

Nicht alle, aber doch >>99%. So z.B. der TO dieses Threads. Und die TOs 
vieler anderen Threads (nicht nur dieses Forums).

Können so viele Idioten so einheitlich darstellen, dass sie Idioten 
sind, ohne sich abgesprochen zu haben? Nein, können sie nicht. Diese 
geordnete und statistisch überaus signifikante Sammelvorstellung wird 
allein durch das Arduino-Konzept erzeugt.

Das mag dir nicht gefallen, ist aber die reine Wahrheit. Jederzeit nach 
wissenschaftlichen Kriterien ermittel- und darstellbar.

von Mombert H. (mh_mh)


Lesenswert?

c-hater schrieb:
> Das mag dir nicht gefallen, ist aber die reine Wahrheit. Jederzeit nach
> wissenschaftlichen Kriterien ermittel- und darstellbar.
Das hört sich ziemlich stark nach Glauben an. Hier ist die reine 
Wahrheit™, Fakten™ gibts später.

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

Bei 8-Bittern reicht ein volatile nicht, um Zugriffe auf 
größer-8-Bit-Variablen (wie int) interruptsicher zu machen!

von Mombert H. (mh_mh)


Lesenswert?

foobar schrieb:
> Bei 8-Bittern reicht ein volatile nicht, um Zugriffe auf
> größer-8-Bit-Variablen (wie int) interruptsicher zu machen!

Auch bei 64-Bittern ist ein volatile nicht immer ausreichen, um Zugriffe 
auf 8-Bit Variablen interruptsicher zu machen.

von c-hater (Gast)


Lesenswert?

foobar schrieb:

> Bei 8-Bittern reicht ein volatile nicht, um Zugriffe auf
> größer-8-Bit-Variablen (wie int) interruptsicher zu machen!

Das ist vollkommen korrekt.

von Sebastian (Gast)


Lesenswert?

Tom schrieb:
> Magie! Danke, läuft!!

Noch zwei Anmerkungen, Tom.

Erstens ist das digitalWrite des Arduino recht aufwendig und benötigt 
selbst einige us zur Ausführung; direkte Portzugriffe dagegen brauchen 
nur wenige Takte.

Und zweitens sind deine in ISR und regulärem Kontext benutzten Variablen 
als int deklariert. Der Atmega328P des Arduino Nano ist aber ein 8-Bit 
Controller, Zugriffe auf ein int sind also nicht atomar. Es muss daher 
bei allen Schreiboperationen auf diese Variablen die potentiell mehr als 
ein Byte ändern verhindert werden dass die ISR "dazwischen" ausgeführt 
wird und einen seltsamen Inhalt vorfindet. volatile macht das nicht!

LG, Sebastian

von EAF (Gast)


Lesenswert?

Ach, lasst den c-hater mal in Ruhe...
Sein Hass macht ihn so verblendet, dass er vergisst, dass er das mit dem 
Volatile auch mal lernen musste.

Zudem ist er auf dem Gebiet C++, herzerfrischend Kenntnisfrei.
Also einer der Letzten, dessen Urteil man vertrauen sollte.

von Mombert H. (mh_mh)


Lesenswert?

EAF schrieb:
> Ach, lasst den c-hater mal in Ruhe...
> Sein Hass macht ihn so verblendet, dass er vergisst, dass er das mit dem
> Volatile auch mal lernen musste.
Wenn es nur um ihn gehen würde, könnte ich dir zustimmen. Es gibt aber 
andere Forenteilnehmer, die ernst nehmen könnten was er geschrieben hat.

von c-hater (Gast)


Lesenswert?

foobar schrieb:

> Bei 8-Bittern reicht ein volatile nicht, um Zugriffe auf
> größer-8-Bit-Variablen (wie int) interruptsicher zu machen!

Das ist schon wieder so eine Sache, die typische Arduidioten nicht 
verstehen. Das ist schlicht ein anderes Problem.

Das eine ist, die Konsistenz einer Variablen in der nativen 
("elementaren") Größe sicher zu stellen. Dafür ist "volatile" zuständig, 
kann das aber nicht immer leisten. Beim AVR8 (ohne XMega)  aber kann es 
das aber noch. Ist ja auch eine ziemlich primitive Architektur...

Ein anderes Problem ist, die Konsistenz eine Variablen sicher zu 
stellen, die größer ist als "elementar". Das kann "volatile" alleine 
nicht mal für AVR8 leisten.

von c-hater (Gast)


Lesenswert?

EAF schrieb:

> Zudem ist er auf dem Gebiet C++, herzerfrischend Kenntnisfrei.

Das glaubst du wirklich?

von Oliver S. (oliverso)


Lesenswert?

Mombert H. schrieb:
> Es gibt aber
> andere Forenteilnehmer, die ernst nehmen könnten was er geschrieben hat.

Rein fachlich sollten die das auch tun.

Oliver

von re (Gast)


Lesenswert?

foobar schrieb:
> Bei 8-Bittern reicht ein volatile nicht, um Zugriffe auf
> größer-8-Bit-Variablen (wie int) interruptsicher zu machen!
Mombert H. schrieb: [... interruptsicher ...]
c-hater schrieb: [... Das ist vollkommen korrekt 
...]

Sebastian schrieb:
> Es muss daher [...] verhindert werden dass die ISR dazwischen ausgeführt
> wird


Natürlich ist es extrem unsportlich, dem TE nun auch zu sagen, wie man 
das beim AVR machen kann, ohne Mutexe zu benutzen ;-)

| uint8_t a=SREG;
| cli();
| [hier die volatile Variable auswerten oder umkopieren - nicht mehr]
| SREG=a;

HTH
(re)

von foobar (Gast)


Lesenswert?

> Das eine ist, die Konsistenz einer Variablen in der nativen
> ("elementaren") Größe sicher zu stellen. Dafür ist "volatile"
> zuständig,

Nicht mal das.  Volatile ist sehr vage definiert und heißt grob gesagt 
nur: "Optimizer, lass deine Finger von diesen Zugriffen!".

von Mombert H. (mh_mh)


Lesenswert?

Oliver S. schrieb:
> Mombert H. schrieb:
>> Es gibt aber
>> andere Forenteilnehmer, die ernst nehmen könnten was er geschrieben hat.
>
> Rein fachlich sollten die das auch tun.
>
> Oliver
Zählt es als "rein fachlich" den TO als Geisterfahrer zu bezeichnen? 
Gibt es eine wissenschaftlich beweisbahre reine Wahrheit, die eine 
statisch signifikante Sammelvorstellung enthält, die durch das 
Arduino-Konzept erzeugt wird?

von foobar (Gast)


Lesenswert?

> Natürlich ist es extrem unsportlich, dem TE nun auch zu sagen, wie man
> das beim AVR machen kann, ohne Mutexe zu benutzen ;-)

Das wird in den von ihm gefundenen Artikeln über volatile bestimmt schon 
gesagt worden sein - hat er wohl nur nicht berücksichtigt.

Btw, Interrupts sperren ist nur eine Methode ...

von Oliver S. (oliverso)


Lesenswert?

foobar schrieb:
> Nicht mal das.  Volatile ist sehr vage definiert und heißt grob gesagt
> nur: "Optimizer, lass deine Finger von diesen Zugriffen!".

Nein, primär heißt das was ganz anderes.

Oliver

von Mombert H. (mh_mh)


Lesenswert?

Oliver S. schrieb:
> foobar schrieb:
>> Nicht mal das.  Volatile ist sehr vage definiert und heißt grob gesagt
>> nur: "Optimizer, lass deine Finger von diesen Zugriffen!".
> Nein, primär heißt das was ganz anderes.
> Oliver
Was ist den dieses "was ganz anderes"?
Der Standard sagt:
1
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the
2
abstract machine, except as modified by the unknown factors mentioned previously. What constitutes an access to an object that has volatile-qualified type is implementation-defined.
Ich sehe da nicht viel Platz für "was ganz anderes".

von c-hater (Gast)


Lesenswert?

Mombert H. schrieb:

> Zählt es als "rein fachlich" den TO als Geisterfahrer zu bezeichnen?

Das hat wer getan? Niemand. Der einzige, der mit dem Begriff hantiert 
hat, war der gute Stefan S. Und der hat ihn nur auf mich angewandt, 
nicht auf den TO oder gar die anderen Arduidioten.

Du solltest vielleicht mal lernen, Zitate korrekt zu lesen (und damit 
dann auch gleich: korrekt zu zitieren)...

von Mombert H. (mh_mh)


Lesenswert?

c-hater schrieb:
> Mombert H. schrieb:
>> Zählt es als "rein fachlich" den TO als Geisterfahrer zu bezeichnen?
> Das hat wer getan? Niemand. Der einzige, der mit dem Begriff hantiert
> hat, war der gute Stefan S. Und der hat ihn nur auf mich angewandt,
> nicht auf den TO oder gar die anderen Arduidioten.
> Du solltest vielleicht mal lernen, Zitate korrekt zu lesen (und damit
> dann auch gleich: korrekt zu zitieren)...
Zum "korrekt" lesen: Wie soll man das lesen?
c-hater schrieb:
> Stefan ⛄ F. schrieb:
>> c-hater schrieb:
>>> völlig überfordert... Mein Gott
>> Überall um dich herum sind Geisterfahrer.
> Nicht alle, aber doch >>99%. So z.B. der TO dieses Threads. Und die TOs
> vieler anderen Threads (nicht nur dieses Forums).
Wenn ich es nicht so verstanden habe wie du es gemeint hast, solltest du 
auch drüber nachdenken, ob du deine Meinung für andere verständlich in 
Worte gefasst hast.

Zum "korrekt" zitieren: Wie zitiert man hier korrekt?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Mombert H. schrieb:
> Es gibt aber andere Forenteilnehmer,
> die ernst nehmen könnten was er geschrieben hat.

Wen nimmt denn Leute mit so einer Wortwahl ernst?

von c-hater (Gast)


Lesenswert?

Oliver S. schrieb:

> Nein, primär heißt das was ganz anderes.

Genau. Das heißt nix anderes als: lies' es (erneut) von der Adresse im 
RAM-Space, verlaß' dich nicht auf das, was du früher mal aus derselben 
Stelle des RAM-Space gelesen (und in irgendwelchen MCU-Registern 
zwischengelagert) hast.

Das löst halt das Problem, das effizienter Code bevorzugt mit Werten in 
MCU-Registern hantiert, weil das viel schneller geht. Die Register sind 
also aus der Sicht von Hochsprachen eine Art Cache. Und haben naturgemäß 
die Probleme jedes Cache: er könnte bereits ungültig sein, wenn man ihn 
benutzt.

"volatile" sorgt nun dafür, das bei jedem Lesezugriff erneut die Daten 
aus dem RAM-Space in den Registercache gelesen werden. Das macht den 
Code langsamer, aber sorgt halt dafür, dass es den aktuellen Datenstand 
benutzt, wenn dieser zwischenzeitlich durch alternative Mechanismen 
geändert wurde.

von c-hater (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:

> Wen nimmt denn Leute mit so einer Wortwahl ernst?

Leute, die weiter denken können als du. So hoffe ich zumindest...

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> "volatile" sorgt nun dafür, das bei jedem Lesezugriff erneut die Daten
> aus dem RAM-Space in den Registercache gelesen werden.

Und umgekehrt werden alle Schreibzugriffe direkt ins RAM durchgeführt, 
nicht irgendwann später wenn die Funktion/Prozedur zu ende ist.

von c-hater (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:

> Und umgekehrt werden alle Schreibzugriffe direkt ins RAM durchgeführt,
> nicht irgendwann später wenn die Funktion/Prozedur zu ende ist.

Stimmt. Auch das ist wichtig und essentiell.

Mein Gott, du kannst doch offensichtlich auch faktenorentiert 
argumentieren. Warum machst du das nicht auch, wenn das "arduino"-Thema 
Thema ist...

von Sebastian (Gast)


Lesenswert?

c-hater schrieb:
> "volatile" sorgt nun dafür,

Für einen c-hater sehr gut beschrieben.

c-hater schrieb:
> faktenorentiert argumentieren. Warum machst du das nicht auch, wenn das
> "arduino"-Thema Thema ist

Der war nun lustig :)

Aber gut, ich bin auch einer der Arduidioten c-haters, auch wenn ich 
kritisches schon mal in Assembler schreibe ...

LG, Sebastian

von c-hater (Gast)


Lesenswert?

Sebastian schrieb:

> Aber gut, ich bin auch einer der Arduidioten c-haters, auch wenn ich
> kritisches schon mal in Assembler schreibe ...

Nö. Wenn du in der Lage bist, kritische Teile in Assembler zu schreiben, 
bist du definitiv eben NICHT in der Zielgruppen der Arduidioten. Oder 
freundlicher ausgedrückt: der "Arduino-Nutzer".

von Mombert H. (mh_mh)


Lesenswert?

c-hater schrieb:
> "volatile" sorgt nun dafür, das bei jedem Lesezugriff erneut die Daten
> aus dem RAM-Space in den Registercache gelesen werden. Das macht den
> Code langsamer, aber sorgt halt dafür, dass es den aktuellen Datenstand
> benutzt, wenn dieser zwischenzeitlich durch alternative Mechanismen
> geändert wurde.
Mit diesen paar Sätzen definierst du deutlich mehr in volatile hinein, 
als der Standard tatsächlich zusichert. Im Standard kommt kein RAM-Space 
und kein Registercache vor und er definiert ganz sicher nicht, was 
"aktuell" ist.

von Oliver S. (oliverso)


Lesenswert?

Mombert H. schrieb:
> und er definiert ganz sicher nicht, was
> "aktuell" ist.

Ob er das definiert, darüber könnte man geteilter Meinung sein. Keine 
Diskussion braucht es dagegen über die Tatsache, daß der Standard auch 
und gerade im Zusammenhang mit volatile die Begriffe „actual semantics“ 
und „actual objects“ dem Begriff „abstract semantics“ gegenüberstellt.

„8. Example: An implementation might define a one-to-one correspondence 
between abstract and actual semantics: at every sequence point, the 
values of the actual objects would agree with those specified by the 
abstract semantics. The keyword volatile would then be redundant.„

Oliver

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
Noch kein Account? Hier anmelden.