Forum: Compiler & IDEs In ISR wird pointer nicht gescheit gesetzt?


von Paul H. (powl)


Lesenswert?

Hi!

Ich bin mit meinem Latein nach 2 Stunden sinnlosem rumprobieren mal 
wieder am Ende. Das ganze soll ein Lauflicht mit verschiedenen 
Leuchtszenen werden. Die 4 LEDs hängen an PortB. Der Pointer 
currentSceneAdress will in der ISR einfach nicht gesetzt werden, man 
sieht aber anhand des Verhaltens der LEDs, dass currentStep erfolgreich 
auf 0 zurückgesetzt, also die ISR richtig ausgeführt wird.

wenn ich den Codeteil der ISR in die while-Schleife der main-function 
verfrachte, dann funktioniert es, also geh ich mal davon aus, dass der 
Pointer in der ISR nicht richtig neu gesetzt wird. Aber warum? Sieht 
jemand einen Fehler? Immer wieder deprimierend wie man sich an solchen 
komischen Dingen aufhält.

Der Code ist bis aufs mindeste reduziert.
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
volatile uint8_t counter_lightdelay;
7
volatile uint16_t counter_lightshow;
8
9
volatile uint8_t currentScene;
10
volatile uint8_t *currentSceneAdress;
11
volatile uint8_t currentStep;
12
13
14
const uint8_t scene1[] PROGMEM = {
15
(0b1000 << 4) | 10,
16
(0b0100 << 4) | 10,
17
(0b0010 << 4) | 10,
18
(0b0001 << 4) | 10,
19
0};
20
21
const uint8_t scene2[] PROGMEM = {
22
(0b1100 << 4) | 15,
23
(0b0110 << 4) | 15,
24
(0b0011 << 4) | 15,
25
(0b1001 << 4) | 15,
26
0};
27
28
const uint8_t scene3[] PROGMEM = {
29
(0b1111 << 4) | 1,
30
(0b0000 << 4) | 15,
31
(0b1111 << 4) | 1,
32
(0b0000 << 4) | 4,
33
0};
34
35
const uint8_t *lightshow[] PROGMEM = {
36
  scene1,
37
  scene2,
38
  scene3
39
};
40
41
42
int main(void)
43
{
44
  uint8_t temp;
45
46
  DDRB = 0b00001111;
47
48
  TCCR1B = (1 << CS12) | (1 << CS11) | (1 << CS10);
49
  TIMSK = (1 << TOIE1);
50
51
  currentSceneAdress = pgm_read_word(&lightshow[0]);
52
  currentScene++;
53
54
  sei();
55
56
  while(1)
57
  {
58
    if(counter_lightdelay)
59
    {
60
      counter_lightdelay--;
61
    }
62
    else
63
    {
64
      temp = pgm_read_byte(currentSceneAdress + currentStep);
65
66
      if(!temp)
67
      {
68
        currentStep = 0;
69
        temp = pgm_read_byte(currentSceneAdress);
70
      }
71
      currentStep++;
72
73
      counter_lightdelay = temp & 0b00001111;
74
      PORTB = temp >> 4;
75
    }
76
77
    _delay_ms(20);
78
  }
79
}
80
81
82
ISR(TIMER1_OVF1_vect)
83
{
84
  counter_lightshow++;
85
  if(counter_lightshow == 900)
86
  {
87
    counter_lightshow = 0;
88
89
    currentSceneAdress = pgm_read_word(&lightshow[currentScene]);
90
    currentStep = 0;
91
92
    currentScene++;
93
  }
94
}

lg PoWl

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Such mal nach "atomarer Zugriff" oder "atomic access"

von Paul H. (powl)


Angehängte Dateien:

Lesenswert?

danke, ich such mal danach. Habe übrigens meinen Code mal etwas 
auskommentiert, damit sich besser darin zurecht gefunden wird.

von Paul H. (powl)


Lesenswert?

Mit Atomarem Zugriff meinst du nicht zufällig, dass es da einen konflikt 
zwischen Auslesen in der Main-Function und neu Setzen des Pointers in 
der ISR gibt? Das würde aber dann mehr oder weniger zufällig passieren, 
das setzen des Pointers klappt nie. Er springt einfach nicht zur 
nächsten Szene, wie als könnte er auf den Pointer da nicht zugreifen 
aber das ist ja irgendwie auch quatsch. Das ist ein µC, da gibts keine 
Speicherbereiche wo irgendein Befehl nicht drauf zugreifen kann, muss 
irgendwie am C-Code liegen.

Allerdings habe ich den Pointer ja als volatile deklariert, somit müsste 
er auch von der ISR raus zugänglich sein :-(

lg PoWl

von Oliver (Gast)


Lesenswert?

Warum untersuchst du das nicht mal im Simulator? Die Methode "scharfes 
Hinsehen" ist zwar nett, aber wie du selber merkst, kommt man damit 
nicht immer weiter. Für dein Problem reicht der AVR-Studio-Simulator. Am 
besten alle delays vorher auskommentieren oder verkleinern, dann einen 
breakpoint in die ISR, und laufen lassen.

Sehr zu empfehlen ist auch VMLAB. Am Anfang etwas gewöhnungsbedürftig, 
und miserabel dokumentiert (da nicht fertig), aber wenn es dann mal 
läuft, bekommst du einen ganz anderen Einblick in deine Programme.

Oliver

von Stefan E. (sternst)


Lesenswert?

Paul Hamacher wrote:

> Allerdings habe ich den Pointer ja als volatile deklariert, somit müsste
> er auch von der ISR raus zugänglich sein :-(

Nein, hast du nicht. Der Pointer selber ist nicht volatile, sondern nur 
das, worauf er zeigt.

volatile uint8_t *currentSceneAdress;
->
uint8_t* volatile currentSceneAdress;

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ist eben noch ein Fehler mehr.

Nicht-atomarer Zugriff führt zu fiesen, sporadischen Fehlern, die in 
einem Simulator kaum nachvollziehbar sind (es sei denn, das 
Echtzeitverhalten bleibt unberührt).

http://www.roboternetz.de/wissen/index.php/Fallstricke_bei_der_C-Programmierung#Nicht-atomarer_Code

von Paul H. (powl)


Lesenswert?

Danke @ Stefan Ernst,

das hat das Problem gelöst :-)

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.