Forum: Mikrocontroller und Digitale Elektronik Zum Bootloader springen


von Rheingold28 (Gast)


Lesenswert?

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

von Dietmar (Gast)


Lesenswert?

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.

von Dieter M. (Gast)


Lesenswert?

watchdog reset auslösen!

von mimmi (Gast)


Lesenswert?

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

von Rheingold28 (Gast)


Lesenswert?

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

von Helfer (Gast)


Lesenswert?

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().

von Reinhard R. (reinhardr)


Lesenswert?

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

von Rheingold28 (Gast)


Lesenswert?

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
       :
   }

}

von Reinhard R. (reinhardr)


Lesenswert?

Hast du diesen Thread schon gelesen?
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=493336

Gruß,
Reinhard

von Daniel H. (Gast)


Lesenswert?

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?

von Daniel H. (Gast)


Lesenswert?

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...

von Rheingold28 (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.