Forum: Mikrocontroller und Digitale Elektronik PROGMEM und Pointer-Arrays


von Thomas D. (blackworker)


Lesenswert?

Hoi,

Ich möchte über einen Zeiger auf ein Zeiger-Array im Flash-Speicher 
zugreifen, welche wiederum auf Arrays zeigen.

Benutzer AVR ist der Atmel 1284p.
1
#include <avr/pgmspace.h>
2
3
/* Byte */
4
const uint8_t aByte PROGMEM = 123;
5
6
/* int-Array */
7
static const uint8_t aArray[] PROGMEM = {18, 3, 70};
8
static const uint8_t bArray[] PROGMEM = {19, 4, 71};
9
const uint8_t * const Array[] PROGMEM =  {aArray, bArray};
10
11
//Zeiger auf aArray[]
12
static const uint8_t * const Pointer_to_Array PROGMEM = aArray;
13
14
//Zeiger auf Pointer_Array
15
static const uint8_t** const Pointer_to_PointerArray PROGMEM = Array;
16
17
int main(void)
18
{
19
  
20
  //Zugriff direkt auf Array
21
  uint8_t byte1 = (uint8_t)(pgm_read_word(&Pointer_to_Array[1]));
22
  
23
  //Zugriff direkt auf PointerArray
24
  const uint8_t *address_to_array = (const uint8_t*)(pgm_read_word(&Array[0]));  
25
  uint8_t byte2 = (uint8_t)(pgm_read_word(&address_to_array[1]));
26
  
27
  //Zugriff über einen Zeiger auf das PointerArray
28
  //????

Mein Problem ist das ich bis jetzt nicht weiß, wie ich einen Zeiger auf 
die Adresse des Zeiger-Arrays richte (Array[]), bzw wie ich diesen 
wieder korrekt dereferenziere.

Ich hab schon verschiedenste Konstellationen ausprobiert, aber ohne 
Erfolg

Compilerfehler:
1
Error  2  cannot convert 'const uint8_t* const* {aka const unsigned char* const*}' to 'const uint8_t* const {aka const unsigned char* const}' in initialization

Der direkte Zugriff auf das Array[] klappt problemlos, indem ich mir 
erst die Flash-Adresse des Arrays dahinter hole (aArray, bArray) und 
dann einen Zeiger auf einen Wert des aArrays derefernziere.

Nur steh ich grad völlig auf dem Schlauch wie ich diesen Zeiger korrekt 
erzeuge, ich hab schon im Forum stundenlang gesucht aber nichts 
entsprechendes gefunden.

Ich möchte aus performancegründen vermeiden, das "NutzdatenArray" erst 
in den RAM zu kopieren um dann darauf zuzugreifen.

Kann mir da jemand auf die Sprünge helfen?

mfg

von Peter II (Gast)


Lesenswert?

das geht nicht, du musst immer die funktion pgm_read_word aufrufen. Denn 
der GCC anders.

von Thomas D. (blackworker)


Lesenswert?

Peter II schrieb:
> das geht nicht, du musst immer die funktion pgm_read_word aufrufen. Denn
> der GCC anders.

Ich dachte ich könnte das so in etwa machen, wie bei
//Zugriff direkt auf PointerArray
jedoch vorher den Zeiger zum PointerArray auflösen damit ich die 
FLASH-Adresse des Pointer-Arrays habe.

Der Grund ist der, das ich die Funktion die die Daten im Flash 
vearbeitet so universiell wie möglich halten möchte.

Es gibt wirklich keinen Weg das so zu gestalten?

von Stefan E. (sternst)


Lesenswert?

Thomas D. schrieb:
> Compilerfehler:

Nur den Fehler zu posten ist nicht gerade sinnvoll. Ich habe jedenfalls 
keine Lust, mir aus dem Fehler den möglichen Sourcecode zu 
"rekonstruieren", den du probiert hast.

> Mein Problem ist das ich bis jetzt nicht weiß, wie ich einen Zeiger auf
> die Adresse des Zeiger-Arrays richte (Array[])
1
const uint8_t * const * ptr = Array;

> bzw wie ich diesen
> wieder korrekt dereferenziere.
1
const uint8_t * ptr_to_bArray = (const uint8_t*)pgm_read_word(ptr+1);
2
oder
3
const uint8_t * ptr_to_bArray = (const uint8_t*)pgm_read_word(&ptr[1]);


PS: Du könntest dir die Sache aber auch deutlich einfacher machen, indem 
du avrgcc >=4.7 und __flash verwendest.

von Thomas D. (blackworker)


Lesenswert?

Stefan Ernst schrieb:
> Thomas D. schrieb:
>> Compilerfehler:
>
> Nur den Fehler zu posten ist nicht gerade sinnvoll. Ich habe jedenfalls
> keine Lust, mit aus dem Fehler den möglichen Sourcecode zu
> "rekonstruieren", den du probiert hast.
>
>> Mein Problem ist das ich bis jetzt nicht weiß, wie ich einen Zeiger auf
>> die Adresse des Zeiger-Arrays richte (Array[])
>
>
1
const uint8_t * const * ptr = Array;
>
>> bzw wie ich diesen
>> wieder korrekt dereferenziere.
>
>
1
const uint8_t * ptr_to_bArray = (const uint8_t*)pgm_read_word(ptr+1);
2
> oder
3
> const uint8_t * ptr_to_bArray = (const 
4
> uint8_t*)pgm_read_word(&ptr[1]);

Hi Stefan,

das ist der ganze Sourcecode und die Compilermeldung bezog sich auf 
diese Zeile:

//Zeiger auf Pointer_Array
static const uint8_t** const Pointer_to_PointerArray PROGMEM = Array;

Ich dachte man müsste dem Compiler mitteilen dass es sich um 
"verschachtelt Zeiger" handelt

Deine Lösung funktioniert tadellos, danke hierfür!

Nochmal der gesamte funktionierende Code - vllt hilfts ja jemanden
1
#include <avr/pgmspace.h>
2
3
/* Byte */
4
const uint8_t aByte PROGMEM = 123;
5
6
/* int-Array */
7
static const uint8_t aArray[] PROGMEM = {18, 3, 70};
8
static const uint8_t bArray[] PROGMEM = {19, 4, 71, 65};
9
const uint8_t * const Array[] PROGMEM =  {aArray, bArray};
10
11
//Zeiger auf aArray[]
12
static const uint8_t * const Pointer_to_Array PROGMEM  = aArray;
13
14
//Zeiger auf Pointer_Array
15
//static const uint8_t** const Pointer_to_PointerArray PROGMEM = Array;  <<= Geht NICHT!
16
17
const uint8_t * const * ptr = Array;
18
19
20
int main(void)
21
{
22
  
23
  //Zugriff direkt auf Array
24
  uint8_t byte1 = (uint8_t)(pgm_read_word(&Pointer_to_Array[1]));
25
  
26
  //Zugriff direkt auf PointerArray
27
  const uint8_t *address_to_array = (const uint8_t*)(pgm_read_word(&Array[0]));  
28
  uint8_t byte2 = (uint8_t)(pgm_read_word(&address_to_array[1]));
29
  
30
  //Zugriff über einen Zeiger auf das PointerArray
31
  const uint8_t * ptr_to_bArray = (const uint8_t*)pgm_read_word(ptr+1);
32
  uint8_t byte3 = (uint8_t)pgm_read_word(&ptr_to_bArray[1]);

Allerdings würde es mich schon interessieren, weshalb man in diesem Fall 
kein "uint8_t ** Pointer_To_PointerArray" benötigt.. (?)

mfg

von Stefan E. (sternst)


Lesenswert?

Thomas D. schrieb:
> Ich dachte man müsste dem Compiler mitteilen dass es sich um
> "verschachtelt Zeiger" handelt
> ...
> Allerdings würde es mich schon interessieren, weshalb man in diesem Fall
> kein "uint8_t ** Pointer_To_PointerArray" benötigt.. (?)

Hä? 'ptr' ist doch ein uint8_t**.

von Thomas D. (blackworker)


Lesenswert?

Ahhh ich glaub jetzt hab ichs begriffen.

Ich hab einen konstanten uint8_t Pointer deklariert, der auf einen 
weiteren uint8_t Pointer zeigt.

Du hast einen konstanten uin8_t Pointer deklariert, der auf einen 
weiteren konstanten uint8_t Pointer zeigt.

Ist das richtig so?

von Stefan E. (sternst)


Lesenswert?

Thomas D. schrieb:
> Ich hab einen konstanten uint8_t Pointer deklariert, der auf einen
> weiteren uint8_t Pointer zeigt.
>
> Du hast einen konstanten uin8_t Pointer deklariert, der auf einen
> weiteren konstanten uint8_t Pointer zeigt.
>
> Ist das richtig so?

Fast.
Du:  konstanter Pointer zeigt auf nicht-konstanten Pointer
Ich: nicht-konstanter Pointer zeigt auf konstanten Pointer

von Thomas D. (blackworker)


Lesenswert?

Alles klar!!

Danke Stefan ;)

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.