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


von Bronko P. (bronko99)


Lesenswert?

Hab etwa folgenden Code:
1
#define MEM_ROM_LOC(v)       v PROGMEM
2
3
typedef void (* funcPtr_t)(void);
4
5
6
7
static funcPtr_t MEM_ROM_LOC(s0_ts0[]) =
8
{
9
   f1,
10
   f2,
11
   NULL
12
};
13
...
14
15
static funcPtr_t MEM_ROM_LOC(s1_ts0[]) =
16
{
17
   f1,
18
   f2,
19
   NULL
20
};
21
...
22
23
static funcPtr_t MEM_ROM_LOC(*funcList[ABC][DEF]) =
24
{
25
  {
26
      (funcPtr_t *) s0_ts0
27
     ,(funcPtr_t *) s0_ts1
28
  },
29
30
  {
31
      (funcPtr_t *) s1_ts0
32
     ,(funcPtr_t *) s1_ts1
33
  }
34
}

Jetzt möchte ich alle Funktionen der funcList ausführen:
1
...
2
funcPtr_t *tsLocalFuncList;
3
tsLocalFuncList = rtosFuncList[i][j];
4
5
6
for(a = RESET; tsFuncList[a] != NULL; a++)
7
{
8
   /* execute current function */
9
   (tsLocalFuncList[a])();
10
}

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

von Stefan E. (sternst)


Lesenswert?

1
((funcPtr_t)pgm_read_word(&tsFuncList[a]))();

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Bronko P. (bronko99)


Lesenswert?

Danke für die Antwort,

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

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



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

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

von Stefan E. (sternst)


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. ;-)

von Bronko P. (bronko99)


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)

von Karl H. (kbuchegg)


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
1
static funcPtr_t MEM_ROM_LOC(*funcList[ABC][DEF]) =
2
{
3
  {
4
      (funcPtr_t *) s0_ts0
5
     ,(funcPtr_t *) s0_ts1
6
  },
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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Bronko P. (bronko99)


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
>
1
> static funcPtr_t MEM_ROM_LOC(*funcList[ABC][DEF]) =
2
> {
3
>   {
4
>       (funcPtr_t *) s0_ts0
5
>      ,(funcPtr_t *) s0_ts1
6
>   },
7
>
> 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

von Bronko P. (bronko99)


Lesenswert?

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


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

von Stefan E. (sternst)


Lesenswert?

1
tsLocalFuncList = (funcPtr_t) pgm_read_word(&funcList[i][j]);
->
1
tsLocalFuncList = (funcPtr_t*) pgm_read_word(&funcList[i][j]);

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.