Hallo Kollegen,
ich möchte eine größere Anzahl Gleitkommazahlen im Flash ablegen.
Hierzu hab ich angehängte Datei von der TI Homepage genommen und zum
experimentieren erstmal modifiziert.
Für den Anfang will ich nur einen Wert von 18.4 speichern.
Ich bin noch sehr neu im ganzen Thema Mikrokontrollerprogrammierung und
bin mir gar nicht sicher ob das mit Gleitkommazahlen überhaupt so ohne
weiteres geht. Ich hatte die Hoffnung der Compiler rechnet die Zahl
selbstständig in die entsprechende Darstellung mit Mantisse etc. um und
schiebt sie dann in den Flash.
Leider wird immer nur der Ganzzahlanteil, also 18, in den Speicher
geschrieben. Binär:
11111111111111111111111100010010 statt
0 10000011 00100110011001100110011
Hier erstmal der Code, Chip ist ein MSP430G2452 auf Launchpad. Compiler
der CCS:
1
#include<msp430.h>
2
3
floatvalue;// 8-bit value to write to segment A
4
5
// Function prototypes
6
voidwrite_SegC(floatvalue);
7
8
9
intmain(void)
10
{
11
WDTCTL=WDTPW+WDTHOLD;// Stop watchdog timer
12
if(CALBC1_1MHZ==0xFF)// If calibration constant erased
13
{
14
while(1);// do not load, trap CPU!!
15
}
16
DCOCTL=0;// Select lowest DCOx and MODx settings
17
BCSCTL1=CALBC1_1MHZ;// Set DCO to 1MHz
18
DCOCTL=CALDCO_1MHZ;
19
FCTL2=FWKEY+FSSEL0+FN1;// MCLK/3 for Flash Timing Generator
20
value=18.4;// initialize value
21
22
write_SegC(value);// Write segment C, increment value
*Flash_ptr=0;// Dummy write to erase Flash segment
34
35
FCTL1=FWKEY+WRT;// Set WRT bit for write operation
36
37
for(i=0;i<16;i++)
38
{
39
*Flash_ptr=value;// Write value to flash
40
Flash_ptr=Flash_ptr+4;
41
}
42
43
FCTL1=FWKEY;// Clear WRT bit
44
FCTL3=FWKEY+LOCK;// Set LOCK bit
45
}
Interessant ist noch, dass wenn ich einen Breakpoint in der
Unterfunktion setze, der Debugger für die Variable Value immer den Wert
13107.0 zeigt.
Nachdem aus der Unterfunktion wieder rausgesprungen wird, enthält die
Variable wieder den korrekten Wert.
Weiß jemand Rat?
Lg
Eddie
Okay, habs grad versucht. Keine Änderung.
>und dann char *Flash_ptr; // Flash pointer>nach float *Flash_ptr;
Hatte ich im Vorfeld schon probiert, dann nimmt er aber die
Adresszuweisung für den Pointer nicht mehr.
>und Flash_ptr = Flash_ptr + 4;>zu Flash_ptr++;
hatte ich geändert weil ja die Gleitkommazahl in einen 32Bit Wert
umgerechnet werden hätte umgerechnet werden müssen.
Ich kann jetzt auch nicht sagen, warum er nicht auf (float *) casten
will, aber ich hab mich vor ein paar Wochen mal mit der ganzen
Flash-Problematik auseinandergesetzt.
Die TI-Beispiele sind da sehr primitiv, sie sollen ja auch nur
verdeutlichen wie das prinzipiell geht. Da wird eine Variable auf dem
RAM angelegt, dann der Zeiger verbogen und ins Flash geschrieben.
Außerdem ist das Löschen des Segments und das Schreiben der Variablen in
ein und derselben Funktion, d.h. Du kannst immer nur die eine Variable
schreiben, der Rest ist futsch.
In meiner flash.c habe ich also eine Funktion zum Löschen und
verschiedene Funktionen zum Schreiben und hab jetzt mal eben eine
Funktion für float dazugebastelt. Also man löscht erst das Segment, und
dann kann man nach belieben Schreiben.
Außerdem lege ich mit einer Compiler-Direktive die Variable direkt ins
Flash. Das hat den Vorteil, daß man jederzeit, ohne eine Funktion
benutzten zu müssen direkt auf die Variable zurgreifen kann, allerdings
funktionier eine normale Wertzuweisung value=18.5 natürlich nicht mehr,
stattdessen muß man schreiben:
writeFloat(&value , 18.5)
und auf diesen Speicherplatz darf seit dem letzten Löschen noch nicht
geschrieben worden sein.
Ach und nochwas: daß beim Debuggen der Wert der Variablen nicht oder
falsch angezeigt wird, ist normal. Wahrscheinlich liegt das daran, daß
während des Schreibens kein Lese- oder sonstiger Zugriff aufs Flash
erlaubt ist, vermutlich funktioniert dadurch auch das Debuggen nicht.
Also bei mir funktioniert das Beispiel in der main.c (CCS 5.5), die
Werte stehen danach korrekt im Flash.
Gruß wv
Hi,
schonmal danke für eure umfangreichen Mühen! Ich habs jetzt hinbekommen.
Es ging so wie ihrs mir schon beschrieben habt, per cast. Offenbar hatte
ich beim ersten Versuch irgendwo was anderes falsch gemacht.
1
#include<msp430.h>
2
3
floatvalue;// 8-bit value to write to segment A
4
5
// Function prototypes
6
voidwrite_SegC(floatvalue);
7
8
9
intmain(void)
10
{
11
WDTCTL=WDTPW+WDTHOLD;// Stop watchdog timer
12
if(CALBC1_1MHZ==0xFF)// If calibration constant erased
13
{
14
while(1);// do not load, trap CPU!!
15
}
16
DCOCTL=0;// Select lowest DCOx and MODx settings
17
BCSCTL1=CALBC1_1MHZ;// Set DCO to 1MHz
18
DCOCTL=CALDCO_1MHZ;
19
FCTL2=FWKEY+FSSEL0+FN1;// MCLK/3 for Flash Timing Generator
20
value=18.4;// initialize value
21
22
write_SegC(value);// Write segment C, increment value
Ich hab nun mein Programm etwas geändert. Nun wollte ich denselben
Float-Wert in den Haupt Flash bringen. Hierfür habe ich erstmal die
ersten zwei Segmente gelöscht und schreibe dann 1 KB ins zweite Segment.
Interessant ist, dass ich nun den Start des Pointers auf das erste Byte
setzen muss also auf 0xFBFC statt auf 0cFBFF sonst wird der Wert falsch
in den Flash geschrieben. Hier nochmal zur Erläuterung:
1.KB im Flash geht von 0xFFFF bis 0xFBC0
2.KB im Flash geht von 0xFBFF bis 0xF800
Im ersten Codebeispiel habe ich den Wert in den Information Memory
geschrieben und den Pointer auf das hinterste der 4 Byte gesetzt.
Hier im Main Flash muss der Pointer offenbar auf das erste der 4 Byte
zeigen.
Hier richtig:
*Flash_ptr=0;// Dummy write to erase Flash segment
100
Flash_ptr=(float*)(0xFFFF-i);
101
}
102
103
Flash_ptr=(float*)0xFBFC;
104
for(i=0;i<256;i++)
105
{
106
while(FCTL3&BUSY);
107
FCTL1=FWKEY+WRT;// Set WRT bit for write operation
108
*Flash_ptr=value;// Write value to flash
109
while(FCTL3&BUSY);
110
Flash_ptr--;
111
}
112
113
FCTL1=FWKEY;// Clear WRT bit
114
FCTL3=FWKEY+LOCK;// Set LOCK bit
115
}
Anfangs hatte ich den Pointer auf das letzte der 4 Byte gesetzt, also
auf 0xFBFF und dann wurden die 4 Byte genau drum herum verteilt.
D.h. die ersten zwei gingen nach 0xF800 und 0xF801 und die anderen zwei
Byte gingen nach 0xF7FC und 0xF7FD. Siehe hierzu auch mal das angehängte
Dokument.
Gruß
Eddie
Die Segmente im "Haupt"-flash sind 512 Byte groß, es reichen also 4
Löschvorgänge um 2kB zu löschen. Außerdem stehen im obersten Segment von
0xFE0 bis 0xFFFF die Interuptvektoren, dieses Segment würde ich auf
keinen Fall löschen, sonst wunderst Du Dich später, wenn ein Interrupt
im Nirwana landet.
Gruß wv
Am Anfang bist du über die Überdeckung der Variablen value gestolpert.
Du solltest eine der beiden umbennen.
Andere den Namen von value
float value;
Und passe den Aufruf an
write_SegC(value);
Hi,
>Am Anfang bist du über die Überdeckung der Variablen value gestolpert.
Ich weiß, aber eine Änderung der Benamung hat nichts geändert, daher hab
ichs ersmal wieder so gelassen.
>Außerdem stehen im obersten Segment von>0xFE0 bis 0xFFFF die Interuptvektoren
Ookay - muss ich die nun da wieder reinschreiben oder initialisiert sich
das irgendwie von selbst?
Ich bin noch ziemlich neu in all dem und hab mit den Interrupts noch
nicht viel gemacht.
Nachdem ich nach mehreren erfolglosen Versuchen das Segment A des
I.Flash`s endlich erfolgreich beschreiben konnte, durfte ich dananch
auch feststellen, dass ich mir die Kalibrierkonstanten damit
überschrieben hatte.
Damit war der G2553 des Launchpads schon erstmal futsch. Irgendwann muss
ich mal den Crystal aufs Board auflöten und dann gibt`s im Netz ja div.
Programme die die da wieder reinschreiben. Zum Glück war ja noch der
G2452 beim Launchpad dabei.
Wo steht denn eigentlich genau geschrieben wo welche Speicherbereiche im
Chip sind? Die Doku von TI ist da irgendwie sehr vage.
Im Datenblatt des Chips ist nur ne kleine Tabelle (siehe Seite 11).
In der Family description ist auch nur ne prinzipielle Angabe (siehe
Seite 310).
Hab die Datenblätter mal angehängt.
LG
Eddie
Hallo Eddie,
das mit den Interruptvektoren ist nicht so schlimm, beim nächsten Laden
des Programms sind sie wieder da. Nur funktioniert so ein Programm
nicht, wenn man Interrupts benutzt. Wenn man also unbedingt während des
Programmlaufs in das oberste Segment was schreiben will, muß man vorher
die Vektoren sichern und danach wieder reinschreiben.
Anders verhält es sich mit den Kalibrierdaten, die werden bei der
Herstellung des Chips reingeschrieben und sind dann da bis Du sie
löschst...
Die Anordnung der Speicherbereiche findest Du im Datenblatt des
jeweiligen Chips, da ja die Größe von Flash und Ram unterschiedlich ist.
Das Schema ist aber immer das gleiche:
0x0000 - 0x000F CPU - Register
0x0010 - 0x00FF 8 Bit Periferie z.B. IO Ports
0x0100 - 0x01FF 16 Bit Periferie z.B. Timer
0x0200 bis je nachdem wieviel Ram der Chip hat, dort sitzen
dei Variablen, Stackpointer usw. RAM
------------------------------------
je nach Ram-Größe ist hier ein Loch
------------------------------------
FLASH
0x1000 InfoD
0x1040 InfoC
0x1080 InfoB
0x10C0 InfoA
--------------------
Loch
--------------------
je nach Größe des Flash
beginnt dieser nun hier irgendwo
und geht immer bis
0xFFFF FLASH ENDE
--------------
Dann lohnt sich auch ein Blick in das Linker - Command - File, da steht
die Information für den Linker, wo welche Speicherbereiche im Chip zur
Verfügung stehen. Das File steht im Haupverzeichnis deines Projekts, und
heißt lnk_msp430gxxxx.cmd, je nach verwendetem Chip.
Außerdem entsteht nach jedem Build deines Projekts im Unterverzeichnis
\Debug deines Projekts eine Datei, die meinProjekt.map heißt. Das ist
die Ausgabe des Linkers, dort kann man genau sehen, wo welche Variablen
gelandet sind.
Allerdings weiß der Linker natürlich nichts von Deinen verbogenen
Zeigern, und daran sieht man auch die ganze Problematik dieser
Geschichte. Ich weiß, daß Du ein Beispiel von TI hier modifiziert hast.
Das ist auch soweit ok, um sich mit den ganzen Funktionen rund ums Flash
vertraut zu machen. Allerdings funktioniert das alles nicht mehr, wenn
das Programm größer wird, wie Du am Beispiel der Interruptvektoren
gesehen hast, denn solange Du sie nicht benutzt, merkst Du auch nicht
wenn sie weg sind. Wenn Du aber später irgendeine Funktion hinzufügts,
die sie benutzt, wird Dir das ganze mit sehr merkwürdigen Effekten
abschmieren.
Genauso kann das passieren, wenn Du einfach Zeiger verbiegst, und
irgendwelche Segmente löschst. An Anfang ist Dein Programm klein, die
oberen Segmente sind alle leer (bis auf die besagten Interruptvektoren),
und dann erweiterst Du Dein Programm immer mehr, und dann wird
irgendwann, wenn Du nicht mehr an diese Funktion denkst, löscht Dir
deine eigene Funktion Teile Deines Programms.....
Ich finde es auch nicht gerade professionell von TI, so ein Beispiel in
die Welt zu setzen, ohne das weiter zu kommentieren oder wenigstens
einen Anhaltspunkt zu geben, wie man das vernünftig angeht.
Gruß wv
Hey super, vielen Dank. Ich habs jetzt auch erstmal so programmiert dass
das erste (eigentlich letzte Segment bis 0xFFFF) nicht gelöscht wird
sondern die zwei Segmente oben drüber.
Danke für die vielen Mühen von überall.
Beim nächsten Mal muss ich das dann mal analog deiner Beispiele machen.
Dann ist auf jeden Fall übersichticher und man bringt sich nicht so
schnell selbst aus dem Tritt.
Auch die viele Adressenrechnerei im HEX-Format kann einen ganz schön
durcheinander bringen. So hab ich mich auch erstmal voll vertan als ich
die Adresse des zweiten Segmentes ausrechnen wollte und hab doch glatt
0xFFFF-512 statt - des Hexwertes davon - also 0x200 - gerechnet und
mich dann gewundert wieso ich nicht genau auf dem letzten Byte des
nächsten Segmentes lande. Aber gut, dann hab ichs doch noch geschnallt:)
Hier nochmal mein fertiger Code:
A. H. schrieb:> Übrigens - was sind eigentlich Compilerdirektiven?
grob gesagt, alles was mit #pragma anfängt.
Normalerweise "weiß" der Compiler, was er mit einem .c und einem .h file
anzufangen hat, genauso der Linker. Diese Direktiven dienen dazu, dieses
Verhalten zu beeinflussen, wo es notwendig ist.
In unserem Beispiel bedeutet die Deklatation der Variablen value
float value;
für den Compiler, daß er Speicherplatz für eine float-Variable
bereitstellen muß. Nun schaut er in der Runtime-Support-Library nach,
wie groß eine float auf diesem System ist, und reserviert eine zunächst
virtuelle Adresse und die drei folgenden (insgesamt 4) Byte. Dem Linker
wurde der zur Verfügung stehende Speicher über das Linker-Command-File
mitgeteilt. Da es sich um ein variable Größe handelt, wird ihr nun eine
feste Adresse im RAM zugewiesen.
Nun wollten wir aber eigentlich Speicherplatz auf dem Flash haben, und
wollen das dem Linker mitteilen, also schreiben wir:
#pragma DATA_SECTION(value , ".infoC")
float value;
Jetzt weiß der Linker (dem Compiler ist das egal), daß er diesen
Speicher im Flash, und zwar genau im infoC reservieren muß. Es geht also
ganz ohne Hex-Rechnerei, das erledigt nämlich der Linker, der dann auch
darauf achtet, daß sich nichts in die Quere kommt.
Man kann so auch mehrere Variablen oder ganze Bereiche im Flash
reservieren. Wenn Du also ein ganzes Segment vollschreiben willst:
#pragma DATA_SECTION(value , ".infoC")
float value[16];
Ich bleibe erstmal absichtlich beim InfoMem, da gehts etwas einfacher,
weil diese Bereiche im Linker-Command-File vordefiniert sind, der
restliche Bereich des Flash ist dort ein ganzer Block. Es geht aber
auch, dazu später.
Jetzt können wir die Funktion aus dem TI-Beispiel nehmen (siehe meine
flash.c, flash.h) aber immer Löschen und Schreiben trennen. Du willst ja
später sicherlich irgendwelche Sensorenwerte lesen und speichern, die so
nach und nach eintrudeln, dann kannst Du nicht bei jedem Aufruf das
Flash wieder löschen.
----
1
//Prototypes
2
voidwriteFloat(float*Flash_ptr,floatvalue);
3
voideraseSegment(void*pointer);
4
5
//Array-Variable im Flash
6
#pragma DATA_SECTION(value , ".infoC")
7
floatvalue[16];
8
inti;
9
10
11
12
intmain(void)
13
{
14
//Deine Initialisierung ist soweit richtig
15
//..
16
17
eraseSegment(&value);
18
19
for(i=0;i<16;i++)
20
{
21
writeFloat(&value[i],18.5);
22
}
23
}
24
25
voidwriteFloat(float*Flash_ptr,floatvalue)
26
{
27
FCTL3=FWKEY;// Clear Lock bit
28
FCTL1=FWKEY+WRT;// Set WRT bit for write operation
29
*Flash_ptr=value;// Write value to flash
30
FCTL1=FWKEY;// Clear WRT bit
31
FCTL3=FWKEY+LOCK;// Set LOCK bit
32
}
33
34
voideraseSegment(void*pointer)
35
{
36
char*seg_pointer;
37
38
seg_pointer=pointer;
39
FCTL1=FWKEY+ERASE;// Set Erase bit
40
FCTL3=FWKEY;// Clear Lock bit
41
*seg_pointer=0;// Dummy write to erase Flash segment
42
FCTL1=FWKEY;// Clear Erase bit
43
FCTL3=FWKEY+LOCK;// Set LOCK bit
44
}
Du siehst, es geht alles auch ohne Hex-Rechnerei. Die Funktionen sind
für alle Info-Segmente D,B,C anwendbar, mit einer kleinen Änderung am
Linker-Command-File geht's auch in den anderen Segmenten, da muß man
dann doch ein bißchen rechnen.
Die spannende Frage hierbei ist noch:
Ich möchte Sinuswerte im Flash ablegen. Dazu hab ich sie in einem Float
Array definiert und schreibe sie dann in den Flash. Das funktioniert
soweit auch, aber wenn ich sie doch eh im Array festlege, wieso schreibe
ich sie dann nochmal in den Flash? Das ist ja nur doppelter
Speicherverbrauch. Einmal im Flash und einmal im RAM. Aber ein anderes
mittel gibts ja auch nicht. Egal ob ich deine oder die Methode aus dem
TI Beispiel benutze, ich muss die werte ja immer erst mal in irgendeiner
Art von Variablen/ Constanten ablegen damit ich sie in den Flash
schieben kann.
LG
A. H. schrieb:> Ich möchte Sinuswerte im Flash ablegen.
Wenn du die Werte bereits zur Übersetzung kennst, kannst du sie direkt
als Konstantanten ablegen. Sie landen dann nur im Flash. Du kannst sie
dann direkt aus dem Flash ausgeben, oder nach einander über eine einzige
Variable einzeln laden und verarbeiten.
Beschreib einmal dein Projekt.
Ich möchte per PWM einen Sinus erzeugen. Dazu möchte ich einen
Viertel-Sinus als Werte speichern und dann entsprechend für den duty
cycle verwenden.
Nun hatte ich überall gelesen dass die Leute die Werte in den Flash
legen und von da abfragen. Also wollte ich das gleich tun. Darauf
bezieht sich der obige Thread. Nun, mittlerweile hab ichs hinbekommen,
frag mich aber halt wieviel Sinn das macht, da ich die Werte ja eh als
Konstanten im RAM liegen haben muss um sie von da in den Flash schreiben
zu können.
LG
A. H. schrieb:> frag mich aber halt wieviel Sinn das macht, da ich die Werte ja eh als> Konstanten im RAM liegen haben muss um sie von da in den Flash schreiben> zu können.
Nein, du brauchst die Variablen nicht im RAM! Du kannst das array als
Konstanten vollständig im Flash ablegen.
Zu deinem Verständnis: Wie kommen die Werte zur Laufzeit ins RAM?
Natürlich aus dem Flash. Bei deiner Variante hast du dreifachen Speicher
verbraucht.
- Flash zu RAM Initialisierung
- Werte im RAM
- Flash zur Laufzeit beschrieben
Puhhhh ...
A. H. schrieb:> wenn ich sie ganz normal in ein Array deklariere, dann sind sie> doch erst mal im RAM dachte ich.
Jein.
float myArray[]; ---> RAM
const float myArray[] = {0.12 , 0.17 ... usw}; ---> Flash
Wenn es sich um konstante Werte handelt, wie bei Deiner Sinus-Tabelle,
dann definiert man sie einfach als Konstante. Dadurch landen sie
automatisch im Flash.
Die ganzen anderen Funktionen, die auch teilweise spezielle
Linker-Anweisungen benötigen, braucht man nur, wenn man während der
Laufzeit ins Flash schreiben will, beispielsweise um Sensorenwerte zu
loggen.
Gruß wv
wv schrieb:> float myArray[]; ---> RAM>> const float myArray[] = {0.12 , 0.17 ... usw}; ---> Flash
Und ganz fies:
float myArray[] = {0.12 , 0.17 ... usw}; ---> RAM
Wird beim Starten initialisiert. Wenn man Pech hat, schlägt in dieser
Zeit schon der Watchdog zu.
Dann muss man in _system_pre_init() den Watchdog ausschalten. BTDT.
Max
Okay, danke. Dann hab ich die jetzt erstmal per const in den Flash
geschickt.
Das Ganze soll ja ne Sinus Pwm werden. Häng da jetzt grad an der
nächsten Stelle. Aber da mach ich mal nen neuen Fred auf. Ist jetzt ein
anderes Thema.
Schonmal riesen danke an alle Helfer
Hallo zusammen.
dieser Thread hat mir schon sehr viel weiter geholfen.
Ich habe versucht in einem individuellen Flash Sektor 0x100 groß
einen const struct zu initialisieren.
#pragma DATA_SECTION(Ueberstrom , ".Config")
const TMenueItem Ueberstrom = {'Ueberstrom', 1, 10, 1000}
die Initialisierung funktioniert mit dem Vorsatz const leider nicht.
Dann liegt die Variable zwar im Flash, ich kann aber mit der Funktion
void writeLong(Long *Flash_ptr, Long value)
{
FCTL3 = FWKEY; // Clear Lock bit
FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
*Flash_ptr = value; // Write value to flash
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK; // Set LOCK bit
return;
}
den Wert nicht ändern und die Initialiserung wird nicht übernommen.
Habt ihr hierfür auch noch eine Idee?
Danke
Hallo,
das habe ich auch herausgefunden. Allerdings ist ja dann der ganze
Flashbereich gelöscht. gibt es auch eine Möglichkeit nur einen Wert zu
ändern?
Wie macht man das sonst.
512 Byte im Ram zwischenpeichern und dann alles umkopieren und den
gewünschten Wert ändern?
Hallo Dieter,
man muß tatsächlich immer einen ganzen Block löschen, also muß man auch
alles vorher ins RAM sichern, den geänderten Wert austauschen und wieder
zurückschreiben.
Zeig doch mal den Ausschnitt von Deinem Linker-Command-File, wo du
.Config definiert hast. Da muß Du nämlich verhindern, daß Dein struct
über eine Blockgrenze geht, denn dann müßtest Du beide Blöcke sichern
und löschen.
const muß bei der initialisierung weg, denn das ist eine
Compileranweisung, den Wert nicht mehr zu ändern. Das #pragma
DATA_SECTION legt die Variable bereits ins Flash.
Ob man jetzt wirklich jedesmal den ganzen Block sichern und
zurückschreiben muß, ist eine Frage der Erfordernisse und der richtigen
Strategie. Eventuell sind ja in Deinem TMenueItem Dinge die sich während
der Laufzeit nicht ändern. Dann könnte man das ja aufteilen in eine
Struktur, die wirklich konstant bleibt und eine weitere, eventuell
kleinere Struktur mit veränderlichen Werten, die dann vielleicht ins
InfoMem paßt, da braucht man dann nur 64 byte sichern und wieder
zurückschreiben.
Gruß wv
Strategie ist ein gutes Stichwort. Wenn immer nur ein oder wenige Werte
gespeichert werden, kann man einen Rinbuffer aufbauen. Dann wird nur
noch bei Überlauf gelöscht.
Hallo
danke für die Antworten.
Also TMenueItem ist wie der Name schon sagt ein Eintrag eines Menüs.
Also z.b. Überstrom. Hier ist eben der Name des Menüs, der Parent, Min,
Max und eben der eigentliche Wert definiert.
Der Benutzer soll hier während der Laufzeit den eigentlichen Wert
ändern.
Das Problem ist das das ganze Menü auf diesen Typen basiert und man sich
mit Parent und Child durch das Menü durchhangelt. Funktioniert soweit
auch wunderbar.
Dann werde ich mir jetzt eine Funktion basteln in der ich 512 byte in
den Ram schiebe und dann wert veränder und dann wieder zurück.
Wenn jemand einen Ressourcen schonenden Vorschlag hat, nur her damit.
---------
Es handelt sich bei mir um den MSP430G2955
Erstes Flashsegment liegt hier bei 0x2100 Die länge habe ich hier mit
0x200
definiert. Wenn ich mich nicht verlesen habe, sollte das ein Segment
sein.
Hier würde ich dann alle Menüeinträge ablegen welche zur Laufzeit
verändert werden können.
---------
Das Problem wenn ich const weg lasse, wird meine Variable nicht
initialisiert.
Es steht in jedem Long dann -1 und das Char array wird auch nicht
initialisiert.
--------
Den Vorschlag mit dem Ringpuffer habe ich noch nicht ganz verstanden.
Nur angenommen ich würde in TMenueItem.Value nicht den Wert selbst
ablegen sondern nur einen Zeiger auf den Werte, würde ich zum einen mehr
Speicher benötigen und zum anderen muss dieser Pointer ja auch irgendwie
wider geschrieben werden und das ist ja in dem Fall auch wieder im
Flash.
Aber vielleicht habe ich dich auch missverstanden.
Danke für eure Hilfe
Mit dem Ringpuffer geht es nur für einzelne Werte. Man reserviert
einfach das mehrfache an Speicherplatz. Der freie Speicher hat immer
0xFFFF. Den kannst du mit einzelnen Werfern überscvhreibern. Den letzten
Eintrag findest du durch die Suche nach 0xFFFF. Wenn alle pufferplätze
voll sind, wird das Segment gelöscht und man fängt wieder am
Pufferanfang an.