Hallo,
bin auf der Suche nach einer Möglichkeit an einer bestimmten Stelle im
Flash ein Byte zu reservieren, an der ich die Softwareversion setzen
kann. Das setzen der Version geschiet im C-Code und soll bei der
Kompilieren dann aber an der benannten Stelle im Flash gesetzt werden
um ein späteres Auslesen zu ermöglichen.
Das ganze soll für Atmels funktionieren
Ich verwende das AVR-Studio 4.16 mit dem GCC Kompiler.
Was ich im Vorfeld über das Thema gefunden haben war im Trade:
Daten im FLASH an Addressen > 0xFFFF explizit ablegen
-http://www.mikrocontroller.net/topic/new?forum_id=1
darin wurde folgendes geschrieben:
Aha! Danach habe ich selbst auch schon gesucht, und Dein Posting enthält
in der Tat die Antwort auf Deine Frage.
Der Compiler weist die Objekten (Code, Variablen, Konstanten etc.)
bestimmten Speicherbereichen zu. Diese haben Namen, und die
letztendlichen Adressen der Bereiche werden dann vom Linker festgelegt.
Die im Kommentar genannte Option weist den Linker an, den angegebenen
Speicherbereich für den Speicherbereich mit dem betreffenden Namen zu
verwenden.
Die attribute-Option im Programmtext sorgt dafür, dass die definierte
Konstante einen eigenen Namen erhält, der dann zum Linker weitergereicht
wird, damit dieser die Adresse zuweisen kann.
Die Option muss ins Makefile eingetragen werden, damit es funktioniert,
bzw. bei manuellem Linken in die Befehlszeile mit eingetragen werden.
> dass die definierte Konstante einen eigenen Namen erhält
Oups, falsch... richtig ist:
"dass die definierte Konstante in einem Speicherbereich mit einem
eigenen Namen liegt"
Ja, genau.
Und zwar muss es in der Zeile des Makefiles eingetragen werden, die das
.elf-File generiert.
Aus diesem wird dann an anderer Stelle das .hex-File erzeugt, aber die
Adresszuweisung erfolgt durch den Linker beim Erzeugen der .elf-Datei.
Es gibt weitere Bereiche, die automatisch zugewiesen werden, z.B. muss
die Sprungvektortabelle bei 0 liegen, dann kommt ein Preloader, danach
der eigene Programmtext, EEPROM-Bereiche liegen woanders,
volatile-Variablen, Heap und Stack im Ram usw.
Man kann sich die Adresstabelle des Linkers anzeigen lassen, aber der
Befehl dazu fällt mir gerade nicht ein.
Das hängt mit den .map-Dateien ("Speicherkarte") zusammen, die (je nach
Makefile) ggf. erzeugt wird.
Man muss natürlich ein wenig aufpassen, dass die Speicherbereiche sich
nicht ins Gehege kommen... So eine Versionskonstante wird man wohl ans
Ende des Flashs legen, oder vielleicht auch an den Anfang hinter die
Sprungvektoren.
Bei mir steht im Makefile an einer Stelle sowas:
# Linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
Da könnte man das hinzufügen. Wie man hier sieht, wird dadurch auch die
.map-Datei erzeugt, in der die Adresszuweisungen zu den
Speicherbereichen und anderen Objekten stehen.
Die Optionen sind in der man-page zum avr-gcc genauer beschrieben.
Am Besten auch mal die Gebrauchsanweisung zu make und Makefile lesen,
das ist sehr, sehr nützlich, da hier die ganze reale Arbeit verteilt
wird. Wenn man sich das selbst anpassen kann, spart man sich viel
manuelles Immer-wieder-Getippe.
Übrigens kann man sich auch die fuses automatisch generieren lassen.
Wie man das im Programmtext macht, ist auf der Homepage zur avr-libc
beschrieben, und es sieht bei mir in einem Beispiel so aus:
#include <avr/io.h>
//LFUSE_DEFAULT (FUSE_CKSEL1 & FUSE_CKSEL2 & FUSE_CKSEL3 & FUSE_SUT0)
//HFUSE_DEFAULT (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_SPIEN & FUSE_JTAGEN)
FUSES = {
.low = 0xff,
.high = (FUSE_CKOPT & FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_SPIEN),
// .extended = EFUSE_DEFAULT,
};
Dazu habe ich mir im Makefile noch dieses eingetragen:
%.fuses: %.elf
@echo
@echo $(MSG_FUSES) $@
-$(OBJCOPY) -j .fuse --set-section-flags=.fuse="alloc,load" \
--change-section-lma .fuse=0 -O $(FORMAT) $< $@
Dies erzeugt eine .fuses-Datei im hex-Format, in dem dann die Bytes
direkt drinstehen.
$ cat test.fuses
:02000000FFC936
:00000001FF
Das könnte man nun automatisiert zum automatischen Programmieren der
Fuses mit avrdude benutzen, aber dazu fehlt mir noch das script (das man
dann ins Makefile eintragen könnte.
Du schreibst, dass es Sinn macht, die Versionskonstante ans
Ende des Flashs zu legen oder an den Anfang nach den Sprungvektoren.
Die Sprungvektoren sind doch bestimmt je nach Programm nicht immer
gleich groß oder (kennn mich da nciht so aus).
Mein Ziel ist es, eine Stelle zu definieren, die für alle Controller und
Programmgröße gültig sein kann.
Ich werde jedoch erst mal ausprobieren, dann mit festen Stellen im Flash
habe ich noch nicht gearbeitet.
eingefügt (habe einfach das aus dem Beispiel mal genommen und gekürzt)
Vor dem Kompilieren habe ich dann das geänderte Makefile herangezogen
und verwendet. Es Lies sich alles ohne Fehlermedungen oder warnungen
Umsetzten. Nur Leider in der generrieten *.hex-Datei konnte ich den Wert
an der definierten Stelle nicht finden.
???Was ist falsch gelaufen????
Naja es sind acht Byte wie im Beispile. sieben, warum? Mit der
Adressierung blick ich auch noch nciht durch. Wenn ich mir das INTEL
Hex-Format anschaue, gibt es nur vier Byte für die Adresse, plus zwei
Byte davor für die Datenlänge und zwei Bayte danach für den Record-Type.
Sind die vier zusätlichen Bytes mit in dem Beispiel:
1
-Wl,--section-start,.My_Mem_Section=0x00010000
Wenn ich mir das generriete *.hex-File anschaue, was ja auch nach dem
INTEL Hex-Format aufgebaut ist, sind dort ja dann auch nur vier Byte
Adresse. Warum also mit acht Adressieren?
Planlos, drotz Recherche
Lutz Eidenmüller wrote:
> Planlos, drotz Recherche
Dann recheriere zuerst mal das Datenblatt zu deinem Controller. Da steht
drin, wieviel Flash-Speicher der hat (Achtung, genau lesen, in den
Datenblättern von Atmel sind an vielen Stellen Wordadressen angegeben,
nicht Byteadressen!).
Bei einem ATMega8 z.B. sind es 8KB = 8192 Bytes. In hexadezimaler
Schreibweise sind das 0x2000 Bytes. Auch wenn Du links noch mehr Nullen
davorhängst, und z.B. 0x0002000 schreibst, sind es immer noch nur 8192
Bytes.
Du hast in deinem Makefile 0x000BC000 angegeben. Das sind 770048 Bytes =
752KB. Hat dein Controller soviel Speicher?
Gruss
Andreas
Hallo Andreas,
danke für die Antwort. Das macht natürlich Sinn. Habe mich durch einen
anderen Beitrag verunsichern lassen. Werde es noch mal probieren.