INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Falle bei lokalen Variablen
01.02.2020, 22:40
Beitrag #1
Falle bei lokalen Variablen
Hallo,

ich habe mehrere Stunden gebraucht, um folgenden Fehler zu finden: In einer Funktion zum Senden eine Zeichens über I2C hatte ich:

Code:
void sendeDATA0() {
  word RegisterWert;
  //  TWI_SR ist ein Register des Two-Wire-Interfaces des DUE
  ....
  do {
    RegisterWert = *TWI_SR & 0x04; // TXREADY
  }
  while (RegisterWert == 0);
  ...
}


Die Bedingung (RegisterWert==0) ist nie erfüllt (was nicht sein kann), die Schleife hängt.

Aber so geht es:

Code:
word RegisterWert;

void sendeDATA0() {
  //  TWI_SR ist ein Register des Two-Wire-Interfaces des DUE
  ....
  do {
    RegisterWert = *TWI_SR & 0x04; // TXREADY
  }
  while (RegisterWert == 0);
  ...
}


Offensichtlich optimiert der Compiler das wiederholte Lesen aus dem Register weg, weil er erkennt, dass der RegisterWert außerhalb der Schleife nie gebraucht wird. Wenn RegisterWert als globale Variable deklariert ist, dann liest er den Wert auf jeden Fall mehrfach ein, das ergibt sich aus dem Timing.

Vielleich hat ja jemend eine Anregung, wie man das (in der IDE) solider programmieren kann. Vielleicht ist ja der nächste Compiler noch schlauer und erkannt auch, dass die globale Variable nie gebraucht wird und optimiert wieder weg.

Grüße
GuaAck
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.02.2020, 23:14
Beitrag #2
RE: Falle bei lokalen Variablen
(01.02.2020 22:40)GuaAck schrieb:  Hallo,

ich habe mehrere Stunden gebraucht, um folgenden Fehler zu finden: In einer Funktion zum Senden eine Zeichens über I2C hatte ich:

Code:
void sendeDATA0() {
  word RegisterWert;
  //  TWI_SR ist ein Register des Two-Wire-Interfaces des DUE
  ....
  do {
    RegisterWert = *TWI_SR & 0x04; // TXREADY
  }
  while (RegisterWert == 0);
  ...
}


Die Bedingung (RegisterWert==0) ist nie erfüllt (was nicht sein kann), die Schleife hängt.

Aber so geht es:

Code:
word RegisterWert;

void sendeDATA0() {
  //  TWI_SR ist ein Register des Two-Wire-Interfaces des DUE
  ....
  do {
    RegisterWert = *TWI_SR & 0x04; // TXREADY
  }
  while (RegisterWert == 0);
  ...
}


Offensichtlich optimiert der Compiler das wiederholte Lesen aus dem Register weg, weil er erkennt, dass der RegisterWert außerhalb der Schleife nie gebraucht wird. Wenn RegisterWert als globale Variable deklariert ist, dann liest er den Wert auf jeden Fall mehrfach ein, das ergibt sich aus dem Timing.

Vielleich hat ja jemend eine Anregung, wie man das (in der IDE) solider programmieren kann. Vielleicht ist ja der nächste Compiler noch schlauer und erkannt auch, dass die globale Variable nie gebraucht wird und optimiert wieder weg.

Grüße
GuaAck

...also auf den ersten Blick fällt mir auf das du den Registerwert als word deklariert hast... aber word ist wohl auf dem DUE 32Bit breit bei den ATMegas wohl 16Bit... NUR 16 oder 32 Bit passen in ein I2C Register nicht rein...das dürfte bei allen Prozessoren 8 Bit haben... das werfe ich mal ein ohne nachzusehen.
lgbk

1+1 = 10 Angel ...und ich bin hier nicht der Suchmaschinen-Ersatz Dodgy...nur mal so als genereller Tipp..
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.02.2020, 23:25
Beitrag #3
RE: Falle bei lokalen Variablen
Zitat:...also auf den ersten Blick fällt mir auf das du den Registerwert als word deklariert hast... aber word ist wohl auf dem DUE 32Bit breit bei den ATMegas wohl 16Bit... NUR 16 oder 32 Bit passen in ein I2C Register nicht rein...das dürfte bei allen Prozessoren 8 Bit haben... das werfe ich mal ein ohne nachzusehen.
lgbk

Stimmt, RegisterWert hat 32 Bit, weil auch die Register im DUE (Atmel Sam3x) 32 Bit breit sind. Der Sam3X nutzt nur das letze Byte für Daten an oder vom I2C. Aber in anderen Registern (z. B. zum Status) werden auch die höheren Bits genutzt.

Gruß
GuaAck
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.02.2020, 23:26
Beitrag #4
RE: Falle bei lokalen Variablen
(01.02.2020 23:23)GuaAck schrieb:  ... Der Sam3X nutzt nur das letze Byte für Daten an oder vom I2C. Aber in anderen Registern (z. B. zum Status) werden auch die höheren Bits genutzt.
...

du meinst da jetzt die Statusregister vom I2C Interfacing ? Weil das andere Register 32 Bit beim DUE haben ist ja normal..

1+1 = 10 Angel ...und ich bin hier nicht der Suchmaschinen-Ersatz Dodgy...nur mal so als genereller Tipp..
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.02.2020, 23:46
Beitrag #5
RE: Falle bei lokalen Variablen
(01.02.2020 23:26)Bitklopfer schrieb:  
(01.02.2020 23:23)GuaAck schrieb:  ... Der Sam3X nutzt nur das letze Byte für Daten an oder vom I2C. Aber in anderen Registern (z. B. zum Status) werden auch die höheren Bits genutzt.
...

du meinst da jetzt die Statusregister vom I2C Interfacing ? Weil das andere Register 32 Bit beim DUE haben ist ja normal..

Ja genau,
Gruß
GuaAck
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
02.02.2020, 08:32
Beitrag #6
RE: Falle bei lokalen Variablen
Hallo,

auf den ersten Blick sehe ich nur, daß volatile fehlt.
Der Compiler weiß nichts davon, daß sich der Wert von TWI_SR von außen ändern kann.
Er liest das Register also einmal nur beim ersten Durchlauf der Schleife.
Also volatile word RegisterWert;

Gruß aus Berlin
Michael
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
02.02.2020, 09:25
Beitrag #7
Thumbs Up RE: Falle bei lokalen Variablen
Danke,

"volatile" scheint das gesuchte "Zauberwort" zu sein. Probiere ich heute Abend, bin aber nach der Beschreibung sicher, dass es dann geht.

Danke nochmal und viele Grüße
GuaAck
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
02.02.2020, 18:00
Beitrag #8
RE: Falle bei lokalen Variablen: Lösung gefunden
So geht es:
Code:
volatile word* TWI_SR =    (word*)0x4008C020; // HIER volatile!!!!

void sendeDATA0() {
  word RegisterWert;
  //  TWI_SR ist ein Register des Two-Wire-Interfaces des DUE
  ....
  do {
    RegisterWert = *TWI_SR & 0x04; // TXREADY
  }
  while (RegisterWert == 0);
  ...
}
Jetzt ist dem Compiler bekannt, dass TWR_SR (oder der Pointer darauf?) von extern verändert werden kann und er es deshalb immer einlesen muss.

Gruß
GuaAck
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Werte im Sketch in Variablen speichern Bitklopfer 4 230 06.09.2020 10:25
Letzter Beitrag: Bitklopfer
  map() mit Variablen anstatt Zahlen? Norman 15 1.035 16.05.2020 18:14
Letzter Beitrag: Norman
  Externes "Ansprechen" von Variablen xXIchbinannonymXx 3 681 20.11.2019 20:20
Letzter Beitrag: Tommy56
  Sleep Modus aktivieren (Reed-Switch Falle) Wochenendprogrammierer 20 2.640 01.07.2019 21:16
Letzter Beitrag: hotsystems
  Wasserverbrauchszähler, statische Variablen, komisches Verhalten in der loop() pzYsTorM 14 2.143 19.03.2019 20:33
Letzter Beitrag: Hilgi
  char in Variablen aufteilen fv1895 7 1.512 06.01.2019 11:59
Letzter Beitrag: Tommy56
  Variablen zu einem CHAR verbinden und einbinden Frank_aus_WOB 3 1.906 02.01.2019 09:07
Letzter Beitrag: Tommy56
  Verkettung von Variablen flint74 5 1.247 30.12.2018 14:33
Letzter Beitrag: Tommy56
  Variablen über Eingabe im Setup beschreiben heini320 3 1.124 30.12.2018 11:37
Letzter Beitrag: Tommy56
  Zentrale Variablen für verschiedene Klassen Smirgel 3 1.016 29.10.2018 21:24
Letzter Beitrag: Tommy56

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste