Forum: Compiler & IDEs optimize Os / O0


von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Hallo
Ich hab ein seltsames Problem und komm nicht mehr recht weiter.

Der Code fragt verschiedene Kanäle von der ADC ab.
In einer früheren Version hat der Code mal funktioniert.
Das Problem ist das ich außerhalb von der Funktion nur noch wirrwarr an 
Daten habe in der ADC_Value, bzw. auch zerstörte Adressen und absturz 
des MCU.

Unter optimierung O0 hab ich keine Probleme, Unter den anderen schon.
Wenn ich die Zeile mit dem System auskommentier und mir direkt die Werte 
abfrage(=Ausgabe über UART) funktioniert das.
1
void ADC_refresh(System_def *system)
2
{
3
static unsigned char kanal;
4
5
    if(IRQ.ADC_state)//Daten vorhanden
6
    {
7
      asm("nop"); uart_puts("");
8
9
      system->ADC_Value[kanal] =IRQ.ADC_value / 4;//
10
11
      kanal++;
12
      if(kanal == 2){kanal=6;}
13
      if(kanal == 8){kanal=0;}
14
15
      //ADC neueinstellen
16
      ADMUX=(ADMUX & ~(0x1F)) | (kanal & 0x1F);;
17
      ADCSRA|=(1<<ADSC);
18
      IRQ.ADC_value=0;
19
      IRQ.ADC_state=0;
20
    }
21
22
}

Ich hab mal das List mit angefügt.
Kennt einer das Verhalten?
Zwischendurch hat er mir die komplette if abfrage auch komplett weg 
optimiert und ich konnte mir die nur noch ausgeben, wenn ich eine 
zusätzliche UART Ausgabe am anfang gesetzt hatte.

Hoffe ihr habt ein Tip für mich.

von Εrnst B. (ernst)


Lesenswert?

> if(IRQ.ADC_state)

Der Name "IRQ" lässt darauf schliessen, dass das im IRQ gesetzt wird. 
Volatile?

=> Fehler liegt ausserhalb des gezeigten Code-Schnippsels.

von Peter (Gast)


Lesenswert?

Hallo
Danke für deine Antwort.
Es ist Volatile, das der Fehler außerhalb des gezeigten liegen soll 
zeigt mir das ich den Codeabschnitt da richtig gemacht hab.

Außerhalb wird nur die ADC init. in der IRQ die State gesetzt und den 
ADC Wert gespeichert.
Außerhalb der Funktion sind aber wirre Daten in den ADC_value, aber nur, 
wenn ich die Optimierung drin hab.

In einer anderen Version eines anderen Projektes funktionierte das.

Ich vermute das mir mein compiler ärger macht, wär nicht das erste 
mal...

von Εrnst B. (ernst)


Lesenswert?

Peter schrieb:
> Ich vermute das mir mein compiler ärger macht, wär nicht das erste
> mal...

Glaub ich erstmal nicht.
Fast jedes mal wenn hier einer Postet "Der Compiler machts falsch" kommt 
am Schluss raus, dass der Code Falsch war, und der Compiler nur den 
vorhandenen Fehler im Quelltext "anders als erwartet" ausnutzt.

Wo wird "system" instanziiert, welches deine Funktion als Parameter 
kriegt?
Irgendwo am Stack?

von Peter D. (peda)


Lesenswert?

Peter schrieb:
> Zwischendurch hat er mir die komplette if abfrage auch komplett weg
> optimiert

Dann solltest Du dem nachgehen und es nicht austricksen.

Wegoptimieren hat immer einen Grund. Entweder ein Code hat keinen Effekt 
oder eine Bedingung ist immer wahr oder immer falsch.

Imho muß bei einer Struct das Member volatile sein, damit der Zugriff 
darauf nicht wegoptimiert werden kann.

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:
> Imho muß bei einer Struct das Member volatile sein, damit der Zugriff
> darauf nicht wegoptimiert werden kann.

Wird eine Struct als const oder volatile deklariert, dann gilt das für 
jedes Member.

von Peter (Gast)


Lesenswert?

Hallo
Danke für die Antworten.
Hmm init. wird System in der Main schleife.
Ich bin ja auf der suche nach dem Fehler. Warum muss eine intere 
Struktur volatile sein? Ich dachte nur Globale müssten dies, da der 
compiler die IRQ an sich nicht sieht, bzw die Main?

Ich werde es mal mit einem volatile versuchen, ich fands nur merkwürdig, 
weil bisher die Funktion bisher immer funktionierte wie ich sie schrieb.

Ändere ich außerhalb der ADC den Inhalt von dem ADC_Value, wird diese 
korrekt überall erkannt, nur sobald der IRQ dazukommt hab ich Probleme.

von Peter D. (peda)


Lesenswert?

Insbesondere bei Codeschnipselchen sind immer alle Definitionen der 
benutzten Variablen und Funktionen besonders wichtig.

Anfänger denken aber leider oft, die kann ja jeder im Kaffesatz lesen.

von (prx) A. K. (prx)


Lesenswert?

Peter schrieb:
> Ich bin ja auf der suche nach dem Fehler. Warum muss eine intere
> Struktur volatile sein? Ich dachte nur Globale müssten dies, da der
> compiler die IRQ an sich nicht sieht, bzw die Main?

Da ausser dir niemand weiss wovon hier überhaupt die Rede ist ...

von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist der Quellcode von mir, vielleicht überseh ich ja etwas.
Für mich ist der eingliche interessante Teil der, den ich als schnipsel 
hier angehangt hatte.

Vielleicht gibt das mehr Klarheit über mein Problem.

von Peter (Gast)


Angehängte Dateien:

Lesenswert?

ups.. hatte meine struct vergessen.

von (prx) A. K. (prx)


Lesenswert?

Und wo ist der ADC-IRQ?

von Peter (Gast)


Lesenswert?

Der IRQ ist in der config.c, ganz unten.

In der Main ist in der mitte von den Includes die "volatile IRQ_def IRQ 
= {0};"
Die structs hatte ich vergessen einzufügen und nachgetragen.

von (prx) A. K. (prx)


Lesenswert?

Peter schrieb:
> Der IRQ ist in der config.c, ganz unten.

Nö.

von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Arg.. sorry du hast recht, in einem anderen Projekt ist es in er 
Config.c.
Hier ist es in der IRQ.c..
Habe es angehängt.

von Oliver S. (oliverso)


Lesenswert?

Peter Dannegger schrieb:
> Wegoptimieren hat immer einen Grund. Entweder ein Code hat keinen Effekt
> oder eine Bedingung ist immer wahr oder immer falsch.

oder es ist schlicht eine Fehlinterpretation der Debuggeranzeige.

Olvier

von Karl H. (kbuchegg)


Lesenswert?

Dein Code ist ziemlich unübersichtlich.

Hast du denn schon kontrolliert, ob vom ADC überhaupt je ein Interrupt 
kommt?

Wenn hier
1
void ADC_Conf()
2
{
3
#if F_CPU == 16000000
4
  ADCSRA  = (1<<ADEN) | (1<<ADSC) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);///16MHz/128 = 125kHz (50-200kHz) = 125kHz
5
#elif F_CPU == 8000000
6
  ADCSRA  = (1<<ADEN) | (1<<ADSC) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);///8MHz/128 = 62.5kHz (50-200kHz) = 62.5kHz
7
#elif F_CPU == 4000000
8
  ADCSRA  = (1<<ADEN) | (1<<ADSC) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1);///4MHz/64 = 62.5kHz (50-200kHz) = 62.5kHz
9
#endif
10
...

F_CPU nicht einen der erwarteten Werte hat, dann wird stillschweigend 
der ADC überhaupt nicht konfiguriert und auch nie gestartet. Wodurch 
auch nie der ADC Interrupt kommt, IRQ.ADC_state nie 1 wird und damit in 
ADC_refresh auch nie irgendwas passiert.

Alles in allem:
Puh. Ganz ehrlich. Ich denke du hast das da alles masslos übertrieben. 
Was soll das denn überhaupt werden? Wenn der Kommentar in main.c 
'Leuchtturm' noch einigermassen stimmt, dann ist das Komplettsystem doch 
heillos zu kompliziert aufgebaut. Diese Komplexität, noch dazu weil das 
alles recht sinnfrei in einzelne Files aufgeteilt ist, durchblickt man 
doch nicht mehr. Irgendwie beeinflusst da alles über 5 Ecken das 
restliche System, wenn es geradlinig viel einfacher wäre. Wenn die Zeit 
da ist, eine ADC Messung zu machen, dann mach sie einfach. Die paar µs, 
die das braucht sind doch völlig uninteressant.

von Kaj (Gast)


Lesenswert?

Karl Heinz schrieb:
> dann ist das Komplettsystem doch
> heillos zu kompliziert aufgebaut. Diese Komplexität, noch dazu weil das
> alles recht sinnfrei in einzelne Files aufgeteilt ist, durchblickt man
> doch nicht mehr.

Da stimme ich zu. Er hat z.B. 2x F_CPU definiert. einmal in der main.c 
und einmal in der main.h.
Sollte da nicht (normalerweise) der compiler mekern von wegen 
"redifinition of F_CPU"?
Und soweit ich weiß, heißen die Interrupt Service Routinen auch nicht 
mehr "SIGNAL" sondern "ISR", und das auch nicht erst seit gestern. Aber 
ich kann mich natürlich auch irren.

Um was für einen Controller handelt es sich eigentlich genau?

Grüße

von Peter (Gast)


Lesenswert?

Es ist nachher eine Lichtsteuerung für ein Leuchtturmmodell.
Der ADC läuft, das kann ich testen indem ich direkt mir den ADC Wert in 
die UART rausschicke und dieser Wert ändert sich auch.
Die 2 F_CPUs werden nicht beanstandet, da sie die gleichen Werte haben, 
aber danke für den Hinweis.

Ich habe mehrere Dateien genommen, weil ich für die Projekte immer 
unterschiedliche Funktionen mitnehme.

Das da ist nur das Grundgerüst für die spätere Logic, wie das Licht 
angeht und soweiter.

Ich programmier in Eclipse, da kann ich relativ einfach zwischen den 
Dateien rumspringen. Das ist auch der Grund warum ich nur ein schnipsel 
gepostet hatte.

Vielen Dank fürs anschauen von meinem Code, bin für 
Verbesserungsvorschläge ganz offen.

von Karl H. (kbuchegg)


Lesenswert?

Kaj schrieb:
> Karl Heinz schrieb:
>> dann ist das Komplettsystem doch
>> heillos zu kompliziert aufgebaut. Diese Komplexität, noch dazu weil das
>> alles recht sinnfrei in einzelne Files aufgeteilt ist, durchblickt man
>> doch nicht mehr.
>
> Da stimme ich zu.

Was ich eigentlich meinte.
Er hat schon eine gewisse Systematik drinnen. Nur ist die IMHO nicht 
besonders schlau.
Er hat alle Initialisierungen in einem File, alle IRQ in einem File, 
usw. usw.
Besser wäre es, alles was zb mit dem ADC zu tun hat, in einem File zu 
haben. So wie es jetzt ist, scrollt man sich bei gleichzeitigem 
ständigen Filewechsel im Editor zu Tode, bei der Fehlersuche. Alleine 
das Rückverfolgen, wie und wo eigentlich dieser state jemals gesetzt 
wird und unter welchen Umständen das passiert, das ist ein Horror obwohl 
das eigentlich eine recht einfache Sache sein sollte.
Genauso die Sache mit den Timern. Das es da 3 Subtimer in Variablen 
gibt, ist schon in Ordnung. Aber leg um Himmels Willen das Runterzählen 
dieser Subtimer zur Gänze in die Timer-IRQ. Das braucht nicht in main 
sein!
(Und da es sich bei diesen Variablen um tatsächliche Zahlenwerte 
handelt, finde ich ein
1
  if( !Timer )
nicht so prickelnd. Ein
1
  if( Timer == 0 )
wird in 2 Zehntelsekunden ohne großes Nachdenken verstanden.
Manchmal ist es nicht schlau, wenn man in C alles ausnutzt was möglich 
ist.

von Peter (Gast)


Lesenswert?

Hintergrund der ausgelagerden Zeitwerten war nur, das ich die IRQ so 
kurz halten wollte wie möglich und ich in der Main eh immer wieder 
durchlaufe.

Das es durcheinander ist mit den verschiedenen inits und IRQ ist da 
schlimm, gebe ich zu. Da werd ich nochmal hinter gehen.

Die IF abfrage mit dem ! hatte ich mir irgendwie am Anfang angewöhnt, 
bisher hatte noch keiner meine Programme gegenschauen müssen. Ich hab 
daher wohl ein eigensinnigen Style.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Hintergrund der ausgelagerden Zeitwerten war nur, das ich die IRQ so
> kurz halten wollte wie möglich

Das bringt dir in deiner Anwendung genau gar nichts ausser einem 
übermässig komplexen Programm mit dem du dir selber ins Knie schiesst 
und dessen Komplexität du nicht mehr beherrscht. Nichts in deinem 
Programm ist auch nur annähernd so zeitkritisch, dass es darauf ankommen 
würde, ob eine ISR eine halbe oder eine ganze MykroSekunde (= 
Millionstel Sekunde!) läuft.

Dein Programm bewegt sich auf der Ebene von Millisekunden bzw. 
Vielfachen davon! Die paar µs die ab und an in einer ISR verbraucht 
werden sind Promille davon! Völlig uninteressant und von niemandem ohne 
Messgeräte feststellbar, dass sie überhaupt stattfinden. Kein 
menschlicher Benutzer kann je feststellen, dass die Antwort auf ein 
eingetipptes Kommando 2 Millionstel Sekunden später kommt, weil der Mega 
in der Zwischenzeit noch eine Runde Software-Timer erniedrigen gespielt 
hat und noch schnell den ADC ausgewertet und in den globalen Pool 
gestellt hat.

von Peter (Gast)


Lesenswert?

Ok, werde ich in zukunft die Timer geschichte in meiner IRQ Struct 
packen und direkt im ISR abhandeln.

Aber warum genau ich ein Problem habe, das wenn ich den Wert in meiner 
ADC Routine in meine System Struct packe kannst du nicht auf den ersten 
Blick sehen oder?

Sobald ich den Wert IRQ.ADC_Value in der Unterroutine ADC_refresh auf 
die System.ADC_Value[] umsetze, spinnt der rum. Zeigt mir entweder 
schrott an oder stürzt ab und startet neu.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Ok, werde ich in zukunft die Timer geschichte in meiner IRQ Struct
> packen und direkt im ISR abhandeln.
>
> Aber warum genau ich ein Problem habe, das wenn ich den Wert in meiner
> ADC Routine in meine System Struct packe kannst du nicht auf den ersten
> Blick sehen oder?

Nein.
das müsste man jetzt genauer analysieren. Ich schätze mal, das irgendwo 
ausserhalb der Arraygrenzen zugegriffen wird, warum auch immer.
Der Punkt ist: deine Codewirrwarr ist so unübersichtlich, dass ich eher 
keine Lust habe, den jetzt zu entwirren. Vor allen Dingen, weil die 
Alternative übersichtlicher und viel einfacher zu erfassen wäre.

von Peter (Gast)


Lesenswert?

Bin gerade dabei den Code bisschen zu entflächten und übersichtlicher zu 
schreiben. Ich werde dabei noch ein Test machen und alles außer die UART 
und ADC laufen lassen und schauen wie sich das verhält.

Danke für die Tipps und deine Mühen, ich wollte auch nur schauen ob es 
auf den 1. Blick was zu beanstanden ist. Denke der Fehler ist irgendwo 
vertsteckt und nicht in der Routine die ich zu beginn gepostet hab.

Wenn ich mehr weiß, melde ich mich wieder.

von Peter D. (peda)


Lesenswert?

Am einfachsten wäre die Hilfe, wenn der gepostete Code compilierbar 
wäre.

So erstickt man ja nur in Fehlermeldungen:
1
main.c:32:25: error: system/uart.h: No such file or directory
2
main.c:34:27: error: system/eeprom.h: No such file or directory
3
main.c:37:28: error: system/softpwm.h: No such file or directory
4
main.c:44:25: error: system/uart.c: No such file or directory
5
In file included from main.c:45:
6
system/config.c: In function 'ADC_refresh':
7
system/config.c:131: warning: implicit declaration of function 'uart_puts'
8
system/config.c:122: warning: unused variable 'value_n'
9
system/config.c:121: warning: unused variable 'value'
10
....

Und die Verzeichnisstruktur mit zippen, damit man nicht erst raten muß.
Und generell immer das Target mit angeben wäre ne extrem saugute Idee.

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.