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
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.
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?
> 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/:
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.
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:
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 :)
Ä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.
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.
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.
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.