C Grundlagen Bootloader

Probiere folgendes:

0x3800 ist nun auf einen void Funktionspointer gecastet.



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

int main(void)
{

  // ...
  boot_start(); // hier zum Bootloader springen
  // ...

}


In deinem Bootloader hast du den Sprung zu 0x0000 wahrscheinlich nur zum Testen.

Du hattest geschrieben, deine Applikation wird nicht ausgeführt.
Zum Schluss führst du die Routine start() aus, die finde ich nirgends.
 
In Zeile 396 findest du den Aufrufer. Das mit dem typenlosen cast habe ich auch schon probiert. Meckern tut er dann nicht tut so aber auch nicht was ich will. Meine Applikation startet dann überhaupt nicht. Ohne startet sie.
 
Ich meinte 379 sorry. Die müsstest du sehen!
 
Ah ja, ich sehe es.
Meckern tut er dann nicht tut so aber auch nicht was ich will. Meine Applikation startet dann überhaupt nicht. Ohne startet sie.

Also dazu habe ich im Moment auch keine Idee. Ich schau mir das aber noch mal an, nur heute nicht mehr.
Vielleicht ist ja noch jemand der eventuell helfen kann ?

Dirk :ciao:
 
Es gibt noch eine Möglichkeit mit


CodeBox C
goto *0x3800
da meckert er nicht, geht aber nicht in den bootloader von der applikation aus.
 
Ich weiß nicht ob das funktioniert, habe ich noch nie genutzt.

Welche Fusebits hast du denn programmiert, eventuell passt die Adresse ja nicht zur Einsprungadresse.
 
Moin Dirk,

ich glaube da hat was ganz anderes ein Problem. Wenn ich den Watchdog dazu nehme, spinnt mein Programm auch rum.
Wird wahrscheinlich an meinem Programm liegen.

Aber rein Theoretisch, wäre das möglich mit dem springen an die Adresse mit dem Funktionszeiger?
 
Hallo Jan,

ja das sollte funktionieren. Ich mache das so und andere auch.

Noch ein Hinweis, der aber wahrscheinlich nichts mit deinem Problem zu tun hat (oder vielleicht doch :):

Wenn du vom Bootloader an die Adresse 0 springst, also zu deiner Applikation, entspricht dies keinem Reset! Falls der Bootloader irgendwelche Peripheriemodule (USART, SPI, Timer, IO ...) konfiguriert hat, bleiben diese so konfiguriert. Deshalb mache ich immer einen Reset über Watchdog und beim Start des Bootloaders kann man überprüfen, welche Ursache der Reset hatte. War es der WD, dann starte ich sofort die App (falls vorhanden) ohne vorher Periperiemdoule zu konfigurieren.
 
Moin Dirk,

ich habe es mal ausprobiert ohne irgendwelche Interrupts. Siehe da.. Es funktioniert!
Das heißt wenn die Timer aktiviert sind, klappt das überhaupt nicht, selbst ein

CodeBox C
 cli();
reicht da nicht aus, nur wieso nicht? Deaktiviere ich damit die Interrupts nicht?
Erst wenn ich die Clock und den Interrupt im Register selbst deaktiviert habe (OCIE & CSxx).. dann klappt es.

Was mir noch aufgefallen ist. Irgendwas muss dann aber immer noch dazwischen funken. Habe manchmal komische Zeichen im Display oder es fehlen teile vom String (was ohne den Funktionszeiger bis jetzt noch nie vorgekommen war..)
Das ist doch sehr komisch oder?
 
Hallo Jan,

ich gehe mal davon aus, dass der Bootloader vom mikrocontroller.net funktioniert. Ich habe mir diesen nun nicht genauer angeschaut.
Es wird dort die Interrupt-Vector-Tabelle im Bootbereich genutzt. Anscheinend für Uart im Interrupt-Betieb, also kein Polling. Die IVT wird kurz vor dem Sprung zu Adresse 0 wieder in den Reset-Zustand versetzt, die startet also ab Adresse 0. Vorher müssen die Interrupts global ausgeschaltet werden. sei() mach das.

Achtung beim Hauptprogramm: Anscheinend ist der UART weiter aktiviert, wenn du global die Interrupts aktivierst, gibt es eventuell einen "Absturz".
Ich habe nun aber den Code nicht genauer angeschaut. Das ist ein Grund, warum ich im Bootloader den Weg über einen Watchdog Reset gehe, da ich damit einen echten Reset erreiche und alles in den Reset-zustand gebracht wird.

Baue mal nach _delay_ms(500) ein cli(); ein und deaktiviere dort ggf. noch den UART.

Dirk :ciao:



CodeBox C
 while(boot_state!=BOOT_STATE_EXIT);
   
   uart_puts("*  ->Reset now!\n\r"                    );
       uart_puts("***********************\n\r"        );
   _delay_ms(500);
   
   /* Interrupt Vektoren wieder gerade biegen */
   temp = GICR;
   GICR = temp | (1<<IVCE);
   GICR = temp & ~(1<<IVSEL);
   
   /* Reset */
   start();
   
   return 0;
 
Es liegt nicht an dem Bootloader Glaube ich sondern an meiner Applikation. Irgendwie verschluckt der sich da wenn ich zum bootloader und wieder zurück springe.. Muss lernen bessere Struktur in meinen Code zu kriegen.
 
Es liegt nicht an dem Bootloader Glaube ich sondern an meiner Applikation.
Wenn der Bootloader die Interrupts nicht wieder deaktiviert, ist das definitiv ein Fehler! Allgemein ist es problematisch, wenn der Bootloader irgend etwas konfiguriert hat, von dem du in der Applikation nichts weißt.

Also ein cli() im Bootloader einbauen!
 
Wenn ich von meinem Hauptprogramm, wieder in den bootloader springe, sollte ich vorher auch die ganzen Interrupts deaktivieren?
 
Moin Dirk, habe das jetzt in den Bootloader mit eingebunden.

Hier mal ein Screenshot von meiner UART Ausgabe.
upload_2017-9-14_6-21-40.png

Das sollte eigentlich auf meinem Terminal zu sehen sein.

Hier sieht man was wirklich angezeigt wird..
upload_2017-9-14_6-22-14.png

Es taucht immer wieder mal "K1 un" auf.. Das wird zu dieser Zeit aber nicht ausgegeben bzw. irgendwo verarbeitet.
Was kann das sein? Das ist eigentlich jetzt das Hauptproblem, was ich nicht in den Griff bekomme..

Kommt da irgendwas mit Adressen durcheinander?
 
Fakt ist, wenn ich diese Routine aufrufe, egal ob ich jetzt den Watchdog oder den Zeiger nehme, immer gibt es Probleme bei der Ausgabe am UART oder GLCD.



CodeBox C
void bootloader(void)

{

cli();
TIMSK = 0x00;
TCCR1B = 0x00;
[I]_delay_ms[/I](500);
// wdt_enable(WDTO_15MS);
// while(1){};
// wdt_disable();
// void (*boot)() = (void (*)(void)) 0x3800;
// boot();
}


Kann ich in meinem Projekt eigentlich einstellen, dass er Speicher ab 0x3800 nicht mehr Frei ist? Sprich eine Grenze?
 
Hallo Jan,

es fehlen auch Zeichen in der vorletzten Zeile und die erste Zeile mit "*" kommt in deinem Code nicht vor?!
Es ist schwer zu sagen, woran es liegen könnte, ich sehe auch nicht viel vom Code.

Du aktivierst Interrupts, ist das für den UART oder ist das für etwas anderes?

Um die Ursache des Fehlers besser finden zu können, würde ich das Programm möglichst vereinfachen, also alles andere, was nicht notwendig ist erst mal "abschalten" und wenn möglich Interrupts deaktivieren. Falls es mit dem Bootloader zusammenhängt (der initialisiert ja auch einen UART und läßt den einfach so, nicht im Resetzustand bei der Applikation) auch mal direkt die App starten, also ohne Bootloader davor (Fusebits). Später beim Bootloader auf jedenfall vor dem Rücksprung zur Applikation die Interrupts deaktivieren, bevor die Interrupt Vektor Tabelle wieder auf den Applikationsbereich verbogen wird!

Also versuchen die UART Ausgabe mit einem Minimalsystem laufen zu lassen.
 
Fakt ist, wenn ich diese Routine aufrufe, egal ob ich jetzt den Watchdog oder den Zeiger nehme, immer gibt es Probleme bei der Ausgabe am UART oder GLCD.

Das mit der Obergrenze setzten weiß ich im Moment nicht.

Du deaktivierst ja Interurpts global, wenn der UART die nutzt ist klar, dass es nicht mehr richtig funktioniert. Warum es bei der Displayausgabe Probleme gibt, kann ich nicht sagen, dafür kenne ich zu wenig (praktisch nichts) von deinem Code.
 
Wenn ich die App flashe, klappt alles wie es soll (also ohne Bootloader). Die Texte werden richtig ausgegeben und keine Fehler. Ist der Boot.c mit drauf, fangen diese Symptome an.

Habe die Source mal mit beigefügt.
 

Anhänge

  • App.c
    28,5 KB · Aufrufe: 5
  • Boot.c
    10,1 KB · Aufrufe: 5

Ü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)