Hi,
ich habe hier ein Problem zum Haare raufen und finde einfach nicht ruas
was mit meinem AVR Studio / WinAVR los ist.
Ich habe WinAVR und AVR Studio schon neu installiert und auch die
Updates für AVR Studio installiert.
Ich möchte ein Programm schreiben, dass einfach nur eine LED mittels PWM
ansteuert - wobei der PWM Wert aus einem ADC-Signal berechnet wird.
Aber das Verhalten von AVr Studio ist völlig unnochvollziehbar.
Z.B.: Die LED sollte gleichmäßig leuchten, flackert aber. Der PWM-Wert
wurde in der main vor der while(1) { ... } Schleife festgelegt - die LED
müsste eigentlich gleichmäig leuchten, da dass Hauptprogramm das OCR1A
Register gar nicht anfasst. Zur Fehlereingrenzung, habe ich dann mal den
ganzen Inhalt der While(1)-Schleife (nicht die Schleife selbst!)
auskommentiert und siehe da: LED leuchtet gleichmäßig. Ok, dann also
schritt für schritt wieder Programmteile einkommentiert um den Fehler zu
einzugrenzen - aaber: nachdem ich alles wieder einkommentiert hatte
(also das exakt gleiche Programm wie beim Flackern) leuchtet die LED
gleichmäßig.
Und zig weiterer solch verrückter Sachen. Teilweise hatte ich ne
if-Abfrage mit drin, die bei gedrückter Taste den LED-PWM Wert z.B. mit
100 überschrieben sollte. Solange das drin war ging überhaupt nichts
mehr. Nachdem ich den Einzeiler wieder gelöscht hatte gings immer noch
nicht. Dann habe ich ne andere Optimierungsstufe gewählt und plötzlich
gings wieder. Bis zum nächsten Vorfall dieser Art (z.B. eine Variable
nicht mehr durch 5, sondern durch 10 zu teilen). Und im Simulator läuft
das auch ganz normal da durch und berechnet auch völlig korrekte Werte.
Bitte sagt mir, dass schon wer solch ein seltsames Verhalten beoabachten
und beheben konnte. Ich stehe echt vor einem Rätsel... Die Übertragung
in den Flash Speicher kanns ja eigentlich auch nicht sein - die wird ja
danach verifiziert... Nutze da den ISP Anschluss meines STK500.
Für jede Hilfe wäre ich echt dankbar, sonst fall ich vom
Programmierglauben ab...
Es liest zyklisch drei ADC Kanäle ein ("adc_convert(x,40)" bildet
Mittelwert aus je 40 Messungen) limitiert und glättet die Werte und
rechnet sie in 8-Bit PWM Werte um.
Das Krasse ist halt, dass es einwandfrei funktioniert und dann ändere
ich eine Zahl im programm und plötzlich ist tote Hose...
Welchen µC hast du und wie ist der SRAM Verbrauch?
Vielleicht geht deinem µC zur Laufzeit der Speicher aus und du
beobachtest die Effekte eines Stackoverflow, der dir Variablen zerhaut.
avr-size ist dein erster Freund ;-)
http://www.mikrocontroller.net/articles/AVR-GCC#Tipps_.26_Tricks
Es ist ein ATmega8. AVR Studio sagt mir, ich würde 2128 bytes
verbrauchen (avr-size gibt mir die selbe Zahl aus):
Ausgabe von AVR Studio:
1
AVRMemoryUsage
2
----------------
3
Device:atmega8
4
5
Program:2128bytes(26.0%Full)
6
(.text+.data+.bootloader)
7
8
Data:0bytes(0.0%Full)
9
(.data+.bss+.noinit)
10
11
12
Buildsucceededwith0Warnings...
Im Anhang nochmal die Ausgaben von avr-size und avr-nm (wobei ich mit
avr-nm nicht viel anfangen kann ^_^)
Aber ich führe ja doch keine unendlich komplizierten Float
Rechenoperationen durch. Wenn der Controller nicht ein paar
Integer-Variablen aufsummieren und durch ne Ganzzahl dividieren kann,
muss doch was im Busch sein...
Ich trau mich kaum zu fragen, aber könnte der Controller gestorben sein?
Wäre das erste Mal, dass mir das passiert aber möglich ist alles. Aber
sind die bei mir aufgetretenen Symptome ein sicheres Zeichen für nen
defekten Controller?
Ähm, ist deine adc_convert()-Funktion auch volatile deklariert?
Nicht dass der Compiler meint, drei Aufrufe mit gleichen konstanten
Parametern können wir optimieren. (Und die Optimierung fällt weg wenn
ein anderer Parameter ausprobiert wird...).
// Prototyp z.B.
volatile uint16_t adc_convert(uint8_t, uint8_t);
red=adc(1,40);// wird real durchgeführt und Ergebnis kommt in Puffer
17
red+=oldr;
18
red+=adc(1,40);// gepuffertes Ergebnis adc(1,40) wird benutzt
19
red+=oldr;
20
red+=adc(1,40);// gepuffertes Ergebnis adc(1,40) wird benutzt
21
red+=oldr;
22
red/=6;
23
24
returnred;
25
}
mit Optimierung -O1 übersetzt wird, wird nur der erste adc() aufruf
ausgeführt. Die anderen Aufrufe nutzen ein Zwischenergebnis.
Ich kann das durch ein volatile im Funktionsprototyl nicht ändern. Und
wie man dem Compiler an der Stelle das Optimieren abgewöhnt, weiss ich
nicht.
Wenn die Rückgabe von adc() einen volatile Wert beinhaltet oder
innerhalb adc ein volatile Wert bearbeitet wird, erfolgt keine
Pufferung.
Das ist ja abgefahren, dass er die Funktion nur einmal aufruft ohne zu
wissen was darin passiert... Aber es funktioniert ja auch bei -O0 (also
ohne Optimierung) nicht :-(
Zudem - wenn er da immer den gleichen Wert als Funktionsrückgabe nehmen
würde (und sei es auch 65000), dürfte sich das Programm ja dennoch nicht
aufhängen. Egal welcher Wert z.B. in "res_red" am Ende der
adc-Wandlungen steht, die nachfolgende Limitierung sorgt ja dafür, dass
immer ein gültiges Ergebnis für die PWM Generierung geschickt wird.
Aber volatile Deklarationen habe ich nirgends verwendet. Dachte das wäre
nur notwendig, wenn ich globale Variablen in Interrupts ansprechen will.
die ADC-Funktionen liegen extern in einer adc.c und adc.h die ich mit
ins Programm eingebunden habe.
>Ich trau mich kaum zu fragen, aber könnte der Controller gestorben sein?
Ich würd's zumindest versuchen auszuschließen - einfach mal 'nen
frischen Kandidaten auf den elektrischen Stuhl setzen. Dauert 2 Minuten
und spart u.U. mehrere Stunden Fehlersuche im Code.
Gruß
Kai
André Wippich wrote:
> Das ist ja abgefahren, dass er die Funktion nur einmal aufruft ohne zu> wissen was darin passiert...
Der springende Punkt ist:
Der Compiler weiss was in dieser Funktion passiert.
Und die Datenflussanalyse hat ergeben, dass diese Funktion
bei gleichen Argumenten auch immer das gleiche Ergebnis liefern
wird.
Deshalb kann der Compiler diese Optimierung machen.
Kai Giebeler wrote:
> Ich würd's zumindest versuchen auszuschließen - einfach mal 'nen> frischen Kandidaten auf den elektrischen Stuhl setzen. Dauert 2 Minuten> und spart u.U. mehrere Stunden Fehlersuche im Code.
Leider ist es die SMD-Variante und SMD-Auslöten war noch nie so meine
Stärke. Zumindest nicht mit dem Werkzeug hier zu Hause. Könnte höchstens
mit nem heissen Lötkolben Pin für Pin hochhebeln, beten dass die
Leiterbahnen auf der Paltine bleiben und dann nen Ersatz reinlöten. Und
die Arbeit wollte ich mir eigentlich nur machen wenn es auch sinnvoll
ist.
Karl heinz Buchegger wrote:
>Der springende Punkt ist:>Der Compiler weiss was in dieser Funktion passiert.>Und die Datenflussanalyse hat ergeben, dass diese Funktion>bei gleichen Argumenten auch immer das gleiche Ergebnis liefern>wird.>>Deshalb kann der Compiler diese Optimierung machen.
Naja, aber in der Funktion werdenja die ADC Register eingelesen, deren
Inhalte sich abhängig von äußeren Einflüssen ständig ändern können. Dann
wäre es doch sehr schwach, wenn der Compiler eine Funktion wegoptimiert,
in der mit Registern gearbeitet wird. Bei ner Funktion, die einfach nur
die Summe aus zwei Variablen bildet wäre das ja was ganz anderes.
Aber als Fazit glaube ich langsam echt, dass der ATmega8 einen Schaden
hat. Er läuft mit einem externen 16MHz Quarz, d.h. eine ISP Frequenz
von 1.845 MHz (STK500-Einstellung) sollte kein Problem sein. Das
Programmieren des Flash funktioniert, aber beim Verifizieren hängt sich
der Programmer auf, bzw. meldet dass ein Fehler beim Ausführen des
Kommandos aufgetreten ist. Das macht mich schonmal sehr stutzig. Hatte
es vorher nicht bemerkt, weil ich immer mit 57,6kHz habe Programmieren
lassen und dabei alle Programmierschritte einwandfrei durchlaufen
wurden.
Außerdem: Ich habe eine (ohne Optimierung) laufende Programmversion
aufgebläht, indem ich einfach ein paar Funktionen mit eingefügt habe,
die das Programm aber nicht verwendet. War dann bei 5366 Bytes (65,5%
voll) Speicherbelegung und ohne dass sich am Programmablauf etwas
geändert hat, funktionierte nichts mehr...
Vielleicht löte ich den ATmega8 morgen wirklich mal aus. Das wird ein
Spaß :-(
André Wippich wrote:
> Aber als Fazit glaube ich langsam echt, dass der ATmega8 einen Schaden> hat. Er läuft mit einem externen 16MHz Quarz, d.h. eine ISP Frequenz> von 1.845 MHz (STK500-Einstellung) sollte kein Problem sein.
Kann auch an zu langen ISP Kabeln liegen...
Leider auch nicht. Das ganze läuft mit 5V.
Es ist echt der erste Atmel der solch unerklärliches Verhalten zeigt und
ich habe schon mit zig ATmega8, AT90CAN128 und einigen anderen Typen von
Atmel gearbeitet. Und dann natürlich auch schon mit den kleinen
Standardproblemen zu tun gehabt. Meist kann man den Fehler ja schnell
eingrenzen und dann auch beheben:
- Spannungsversorgung geht in die Strombegrenzung
--> Kurzschluss auf der Platine
- ISP-Programmer bekommt keine Verbindung
--> ISP-Frequenz zu hoch
--> Reset-,SCK-, MISO- oder MOSI-Leitung ist unterbrochen (z.B. kalte
Lötstelle)
--> Fuse-Bit Fehler (z.B. falsche Taktquelle eingestellt)
- Seltsames Programmverhalten
--> Mist programmiert (auskommentieren bis die Fehlerpassage entdeckt
wurde)
Aber nichts davon lässt sich auf mein Problem anwenden :-(
Ich schätze der ATmega8 ist wirklich hinüber... Ich habe mal meine
Bastelkiste durchwühlt und noch einen 16 MHz Quarz und einen DIL28
ATmega8 gefunden. Damit konnte ich mein Programm direkt auf dem STK500
ausprobieren und dort liefen einwandfrei auch die Versionen, die bei der
der SMD ATmega8 in meiner Schaltung den Dienst versagt.
D.h. also Lötkolben raus und ab dafür... Weiß noch nicht wann ich das
mache - bin grad ziemlich verschnupft und da ist fummeliges SMD-Entlöten
nicht grad der beste Freizeitvertreib. Aber ich werde die Ergebnisse
hier posten.
Ach ja, als kleine Zusatzinfo: Das "Verify FLASH" von AVRStudio
funktionierte auch beim eingesteckten ATmega8 nicht bei Frequenzen über
115kHz - die Programmierung ("Program FLASH") schon. Das kann also nicht
dem (wahrscheinlich) defekten ATmega8 zugeschoben werden. Vielleicht ein
Bug von AVR Studio (nutze AVR Studio 4.13.571 Service Pack 2)...
Danke :-)
Ich habe mich gestern drangesetzt, den alten ATmega8 ausgelötet und
einen neuen eingelötet (was für eine Fummelarbeit stöhn). Jetzt
funktioniert alles, wie es soll. Liegt zwar noch ein gutes Stück
Programmierarbeit vor mir, aber solange der AVR das macht, was ich
programmiert habe, sehe ich da keine Schwierigkeiten