Forum: Compiler & IDEs Probleme mit SDCC-Snapshots > 3.6.0


von Vancouver (Gast)


Lesenswert?

Moin,

ich habe einige mysteriöse Probleme mit aktuellen SDCC snapshots für 
PIC14 (pic16f18xx). Um es gleich zu sagen: Ich weiß nicht genau, was 
nicht funktioniert und warum. Da Projekt ist mittlerweile recht komplex, 
und ich kann die Fehlerbedingung nicht so einfach isolieren. Ich möchte 
nur wissen, ob jemand von Euch schon mal ähnlichen Ärger mit aktuellen 
SDCCs hatte.

SDCC version ist 3.6.6-201705xx für Linux. Das Problem betrifft die 
aktuellen Snapshots mindestens
ab Mai. Bei 3.6.0 treten diese Fehler nicht auf.


1. In einer while(1)-Loop wird in einem switch-Statement eine globale 
Variable ausgewertet, die zuvor in einem Interrupt-Handler gesetzt wird. 
Es gibt maximal 16 verschiedene cases, aber nicht alle können in der 
aktuellen Version auftreten. Dennoch ist der Code dafür bereits 
vorbereitet, d.h es gibt einen case-Zweig, der aber nichts tut bzw. nur 
eine Debug-Message über den UART ausgäbe, falls der case eintreten 
würde. Mit diesem case-Zweig im Code läuft der PIC völlig ins Nirwana 
und tut garnichts. Wird der Case-Zweig auskommentiert, dann gehts. 
Wohlgemerkt: Der entsprechende case tritt niemals ein.

Es gab schon früher Probleme mit switch-Anweisungen, ich erinnere mich 
an eine kryptische Fehlermeldung mit einer "Evelyn" und einem "Dog", die 
ungefähr so hilfreich war wie ein Windows-Bluescreen. Diese Meldung 
kommt ab 3.6.x nicht mehr, stattdessen die beschriebene Fehlfunktion.

Sieht so aus, als gäbe es hier ein Problem mit der Jump-Table. Ich 
könnte eine If-Kaskade verwenden, aber das ist natürlich ineffizient.

Die SDCC-Doku ist hier etwas missverständlich. Müssen die Case-Zweige 
numerisch geordnet sein? Gibt es bei Switch-Anweisungen im SDCC etwas zu 
beachten, das ich nicht weiß?

2. Es gibt offenbar ein Problem mit dem Setzen und Lesen von Bitfields. 
Werden nacheinander zwei oder mehr Fields verändert, so ist das 
Ergebnis, sagen wir, indeterministisch. Das gleiche gilt wenn nach dem 
Schreiben sofort eine Leseoperation folgt. Das Problem gabs früher schon 
beim Setzen einzelner Portbits, aber jetzt anscheinend auch mit 
Bitfield-Variablen.


Ich hatte bisher eine recht hohe Meinung vom SDCC, aber mittlerweile bin 
ich etwas pissed. Warum ist der PIC-Port immernoch in so einem lausigen 
Zustand? Für die ganzen vorchristlichen 8051 und Z80-Ports gibt es 
regelmäßige Bugfixes, aber bei den PICs tut sich irgendwie nichts mehr. 
Ist der Port überhaupt noch in Entwicklung? Ich bin allerdings nicht 
sicher, ob die oben beschriebenen Probleme vom PIC-Backend verursacht 
werden oder ein generelles SDCC-Problem sind.


Wie gesagt, ich wollte nur mal rumhören, was ihr so erlebt habt mit 
SDCC/PIC.

: Verschoben durch User
von Jim M. (turboj)


Lesenswert?

Vancouver schrieb:
> In einer while(1)-Loop wird in einem switch-Statement eine globale
> Variable ausgewertet, die zuvor in einem Interrupt-Handler gesetzt wird.

Zeige Deinen Code. Bei dieser Konstruktion kann einiges schief gehen, 
wenn die Variable mehrfach ausgewertet (gelesen) wird. Das sieht man 
dann aber erst im Disassembly!

Abhilfe ist eventuell eine Variable zum Zwischenspeichern:
1
volatile unsigned char intValue;
2
3
void foo()
4
{
5
  unsigned char tempVal = intValue;
6
7
  switch(tempVal) {
8
    case BLAH: ;
9
10
  }
11
}

von Jim M. (turboj)


Lesenswert?

Vancouver schrieb:
> SDCC version ist 3.6.6-201705xx für Linux. Das Problem betrifft die
> aktuellen Snapshots mindestens
> ab Mai. Bei 3.6.0 treten diese Fehler nicht auf.

Dann mach doch mal einen Bugreport. Hätte ich hier gar nicht erst 
gepostet, das Snapshots schon mal Fehler enthalten ist eigentlich 
normal...

von Vancouver (Gast)


Lesenswert?

Jim M. schrieb:
> Zeige Deinen Code

Habe den Code jetzt nicht hier, aber die Struktur ist etwa so:
1
uint8_t address, functionSel;
2
3
4
main()
5
{
6
7
    do_something_here();
8
    while (1)
9
   {
10
         if (address==myAddress)  // address set in int handler
11
         {
12
               switch (functionSel)     // functionSel set in int handler
13
                  case CONSTANT1: ... break;
14
                  case CONSTANT2: ... break;
15
                 ...
16
                 default: break;
17
       }
18
19
      do_something_else_here();
20
  } 
21
22
}


Was genau kann da schief gehen?

von Vancouver (Gast)


Lesenswert?

Jim M. schrieb:
> Dann mach doch mal einen Bugreport. Hätte ich hier gar nicht erst
> gepostet, das Snapshots schon mal Fehler enthalten ist eigentlich
> normal...

Ja, das stimmt zwar, aber der Fehler ist irgendwie zu diffus für einen 
Bugreport. Ich weiß nicht genau, was wann schiefgeht und warum. Damit 
können die Entwickler vermutlich recht wenig anfangen.

von Jim M. (turboj)


Lesenswert?

Vancouver schrieb:
>> Dann mach doch mal einen Bugreport. Hätte ich hier gar nicht erst
>> gepostet, das Snapshots schon mal Fehler enthalten ist eigentlich
>> normal...
>
> Ja, das stimmt zwar, aber der Fehler ist irgendwie zu diffus für einen
> Bugreport. Ich weiß nicht genau, was wann schiefgeht und warum. Damit
> können die Entwickler vermutlich recht wenig anfangen.

Für das Bitfield Zeugs sollte man einen Testfall in C relativ schnell 
schreiben können.

Für das switch() {} hätte ich erstmal den C Code gesehen. Wenn die 
Variable nicht volatile ist, darf er sie IMHO auch mehrmals lesen. Deine 
Fehlerbeschreibung klingt jedenfalls so.

Es wäre sicher hilfreich den vom Compiler generierten Assambler Code 
auch lesen zu können...

von Lutz (Gast)


Lesenswert?

Vancouver schrieb:
> 1. In einer while(1)-Loop wird in einem switch-Statement eine globale
> Variable ausgewertet, die zuvor in einem Interrupt-Handler gesetzt wird.
> Es gibt maximal 16 verschiedene cases, aber nicht alle können in der
> aktuellen Version auftreten. Dennoch ist der Code dafür bereits
> vorbereitet, d.h es gibt einen case-Zweig, der aber nichts tut bzw. nur
> eine Debug-Message über den UART ausgäbe, falls der case eintreten
> würde. Mit diesem case-Zweig im Code läuft der PIC völlig ins Nirwana
> und tut garnichts. Wird der Case-Zweig auskommentiert, dann gehts.
> Wohlgemerkt: Der entsprechende case tritt niemals ein.

Hmm, mit 'switch' und mehr als 16 'cases' hatte ich auch schon mal für 
den Z80 Probleme. Hatte das aber nicht näher untersucht...
Auf jeden Fall gingen die Compilezeiten ordentlich nach oben :-/

von Bernd N (Gast)


Lesenswert?

>> ich erinnere mich an eine kryptische Fehlermeldung mit einer "Evelyn" und einem 
"Dog"

conditional flow changed by optimizer: so said EVELYN the modified DOG.
https://www.youtube.com/watch?v=agoDHke6a1U

Zeig mal mehr Code her.

von Vancouver (Gast)


Lesenswert?

Wie gesgt, ich habe den Code nicht hier, das muss ich am Wochenende 
machen.

Warum ist das mehrfache Lesen von volatile-Variablen ein Problem?

von Vancouver (Gast)


Lesenswert?

Bernd N schrieb:
> conditional flow changed by optimizer: so said EVELYN the modified DOG.
> Youtube-Video "Evelyn, A Modified Dog"

Nett, aber ich habe keine Ahnung, was mir das sagen will. Muss man den 
Songtext verstehen, um ein Switch-Statement debuggen zu können?

von Bernd N (Gast)


Lesenswert?

>> conditional flow changed by optimizer: so said EVELYN the modified DOG.
Bekommst du denn diese Fehlermeldung ? ich warte mal auf dein gesamtes 
Program um ne Aussage zu treffen.

>> Muss man den Songtext verstehen, um ein Switch-Statement debuggen zu können?

Das setzen die Macher des SDCC vorraus :-) sind halt einige Zappa Fans 
darunter. Daher die dämliche Fehlermeldung.

von Vancouver (Gast)


Lesenswert?

Bernd N schrieb:
> Bekommst du denn diese Fehlermeldung ? ich warte mal auf dein gesamtes
> Program um ne Aussage zu treffen.

Vor 3.6.0 ja, seit 3.6 nicht mehr. Aufgrund dieser Fehlermeldung habe 
ich früher die "unbenutzen" case-Branches auskommentiert, damit 
überhaupt etwas funktioniert. Bei 3.6 habe ich dann nochmal probiert, 
den Branch drinzulassen und mich gefreut, dass die Fehlermeldung weg 
ist. Aber es funktioniert immer noch nicht.

von Philipp Klaus K. (pkk)


Lesenswert?

Vancouver schrieb:
>
>
> Was genau kann da schief gehen?

Der Compiler könnte Code gnerieren, der sich darauf verlässt, dass 
functionSel bei mehrmaligem lesen innerhalb von main() seinen Wert nicht 
ändert, da functionSel nicht volatile ist.

Philipp

von Philipp Klaus K. (pkk)


Lesenswert?

Bernd N schrieb:
> conditional flow changed by optimizer: so said EVELYN the modified DOG.

Das ist keine Fehlermeldung, sondern nur eine Warnung.

Philipp

von Philipp Klaus K. (pkk)


Lesenswert?

Vancouver schrieb:
> Die SDCC-Doku ist hier etwas missverständlich. Müssen die Case-Zweige
> numerisch geordnet sein? Gibt es bei Switch-Anweisungen im SDCC etwas zu
> beachten, das ich nicht weiß?

switch sollte sich gemäß den C-Standard verhalten.

Aber:

1) Es könnte einen Bug geben. Das ist bei pic14 und pic16 
wahrscheinlicher als in den anderen Backends.
2) Bei Verwendung von --nojtbound ist das Verhalten nicht mehr 
standardkonform. Aber die Option wird demnächst eh entfernt.

Philipp

von Philipp Klaus K. (pkk)


Lesenswert?

Vancouver schrieb:
> Ich hatte bisher eine recht hohe Meinung vom SDCC, aber mittlerweile bin
> ich etwas pissed. Warum ist der PIC-Port immernoch in so einem lausigen
> Zustand? Für die ganzen vorchristlichen 8051 und Z80-Ports gibt es
> regelmäßige Bugfixes, aber bei den PICs tut sich irgendwie nichts mehr.
> Ist der Port überhaupt noch in Entwicklung? Ich bin allerdings nicht
> sicher, ob die oben beschriebenen Probleme vom PIC-Backend verursacht
> werden oder ein generelles SDCC-Problem sind.

Es fehlt halt an Entwicklern. Insbesondere an Entwicklern, die sich für 
PIC interessieren.
Dem Changelog nach gab es seit Februar keine Bugfixes im pic14-Backend 
mehr.

Auch bei den PIC muss man nochmal unterscheiden. Das pic16-Backend ist 
in einem deutlich besseren Zustand als pic14, auch wenn es noch nicht so 
gut wie die anderen ist.

Philipp

von S. R. (svenska)


Lesenswert?

Vancouver schrieb:
> Warum ist das mehrfache Lesen von volatile-Variablen ein Problem?
1
if(a == 1) {
2
 ... a ist eins
3
} else if(a == 2) {
4
 ... a ist zwei
5
} else {
6
 ... a ist weder eins noch zwei
7
}

Wenn sich 'a' zwischen der Auswertung der Zweige ändert, kommst du unter 
Umständen mit a==1 in den Else-Zweig, was natürlich falsch ist. Der 
Compiler darf ein switch als eine solche if-Kaskade übersetzen, was dann 
ein Problem sein kann.

Mache die Variable 'volatile' und speichere sie möglicherweise sogar 
zwischen (d.h. mache den Lesezugriff explizit). Ohne 'volatile' ist dein 
Code ohnehin fehlerhaft.

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.