Hallo, ich habe ein Problem mit dem freien SDCC Compiler. Ich setzte als IDE Visual Studio ein, und lasse mir über ein Makefile mittels SDCC die C-Dateien übersetzten. Controller: AT89C51CC03 Nun bekomme immer die Warnung: 1>main.c:67: warning 110: conditional flow changed by optimizer: so said EVELYN the modified DOG Ich habe bereits in Erfahrung gebracht, dass der Compiler an dieser Stelle etwas unsauber arbeitet, und nicht erkennt, wenn z.B. die Variable einer Fallunterscheidung (SWITCH/CASE) in einer Interrupt Routine verändert wurde. Nun würde ich gerne von einem Profi wissen, wie ich am besten die Optimierung für die Funktion die diese Fallunterscheidung enthält deaktiviere. Irgendwie hat der Zusatz volatile bei der Variablen auch nicht geholfen. DANKE und Beste Grüße an alle Besucher der Foren und das Team von www.mikrocontroller.net TOM
Ein minimales Codebeispiel, das dieses Problem erzeugt, ist zu viel verlangt?
Hallo, eigentlich wollte ich gerne wissen, wie die Optimierung generell für ein File bzw. eine Funktion abgeschaltet werden kann. Aber wenn unbedingt Code gewünscht ist:
1 | volatile BYTE __xdata cmd5 = CMD_STOPP; |
2 | |
3 | .
|
4 | .
|
5 | .
|
6 | |
7 | |
8 | void doMot5(void) |
9 | {
|
10 | #ifdef KASDEB
|
11 | can_data.INDEX = 0x4444; |
12 | can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR)) << 24) |
13 | + (((long)(wait)) << 8) + ((long)(cmd5)); |
14 | SendCANMsg(); |
15 | #endif
|
16 | |
17 | switch(cmd5) |
18 | {
|
19 | case CMD_STOPP: |
20 | if (M5POW == ON) |
21 | {
|
22 | M5POW = OFF; |
23 | wait = DELAY_STOPP; |
24 | break; |
25 | }
|
26 | if (M5DIR == RUECK) |
27 | {
|
28 | M5DIR = VOR; |
29 | wait = DELAY_UM; |
30 | }
|
31 | cmd5 = NOP; |
32 | break; |
33 | |
34 | case CMD_VOR: |
35 | if (M5POW == ON) |
36 | {
|
37 | if (M5DIR == VOR) |
38 | {
|
39 | cmd5 = NOP; |
40 | break; |
41 | }
|
42 | else
|
43 | {
|
44 | M5POW = OFF; |
45 | wait = DELAY_STOPP; |
46 | break; |
47 | }
|
48 | }
|
49 | else
|
50 | {
|
51 | if (M5DIR == VOR) |
52 | {
|
53 | M5POW = ON; |
54 | wait = DELAY_ON; |
55 | cmd5 = NOP; |
56 | break; |
57 | }
|
58 | else
|
59 | {
|
60 | M5DIR = VOR; |
61 | wait = DELAY_UM; |
62 | break; |
63 | }
|
64 | }
|
65 | break; |
66 | |
67 | case CMD_RUECK: |
68 | if (M5POW == ON) |
69 | {
|
70 | if (M5DIR == RUECK) |
71 | {
|
72 | cmd5 = NOP; |
73 | break; |
74 | }
|
75 | else
|
76 | {
|
77 | M5POW = OFF; |
78 | wait = DELAY_STOPP; |
79 | break; |
80 | }
|
81 | }
|
82 | else
|
83 | {
|
84 | if (M5DIR == RUECK) |
85 | {
|
86 | M5POW = ON; |
87 | wait = DELAY_ON; |
88 | cmd5 = NOP; |
89 | break; |
90 | }
|
91 | else
|
92 | {
|
93 | M5DIR = RUECK; |
94 | wait = DELAY_UM; |
95 | break; |
96 | }
|
97 | }
|
98 | break; |
99 | |
100 | case NOP: |
101 | |
102 | #ifdef KASDEB
|
103 | can_data.INDEX = 0x3333; |
104 | can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR)) |
105 | << 24) + (((long)(wait)) << 8) + ((long)(cmd5)); |
106 | SendCANMsg(); |
107 | #endif
|
108 | |
109 | break; |
110 | |
111 | default:
|
112 | #ifdef KASDEB
|
113 | can_data.INDEX = 0x3333; |
114 | can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR)) |
115 | << 24) + (((long)(wait)) << 8) + ((long)(cmd5)); |
116 | SendCANMsg(); |
117 | #endif
|
118 | |
119 | break; |
120 | }
|
121 | #ifdef KASDEB
|
122 | can_data.INDEX = 0x5555; |
123 | can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR)) |
124 | << 24) + (((long)(wait)) << 8) + ((long)(cmd5)); |
125 | SendCANMsg(); |
126 | #endif
|
127 | |
128 | }
|
habe es auch schon mit diesen Pragmas versucht: #pragma save /* save the current settings */ #pragma nogcse /* turnoff global subexpression elimination */ #pragma noinduction /* turn off induction optimizations */ ----- C Code ------ #pragma restore /* turn the optimizations back on */ versucht, aber die Warnung mit der Optimierung verschwindet nicht! Beste Grüße TOM
die Warnung hat nicht mit voaltile oder Interrupts zu tun cmd5 = NOP; du änderst den wert, den du für das Switch verwendest. Was erwartest du dann als Ergebnis? Soll er dann den passenden Case ausführen oder nicht?
Hallo, der CASE NOP würde dann als nächstes durchlaufen, wenn sich cmd5 nicht mehr ändert. Aber das ist alles nicht mein Problem! Ich möchte die Optimierung verhindern. Oder das ganz so umbauen, dass keine Optimierung mehr stattfindet, aber ohne den Switch in der Funktion zu ändern. Gruß TOM
Dann mach aus dem Switch eine Reihe von "if-then-else" Blöcken. Da ist dann klar, an welchen Stellen "cmd5" ausgewertet wird.
Peter II schrieb: > du änderst den wert, den du für das Switch verwendest. Was erwartest du > dann als Ergebnis? Das kann aber nicht das Problem sein. Das ist genau geregelt, wie das abläuft. Der Wert von cmd5 wird genau hier
1 | switch(cmd5) |
einmalig ausgewertet und danach entschieden, welcher case anzuspringen ist. Was danach mit cmd5 weiter passiert, ist für den switch uninteressant. Wenn das ein Problem wäre, dann hätten Millionen von Statemachines ein ernstes Problem.
:
Bearbeitet durch User
Tom schrieb: > 1>main.c:67: warning 110: conditional flow changed by optimizer: so said > EVELYN the modified DOG > > Ich habe bereits in Erfahrung gebracht, dass der Compiler an dieser > Stelle etwas unsauber arbeitet, und nicht erkennt, wenn z.B. die > Variable einer Fallunterscheidung (SWITCH/CASE) in einer Interrupt > Routine verändert wurde. Das wäre aber schon ein Grund, mal ein ernstes Wörtchen mit dem Compilerbauer zu sprechen. Solche Probleme dürfen in einem professionellen Compiler nicht vorkommen. > Nun würde ich gerne von einem Profi wissen, wie ich am besten die > Optimierung für die Funktion die diese Fallunterscheidung enthält > deaktiviere. musst du in der Doku zum Compiler nachsehen. Hast du schon mal probiert, mit einer Zwischenvariablen zu arbeiten?
1 | tmp = cmd5; |
2 | switch( tmp ) { |
3 | ....
|
spätestens jetzt darf der Compiler das volatile bei cmd5 nicht mehr ignorieren. Wenn doch, dann verlang dein Geld zurück.
Karl Heinz schrieb: > Wenn doch, dann verlang dein Geld zurück. Das dürfte bei SDCC ein ... interessantes Unterfangen sein, meinst Du nicht auch?
Hallo, danke Karl-Heinz für die Klarstellung in Bezug auf den Switch! Ich habe gerade eine Zwischenvariable probiert, leider auch ohne Erfolg. Der SDCC ist ein freier Compiler, daher leider keine Chance auf Regress! ;-) http://sdcc.sourceforge.net/ wenn ich:
1 | .....
|
2 | switch(4) |
3 | {
|
4 | case CMD_STOPP: (CMD_STOPP ist der wert 4) |
5 | .....
|
verwende dann läuft es durch! Aber was soll das, dann brauche ich keinen Switch! In diesem Fall könnte er dann sinnvoller Weise wirklich den Switch wegoptimieren! Naja, muss wohl mal eine neuere Version des SDCC versuchen aufzutreiben. Danke für die Mithilfe bis hier hin. TOM
Karl Heinz schrieb: > Solche Probleme dürfen in einem professionellen Compiler nicht > vorkommen. Genau das dürfte beim SDCC nicht der Fall sein: mit dem Bau dieses Compilers verdient sich keiner seine Brötchen. Allerdings verwechselst du wohl gerade „professionell“ mit „qualitativ hochwertig“, fürchte ich. Es gibt ausreichend professionelle Software, die letzteres eher nicht ist … (Trotzdem sollte der Compiler im 21. Jahrhundert natürlich in der Lage sein, “volatile” ordentlich zu verarbeiten.)
Hi, sorry Leute! Ich muss alles zurücknehmen! Der Optimierer hatte recht! Irgendwo im Projekt habe ich den Code
1 | ....
|
2 | wait--; |
3 | }
|
4 | else
|
5 | {
|
6 | if (!(cmd5 == NOP)) |
7 | {
|
8 | doMot5(); |
9 | }
|
10 | }
|
11 | ....
|
gefunden, so dass der CASE NOP nie ausgeführt wurde! Ich habe diesen CASE entfernt, und der Compiler läuft durch! Tja bei fremdem Code sollte man halt genauer hinschauen! Sorry für die Verschwendung eurer Zeit! Falls aber jemand weiß wie (#Pragma oder anders) man die Optimierung für Funktionen, Module, Dateien und generell abschalten kann, so wäre ich über diese Info dankbar. In der Doc habe ich nichts derart gefunden, oder überlesen! Beste Grüße TOM
Tom schrieb: > die Optimierung für > Funktionen, Module, Dateien und generell abschalten kann Man schaltet sie nicht ab, denn es gibt immer eine Möglichkeit Code ans Laufen zu bekommen mit eingeschalteter Optimierung. Wenn Code mit eingeschalteter Optimierung nicht läuft, dann ist er fehlerhaft (= verstößt gegen den Standard).
Rabe schrieb: > Wenn Code mit eingeschalteter Optimierung nicht läuft, dann ist er > fehlerhaft (= verstößt gegen den Standard). Bei korrekt arbeitenden Compilern muss das so sein. Bei GCC wohl keine Frage. Bei SDCC würd ich das aber nicht unterschreiben. Und bevor man die Entwickler da mit einen Bugreport für irgendeinen seltenst auftretenden Grenzfall nervt: Lieber etwas umformulieren, oder mit (RTFM) #pragma nogcse #pragma noloopreverse #pragma nooverlay usw. usf. Exakt die Optimierung verhindern, die Probleme macht.
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.