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.
> 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.
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...
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?
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.
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.
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.
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.
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 ...
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.
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.
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
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.
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
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.
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.
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.
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.
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.
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.
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.