Hallo Forum,
mal wieder eine Frage von mir.
Es geht um einen ATmega2560 und dessen Flash-Speicher.
Ich habe Konfigurationsdaten im Flash (sehr viele Tabellen, passsen und
sollen nicht ins EEPROM), soweit klappt auch alles.
Diese Tabellen sollen jedoch "im Feld" also ohne PC oder Programmer oder
Ähnliches veränderbar sein.
Ein AVR kann ja seinen eigenen Flash-Inhalt verändern
(Bootloader-Funktion), aber dazu muss der Code, der den Flash verändern
soll aus dem Bootloaderbereich ausgeführt werden.
Dazu muss ich also einige Funktionen in eine eigene Section legen, die
dann an der Adresse 0x7E00 liegt (Startadresse des kleinsten
Bootloader-Bereichs).
Für meine Bootloader verschiebe ich immer die gesamte .text-Section an
die Adresse, aber das ist hier ungewünscht.
Ich werde wohl eine eigene section erstellen müssen und die Funktionen
mit dem passenden Attribut versehen.
Da ich aber mittels -Wl,--gc-sections linken muss, muss wohl das
Linkerscript verändert werden, damit die section nicht verworfen wird
(oder ist das falsch?)
Des weiteren brauche ich eine 2. Custom-Section, die die
Kofiguratonsdaten immer an die selbe Stelle im Flash schreibt. Diese
Section sollte 1-2 Pages lang sein und darin sollte kein ausführbarer
Code stehen, damit die Pages komplett gelöscht und neu beschrieben
werden können.
so eine Art Pseudo-Code, wie es dann mal aussehen soll:
1
const__attribute__((section(".flashData")))
2
uint16_ttable[360]={/* ... */};
3
4
voidupdateDataTables(void)
5
__attribute__((section(".updateFlash")));
6
voidupdateDataTables(void){
7
//hole die neuen Daten
8
//und berechne die werte des arrays
9
10
//lösche die Pages der Section .flashData
11
//und fülle sie mit den neuen Daten
12
}
Schön wäre natürlich, wenn man dann im Porgramm auf table[i] genauso
zugreifen könnte, wie wenn ich es mit __flash gekennzeichnet hätte.
Könnte mir jemand erklären, wie ich das Default-Linkerscript der
avr6-Architektur (zu der der ATmega2560 meines Wissens gehört)
modifizieren müsste?
Danke im Voraus
N.G.
Für den Bootloader bietet sich .bootloader an.
Wozu braucht table[] eine eigene Section? Alles, was der Bootloader
braucht, ist das Symbol. Wenn der Bootloader Teil der Applikation ist
sollte das kein Problem sein. Und die Zieladresse braucht er natürlich
auch, wobei zu beachten ist, dass die Adressen i.d.R nicht in 16 BIts
passen.
Hallo Johann,
das heißt, dass es schon eine Section gibt, die ich nur noch passen
verschieben müsste? Das wäre schon mal gut.
Johann L. schrieb:> Wozu braucht table[] eine eigene Section?
Ich dachte, dass es einfacher ist, eine neue Section zu erzeugen, in der
nur die Tabelle liegt. Diese Section liegt dann an einer festen Adresse,
die dann vom Code im bootloader verändert wird.
Eine eigene Section deshalb, damit nicht direkt dahinter Code liegt, den
ich dann auch lösche.
> Wenn der Bootloader Teil der Applikation ist> sollte das kein Problem sein.
Der "Bootloader" hier ist eben kein Bootloader, er dient nur zum
modifizieren des Flashes
> wobei zu beachten ist, dass die Adressen i.d.R nicht in 16 BIts> passen.
Ja, soweit ich weiß, muss man EIND noch manuell auf 1 oder 0 setzen,
oder kann das der GCC inzwischen automatisch?
N. G. schrieb:> Hallo Johann,>> das heißt, dass es schon eine Section gibt, die ich nur noch passen> verschieben müsste? Das wäre schon mal gut.
Was willst du denn "verschieben"?
> Johann L. schrieb:>> Wozu braucht table[] eine eigene Section?> Ich dachte, dass es einfacher ist, eine neue Section zu erzeugen, in der> nur die Tabelle liegt. Diese Section liegt dann an einer festen Adresse,> die dann vom Code im bootloader verändert wird.
Die Adresse ist beim Static Link immer fest, und hier ist die Adresse
dem Bootloader ja bekannt — im Gegensatz zu einem separaten Bootloader.
Weiters brauchst du nur die länge der Sequenz, die hier per sizeof zur
Verfügung steht. Auch wenn's ein paar Byte mehr kostet, kann diese Size
in eine globale Variable geschrieben werden, die der Bootloader lesen
kann.
Geht natürlich auch über Symbole, die du per Linker-Skript verfügbar
machst.
> Eine eigene Section deshalb, damit nicht direkt dahinter Code liegt, den> ich dann auch lösche.
Ak, ok. Leuchtet ein :-)
>> Wenn der Bootloader Teil der Applikation ist>> sollte das kein Problem sein.>> Der "Bootloader" hier ist eben kein Bootloader, er dient nur zum> modifizieren des Flashes
D.h. die zu beschreibenden Objekte sind als const volatile zu
deklarieren.
>> wobei zu beachten ist, dass die Adressen i.d.R nicht in 16 Bits>> passen.>> Ja,> soweit ich weiß, muss man EIND noch manuell auf 1 oder 0 setzen,> oder kann das der GCC inzwischen automatisch?
avr-gcc geht davon aus, dass EIND immer den gleichen Wert hat.
Indirekte Sprünge werden über Linker-Stubs aka. .trampolines erledigt.
Aber es geht nicht um EIND sondern z.B. RAMPZ, d.h. Lesen aus dem Flash
(.progmem.data) et al.
Johann L. schrieb:> N. G. schrieb:>> Hallo Johann,>>>> das heißt, dass es schon eine Section gibt, die ich nur noch passen>> verschieben müsste? Das wäre schon mal gut.>> Was willst du denn "verschieben"?
Woher weiß denn der Linker, wo die section liegen muss? Weil das ist ja
einerseits vom Device abhängig (wobei das nicht das Problem wäre, da der
Linker den Typen ja kennt) und andererseits von den Settings der Fuses
(also wie groß der Bootloader ist).
Also denke ich, dass man dem Linker irgendwie mitteilen muss, wo die
Section zu liegen hat. Das meint ich mit verschieben.
Johann L. schrieb:> D.h. die zu beschreibenden Objekte sind als const volatile zu> deklarieren.
Warum const volatile?
Also ich verstehe den Sinn dahinter, const weil ich sie nur lese und
volatile, weil sie sich ohne zutun des Compilers ändern können, aber:
Wenn ich das volatile weglasse: was passiert dann? (Ich werde mir sobald
ich den Code geschrieben habe das disassembly schauen, aber vllt gibts
ja schon eine Prognose vom Guru ;) )
Johann L. schrieb:>>> wobei zu beachten ist, dass die Adressen i.d.R nicht in 16 Bits>>> passen.>>>> Ja,>>> soweit ich weiß, muss man EIND noch manuell auf 1 oder 0 setzen,>> oder kann das der GCC inzwischen automatisch?>> avr-gcc geht davon aus, dass EIND immer den gleichen Wert hat.> Indirekte Sprünge werden über Linker-Stubs aka. .trampolines erledigt.>> Aber es geht nicht um EIND sondern z.B. RAMPZ, d.h. Lesen aus dem Flash> (.progmem.data) et al.
Okay, mein Fehler.
Ich meinte etwas anderes, bzw. habe zwei Dinge in einen Topf geworfen.
Brauche ich EIND nicht zu setzen, um zum Bootloader-Bereich zu springen,
weil der über der 64kB-Grenze liegt? Weil das ist ja ein direkter
Sprung/Call und sollte nichts mit den trampolines zu tun haben.
Aber nichts desto trotz hast du mit RAMPZ natürlich recht. Wobei RAMPZ
doch 0 bleiben kann, wenn die zu verändernden Daten auf Pages liegen,
die von einem 16bit-Pointer erreicht werden können.
PS: So eine Unterhaltung mit dir ist immer unglaublich bildend :D
Okay, wenn ich das wollen würde, würde ich mein Problem seeeehr
umständlich lösen...
Okay, nochmal von vorne mit genauerer Erklärung der Gegebenheiten:
ich habe mehrere Tabellen (am ende Wahrscheinlich 3, das Programm ist
aber noch in der Entwicklung).
Diese Tabellen sind Lösungen verschiedener Gleichungen in Abhängigkeit
verschiedener Winkel.
Soweit alles noch kein Problem.
Nur haben die Formel Koeffizienten, die von Zeit zu Zeit mal (manuell)
verändert werden müssen.
Es soll ein Menü geben, in welchem man die Faktoren verändern kann.
Jetzt könnte man die Faktoren einfach im RAM speichern und jedes mal
damit rechnen. Nur sind die Gleichungen lang und mit Gleitkomma sehr
aufwändig.
Deswegen sollen Tabellen erstellt werden, die einmal vom AVR errechnet
und anschließend gespeichert werden.
Genau da sitzt eben mein Problem: ich muss die __flash-Tabellen aus dem
Programm heraus verändern.
Also:
Mensch geht an ein Interface und stellt in einem Menu einen neuen
Koeffizienten ein.
Der AVR springt zum Bootloaderbereich.
Dort berechnet er die neue Tabelle mit dem geänderten Koeffizienten ein
mal und speichert sie dann an den Platz der alten Tabelle.
Danach springt der AVR zurück zum Menü.
N. G. schrieb:> Warum const volatile?
Stell dir vor der Compiler kennt einen der Werte im Original-Array zur
Compilezeit und macht z.B. ein LDI *,42 daraus.