Pointer Problem mit SDCC

OP #404093
Lesenswert?

Hallo,

ich hab mir ein Menü programmiert, das die Funktionen über Pointer
aufruft. Jetzt hätte ich beim Aufruf der Funktionen gerne einen
Parameter übergeben.
SDCC meldet mir
D:/Daten/8051/C/Menü.c:120: warning 92: Functions called via pointers
must be 'reentrant' to take arguments
und kompiliert die Funktionen danach nicht mehr.

Kann mir jemand verraten wie ich beim Aufruf von Funktionen über
Pointer einen Parameter übergeben ?

Im Anhang findet ihr mein komplettes Programm.

Gruß Michael
Angehängte Dateien:
OP #404094
Lesenswert?

Nochmal ich :-)

Im Thread http://www.mikrocontroller.net/forum/read-2-40721.html im
Beitrag von Karl Heinz Buchegger (etwa in der Mitte) ist sowas erklärt,
aber funktioniert nicht.

P.S. Das Struct des Menüs hab ich bereits geändert
typedef struct MENU {
  const unsigned char *MenueText;
  unsigned char MenueNo;
  unsigned char NextMenueNo;
  void (*MenueFunction)(unsigned char);
} MENUE_ENTRY;
#404095
Lesenswert?

Nun, du möchtest mit

  Menue[ArrayPos+MenuePos].MenueFunction(MenuePos);

deine Funktion aufrufen.

Wie ist MenuFunction deklariert:

typedef struct MENU {
  const unsigned char *MenueText;
  unsigned char MenueNo;
  unsigned char NextMenueNo;
  void (*MenueFunction)( void );
} MENUE_ENTRY;


Da steht:
Menufunction ist ein Zeiger auf eine Funktion die nichts
zurückliefert (das erste void) und keine Argumente nimmt (das
zweite void). Wenn du also der Funktion Argumente geben willst,
dann musst du das in der Deklaration des Funktionszeigers auch
vereinbaren:

  void (*MenueFunction)( unsigned char );

Jetzt ist MenuFunction ein Zeiger auf eine Funktion die als
erstes Argument einen unsigned char nimmt.

Natürlich müssen jetzt auch alle Funktionen die du an so
einem Funktionszeiger binden willst auch tatsächlich einen
unsigned char annehmen.
OP #404096
Lesenswert?

Hallo Karl Heinz,
genau das hab ich in meinem 2.Post beschrieben, aber die Fehlermeldung
bleibt dieselbe. Das merkwürdige ist, das die gleiche Zeile bemängelt
wird.

Es funktioniert auch, wenn ich einen Zeiger benutze der nicht in einem
Struct definiert ist.
Ich suche also weiter, wie richtig auf Elemente eines Structs
zugegriffen wird.
#404097
Lesenswert?

Das stimmt an und für sich alles, da das Standard-C ist.

Die Fehlermeldung allerdings deutet darauf hin, dass das
ein compilerspezifisches Problem ist. Der Ausdruck 'reentrant'
ist im C-Standard nicht definiert (auch wenn wir alle wissen
was damit gemeint ist). Da wirst du also im Compiler-Handbuch
suchen muessen, was dem Compiler da nicht passt.
Gast #404098
Lesenswert?

ich kenn mich zwar mit dem sdcc nicht so aus, aber hast du mal folgendes
probiert (sollte eigentlich mit jedem compiler möglich sein) :



typedef void (FKT_ZEIG) (char cParameter1);

void test (char cPar1)
{
 ...
}


FKT_ZEIG *func1 = (FKT_ZEIG *) &test;

void main (void)
{
  char cP = 10;

  ...

  if (func1 != NULL)
  {
    func1 (cP)
  }

  ...
}
#404100
Lesenswert?

> Es funktioniert auch, wenn ich einen Zeiger benutze der nicht in
> einem Struct definiert ist.

Das ist interessant.

Versuch mal:
  (Menue[ArrayPos+MenuePos].MenueFunction)(MenuePos);

oder

  (*(Menue[ArrayPos+MenuePos].MenueFunction))(MenuePos);

Sollte eigentlich keinen Unterschied machen, wenn ich die
Precedence Regeln noch richtig im Kopf habe, aber es soll
ja auch schon Compilerfehler gegeben haben.
OP #404101
Lesenswert?

@TheMason

unsigned int foo1( int Arg1 )
{
  return (int)( Arg1 + 0.5 );
}

void main(void)
  {
    unsigned int (*MyFunc)( int );
    MyFunc = foo1;

    i = (*MyFunc)( 4 );   /* Aufruf der Funktion ueber den Pointer */
  }

Das funktioniert, wobei Das Ergebnis natürlich Quatsch ist.

@Karl Heinz
Das Klammern reicht nicht, aber ich habe auch den Verdacht, das es am
Compiler liegt.
Bei Gelegenheit werde ich das mal Visual C testen.
#404103
Lesenswert?

Auf einer Website (google: SDCC reentrant)
habe ich folgenden Satz gefunden:

<Zitat>
Avoid calling functions from within an ISR. If you must do this,
declare the function as reentrant (see SDCC manual) which allocates
all local variables in the function on the stack instead of in RAM.
</Zitat>

besonders der letzte Satzteil
"which allocates all local variables in the function on the stack
instead of in RAM" lässt bei mir die Alarmglocken klingen.

Auf jeden Fall: Das ist irgendetwas SDCC spezifisches.

Aus mehreren anderen Websites habe ich mal folgendes abgeleitet:

typedef struct MENU {
  const unsigned char *MenueText;
  unsigned char MenueNo;
  unsigned char NextMenueNo;
  void (*MenueFunction)(unsigned char) reentrant;
} MENUE_ENTRY;

Und dann natürlich noch jede Funktion mit dem Zusatz 'reentrant'
ausstatten.
Gast #404105
Lesenswert?

Etliche 8bit Microcontroller tun sich mit Daten auf dem Stack erheblich
schwerer als mit statisch adressierten Daten. Vor allem wenn die
Architektur zu einem Zeitpunkt entstand, als C in diesem Sektor noch
nicht verbreitet war (8051,PIC).

Und so ist es bei solchen Compilern üblich, bis auf Widerruf lokale
Daten statisch zu adressieren. Macht Keil auch nicht anders.
Gast #404106
Lesenswert?

also ist das verhalten von funktionszeigern beim sdcc nicht so einfach
wie ich es unter standard c gewohnt bin.
gibt es damit eigentlich probleme bei anderen compilern (z.b.
mspgcc/armgcc usw ...) ?!
würde mich mal interessieren wenn ich mal was mit beispielsweise
eclipse mache ... (ob es da auch ähnlich problematisch ist)

gruß
rene
Gast #404107
Lesenswert?

Eclipse ist kein Compiler.

GCC für ARM,AVR,MSP430 arbeitet normal, eine spezielle Kennzeichnung
derartiger Funktionen ist nicht erforderlich.

Zilog Z8 kann zwar mit Stack-Daten umgehen, der Compiler benutzt in
Standardeinstellung jedoch statische Adressierung.

Compiler für Microcontroller sind meistens mit architekturspezifischen
Eigentümlichheiten gesegnet. Getrennte Adressräume für Code und Daten
erschweren das Leben (8051,AVR,PIC), Interrupt-Routinen müssen speziell
behandelt werden (alle), komprimierter Code fordert Tribut (ARM-Thumb),
ROM-Banking kann u.U. eine Reorganisation des Quellcodes erfordern
(PIC), ...
Gast #404108
Lesenswert?

@a.k.

sorry, meinte natürlich nicht eclipse als solches sondern mit den
jeweilgen plugins für verschiedene mikrocontroller unter eclipse.

mit den wüsten adressräumen beim 8051 habe ich schon bekanntschaft
gemacht. beim msp430 hatte ich bis jetzt keine probleme (speziell mit
funktionszeigern, da ich oftmals exzessiven gebrauch davon mache :-)
deswegen hab ich auch meinen (überflüssigen) senf dazugegeben, weil
mich mal interessieren würde bei welchen prozessoren funktionszeiger
probleme machen können.

gruß
rene

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