mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik C-Problem, Zeiger auf Funktion


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

für folgendes Problem finde ich keine Lösung (C, KEIL, REALVIEW, ARM7):

Es soll zu einer Programmadresse verzweigt werden. Die Adresse ist in 
der Speicherstelle 0x10FFFC - 0x10FFFF (4 Bytes).

Folgendes habe ich mir ausgedacht:

void (* up)(); // ein Zeiger auf eine Funktion

up() ;         // Aufruf der Funktion


Wie bekomme ich den Zeiger mit dem Inhalt der Adresse (siehe oben) 
geladen?

Gibt es einen eleganteren Weg die obige Adresse aufzurufen?

Viele Grüße

Martin

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht so:

void (* up)(); // ein Zeiger auf eine Funktion
up = (void *)0x10FFFC;
up() ;         // Aufruf der Funktion

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert leider nicht. Es kommt ein Warning beim Compilieren:

update.c(88): warning:  #513-D: a value of type "void *" cannot be 
assigned to an entity of type "void (*)()"

und nach up() versucht das Programm ab Adresse 0x110000 weiterzulaufen. 
Was nicht funktioniert, da das Flash nur bis 0x10FFFF reicht.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Warning verschwindet mit:

up = (void (*)()) 0x10FFFC  ;

Der Zeiger enthält 0x10FFFC und verzweift zu dieser Adresse. Aber er 
soll zur Adresse die in 0x10FFFC steht verzweigen.

Wie kann ich den Inhalt der Adresse 0x10FFFC in den Zeiger bekommen?

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sprich bei 0x10FFFC steht die Adresse von "up"? Und die willst du dem 
Funktionspointer zu up zuweisen?

Autor: Volker Zabe (vza)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
struct tVect{
   void (* up)();
};

struct tVect *vect = (struct tVect*) 0x10FFFC; // Zeiger initialisieren

vect->up();   // Aufruf

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> void (* up)(); // ein Zeiger auf eine Funktion

Zumindest in C89 geht das nicht, da fehlt ein void in den runden 
Klammern.

> up = (void *)0x10FFFC;

Hier motzt der Compiler zurecht, hier wird einem Funktionspointer (up) 
ein void-Pointer zugewiesen.
Außerdem ist das nicht die Funktionsadresse, sondern die Adresse eines 
32-Bit-Werts, an dem die Funktionsadresse gespeichert ist. Das muss also 
einmal dereferenziert werden.

Etwas lesbarer wird das ganze mit einem /typedef/:
typedef void (*PFUNCTION)(void);

PFUNCTION up;

up = * ((PFUNCTION *) 0x10fffc));

Autor: Volker Zabe (vza)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:
> Etwas lesbarer wird das ganze mit einem /typedef/:
> typedef void (*PFUNCTION)(void);
>
> PFUNCTION up;
>
> up = * ((PFUNCTION *) 0x10fffc));

Das ist aber nicht das Gewünschte. Der TO will doch an die Adresse 
springen die in 0x10fffc steht.

struct tVect{
   void (* up)(void);
};

struct tVect *vect = (struct tVect*) 0x10FFFC; // Zeiger initialisieren

vect->up();   // Aufruf

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:
>> void (* up)(); // ein Zeiger auf eine Funktion
>
> Zumindest in C89 geht das nicht, da fehlt ein void in den runden
> Klammern.

doch, das geht m.W. auch mit C89 ohne void.
Mit void geht es natürlich auch.

Neben der Kombination Timo+Martin:
  void (*up)() = (void (*)()) 0x10FFFC  ;
  up();
geht auch der direkte Weg zum Glück:
  ((void (*)()) 0x10FFFC)();

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Weg funktioniert:

 void (* up)();                      // Zeiger auf eine Funktion
 int * uploader ;                    // Zeiger auf einen 32 Bit Integer

 uploader = (int *) 0x10FFC ;        // Integerzeiger zeigt auf 0x10FFFC
 up       = (void (*)()) *uploader ; // Inhalt von 0x10FFFC als Adresse

 up() ;                              // Aufruf der Adressse

Die eleganteren Codeausschnitte, die zwischenzeitlich gepostet wurden, 
schaue ich mir natürlich noch an.

Vielen Dank an alle :)

Autor: Volker Zabe (vza)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Äh schohn wieder überschnitten.
Rufus Lösung geht auch. (Habe das eine Sternchen übersehen.) ;-)

So jetzt hat er aber genug Lösungen.

Wenn es aber der Reset-Vektor ist, an dem der TO springen will, sollte 
man lieber nach dem Soft-Reset in der Doku suchen. Dann spring man nicht 
nur an den Anfang des Programms, sondern es werden auch alle Register 
zurück gesetzt.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:
> Etwas lesbarer wird das ganze mit einem /typedef/:
> typedef void (*PFUNCTION)(void);
>
> PFUNCTION up;
>
> up = * ((PFUNCTION *) 0x10fffc));

Da steht eine Klammer zuviel (oder eine zuwenig, je nachdem :-)
und die beiden Sterne müssen weg.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Da steht eine Klammer zuviel (oder eine zuwenig, je nachdem :-)
> und die beiden Sterne müssen weg.

sorra, ich hatte gedacht, er will die Adresse 0x10FFFC
anspringen. Aber da steht ja erst die Funktionsadresse.

Dann hast du mit den Sternchen natürlich recht.
Nur die Klammern sind noch falsch.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, es genügt eine schließende Klammer am Ende.

Tippfehler meinerseits.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dementsprechend korrigiere ich natürlich auch meine Varianten von oben:

Klaus Wachtler schrieb:
> Neben der Kombination Timo+Martin:
>
>   void (*up)() = (void (*)()) 0x10FFFC  ;
>   up();
> 
> geht auch der direkte Weg zum Glück:
>
> ((void (*)()) 0x10FFFC)();
> 

Heißen muß es:
    void (*up)() = *(void (**)()) 0x10FFFC;
    up();
bzw.
    (*((void (**)())0x10FFFC))();

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

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:

> Heißen muß es:
>
>     void (*up)() = *(void (**)()) 0x10FFFC;
>     up();
> 
> bzw.
>
>     (*((void (**)())0x10FFFC))();
> 

und spätestens jetzt sieht man auch, warum ein typedef bei 
Funktionspointer-Datentypen meistens eine extrem gute Idee ist.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm, das ist Geschmackssache.
Übersichtlicher finde ich es mit typedef auch nicht, und auch nicht
weniger fehleranfällig.

Verstehen muß man es mit oder ohne typedef.

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.