mikrocontroller.net

Forum: Compiler & IDEs [avr-gcc]Array mit Strings im Flash und Zeiger darauf in Struct


Autor: C_R (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe folgendes Problem.
Habe ein Array von Strings im Flash und möchte den Zeiger mit in einem
Struct welches ebenfalls im Flash liegt übergeben.
Nur komme ich danach nicht an die Strings ran.

Hoffe ihr habt eine Lösung für mich.

typedef struct
{
    uint8_t count;
    PGM_VOID_P pLines;  // ????
    t_display_fnc display_fnc;
    t_fnc fnc;
}t_subitem;

const char Text0[] PROGMEM =  " Text0 ";
const char Text1[] PROGMEM =  " Text1 ";
const char Text2[] PROGMEM =  " Text2 ";
const char Text3[] PROGMEM =  " Text3 ";

PGM_P Sub_items[]  =
{
   Text0,
   Text1,
   Text2,
   Text3
};

t_subitem SubItems[] PROGMEM = 
{
  {4,
  &Sub_items, 
  DisplayFunc0,
  Func0},
  
};

static void sub_startup (void)
{
       static t_subitem item;
       char buf[25];
  
  memcpy_P(&item, &SubItems[0], sizeof(t_subitem));
   test_fnc = item.fnc;
//
// hier will ich dann auf die Strings zugreifen,
// bekomme das aber irgendwie nicht hin.
// Wie muss man das genau machen.
//
    item.display_fnc();
}


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

Bewertung
0 lesenswert
nicht lesenswert
mal es dir auf


Du hast

   SubItems (Flash)
   +--------------------+
   |  count        4    |
   |  pLines       o-------------------------+
   |  display_fnc  o-----> DisplayFunc0      |
   |  fnc          o-----> Func0             v Sub_items  (Flash)
   +--------------------+                    +------------+
                             +---------------------o      |
                             |               +------------+
                             v  (Flash)    +------o       | 
                          "Text0"          | +------------+
                                           | |    o-------------+
                                    +------+ +------------+     |
                                    |        |    o       |     |
                                    |        +----|-------+     |
                                    v (Flash)     |             v (Flash)
                                "Text1"           v (Flash)    "Text2"
                                                "Text3"


Das ist deine Datenstruktur.
Normalerweise greift man über einen Pointer zu, in dem man entweder 
einen * oder einen -> benutzt. Ist das Ende des Pfeiles im Diagram aber 
mit (Flash) gekennzeichnet, dann geht das nicht und du musst stattdessen 
eine der pgm_read_xxx Funktionen benutzen. Der übergibst du die Adresse 
von der du lesen möchtest und die Funktion besorgt dir die Daten an 
dieser Adresse (am Ende des Pfeiles)
  memcpy_P(&item, &SubItems[0], sizeof(t_subitem));
   test_fnc = item.fnc;
//
// hier will ich dann auf die Strings zugreifen,
// bekomme das aber irgendwie nicht hin.
// Wie muss man das genau machen.
//


// Du hast das item vom Flash in den SRAM umkopiert. D.h. auf das
// item kannst du ganz normal zugreifen.

// Du willst zb an den 0-ten Pointer im Array ran.
// Wo steht der?
// Der ist abgespeichert, an der Speicheradresse, auf die
// item.pLines zeigt
// Genaugenomen: Von dieser Adresse ausgehend, ist es der 0-te Pointer
//
// um an den Pointer zum Text zu kommen, würde man normalerweise machen
//
//   char* Text = item.pLines[0];
//
// aber das geht nicht, den das Ende vom Pfeil, der aus item.pLines
// rausgeht, endet in einem Kästchen, das mit Flash markiert ist.
// Also muss eine pgm_read_xxx Funktion her.
//
//  char* Text = pgm_read_word( &item.pLines[0] );
//
// Damit hast du den Pfeil, der von item.pLines[0] im Diagram ausgeht und
// der auf den Text zeigt. Mit diesem Pointer wiederrum kannst du den Text
// auslesen.
// Aber auch hier wieder: Das Ende des Pfeiles ist mit Flash markiert. Also
// kann man nicht einfach zugreifen, sondern muss Speizialfunktionen
// benutzen


    item.display_fnc();

Autor: C_R (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl,

danke erstmal das du mir hilfst das Problem zu lösen.
Nur leider funktioniert das nicht wirklich oder ich verstehe es nicht.

Ich habe es jetzt so gemacht wie du geschrieben hast.
char *text = pgm_read_word( &item.pLines[0] );

und dann um an die einzelnen Strings zu kommen
strcpy_P(buf, text[0]);

leider ohne Erfolg.
Habe dann folgendes versucht
void *texte = (void*)pgm_read_word( &item.pLines );

da es ja eigentlich der Pointer ist oder liege ich da falsch?
In texte müsste dann doch der Zeiger von items sein?

Aber irgendwie komme ich immer noch nicht an die Strings ran, das ist
echt zum Haare raufen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C_R schrieb:
> und dann um an die einzelnen Strings zu kommen
> strcpy_P(buf, text[0]);

Wozu soll das "[0]" hier dienen?

Autor: C_R (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Wozu soll das "[0]" hier dienen?

Das hatte ich dann gemacht als ich per
void *texte = (void*)pgm_read_word( &item.pLines );
versucht habe an meine Strings zu kommen.

Aber auch ohne [0] funktioniert es nicht.

Wenn jemand einen Lösungsweg hat, wäre ich sehr dankbar.

Noch ein paar Informationen:
Also in "item.pLines" ist auf alle Fälle die Startadresse von 
Sub_items gespeichert. Also müsste man doch nur den Wert wieder als 
Pointer nehmen um auf das Stringarray per
strcpy_P(buf, strings[i]);
zugreifen zu können.
Leider bekomme ich das nicht hin :-(

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C_R schrieb:
> Aber auch ohne [0] funktioniert es nicht.

In Kombination mit welchen anderen Code?

Wenn du immer nur einzelne Zeilen in den Raum wirfst, weiß doch keiner, 
was du nun tatsächlich ausprobiert hast.

PGM_P Sub_items[]  =
{
   Text0,
   Text1,
   Text2,
   Text3
};
Aber alles, was eigentlich funktionieren sollte, wird nicht 
funktionieren, weil die Pointerliste nämlich gar nicht im Flash liegt.

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

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:

> Aber alles, was eigentlich funktionieren sollte, wird nicht
> funktionieren, weil die Pointerliste nämlich gar nicht im Flash liegt.

Shit.
Du hast recht.
Genau deswegen hasse ich solche Datentyp Makros. Insbesondere im 
Zusammenhang mit Pointern.
Man hat nur Probleme damit.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde das ganze erst einmal komplett im Ram realisieren, und erst, 
wenn das funktioniert, und alle Texte da wieder rauskommen, wo sie auch 
sollen, schrittweise von innen nach aussen die Daten ins Flash 
verschieben, und die Zugriffsfunktionen dazu einbauen.

Und nach jedem Schritt erst weiter machen, wenn ALLE Warnungen gelöst 
wurden.

Dann klappt es auch mit dem PROGMEMs.

Oliver

Autor: C_R (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> In Kombination mit welchen anderen Code?
>
> Wenn du immer nur einzelne Zeilen in den Raum wirfst, weiß doch keiner,
> was du nun tatsächlich ausprobiert hast.

Es ist immer noch der selbe Code wie im Threadstarter.

Stefan Ernst schrieb:
> PGM_P Sub_items[]  =
> {
>    Text0,
>    Text1,
>    Text2,
>    Text3
> };
> Aber alles, was eigentlich funktionieren sollte, wird nicht
> funktionieren, weil die Pointerliste nämlich gar nicht im Flash liegt.

Bei mir ist PGM_P als
typedef char PROGMEM prog_char;
#define PGM_P const prog_char *
 definiert, was mich zu der Annahme bewegt hat das es im Flash sein 
muss.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C_R schrieb:
>> Wenn du immer nur einzelne Zeilen in den Raum wirfst, weiß doch keiner,
>> was du nun tatsächlich ausprobiert hast.
>
> Es ist immer noch der selbe Code wie im Threadstarter.

Das bezog sich hierauf:

> Ich habe es jetzt so gemacht wie du geschrieben hast.
> char *text = pgm_read_word( &item.pLines[0] );
> und dann um an die einzelnen Strings zu kommen
> strcpy_P(buf, text[0]);

Meine Frage: Wozu soll das "[0]" hier dienen?

> Das hatte ich dann gemacht als ich per
> void *texte = (void*)pgm_read_word( &item.pLines );
> versucht habe an meine Strings zu kommen.
>
> Aber auch ohne [0] funktioniert es nicht.

Und hier ist nun nicht mehr klar, mit was zusammen du es ohne [0] 
überhaupt probiert hast. Mit
char *text = pgm_read_word( &item.pLines[0] );
oder
void *texte = (void*)pgm_read_word( &item.pLines );
oder vielleicht noch was anderem?

>> Aber alles, was eigentlich funktionieren sollte, wird nicht
>> funktionieren, weil die Pointerliste nämlich gar nicht im Flash liegt.
>
> Bei mir ist PGM_P als
> typedef char PROGMEM prog_char;
> #define PGM_P const prog_char *
> definiert, was mich zu der Annahme bewegt hat das es im Flash sein
> muss.

Also ist PGM_P ein Pointer auf Flash (*), das bedeutet ja aber nicht, 
dass damit der Pointer selber auch im Flash liegt (und tut er auch 
nicht).

(*): Was aber rein dokumentarischen Zwecken dient, denn "Pointer auf 
Flash" und "Pointer auf RAM" sind letztlich ein und dasselbe.

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

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> C_R schrieb:
>>> Wenn du immer nur einzelne Zeilen in den Raum wirfst, weiß doch keiner,
>>> was du nun tatsächlich ausprobiert hast.
>>
>> Es ist immer noch der selbe Code wie im Threadstarter.

Man könnte es auch so sagen:
Wenn es immer noch 100% der identische Code wie im Eröffnungsposting 
ist, dann ist klar dass der Code immer noch nicht funktionieren kann. Er 
hat vorher nicht funktioniert und er wird es auch jetzt nicht tun. In 
dem Fall würde sich dann eigentlich jede weitere Antwort erübrigen. So 
etwas würde man dann "beratungsresistent" nennen.

Ein paar Änderungen wirst du ja mitlerweile gemacht haben. Die Frage ist 
nur: welche?

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.