wie konstanten Zeiger auf Funktion aus Flash lesen?

Gast #838727
Lesenswert?

Hallo C-Profis,

ich habe folgendes Problem:
Für ein Display-Menü habe ich mir ein Struct für die einzelnen Buttons
gebaut in der Form:
typedef const struct {
  unsigned char xpos;
  unsigned char ypos;
  ...
  void (*program)();    //Zeiger auf Funktion
  ...
} but;

Nun speicher ich die Werte in einem Array aus diesen Structs in den 
Flash:
const but button[MAX_BUTTONS] PROGMEM = {{10,20,...,dimming_high,...},
                                         {...}};
"dimming high" ist nun die Funktion, auf die der Zeiger im Struct zeigt.
Verwende ich PROGMEM nicht und speicher das Array ganz normal, erreiche 
ich die Funktion folgendermaßen:
(*button[index].program)();

Meine Frage ist jetzt, wie kann ich die entsprechende Funktion starten, 
wenn mein Zeiger im Flash liegt? Ist dies überhaupt möglich?

Vielen Dank im voraus.
Gruß
Niklas
Gast #838767
Lesenswert?

Hallo Jörg,

entschuldige bitte, ich hatte vergessen zu erwähnen, dass es um einen 
AVR geht und ich ihn mit gcc programmiere.
Meine Zeigervariable im RAM ist bereits im Struct vorhanden:
void (*program)();

Ich weiß auch, dass ein Zeiger bei den AVRs 16bit groß ist und man ihn 
dementsprechent mit pgm_read_word() liest.
Mit einem normalen Zeiger habe ich auch kein Problem, nur kenne ich die
Syntax nicht, um einen Zeiger auf eine Funktion aus dem ROM zu lesen.
Ich habe es mit (void*)pgm_read_word((&button[i].program)());
versucht, aber AVR-Studio meldet mir:
error: called object '&button[i].program' is not a function

???
Irgendetwas mache ich also falsch. Weist du wie die Syntax richtig 
lauten müsste? Danke

Gruß
Niklas
Gast #838787
Lesenswert?

Jetzt mal so aus dem Bauch heraus...
1
void (*prog)(void) = (void(*)(void))pgm_read_word(&(button[i].program));
2
prog();
Du kannst nicht (void(*)(void))pgm_read_word(&(button[i].program))(); 
direkt aufrufen, weil pgm_read_word ein Makro ist.
Persönliche Seite #838791
Lesenswert?

Ich würde es so angehen (Ungetestet, nur hingeschrieben)
1
typedef const struct {
2
  unsigned char xpos;
3
  unsigned char ypos;
4
  ...
5
  void (*program)(void);    //Zeiger auf Funktion
6
  ...
7
} but;
8

9
// Definitionen
10

11
const but button[MAX_BUTTONS] PROGMEM = {
12
  {10, 20, ..., &dimming_high, ...},
13
  {...}
14
};
15

16
void dimming_high(void)
17
{
18
}
19

20
// Aufruf
21

22
int main(void)
23
{
24
  // so ;-)
25
  void (* fptr)(void); 
26
  fptr = (void (*)) pgm_read_word((&(button[0].program));
27
  fptr();
28

29
  // oder so ;-(
30
  *((void (*)) pgm_read_word((&(button[0].program)))(); 
31
}

EDIT: Mit Werners Antwort hat sich mein ;-( erledigt ;-)
Gast #838797
Lesenswert?

Es funktioniert!!!

Ich danke euch vielmals für eure Hilfe! Ich habe mein Fehler erkannt.
Eigentlich blöde von mir zu versuchen, eine Adresse zu "starten".
Habe die Adresse der Funktion jetzt an einen neuen Funktionszeiger
übergeben, wie von euch vorgeschlagen und es funktioniert auf Anhieb.
Nochmals danke.

Gruß
Niklas

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren