mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik linked lists im program space (flash)


Autor: DrKarlTheodor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, Folgendes Problem:
Ich habe eine Verkettete liste angelegt mit daten gefüllt und diese is 
Flash gelegt.

typedef const struct PROGMEM  MENU_STR
{
  const struct PROGMEM  MENU_STR *sub_menu;
  CALL_FUNC     MenuFuncPtr;
  const unsigned char       text_u8 [15];
}MENU_STRUKTUR;


MENU_STRUKTUR sub_test1 [MENU_MAX]
={
  {NULL , move_midas_logo,"Demo1_t"},
  {NULL , foo            ,"sub menu"},
  {NULL , sw_stand       ,"SW_St_t"},
  {NULL , sm_reset       ,"RESET_t"},
  {NULL , sm_sleep       ,"Sleep_t"}
 };

MENU_STRUKTUR Main_Menu_Table_MenStr [MENU_MAX]
={
  {sub_test1  , move_midas_logo , "Demo1"},
  {sub_test1  , change_menu     , "sub_menu"},
  {NULL       , sw_stand        , "SW_St"},
  {NULL       , sm_reset        , "RESET"},
  {NULL       , sm_sleep        , "Sleep"}
 };

Soweit so gut !

wenn ich jetzt ein Array von Pointern erstelle und diese Auf mein 
Strktur array zeigen lasse:

MENU_STRUKTUR *CurrentMenu_MenStr_ptr[MENU_MAX];

  for (i_u8= 0; i_u8 < MENU_MAX; i_u8++)
  {
    CurrentMenu_MenStr_ptr[i_u8]= &Main_Menu_Table_MenStr[i_u8];
  }

Will ich jetzt auf den Text zugreifen:

pgm_read_byte(CurrentMenu_MenStr_ptr[1]->text_u8);  //kalppt !

will ich aber auf den text meies sub_menus zugreifen klappt das nicht
pgm_read_byte(CurrentMenu_MenStr_ptr[1]->sub_menu[1].text_u8); //klappt 
nicht

Warum geht das so nicht?
Wenn ich das ganze im Ram mache geht es.


Danke!!

Autor: DrKarlTheodor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry,
Das ganze Auf einem AVR XMEGA

Autor: Tom M. (tomm) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DrKarlTheodor schrieb:
> pgm_read_byte(CurrentMenu_MenStr_ptr[1]->text_u8);  //kalppt !

Hier dereferenzierst du einmal. Zur Compile-Time sind alle relevanten 
Grössen bekannt, deshalb musst du nur einmal via pgm_read_byte 
eingreifen, um aus dem Flash zu lesen.

> will ich aber auf den text meies sub_menus zugreifen klappt das nicht
> pgm_read_byte(CurrentMenu_MenStr_ptr[1]->sub_menu[1].text_u8); //klappt
> nicht

Hier liegt der Fall etwas anders, da du Pointer auf Pointer hast. Du 
musst "zu Fuss" dereferenzieren bzw. die Pointer aus dem Flash lesen 
(pgm_read_word). Jetzt dereferenzierst du "übers RAM" und landest 
irgendwo im Flash!

Autor: DrKarlTheodor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kannst du dass ev. an einem Beispiel erleutern?

Autor: DrKarlTheodor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe das so, dass ich erst den die Pointer mit pgm_read_word 
lesen muss.
z.B. so:
MENU_STRUKTUR *test [5]
test [1] = pgm_read_word( &CurrentMenu_MenStr_ptr[1]->sub_menu[1]);

und dann mit pgm_read_byte das zeichen aus dem String

pgm_read_byte(test[1]->text[1]);


das funktioniert so aber nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DrKarlTheodor schrieb:
> Ich verstehe das so, dass ich erst den die Pointer mit pgm_read_word
> lesen muss.
> z.B. so:
> MENU_STRUKTUR *test [5]
> test [1] = pgm_read_word( &CurrentMenu_MenStr_ptr[1]->sub_menu[1]);

Du kannst hier keinen -> benutzen!

Mal dir die Situation auf
  Current...                   F Main_Menu_Table_MenStr
  +-----------+                 +-----------------+
  |   o------------------------>|    o---------------------+
  +-----------+                 | move_midas_logo |        |
  |   o------------------+      | "Demo1"         |        |
  +-----------+          |      +-----------------+        |   F sub1
  |   o---------------+  +----->|    o-----------------+   |    +--------------------+
  +-----------+       |         | change_menu     |    |   +--->|  * NULL            |
  |   o-------------+ |         | "sub_menu"      |    +------->|  * move_midas_logo |
  +-----------+     | |         +-----------------+             |  * "Demo1_t"       |
  |   o----------+  | +-------->|   NULL          |             +--------------------+
  +-----------+  |  |           | sw_stand        |             |  * NULL            |
                 |  |           | "SW_St"         |             |  * foo             |
                 |  |           +-----------------+             |  * "sub menu"      |
                 |  +---------->|   NULL          |             +--------------------+
                 |              | sm_reset        |             |  * NULL            |
                 |              | "RESET"         |             |  * sw_stand        |
                 |              +-----------------+             |  * "SW_St_t"       |
                 +------------->|   NULL          |             +--------------------+
                                | sm_sleep        |             |  * NULL            |
                                | "SLEEP"         |             |  * sm_reset        |
                                +-----------------+             |  * "RESET_t"       |
                                                                +--------------------+
                                                                |  * NULL            |
                                                                |  * sm_sleep        |
                                                                |  * Sleep_t"        |
                                                                +--------------------+
 

Das ist die Datenstruktur, die du da zusammengebaut hast.
Mal abgesehen davon, dass sie nicht seh sinnvoll ist (das Array 
Current... braucht in Wirklichkeit kein Mensch) sieht man eines: Immer 
dann, wenn du, um an die Daten zu kommen einem Pfeil folgen musst, an 
dessen Ende ein Kasten steht, der links oben mit einem "F" (wie Flash) 
markiert ist, dann kannst du nicht -> oder * benutzen, sondern musst die 
Adresse an pgm_read.... übergeben und diese Funktion besorgt dir dann 
die Daten.

    CurrentMenu_MenStr_ptr[1]->sub_menu[1]);

CurrentMenu_MenStr_ptr

    das ist ok. Der zugehörige Kasten hat kein F, daher ist

CurrentMenu_MenStr_ptr[1]

    in Ordnung.
    Von dort geht ein Pfeil weg. Sowohl in der Zeichnung als auch
    in deinem Programm:

CurrentMenu_MenStr_ptr[1]->

    Mööp. Ein BLick in die Zeichnung verrät: Der Pfeil endet in einem
    Block, der 'F' markiert ist, die Daten liegen also im Flash.
    Daher kannst du hier nicht -> benutzen, sondern musst mittels
    pgm_read_.... den dich interessierenden Teil holen.
    Was willst do holen?
    Einen Pointer, also 2 Bytes, also ist pgm_read_word dein Freund.
    tmp = pgm_read_word( CurrentMenu_MenStr_ptr[1] + offsetof( sub_menu ) );
Damit hast du jetzt in tmp den Pointer aus dem Flash geholt, der auf das 
sub1 zeigt (in diesem Fall). sub1 ist selber wieder im Flash (ist 'F' 
markiert). Um also an Werte in diesem Block ran zu kommen auf den du 
einen Zeiger hast, muss wieder eine pgm_read.... Funktion bemüht werden.

Wenn du bei verzeigerten Datenstrukturen den Überblick verlierst, wie 
sie aussehen, DANN MAL DIR DIE SITUATION AUF PAPIER AUF!
Wenn du dann noch markierst, welche Teile im SRAM liegen und welche im 
Flash, dann kannst du ganz leicht entscheiden, wie der Zugriff aussehen 
muss. Die Zeichnung leitet dich.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.