Guten Morgen
Ich habe mit dem 2006er Compiler aus einem Programm ein hex-File erzeugt
und dabei folgendes erhalten
...
Creating load file for EEPROM: main.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex main.elf main.eep
...
>Process Exit Code: 0
...
Das war alles super und hat auf anhieb funktioniert.
Als ich das selbe Projekt... wirklich nichts verändert ... mit dem
Winavr-20070525 compiliert habe, stand da folgendes:
Creating load file for EEPROM: main.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex main.elf main.eep
c:\WinAVR-20070525\bin\avr-objcopy.exe: there are no sections to be
copied!
c:\WinAVR-20070525\bin\avr-objcopy.exe: --change-section-lma
.eeprom=0x00000000 never used
make.exe: [main.eep] Error 1 (ignored)
...
>Process Exit Code: 0
...
Erstmal nicht schlimm dachte ich,da ja ">Process Exit Code: 0", aber das
Programm verhielt sich anders. Der MCP2515, den ich über die SPI
ansprach, will plötzlich nicht mehr mit dem Atmel reden. Was kann ich
tun? Was sagt mir diese Fehlermeldung?
Danke
Die Fehlermeldung besagt, dass dir die aktuellen binutils nicht mehr
gewillt sind, eine leere EEPROM-Ladedatei anzlegen. Das ist aber
komplett harmlos, wenn du keine EEPROM-Daten hast, wird dich die
leere Datei ja ohnehin nicht interessieren. (Wenn du welche gehabt
hättest, gäbe es keine Fehlermeldung.)
Dein Problem muss also komplett andere Ursachen haben, die du einfach
mal analysieren musst.
> make.exe: [main.eep] Error 1 (ignored)
Zeigt, dass die neuen Tools den Fehler "EEPROM leer" ignoriert haben.
Das ist eine Einstellung im Makefile (- vor dem avr-objcopy Kommando).
Das ist sicher nicht die Ursache für die unterschiedliche Funktion.
Der wesentliche Unterschied alter WinAVR <-> neuer WinAVR (2007) ist die
sehr erweiterte Optimierung des moderneren GCC. Ein typ. Fall ist z.B.
das ersatzlose Streichen von Leerschleifen, die manche Leute gerne als
Ersatz für die Wartefunktionen (_delay_ms,...) benutzt hatten.
Vielleicht kannst du die Funktionsabweichung im Sourcecode genauer
lokalisieren und magst den Abschnitt (oder ganz) posten. Wenn nicht -
mal auf die Schleifen und bewusstes Nixmachen achten.
:-) Mein grinsen geht von einem Ohr zum Anderen. Vor 1min bin ich der
Sache auf die Schliche gekommen. Dann wollte ich euch sagen, was es war
und BUMMS da hat doch der Stefan das ganze schon vermutet :-).
Es war wirklich die delay-Funktion aus der util/delay.h. Der Aufruf
"_delay_us(XX);" wurde übergangen bzw. wegotimiert und damit hat die SPI
den MCP2515 nicht lange genug Zeit gelassen, den Config.Mode zu
betreten. Ich habe es nun wieder mit einer for-Schleife und einer
wiederkehrenden Addition darin gemacht - wie sonst auch... nur jetzt
mußte ich alles mit volatile abändern. Nu geht's.
Ich finde es schade. Als ich den Quellcode gelesen habe, fand ich es
interessant, dass es eine Funktion gibt, die ja anscheinend eine
definierte Pause erzeugt. Und nun optimiert die sich weg...hmmm... . Der
Herbert hat dazu die passende Frage..."Huuuuu, was soll das?" :-)
Bis dann
Jörg:
> da muss irgendwas anderes faul sein.
Sehe ich genau so. Aber schon mal gut, dass die Ursache eingegrenzt
werden konnte!
Marco:
> Der Aufruf "_delay_us(XX);" wurde übergangen bzw. wegotimiert> und damit hat die SPI den MCP2515 nicht lange genug Zeit> gelassen, den Config.Mode zu betreten.
Vielleicht ist das eine Tückung. Die delay... Funktionen werden als
Inline-Funktionen direkt in den Hauptcode eingebaut. Dadurch sieht man
im Debugger keinen üblichen Funktionsaufruf.
Die korrekte Zeit der delay... Funktionen ist von VIER Sachen
abhängig:
1/ Die F_CPU muss richtig definiert sein. Wenn keine F_CPU definiert
ist, schmeisst delay.h eine Warnung und definiert sich F_CPU auf 1MHz.
Die Schleifen sind sehr zu lang (nicht dein Fall).
2/ Die Zeiten in den Schleifen müssen unterhalb eines F_CPU abhängigen
Maximalwerts liegen. Liegt die Zeit darüber gibt es durch Überläufe
seltsame Effekte. Das Timing wird nicht stimmen.
3/ Die Übersetzung muss mit einer Optimierung gemacht werden. Ohne
Optimierung stimmt das Timing auch nicht.
ADD:
4/ Der Funktionsparameter für die delay... muss zur Compilezeit eine
Konstante sein. Es darf kein erst zur Laufzeit bekannter Variableninhalt
sein.
Morgen alle zusammen
Ich habe gerade eure Kommentare gelesen und denke mir, das ich mich mit
der delay.h mal genauer befassen müsste. Ich mag meine "handgebastelte"
Pause nähmlich garnicht. Und wenn Ihr der Meinung seit, dass die delay.h
funktionieren müsste, dann wird sie das wohl auch. Ich mach mich schlau.
Danke Euch.
PS: Liegt beim Compiler eigentlich irgendwie eine Zusmmenfassung der
mitgelieferten Funktionen ... wie die besagte delay.h ... dabei und
unter Umständen mit Beispielaufrufen? Ich werde oft das Gefühl nicht
los, dass ich mir das Leben mit dem AVR nur unnötig schwer mache, weil
ich die Möglichkeiten des AVR GCC nicht nutze.
Bis dann
Marco