Forum: Mikrocontroller und Digitale Elektronik Versionsstand der SW im Flash ablegen


von Lutz E. (minipilot)


Lesenswert?

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:
1
#include <avr/pgmspace.h>
2
3
//--------------------------------------------------
4
// Linker-Option to link MyMemSection to 0x00010000
5
// -Wl,--section-start,.My_Mem_Section=0x00010000
6
//--------------------------------------------------
7
8
#define MyMemSection __attribute__((section(".My_Mem_Section")))
9
10
const unsigned char my_data[] MyMemSection =
11
{
12
  0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00, 0x0c,
13
  0x2e, 0x6e, 0x63, 0x64, 0x00, 0x62, 0x00, 0x0a, 0x33
14
};

Bin dort aber nicht so durchgestiegen. Kann jemand helfen?

von PJ (Gast)


Lesenswert?

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.

von PJ (Gast)


Lesenswert?

> 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"

von Lutz E. (minipilot)


Lesenswert?

Hallo PJ,

danke für die schnelle Antwort. Was ich aber noch nicht so verstehe, wo 
lege ich denn nun meinen Speicherbereich fest? In dem Beispiel ist:
1
-Wl,--section-start,.My_Mem_Section=0x00010000

benannt. Ist dass der Teil, den ich ins Makefile eintragen muss?

von Olaf (Gast)


Lesenswert?

Normalerweise definierst du deine Speicherbereich im Linkerscript.

Olaf

von PJ (Gast)


Lesenswert?

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.

von PJ (Gast)


Lesenswert?

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.

von Lutz E. (minipilot)


Lesenswert?

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.

von Lutz E. (minipilot)


Lesenswert?

So habe nun mal versucht dies mit den AVR-Studio umgesetzt. Leider war 
es nicht sehr erfolgreich.

Im Makefale habe ich folgendes eingefügt:
1
## Linker flags
2
LDFLAGS = $(COMMON)
3
LDFLAGS += -Wl,--section-start,.Softwareversion=0x000BC000

dann habe ich im Programmcode
1
#define Softwareversion __attribute__((section(".Softwareversion")))

hinzugefügt. In einer Einstellungs.h Datei wurde
1
const unsigned char my_data[] Softwareversion = 
2
{
3
  0xAA
4
};

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

von holger (Gast)


Lesenswert?

LDFLAGS += -Wl,--section-start,.Softwareversion=0x000BC000

Könnte es sein das da eine Null zu viel am Ende ist?

von Lutz E. (minipilot)


Lesenswert?

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

von Andreas V. (tico)


Lesenswert?

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

von Lutz E. (minipilot)


Lesenswert?

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.

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.