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
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 | }
|
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: > 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?
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.
Wie gesgt, ich habe den Code nicht hier, das muss ich am Wochenende machen. Warum ist das mehrfache Lesen von volatile-Variablen ein Problem?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.