www.mikrocontroller.net

Forum: Compiler & IDEs wie konstanten Zeiger auf Funktion aus Flash lesen?


Autor: Niklas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist offenbar ein AVR.  Du musst eine Zeigervariable im RAM anlegen
und diese mittels pgm_read_word() aus dem ROM füllen.

Autor: Niklas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du versuchst den Zeiger bereits im ROM zu dereferenzieren, d. h. die
Funktion aufzurufen.  Lass einfach mal die runden Klammern weg.

Der Typecast nach void * bringt auch nichts.

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt mal so aus dem Bauch heraus...
void (*prog)(void) = (void(*)(void))pgm_read_word(&(button[i].program));
prog();
Du kannst nicht (void(*)(void))pgm_read_word(&(button[i].program))(); 
direkt aufrufen, weil pgm_read_word ein Makro ist.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde es so angehen (Ungetestet, nur hingeschrieben)

typedef const struct {
  unsigned char xpos;
  unsigned char ypos;
  ...
  void (*program)(void);    //Zeiger auf Funktion
  ...
} but;

// Definitionen

const but button[MAX_BUTTONS] PROGMEM = {
  {10, 20, ..., &dimming_high, ...},
  {...}
};

void dimming_high(void)
{
}

// Aufruf

int main(void)
{
  // so ;-)
  void (* fptr)(void); 
  fptr = (void (*)) pgm_read_word((&(button[0].program));
  fptr();

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


EDIT: Mit Werners Antwort hat sich mein ;-( erledigt ;-)

Autor: Niklas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> // oder so ;-(

Versuch mal, diesen Smiley mit deinem Gesicht nachzumachen, also die 
Mundwinkel hängen lassen und ein Auge zukneifen. Ist gar nicht so 
einfach ;-)

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.