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.
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:
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...
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.
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...
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 :-/
>> 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.
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?
>> 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.
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.
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
Bernd N schrieb:> conditional flow changed by optimizer: so said EVELYN the modified DOG.
Das ist keine Fehlermeldung, sondern nur eine Warnung.
Philipp
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
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
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.