Forum: Mikrocontroller und Digitale Elektronik AVR signature.h


von Bronco (Gast)


Lesenswert?

Hallo zusammen,

Zum Verständnis:
Sehe ich das richtig, dass die Werte in
1
__signature[]
anzeigen, für welches Derivat das Hexfile gebaut wurde?

Wenn ich die Signature Bytes mittels "SIGRD" auslesen und mit
1
__signature[]
vergleiche, müßten diese normalerweise identisch sein?

Danke

von Henrik Haftmann (Gast)


Lesenswert?

Also das mit der Signatur verträgt sich nicht sonderlich mit avrdude. 
Mal wieder ein schönes Negativbeispiel, wie Open-Source-Software Hand in 
Hand zusammenarbeitet.

Aber Seitenhieb beiseite: Im Idealfall sollte ein Brennprogramm für AVR 
direkt .elf-Dateien verarbeiten können. Denn diese können mehrere 
„Sektionen“ enthalten, die den Speicherbereichen des AVR (flash, eeprom, 
fuse, lock, osccal und signature) entsprechen. Klar, die Signatur kann 
nicht geflasht aber zur Kontrolle verglichen werden. osccal kann IMHO 
nur gelesen werden.

Direkt .elf-Dateien brennen geht also (zurzeit immer noch) nicht, und 
man geht den Umweg über .hex-Dateien. Diese können jedoch nur einen 
Speicherbereich adressieren, sind also von-neumannisiert. Man behilft 
sich kurzerhand mit den gleichen Speicheradressen wie innerhalb avr-gcc, 
der auch nur von-Neumann kann: Der EEPROM ist ab Speicheradresse 
0x810000, die Fuses ab 0x820000, die Lockbits ab 0x83000 und die 
Signatur ab 0x840000. Diese Zahlen findet man im Linkerskript, siehe mal 
WinAVR/avr/lib/ldscripts/avr35.x

Generiert man also eine All-In-One-Hex-Datei mit der Zeile

avr-objcopy -O ihex -j .text -j .data -j .eeprom -j .fuse -j .lock -j 
.signature a.elf a.hex

ist die entstehende .hex-Datei gegen Ende mit 2-Databyte-Records der 
Funktion 0x04 gespickt, die den High-Teil der Folgeadressen entsprechend 
setzt. Daran verreckt avrdude, aber ElmChans avrpp „verdaut“ eine solche 
Datei bestens, indem es ohne viel Federnlesen (also ohne die 
fürchterlich lange Kommandozeile von avrdude) mit „-ff“ den EEPROM und 
die Fuses gleich mitprogrammiert. Auch prüft es per Signatur ob der Chip 
stimmt.

Interessanterweise bewirkt „-j .data“ (.data sind die mit Nicht-Null 
initialisierten RAM-Bereiche) nicht, dass eine Startadresse 0x80060 
generiert wird, sondern diese Sektion wird unmittelbar an .text 
angehangen.  (Das scheint in avr-objcopy eincompiliert zu sein.) Die 
Standard-Initialisierungssequenz baut darauf auf, das Linker-Skript 
generiert hierzu passend die Labels __data_start und __data_end. Deshalb 
generiert die Standardzeile

avr-objcopy -O ihex -j .text -j .data a.elf a.hex

genau einen zusammenhängenden Bereich, der von avrdude verdaut werden 
kann.
Würde man „-j data“ weglassen, werden alle initialisierten 
RAM-Speicherzellen mit ungeflashtem Flash, also 0xFF initialisiert. 
Einen solchen Fehler zu finden ist verdammt schwierig, denn das Programm 
läuft erst mal aber bekommt falsches Futter.

Hieran sieht man auch, dass sowohl .text als auch .data Flash-Speicher 
verbraucht. Ist man Herr der Lage und bastelt sich sein eigenes 
Linker-Skript, kann man .data auch in den EEPROM verbannen, falls der 
Platz knapp wird.
Einfacher ist es jedoch, gar keine initialisierten Daten zu verwenden 
und die Initialisierung von Daten selbst mit eeprom_read_block() in die 
Hand zu nehmen. Dazu muss nur eine Struktur (struct) definiert werden, 
die alle Daten bündelt und sowohl im RAM (uninitialisiert) und EEPROM 
(initialisiert) angelegt werden. Ganz nebenbei fällt die Möglichkeit des 
quasi-persistenten RAM ab, indem man zyklisch eeprom_update_block() 
aufruft um geänderte Daten zurückzuschreiben.

Um auf die ursprüngliche Frage zurückzukommen:

__signature[] (generiert von „#include <avr/signature.h>“) ist in einem 
AVR-Programm nicht adressierbar, weil dieses Array weder im Flash noch 
im EEPROM oder RAM ankommt. Auch wenn man „if (__signature[0]==0xE3)“ 
oder so schreiben kann und dies auch womöglich anstandslos compiliert 
wird, es kommt schlicht Murks heraus. Denn avr-gcc kennt keine Segmente 
(im Gegensatz zur kommerziellen Konkurrenz) und nimmt stets an, dass 
alles RAM-adressierbar ist. Das kennt man von pgm_read_byte(), was man 
verwenden muss(!!), um Konstanten aus dem Flash zu lesen, und den 
entsprechenden _P-siffigierten String-Funktionen. (Die Konkurrenz 
hingegen „weiß“, ob „ld“ oder „lpm“ generiert werden muss, da es den 
„Segmentkontext des Zeigers“ kennt.) Die Signatur ist nur für das 
Brennprogramm gedacht.

Klar kann man Linkerskript und makefile anpassen, dass __signature[] 
irgendwie adressierbar wird, aber wozu der Riesenaufwand?

Was man machen kann ist selber ein signature[]-Array zu bauen nach dem 
Vorbild der <avr/signature.h>, aber einfacher ist es sicher, mit den 
Byte-Konstanten SIGNATURE_0, SIGNATURE_1 und SIGNATURE_2 zu vergleichen, 
die aus <avr/io.h> herauskommen.

Ich hoffe die Zusammenhänge etwas erleuchtet zu haben.

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.