C Funktionspointer (von "irgendeinem" Bootloader Quellcode)

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Hallo,

was genau passiert, wenn ich die Funktion aufrufe?



CodeBox C
  /* Funktionspointer auf 0x0000 */
   void(*start)( void ) = 0x0000;
#



CodeBox C
start();


Wird dann von Adresse "0" aus weiter gearbeitet?
 
Wird dann von Adresse "0" aus weiter gearbeitet?

Ja.
(Wenn du vom Bootloader zu deiner Applikation springen möchtest (nach Adresse 0), wirkt das nicht, wie ein richtiger Reset)

Mit sowas springe ich zum Beispiel den Bootloader von der Applikation an:



CodeBox C
// the pointer to bootloader
void (*boot_start)(void) = 0x1F800;  // word
// Byte 0x258048 = 0x3F000

boot_start();


Siehe auch HIER.


Dirk :ciao:
 
Ja.
(Wenn du vom Bootloader zu deiner Applikation springen möchtest (nach Adresse 0), wirkt das nicht, wie ein richtiger Reset)

Wieso nicht? Fängt er nach einem "reset" nicht dort auch wieder an?
 
Bei einem echten Reset werden alle I/O-Register mit festgelegten Werten initialisiert. Ein Sprung auf den Resetvektor macht das nicht. Die Register sind also weiterhin wirksam.
Deswegen hatte ich im anderen Thread auch auf den Watchdog verwiesen - der kann einen echten Reset auslösen (wobei man die Reset-Quelle immer noch in einem Register feststellen kann (Externer Reset, Watchdog, BrownOut...)

In jedem Controller-Datenblatt solltest Du in etwa finden:
Resetting the AVR
During reset, all I/O Registers are set to their initial values, and the program starts execution from the Reset Vector.
 
Zuletzt bearbeitet:
Bei einem echten Reset werden alle I/O-Register mit festgelegten Werten initialisiert. Ein Sprung auf den Resetvektor macht das nicht. Die Register sind also weiterhin wirksam.

Genau :)

Du kannst es zum Beispiel so machen:

Am Anfang vom Bootloader prüfen, ob es ein Watchdogreset gegeben hat (Resetquelle untersuchen)
- Falls ja, dann zur Adresse 0 springen (aber auch nur dann, wenn in Adresse 0 kein 0xFF steht. 0xFF = App nicht da ;))
- Falls nein, Bootloader weiter ausführen.

Nach der erfolgreichen Programmierung im Bootloader den Watchdog aktivieren und in eine while(1) schleife gehen, so dass der Watchdog einen Reset ausführt.


Dirk :ciao:
 
Wenn es Hardwaretechnisch egal ist welche Pegel nach dem Sprung aus dem Bootloader herrschen, braucht man doch keinen Watchdog oder?
 
Wenn es Hardwaretechnisch egal ist welche Pegel nach dem Sprung aus dem Bootloader herrschen, braucht man doch keinen Watchdog oder?

Hmmm, du verwechselst das mit dem BrownOutDetector BOD?

Das mit dem Watchdog ist eine einfache Möglichkeit, einen sauberen Reset auszuführen.



CodeBox C
#include <avr/wdt.h>
// ...
wdt_enable(WDTO_30MS);
for (;;);
 
12/* Funktionspointer auf 0x0000 */ void(*start)( void ) = 0x0000;

Mir ist der Syntax noch nicht so ganz klar.
Das ist eine Funktion... Funktionen kenne ich bis jetzt aber nur anders.
 
Die Adresse der Funktion "start" welche keine Parameter erwartet und keine Parameter zurückgibt (Routine) ist 0x0000.

Hier findest du wieder das "*". Das Thema hatten wir ja mit dem Adressoperator "&" letztens schon einmal.
 
Also bis jetzt habe ich nur diese Funktion kennengelernt



CodeBox C
void test(uint8_t para);


Daher wundere ich mich ein wenig über den Syntax abgesehen vom "dereferenzierer"



CodeBox C
void (*boot_start)(void) = 0x1F800; 


Ist denn *boot_start ein zu übergebender Parameter? Wieso steht danach noch mal (void)?
Und das man einer Funktion ohne Rückgabewert, direkt einen Wert zu weisen kann?
 
Routine: ohne Rückgabewert (erstes void) ohne Parameter (zweites void)


CodeBox C
void meine_routine (void)


Die Routine meine_routine zeigt auf die Adresse 0x1F800:



CodeBox C
void (*meine_routine)(void) = 0x1F800;


Bei einer Variablen ist es genauso:



CodeBox C
  int *ptr = 0x1F800;  // ptr zeigt auf die Adresse 0x1F800

  oder auch
  int s;
  int *ptr = &s;  // ptr Zeigt auf Adresse von s
 
C C++1void (*meine_routine)(void) = 0x1F800;

Oh natürlich, peinlich! Ist mir gerade aufgefallen (void) nach dem Namen ist ja korrekt.
Die erste Klammer (*meine_funktion), muss die sein oder würde es auch ohne funktionieren?
 
Weil der * Operator nur auf den Funktionsnamen wirken soll. Ohne Klammer beschwert sich der Compiler.
 
Normalerweise kann eine void Funktion ja keinen Wert annehmen weder zurück geben, daher wundert mich der Syntax.
Also wird nur gesagt, diese Funktion soll an der entsprechende Adresse ausgeführt oder abgelegt werden?
 
Ja, bei einem Aufruf der Funktion wird das Programm ab der entsprechenden Adresse fortgesetzt.
 
Ja, hier wird ein CALL oder EICALL ausgeführt. Ein JMP (IJMP, EIJMP) kann man auch mit inline assembler machen.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)