Hallo Leute, ich arbeite zur Zeit an meinen ATmega32u4 und möchte aus der Software zum Bootloader springen damit ich eine neue Software flashen kann. Laut Handbuch liegt die Booatloader-Adresse bei 0x3800. Leider stürzt mir das Programm ab wenn ich dort hinspringe. Kann mir vielleicht jemand einen Tip geben wie ich das Problem beheben kann? Das Programm ist in C geschrieben. Danke für die Hilfe. Gruß Rheingold
Ich weiss nicht, ob das per Hineinspringen geht. Ich mache das per Reset. Wenn die Taste OK beim Einschalten (Reset) gedrückt gehalten wird, aktiviert sich der Bootloader. OK ist in der normalen Firmware die Taste, die der Beutzer im Menü benutzt, um etwas auszuwählen. Der Benutzer wählt als den Menüpunkt "Firmware aktualisieren", drückt 3s lang auf OK (er sieht einen Countdown auf dem LCD) und dann macht die Firmware per Watchdog den Reset. Die gedrückte OK-Taste startet beim folgenden Reset den Bootloader.
Rheingold28 schrieb: > Laut Handbuch liegt die Booatloader-Adresse bei 0x3800. Leider stürzt > mir das Programm ab wenn ich dort hinspringe. Wie sieht dafür der Quellcode aus? Ansonsten Schritt 3 und auch der Rest vom Artikel: AVR Bootloader in C - eine einfache Anleitung und all die anderen, je nach belieben... AVR Bootloader FastBoot von Peter Dannegger AVR-Bootloader mit Verschlüsselung von Hagen Re AVR Bootloader FastBoot von Peter Dannegger/Tutorial ATtiny13 Kavr: AVR Hexfile Boot Loader
Der Quellcode sieht so aus! #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "usb_srs_hid_v1_2.h" #include "TWI_IO.h" struct struct_interrupt { uint8_t t0ocA; } interrupt; typedef void (*boot_reset_fptr_t)(void); int main(void) { UINT Bootloader = 0; sei(); boot_reset_fptr_t start_bootloader = (boot_reset_fptr_t) 0x3800; : : : while(1) { uint8_t volatile port, port_alt; // Portpins port = ReadPortPins(); : : if(Bootloader==1) start_bootloader(); //Sprung zur //Bootloader Adresse : } } Gibt es eine andere Möglichkeit? Gruß Rheingold
Rheingold28 schrieb: > Laut Handbuch liegt die Booatloader-Adresse bei 0x3800. Leider stürzt > mir das Programm ab wenn ich dort hinspringe. Was sagen die Fuses zum Bootloader-Bereich? Stimmen Handbuch/Annahmen und Fuses überein? Würde direkt vor dem Sprung in den Bootloader Interrupts nicht mehr annehmen - cli().
Muss die Sprungaddresse in Worten oder Bytes ausgedrückt werden? Ich meine mal auf AVR Freaks etwas dazu gelesen zu haben. Beim umgekehrten Sprung aus dem Bootloader ins Programm (0x0000) ist das ja egal, aber hier wäre das ein Problem. Gruß, Reinhard
Hallo Leute, vielen Dank für eure Hilfe, leider habe ich das Problem immer noch nicht gelöst. Zum Testzwecken, habe ich mal versucht die Bootloader-Adresse in 0x7000 umzuändern. Ohne Erfolg! Wie ich aus dem Handbuch ATmega16/32u4 entnehmen kann, sollte das IVSEL-Bit auf 1 gesetzt werden damit der Sprung zum Bootloader möglich wird. Leider war dieser Schritt auch nicht erfolgreich. Ich habe zusätzlich noch 2 Zeilen hinzugefügt, die mir den Interrupt ein- bzw. ausschaltet. Muß ich im Programm noch was ergänzen, damit es aus dem Programm zum Bootloader springen kann? Hat jemand noch eine andere Idee? Viele Grüsse Rheingold #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "usb_srs_hid_v1_2.h" #include "TWI_IO.h" struct struct_interrupt { uint8_t t0ocA; } interrupt; typedef void (*boot_reset_fptr_t)(void); int main(void) { UINT Bootloader = 0; sei(); boot_reset_fptr_t start_bootloader = (boot_reset_fptr_t) 0x3800; //boot_reset_fptr_t start_bootloader = (boot_reset_fptr_t) 0x7000; : : : while(1) { uint8_t volatile port, port_alt; // Portpins port = ReadPortPins(); : : if(Bootloader==1) { cli(); MCUCR |= (1 << IVSEL); //IVSEL-Bit auf 1 setzen sei(); start_bootloader(); //Sprung zur //Bootloader Adresse : } }
Hast du diesen Thread schon gelesen? http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=493336 Gruß, Reinhard
Bootloader Startadresse des Datenblattes nehmen, und *2 (Byte/Wort) Befehl: asm volatile ("jmp 0xE000"); Im Bootloader muss in den Linker Options angegeben werden, das das Programm (der Bootloader) in den entsprechenden Programmbereich geschrieben wird (sieht etwa so aus -Wl,--section-start=.text=0xE000) Frage, Normalerweise wird erst der Bootloader geladen, und dann darüber die Software, hast du dies so gemacht... funktioniert dies soweit?
Anmerkunkt IVCE sollte ebenfalls 1 gesetzt werden, dass das IVSEL gesetzt werden kann.... unabhängig davon sollte die Software jedoch in den boootloadermode springen, und der Bootloader sollte laufen, dies hat erst einen Einfluss, wenn im Bootloader Interrupts ausgelösst werden...
Hallo, nun, das Problem habe ist anscheinend gelöst. 1.Wenn IVSEL auf 1 gesetzt wird, muß vorher auch der IVCE auf 1 gesetzt werden damit IVSEL funktioniert. Danach wird IVCE durch die Hardware wieder auf 0 gesetzt. 2.In meiner Software verwende ich einen Timer-Interrupt. Der sollte deaktiviert werden bevor er zum Bootloader springt. (Siehe Quellcode) Vielen Dank an alle, besonders Reinhard R. & Daniel H. die mir zur Lösung geholfen haben. Gruß Rheingold #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "usb_srs_hid_v1_2.h" #include "TWI_IO.h" struct struct_interrupt { uint8_t t0ocA; } interrupt; typedef void (*boot_reset_fptr_t)(void); int main(void) { UINT Bootloader = 0; sei(); boot_reset_fptr_t start_bootloader = (boot_reset_fptr_t) 0x3800; : : : while(1) { uint8_t volatile port, port_alt; // Portpins port = ReadPortPins(); : : if(Bootloader==1) { MCUCR |= (1 << IVCE); //IVCE = 1 MCUCR |= (1 << IVSEL); //IVSEL = 1 TIMSK0 = 0; //Timer-Interrupt ausschalten start_bootloader(); //Sprung zur //Bootloader Adresse : } }
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.