Hallo liebes Forum :-)
ich habe ein Problem beim Zugriff auf ein Array aus Pointern auf
Structs, die im Flash-Memory liegen. Es geht um einen Kommando-Parser,
den ich schreiben möchte.
Jedes struct, das ein einzelnes Kommando hält ist vom Typ
1
/* to hold one command */
2
typedefstruct{
3
4
char*cmd;
5
uint8_tnumberOfOptions;
6
uint8_tcmdCode;
7
8
}command;
Um die Kommandos einfach zu erzeugen habe ich mir das Makro
ADD_COMMAND(11,"GETEVENTCNT\0",1,0x8B)/* get INT event counter value */
usw...da kommen dann noch ein paar mehr dazu.
Die einzelnen structs werden dann in einem Array gehalten, das auch im
Flash-Speicher liegen soll. Um Compilezeit-Konstanten zu erhalten mache
ich das als Pointer-Array. Das sieht dann so aus:
Jetzt kommts zur eigentlichen Frage:
Ich möchte gerne auf die einzelnen Kommando-Strings im Flash über einen
Index zugreifen können um sie mit einem (im SRAM liegenden) über RS232
empfangenen String zu vergleichen. Hierzu mache ich folgendes:
1
uint8_ti;
2
command*cmdPtr;
3
4
for(i=0;i<=TOTAL_NUMBER_OF_COMMANDS;i++){
5
cmdPtr=(command*)pgm_read_word(commandList[i]);
6
if(strcmp_P(rxString.buffer,cmdPtr->cmd)==0){
7
/* found known command */
8
/* mache irgendwas tolles :-) */
9
}
10
}
Das funktioniert jedoch nicht. Wo liegt also mein Denkfehler?
Bisher habe ich mir das so gedacht:
Im Array commandList liegen lauter Adressen auf structs vom Typ command
im Flash-Memory. Diese Adressen hole ich mit pgm_read_word und weise sie
dem cmdPtr zu. Nun kann man doch mit strcmp_P() direkt auf Adressen im
Flash verweisen, was ich mit cmdPtr->cmd versucht habe. Leider klappt
das nicht...
Habt ihr eine Idee woran das liegen könnte und wie man das beheben kann?
Viele Liebe Grüße,
Stefan
auf alle Inhalte, die mit PROGMEM markiert sind, kannst du nicht direkt
zugreifen, sondenr musst den UMweg über die pgm_xxx Funktionen gehen.
> Im Array commandList liegen lauter Adressen auf structs vom Typ command> im Flash-Memory.
Ja.
Aber das Array, welches diese Adresse hält liegt ja selbst auch im
Flash. Daher ja auch ...
> cmdPtr = (command*)pgm_read_word(commandList[i]);
...
Aber: No.
Hier würdest du ja den Inhalt von commandList[i] an pgm_read_word
übergeben. Das ist aber nicht das was du willst.
Du willst ja von der Flash Adresse vom i-ten Element von commandList
lesen. Also
Hallo Karl Heinz,
erstmal vielen lieben Dank für deine Hilfe!
Das habe ich jetzt so übernommen. Wenn ich das richtig verstanden haben,
dann enthält cmdPtr jetzt eine Adresse zu einem struct im Flash, das
über den Index i ausgewählt wurde. Stimmt das?
Die Funktion sieht dann jetzt so aus (ich habe mal eine geschrieben, die
mir einfach die Kommandos an den PC schickt...zum einfachen testen).
1
chartxBuffer[50];
2
char*cmd;
3
4
for(i=0;i<=TOTAL_NUMBER_OF_COMMANDS;i++){
5
cmdPtr=(command*)pgm_read_word(&commandList[i]);
6
cmd=(char*)pgm_read_word(&cmdPtr->cmd);
7
strcpy_P(txBuffer,cmd);
8
sendText(txBuffer);
9
}
So funktionierts dann :-)
Also da muss ich mich noch etwas dran gewöhnen, mich durch die PROGMEMs
zu hangeln, aber das wird klappen :-)
Vielen lieben Dank nochmals! Jetzt kommen die strings wunderbar bei mir
an :-)
Stefan schrieb:> Hallo Karl Heinz,> erstmal vielen lieben Dank für deine Hilfe!>> Das habe ich jetzt so übernommen. Wenn ich das richtig verstanden haben,> dann enthält cmdPtr jetzt eine Adresse zu einem struct im Flash, das> über den Index i ausgewählt wurde. Stimmt das?
Genau
> for(i=0; i <= TOTAL_NUMBER_OF_COMMANDS; i++){> cmdPtr = (command*)pgm_read_word(&commandList[i]);
Ja
> cmd = (char*)pgm_read_word( &cmdPtr->cmd );
Exakt
> strcpy_P(txBuffer, cmd);
Und auch hier richtig. Das 2.te Argument an strcpy_P ist die Adresse des
Strings im Flash
> So funktionierts dann :-)>> Also da muss ich mich noch etwas dran gewöhnen, mich durch die PROGMEMs> zu hangeln, aber das wird klappen :-)
Dein Fehler war
pgm_read_word, will die Adresse von der es lesen soll.
commandList[i] ist zwar auch eine Adresse (formal - ist ja
datantypmässig ein Pointer) aber nicht die Adresse an der der Inhalt von
commandList[i] steht. Die lautet &commandList[i]
Kannst du nicht einfach __flash verwenden? Dann braucht es dan ganze
Geraffel mit den pgm_read_xxx Funktionen erst garnicht.
Das einzige, worum du dich dann kümmern musst, sind richtige
Deklarationen / Definitionen der entsprechenden Daten und Zeiger.