Hallo Forum,
ich verzweifle gerade dabei den USB Bootloader von Atmel (neu mit iar
kompiliert wegen Änderung Pin) aus meiner Applikation heraus zu starten.
Im Normalfall soll nur die Applikation starten (Fuse gesetzt) und nur
bei Bedarf angesprungen werden.
Wenn ich die Fuse auf Bootloader stelle, funktioniert alles bestens und
auch, wenn noch keine Applikation geladen ist.
Beim Aufruf aus der Applikation startet trotzdem die Applikation nach
einer kurzen Verzögerung.
Hier mein Aufruf:
void(* start_bootloader)(void) = (void
(*)(void))(BOOT_SECTION_START/2+0x1FC/2);
...
udc_detach();
udc_stop();
delay_ms(250);
cpu_irq_disable();
start_bootloader();
Das entsprechende Pin liegt fest auf GND.
Die gleiche Funktion benutze ich auch bei einem xmega128, wo sie perfekt
funktioniert.
Ich hoffe, ihr könnt helfen.
Gruß Daniel
Aus Erfahrung kommt der Bootloader eh nicht mit funktionsfähigem USB
hoch.
1. EEPROM Flag schreiben
2. uC Reset
3. direkt nach dem Start deiner eigenen Applikation EEProm checken und
in den Bootloader springen
Daniel Held schrieb:> Die gleiche Funktion benutze ich auch bei einem xmega128,
Wenn es beim 128er funktioniert, sollte es bem 256er mit den richtigen
Einstellungen auch funktonieren.
Knut B. schrieb:> Wenn es beim 128er funktioniert, sollte es bem 256er mit den richtigen> Einstellungen auch funktonieren.
Ja, das habe ich auch gedacht. Die Sprünge sind komplett identisch,
abgesehen von der BOOT_SECTION_START.
Knut B. schrieb:> Kannst Du mit SRAM machen, wird bei RESET nicht gelöscht. Braucht man> kein EEPROM für.
Ist das echt so einfach? Eine Variable setzen, Reset und dann der
Sprung?
Basti schrieb:> 1. EEPROM Flag schreiben> 2. uC Reset> 3. direkt nach dem Start deiner eigenen Applikation EEProm checken und> in den Bootloader springen
Also dann nur einen direkten Sprung zu BOOT_SECTION_START, oder?
Danke euch.
Knut B. schrieb:> Bist Du sicher, dass Du die richtigen Adressen angegeben hast? Der 256er> hat ja doppelt so viel Flash und doppelt so viel SRAM.
Danke Knut, das war ein Problem - Asche aufs Haupt.
Die Adresse habe ich auf 0x401FC geändert, dass funktioniert jetzt auch.
Allerdings habe ich ein Problem mit dem Eeprom: die Funktionen
nvm_eeprom_read/write_byte und die "normale" eeprom_read/write_byte -
zeigen die auf den selben Speicherbereich?
Wenn ja, müsste ich das Bootloaderbyte mit in meine Eeprom-Struktur
aufnehmen und über nvm_eeprom_read_byte lesen, oder?
Im Moment startet er immer den Bootloader, deshalb vermute ich, dass das
Bootloaderbyte mit meiner Struktur überschrieben wird.
Daniel Held schrieb:> zeigen die auf den selben Speicherbereich?
Es gibt 2 EEPROM-Zugriffsmöglichkeiten, über den NVM adressiert und über
den Speicher adressiert. Erstere greift auf 0x0000 + Adresse zu und
letztere auf 0x1000 + Adresse.
@Knut
Mit dem Reset meinte ich den über den Watchdog. Mit dem "soft" Reset hat
es bei mir auch nie geklappt... Seit dem ich über den Watchdog-Reset
gehe, hatte ich keine Probleme mit dem USB-Bootloader mehr.
Aber auf AVR-Freaks steht ja alles...
Basti schrieb:> Mit dem "soft" Reset hat> es bei mir auch nie geklappt... Seit dem ich über den Watchdog-Reset> gehe, hatte ich keine Probleme mit dem USB-Bootloader mehr.
Der Soft Reset macht exakt das Gleiche, wie der Watchdog. Es gibt keinen
(programm-) technischen Unterschied. Das Software-Reset Bit ist durch
das CCP-Register geschützt und muss vor Benutzung entsperrt werden.
Hm, ist schon wieder eine Weile her...
Gabs nicht zwei Reset-Möglichkeiten am XMega -> Hard-/Soft-Reset ?!
Jedenfalls war das Ergebnis, dass der Controller in den Reset gegangen
ist und USB am Bootloader nicht sauber hoch kam. Vielleicht ist es auch
nur eine Timing-Geschichte, die der Watchdog zum Vorteil hat.
Der Watchdog braucht halt Zeit zum Ablaufen. Wenn bis dahin die Hardware
noch etwas ausgegeben hat, ist sie vielleicht dann fertig damit, bis der
Wachhund zubeißt. Das ist natürlich etwas Anderes, als wenn der Reset
20µs nach Ausführen des Befehls aktiv wird. Ab Resetauslösung verhalten
sich alle Resetquellen genau gleich, da sie dieselbe Hardware im
Controller triggern.
Hmmm, es will einfach nicht klappen :-(
Ich habe jetzt folgendes drin:
#define ADDR_APP_RUN 0x00
#define APP_RUN 0xFF
#define BL_RUN 0x00
...
int main (void)
{
// Check boot flag
Test = eeprom_read_byte(&(pEeprom->StartBL));
if (Test == BL_RUN )
{
asm("jmp 0x401FC");
}
...
eeprom_write_byte(&(pEeprom->StartBL), APP_RUN);
...
}
void UpdateFW(void)
{
udc_detach();
udc_stop();
delay_ms(500);
eeprom_write_byte(&(pEeprom->StartBL),BL_RUN);
cpu_irq_disable();
CPU_CCP = CCP_IOREG_gc;
RST.CTRL = RST_SWRST_bm;
do {} while (1);
}
Leider wird der Bootloader jetzt nicht mehr angesprungen. Als ich das
Programm ohne Bootloader im Debug hatte, stimmte der Eintrag bei Test
jeweils...
Juhu, es funktioniert :-)
Es lag wohl am setzen der Resetregister und am abschalten der
Interrupts.
cpu_irq_disable();
CPU_CCP = CCP_IOREG_gc;
RST.CTRL = RST_SWRST_bm;
@Knut und @Basti
Danke für eure Hilfe - ist eben doch immer drauf Verlass.