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


von C_R (Gast)


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.
1
typedef struct
2
{
3
    uint8_t count;
4
    PGM_VOID_P pLines;  // ????
5
    t_display_fnc display_fnc;
6
    t_fnc fnc;
7
}t_subitem;
8
9
const char Text0[] PROGMEM =  " Text0 ";
10
const char Text1[] PROGMEM =  " Text1 ";
11
const char Text2[] PROGMEM =  " Text2 ";
12
const char Text3[] PROGMEM =  " Text3 ";
13
14
PGM_P Sub_items[]  =
15
{
16
   Text0,
17
   Text1,
18
   Text2,
19
   Text3
20
};
21
22
t_subitem SubItems[] PROGMEM = 
23
{
24
  {4,
25
  &Sub_items, 
26
  DisplayFunc0,
27
  Func0},
28
  
29
};
30
31
static void sub_startup (void)
32
{
33
       static t_subitem item;
34
       char buf[25];
35
  
36
  memcpy_P(&item, &SubItems[0], sizeof(t_subitem));
37
   test_fnc = item.fnc;
38
//
39
// hier will ich dann auf die Strings zugreifen,
40
// bekomme das aber irgendwie nicht hin.
41
// Wie muss man das genau machen.
42
//
43
    item.display_fnc();
44
}

von Karl H. (kbuchegg)


Lesenswert?

mal es dir auf


Du hast
1
   SubItems (Flash)
2
   +--------------------+
3
   |  count        4    |
4
   |  pLines       o-------------------------+
5
   |  display_fnc  o-----> DisplayFunc0      |
6
   |  fnc          o-----> Func0             v Sub_items  (Flash)
7
   +--------------------+                    +------------+
8
                             +---------------------o      |
9
                             |               +------------+
10
                             v  (Flash)    +------o       | 
11
                          "Text0"          | +------------+
12
                                           | |    o-------------+
13
                                    +------+ +------------+     |
14
                                    |        |    o       |     |
15
                                    |        +----|-------+     |
16
                                    v (Flash)     |             v (Flash)
17
                                "Text1"           v (Flash)    "Text2"
18
                                                "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)
1
  memcpy_P(&item, &SubItems[0], sizeof(t_subitem));
2
   test_fnc = item.fnc;
3
//
4
// hier will ich dann auf die Strings zugreifen,
5
// bekomme das aber irgendwie nicht hin.
6
// Wie muss man das genau machen.
7
//
8
9
10
// Du hast das item vom Flash in den SRAM umkopiert. D.h. auf das
11
// item kannst du ganz normal zugreifen.
12
13
// Du willst zb an den 0-ten Pointer im Array ran.
14
// Wo steht der?
15
// Der ist abgespeichert, an der Speicheradresse, auf die
16
// item.pLines zeigt
17
// Genaugenomen: Von dieser Adresse ausgehend, ist es der 0-te Pointer
18
//
19
// um an den Pointer zum Text zu kommen, würde man normalerweise machen
20
//
21
//   char* Text = item.pLines[0];
22
//
23
// aber das geht nicht, den das Ende vom Pfeil, der aus item.pLines
24
// rausgeht, endet in einem Kästchen, das mit Flash markiert ist.
25
// Also muss eine pgm_read_xxx Funktion her.
26
//
27
//  char* Text = pgm_read_word( &item.pLines[0] );
28
//
29
// Damit hast du den Pfeil, der von item.pLines[0] im Diagram ausgeht und
30
// der auf den Text zeigt. Mit diesem Pointer wiederrum kannst du den Text
31
// auslesen.
32
// Aber auch hier wieder: Das Ende des Pfeiles ist mit Flash markiert. Also
33
// kann man nicht einfach zugreifen, sondern muss Speizialfunktionen
34
// benutzen
35
36
37
    item.display_fnc();

von C_R (Gast)


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.
1
char *text = pgm_read_word( &item.pLines[0] );

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

leider ohne Erfolg.
Habe dann folgendes versucht
1
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.

von Stefan E. (sternst)


Lesenswert?

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

Wozu soll das "[0]" hier dienen?

von C_R (Gast)


Lesenswert?

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

Das hatte ich dann gemacht als ich per
1
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
1
strcpy_P(buf, strings[i]);
zugreifen zu können.
Leider bekomme ich das nicht hin :-(

von Stefan E. (sternst)


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.

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

von Karl H. (kbuchegg)


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.

von Oliver (Gast)


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

von C_R (Gast)


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
1
typedef char PROGMEM prog_char;
2
#define PGM_P const prog_char *
 definiert, was mich zu der Annahme bewegt hat das es im Flash sein 
muss.

von Stefan E. (sternst)


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
1
char *text = pgm_read_word( &item.pLines[0] );
oder
1
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
1
> typedef char PROGMEM prog_char;
2
> #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.

von Karl H. (kbuchegg)


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?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.