www.mikrocontroller.net

Forum: Compiler & IDEs AVR Functionpointertabelle im Flash, Function aufrufen


Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab etwa folgenden Code:
#define MEM_ROM_LOC(v)       v PROGMEM

typedef void (* funcPtr_t)(void);



static funcPtr_t MEM_ROM_LOC(s0_ts0[]) =
{
   f1,
   f2,
   NULL
};
...

static funcPtr_t MEM_ROM_LOC(s1_ts0[]) =
{
   f1,
   f2,
   NULL
};
...

static funcPtr_t MEM_ROM_LOC(*funcList[ABC][DEF]) =
{
  {
      (funcPtr_t *) s0_ts0
     ,(funcPtr_t *) s0_ts1
  },

  {
      (funcPtr_t *) s1_ts0
     ,(funcPtr_t *) s1_ts1
  }
}

Jetzt möchte ich alle Funktionen der funcList ausführen:
...
funcPtr_t *tsLocalFuncList;
tsLocalFuncList = rtosFuncList[i][j];


for(a = RESET; tsFuncList[a] != NULL; a++)
{
   /* execute current function */
   (tsLocalFuncList[a])();
}

Ich weiß dass man mittels pgm_read_byte() den ROM lesen kann, aber wie 
macht man das um an eine Funktionsadresse zu kommen?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
((funcPtr_t)pgm_read_word(&tsFuncList[a]))();

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

Bewertung
0 lesenswert
nicht lesenswert
Ich würde allerdings eine Zwischenvariable einführen, dann lässt sich
der Code besser lesen statt mit dieser Typecast-Verrenkung.  Das
Ergebnis im Maschinencode sollte gleich bleiben, so man die Optimierung
aktiviert.

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort,

es geht mir aber um die Zeile
tsLocalFuncList = funcList[i][j];

Ich habe folgendes gemacht
tsLocalFuncList = (funcPtr_t) pgm_read_word(&funcList[i][j]);



und bekomme die Warning:
warning: assignment from incompatible pointer type

Das Programm läuft auch leider nicht. Als ich die Tabellen im RAM hatte 
war alles i.O.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, wie du dir das vorstellst, geht das nicht. Du musst jeden einzelnen 
Funktionszeiger aus dem Flash lesen. Und das gilt im übrigen nicht nur 
für den eigentlichen Aufruf der Funktion, sondern natürlich auch für den 
Test des Pointers gegen Null in der for-Bedingung. Die von Jörg 
vorgeschlagene Zwischenvariable ist damit natürlich umso sinnvoller. ;-)

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast absolut recht. Damit wird das ganze aber zu aufgebläht. In dem 
Fall lasse ich die Tabellen im RAM, außer Ihr kennt eine andere 
Alternative um das Problem zu lösen? Ich bin leider noch AVR Neuling, 
komme vom R8C (da machst du ein const und das Ding ist im ROM. Der 
Zugriff ist ebenso einfach)

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

Bewertung
0 lesenswert
nicht lesenswert
Bronko Pavel schrieb:
> Du hast absolut recht. Damit wird das ganze aber zu aufgebläht.

Glaub ich zwar nicht, aber was willst du eigentlich wirklich machen?

Das du hier Casts brauchst
static funcPtr_t MEM_ROM_LOC(*funcList[ABC][DEF]) =
{
  {
      (funcPtr_t *) s0_ts0
     ,(funcPtr_t *) s0_ts1
  },
macht mich stutzig, da sollte eigentlich keiner notwendig sein.
Auch deine Einführung des Makros MEM_ROM_LOC macht die Sache nicht 
unbedingt übersichtlicher.

Also: Was soll das Ganze eigentlich werden?

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

Bewertung
0 lesenswert
nicht lesenswert
Bronko Pavel schrieb:
> Du hast absolut recht. Damit wird das ganze aber zu aufgebläht.

Der Maschinencode dafür ist so oder so notwendig, der Unterschied
zwischen Flash-ROM und RAM ist nur, ob dort LDS- oder LPM-Befehle
an den entsprechenden Stellen stehen, wobei die LPM-Befehle im
Vergleich zu LDS jeweils einen Takt mehr brauchen.  Der Rest des
Codes (Zurechtlegen der notwendigen Adressregister) wird so oder
so benötigt, ist halt nur die Frage, dass man das beim AVR-GCC
und Flash-ROM-Zugriff nicht so schön einfach hinter zwei Paar
eckigen Klammern verstecken kann.

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Bronko Pavel schrieb:
>> Du hast absolut recht. Damit wird das ganze aber zu aufgebläht.
>
> Glaub ich zwar nicht, aber was willst du eigentlich wirklich machen?
>
> Das du hier Casts brauchst
>
> static funcPtr_t MEM_ROM_LOC(*funcList[ABC][DEF]) =
> {
>   {
>       (funcPtr_t *) s0_ts0
>      ,(funcPtr_t *) s0_ts1
>   },
> 
> macht mich stutzig, da sollte eigentlich keiner notwendig sein.
> Auch deine Einführung des Makros MEM_ROM_LOC macht die Sache nicht
> unbedingt übersichtlicher.
>
> Also: Was soll das Ganze eigentlich werden?


Ja das ist mein kleines zeitscheibenbasierte "Betriebssystem". Du kannst 
dir das so vorstellen: Jede Zeitscheibe hat bis zu 10 Tasks 
(Funktionen). Jeder "State" Besteht aus bis zu 4 Zeitscheiben und dann 
gibt es noch 4 States. Das ganze ist über Präprozessorlogik so 
zusammengesetz, das nur Speicher für die tatsächliche Anzahl von 
Tasks/Timeslices/States kompiliert wird. Natürlich sind 
Tasks/Timeslices/States in Ihrer Anzahl variabel, aber o. g. Werte haben 
sich bewährt. Das ganze kommt bei mittelgroßen Projekten zum Einsatz. Da 
ich den AVR kennenlernen will habe ich damit angefangen es zu portieren 
und am Ende HW unabhängig zu machen, deshalb z.B. MEM_ROM_LOC() Macro 
usw.. Wenn du sagst das Performance "unnötigerweise" verloren geht, dann 
nehm ich halt einen größeren/schnelleren uC (ob ich 3€ oder 5€ zahl ist 
daheim Wurst)

... werd versuchen das nach Jörgs Aussage doch ins Flash zu packen...

Gruß
Bronko

Autor: Bronko Pavel (bronko99)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich pack es irgendwie doch nicht.
tsLocalFuncList = (funcPtr_t) pgm_read_word(&funcList[i][j]);
führt zu
warning: assignment from incompatible pointer type


Wie mache ich es in der for-Schleife um an die nächste Funktion zu 
kommen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tsLocalFuncList = (funcPtr_t) pgm_read_word(&funcList[i][j]);
->
tsLocalFuncList = (funcPtr_t*) pgm_read_word(&funcList[i][j]);

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.