Variabel nicht in ISR Routine?

Gast #7037184
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
}
Gast #7037202
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)
Gast #7038161
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...
Gast #7038192
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.
Gast #7038227
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
Gast #7038231
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.
Gast #7038244
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.
Gast #7038251
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)
Gast #7038254
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!".
#7038255
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?
Gast #7038257
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 ...
#7038262
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".
Gast #7038265
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)...
#7038277
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?
Gast #7038281
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.
Gast #7038285
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.
Gast #7038289
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...
Gast #7038290
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
Gast #7038301
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".
#7038306
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.
#7038308
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren