Hallo,
zum Thema Flash findet man eigentlich einen Haufen Zeug im Netz, aber
ich werde trotzdem nicht so ganz schlau.
Ich möchte das digitalisierte Abbild einer (mathematischen) Funktion in
den Flash-Speicher des ATMega16 schreiben. Dazu lass ich mir zunächst
100 Funktionswerte berechnen, ich rastere die Funktion quasi ab. Diese
Funktionswerte sollen dann als 1D-Array im Flash gespeichert werden.
Als reinen Test, ob ich überhaupt den Flash ansprechen kann, habe ich
erst ein festes Array definiert und es später ausgelesen, was
einwandfrei funktioniert:
Nun ist meine Idee, erst ein leeres Array zu initialisieren und einen
Pointer zu definieren, der auf den Array-Anfang zeigt, was auch
funktioniert:
1
conststaticuint16_tflash_table[100]PROGMEM={};
2
uint16_t*flash_pointer=flash_table;
Zumindest sehe ich im Debugger, dass der Bereich reserviert und mit
Nullen belegt ist und auch der Zeiger zeigt auf die Startadresse.
Danach möchte ich über den Pointer die reservierten Adressen mit den
Funktionswerten beschreiben, was aber ignoriert wird:
1
for(uint16_ti=0;i<100;i++)
2
{
3
*flash_pointer=function(i);
4
}
Das Programm wird so kompiliert, aber in den Adressen ändert sich
trotzdem nichts, der gesamte Bereich bleibt auf 0x00. Soweit ich gelesen
habe, können Flash und SRAM die gleichen Adressen haben und man muss sie
durch PROGMEM unterscheiden, aber wenn ich dieses Wort hinzufüge, bricht
der Compiler ab mit "expected ';' before '__attribute'".
Oder ist schlicht meine C-Syntax falsch? Wie geht man das normalerweise
an?
Grüße
Peter
Peder schrieb:> Danach möchte ich über den Pointer die reservierten Adressen mit den> Funktionswerten beschreiben, was aber ignoriert wird:
Es wird nicht ignoriert. Das Flash ist zur Laufzeit nicht beschreibbar.
D.h. das stimmt nicht ganz. Es gibt schon eine Möglichkeit, Bootloader
müssen das ja auch können. Aber es geht nicht so banal wie du dir das
vorstellst. In einem AVR ist das Flash nur seitenweise beschreibbar, was
für einen Bootloader keine große Rolle spielt, denn der sammelt einfach
eintreffenden Programmcode, bis er eine Seite beisammen hat und schreibt
dann die Seite in einem Rutsch. Aber für ein normales Programm, ist das
nicht brauchbar, zumal dieses Flash Beschreiben auch nur dann
funktioniert, wenn der Code, der es macht in der Bootloader Sektion vom
AVR steht.
Ergo:
Vergiss es. Denk dir was anderes aus. Für dich ist das Flash 'nicht
beschreibbar'. Das Flash ist der Programmspeicher und als solcher für
das Programm unantastbar. Genau das ist es, was eine
'Harvard-Architektur' ausmacht.
Wenn du Daten brauchst die eine Stromabschaltung überleben, dann gibt es
da noch das EEPROM. D.h. wenn es groß genug für deine Zwecke ist.
Die Antwort ist simpel: Du kannst aus Deiner Anwendung heraus kein Flash
beschreiben, nur daraus lesen.
Ja, das hat der böse Hersteller mit Absicht verhindert.
Karl Heinz Buchegger schrieb:> Wenn du Daten brauchst die eine Stromabschaltung überleben, dann gibt es> da noch das EEPROM. D.h. wenn es groß genug für deine Zwecke ist.
Wenn die Daten immer dieselben (d.h. konstant) sind, dann soll er auf
dem PC und (nicht auf dem µC) den Abschnitt
1
for(uint16_ti=0;i<100;i++)
2
{
3
*flash_pointer=function(i);
4
}
laufen lassen und das Ergebnis als Datei imflash.c in C-Syntax ausgeben.
Diese C-Datei kann er dann zu seinem Projekt hinzulinken und schon hat
er sein Array beim nächsten "Brennen" auch im Flash ;-)
Der EEPROM ist mir leider zu klein. Ich brauche mindestens 2kB, aber die
Daten sind dann auch tatsächlich konstant.
Dass man EEPROM und Flash irgendwie aus dem AVR Studio beschreiben kann,
ist mir auch mal aufgefallen, allerdings hab ich dazu recht wenig Infos
gefunden. Aber wenn das ginge, wäre das auch eine Lösung.
Nun wird aber der Programm-Code auch im Flash gespeichert. Wenn ich dann
mein Funktionswerte in den Flash schreiben will, überschreibe ich nicht
den Programm-Code?
Und ich hoffe, die Frage klingt nicht zu sehr nach "Schreibt mir mal
mein Programm", aber wie funktioniert das mit der C-Syntax und dem
Dazulinken? Das einzige Mal, dass ich von Hand linken musste, ist gut
fünf Jahre her und das war per Konsole.
Wenn ich die for-Schleife einfach in eine Datei gebe, in welchem Format
sollte ich das tun? Einfach lückenlos eine Zahl nach der anderen?
Peder schrieb:> Wenn ich die for-Schleife einfach in eine Datei gebe, in welchem Format> sollte ich das tun? Einfach lückenlos eine Zahl nach der anderen?
Am Ende muß genau so etwas da stehen:
> const static uint16_t flash_table[5] PROGMEM = {0,1,2,3,4};
Oliver
Frank M. schrieb:> Die Antwort ist simpel: Du kannst aus Deiner Anwendung heraus kein> Flash> beschreiben, nur daraus lesen.>> Ja, das hat der böse Hersteller mit Absicht verhindert.
Das ist so generell ist das natürlich Blödsinn.
Natürlich kann man Flash beschreiben. Nur halt nicht so "einfach".
Man braucht: eine Flash lib oder halt die Flashfunktionen selber
schreiben.
Diese landen dann im RAM und können Flash schreiben.
Manche uCs können auch Code aus einer Flashpage ausführen und eine
andere beschreiben - Kopie ins RAM dann nicht zwingend.
convert schrieb:> Das ist so generell ist das natürlich Blödsinn.
Ich bezog mich auf den Thread-Titel: "ATMega Flash: Array"
> Natürlich kann man Flash beschreiben. Nur halt nicht so "einfach".> Man braucht: eine Flash lib oder halt die Flashfunktionen selber> schreiben.
Beim ATmega kannst Du das Flash-Memory nur über einen Bootloader
beschreiben.
> Diese landen dann im RAM und können Flash schreiben.
Geht beim ATmega nicht - außer über Bootloader. Der ist aber eine Nummer
zu groß für den TO.
> Manche uCs können auch Code aus einer Flashpage ausführen und eine> andere beschreiben - Kopie ins RAM dann nicht zwingend.
Wir reden über ATmega. Mein Posting hatte keinen allgemeingültigen
Anspruch.
Peder schrieb:> Und ich hoffe, die Frage klingt nicht zu sehr nach "Schreibt mir mal> mein Programm", aber wie funktioniert das mit der C-Syntax und dem> Dazulinken? Das einzige Mal, dass ich von Hand linken musste, ist gut> fünf Jahre her und das war per Konsole.
Du fügst im AVR Studio die erzeugte C-Datei einfach dem Projekt hinzu.
Alternativ kannst Du auch eine Header-Datei erzeugen, die Du dann in
main.c einfach "includierst". Ist sogar noch einfacher.
> Wenn ich die for-Schleife einfach in eine Datei gebe, in welchem Format> sollte ich das tun? Einfach lückenlos eine Zahl nach der anderen?
Nein, so:
meinflash.h (diese Datei musst Du per C-Programm auf dem PC erzeugen):
1
staticconstuint16_tflash_table[100]PROGMEM=
2
{
3
1,
4
2,
5
....
6
};
In main.c Deines µC-Programms schreibst Du dann einfach:
#include "meinflash.h"
Und schon kannst Du auf alle Werte zugreifen.
Dein C-Programm für den PC kann folgendermaßen aussehen:
Der Quellcode ist auf Unix/Linux getrimmt, evtl. musst Du noch windows.h
hinzufügen, damit es auch unter Windows läuft.
@Oliver: Dein "static" wird in einer separaten C-Datei nicht
funktionieren.
Für die Überschrift muss ich mich fast noch entschuldigen, die war
einfach nur nicht fertig und nach dem Beitrag hab ich die glatt
vergessen.
Ansonsten hab ich das Konzept denke ich verstanden. Ich werd das am
Montag mal ausprobieren, dann geb ich Bescheid, wie es lief.
Danke!
Karl Heinz Buchegger schrieb:> Es wird nicht ignoriert. Das Flash ist zur Laufzeit nicht beschreibbar.
[...]
Karl Heinz Buchegger schrieb:> Für dich ist das Flash 'nicht> beschreibbar'. Das Flash ist der Programmspeicher und als solcher für> das Programm unantastbar. Genau das ist es, was eine> 'Harvard-Architektur' ausmacht.
Hallo.
Da möchte ich doch diese Gelegenheit nocheinmal nutzen, um für mein
Beispiel in
Beitrag "Re: [ATMega] Programm aus externem EEprom laden"
zu werben.
Dort habe ich ein Beispiel demonstriert wie man solches eben doch machen
kann.
(Auch aus RWW Sektionen.)
MfG matrixstorm
p.s.: Ich stehe für Fragen gern zur Verfügung.
Die Idee mit der separaten C-Datei ist eigentlich so sonnenklar, dass
man auch selbst hätte drauf kommen können. Ich habe das Ganze soweit
umgesetzt und es hat einwandfrei funktioniert.
Ich verstehe nur nach wie vor nicht, warum es trotzdem möglich war, zur
Laufzeit und sogar innerhalb der main() (!) ein konstantes Array in den
Flash zu schreiben.
Aber sei es drum, für meine Zwecke reicht es, wenn ich mir merke, dass
es so ist.
Danke
Peder schrieb:> Ich verstehe nur nach wie vor nicht, warum es trotzdem möglich war, zur> Laufzeit und sogar innerhalb der main() (!) ein konstantes Array in den> Flash zu schreiben.
Kommt auf dein Testprogramm an.
Des Compilers Optimizer sind ausgefuchster als du denkst. Der findet
raus,wie du dein Array beschreibst und kann in manchen Fällen dann die
Werte aus seinen während der Programmanalyse gemerkten Werten einsetzen,
die nie im Flash gelandet sind und vom Programm auch nie ausgelesen
wurden.
damit hast du das PC Programm davon befreit, dass es 100 Datenpaare
anlegen muss. Es kann beliebig viele machen und muss auch nicht wissen,
wie im AVR Programm die Variable heißt. Das PC Programm erzeugt einfach
nur die Daten, die im AVR Programm zur Initialisierung benutzt werden.
Um alles andere muss es sich nicht mehr kümmern.
Denn: Dem #include ist es egal, was in der anderen Datei steht. Der
Präprozessor ersetzt einfach nur die Zeile mit dem #include durch den
Inhalt der angegebenen Datei. Und erst danach muss wieder gültiges C
rauskommen. Denn der eigentliche C-Compiler sieht dein 'Machwerk' ja
erst, nachdem der Präprozessor alle Textersetzungen vorgenommen hat.
Wenn du willst, kannst du auch so programmieren
int.h
1
int
main.h
1
main
klammer_auf.h
1
(
klammer_zu.h
1
)
test.c
1
#include"int.h"
2
#include"main.h"
3
#include"klammer_auf.h"
4
#include"klammer_zu.h"
wenn der Präprozessor alle #include durch die Inhalte der jeweiligen
Dateien ersetzt hat, dann kommt da raus
1
int
2
main
3
(
4
)
und das ist ja ein gültiges C-Programm, welches anstandslos durch den
Compiler gehen wird.