Forum: Compiler & IDEs WinAVR, AT90USB1287, Bootloader aus App anspringen


von Ulrich P. (uprinz)


Lesenswert?

Hi!

Ich möchte in meinem Projekt den bereits im AT90USB1287 vorhandenen 
Bootloader verwenden. Momentan weiß ich noch nicht wo der her kommt, 
aber beim STK525 und seinen mitgelieferten AVRs ist einer drinn, den man 
per HWB also Taste an PE2 aktivieren kann.

Ich möchte den Bootloader aber aus der Applikation auf dem AVR direkt 
anspringen und damit die Taste überflüssig machen.

Leider schaffe ich es auch nach allem Suchen in diesem Forum nicht.

Die Einsprungssequenz sieht bislang wie folgt aus:
1
{
2
  _CLI();
3
  _delay_ms(1000);
4
  
5
  MCUCR = (1<<IVCE);
6
  MCUCR = (1<<IVSEL);
7
  asm volatile ("jmp 0x1E000");
8
}

d.h. damit mir keine Interrupts dazwischen kommen, klemme ich sie ab und 
warte auch noch eine Zeit lang, in der aber nichts passieren dürfte.
Dann schalte ich die Vectoren um und springe auf den Reset-Vector im 
Bootloader.

Die Lock-/Fusebits sind wie folgt durch ATMEL vorgeliefert und 
hoffentlich durch meine Software korrekt ausgelesen:
Lockbits: 0xEC
FB_High: 0x99
FB_Low: 0x5E
Ext_FB: 0xF3

Was mich zu dem Schluss führt, dass der vorhandene Bootloader 8kByte, 
bzw. 4kWord groß ist. Das deckt sich auch mit der Aussage des 
Datenblattes bzgl. der Bootloaders von Atmel, dass dessen Codegröße mit 
5kByte angibt.

{
  _CLI();
  _delay_ms(1000);

  MCUCR = (1<<IVCE);
  MCUCR = (1<<IVSEL);
  asm volatile ("jmp 0x1E000");
}

Vielen Dank schon mal für Eure Hilfe

Gruß, Ulrich

von Johannes M. (johnny-m)


Lesenswert?

Schau Dir bitte die Dokumentation der _delay-Funktionen in der 
libc-Dokumentation mal an. _delay_ms(1000) geht nur mit Taktfrequenzen 
unter 250 kHz, und ich vermute, dass Du eher mit höheren Taktfrequenzen 
arbeitest...

von Ulrich P. (uprinz)


Lesenswert?

Jep, ist korrekt, aber egal, da sich das angesprochene Problem, nämlich 
der Sprung in den Bootloader auch ohne, oder mit einem kurzen Delay 
nicht bewerkstelligen lässt.

Trotzdem Danke für den Hinweis.

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
ich kenne den bootloader zwar nicht. aber vermutlich wird der eine 
bestimmte weile einen port pin abfragen, und bei erkennen einer 
bedingung nicht weiter springen, sondern im BL-modus bleiben.
das problem dürfte imho sein, dass deine anwendung den pn nicht setzt. 
der bootloader wird also korrekt angesprungen, merkt, dass es nichts für 
ihn zu tun gibt, und er springt wieder zurück.

oder gibt es ein debugging, welches den start des BL anzeigt? wenn ja, 
wann im code?
bye kosmo

von Ulrich P. (uprinz)


Lesenswert?

Da bin ich noch nicht richtig durchgestiegen. Auf der einen Seite sagen 
die Fuses, dass der Bootloader nicht aktiv ist. Also fällt die Variante 
mit dem PE2 als Pin Abfragen flach. Andererseits hat der AT90USB1287 
irgendwie eine Sonderfunktion auf diesem Pin, die den Bootloader 
aktiviert.

Ich habe am Montag erst mit diesem USB AVRs angefangen. Bie den bislang 
gerne und häufig von mir eingesetzten ATmegas gab es keinen 
vorinstallierten Bootloader, bzw. es gab keine Notwendigkeit überhaupt 
einen BL zu verwenden.

Mit dem AT90USB ist es jedoch genau anders. Der vorinstallierte BL macht 
den Chip mit wenigen Handgriffen programmierbar über USB und damit einen 
eigenen ISP Port völlig überflüssig.

Im Grunde ist es nicht tragisch, da bei der Erstprogrammierung eh über 
diesen Taster oder über einen ISP oder JTAG Programmer gegangen werden 
muss, aber es wäre später praktisch, wenn man das System direkt über 
seine PC-Seitige Software updaten könnte, ohne Programmer und spezielle 
Software.

Naja, und dann ist auch ein Grund, dass der HWB Taster ( der an PE2) 
sich bereits nach einer Woche verabschiedet hat. Ich habe aber keine 
Lust das Teil deswegen umzutauschen.

Gruß, Ulrich

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,

>Andererseits hat der AT90USB1287
>irgendwie eine Sonderfunktion auf diesem Pin, die den Bootloader
>aktiviert.

steht in der doku, page 357. auf der nachfolgenden seite gibts auch ein 
schönes ablauf-diagramm.

was genau funktioniert denn nicht? der installierte BL meldet sich 
vermutlich nicht. läuft die application erneut?
bye kosmo

von Ulrich P. (uprinz)


Lesenswert?

Hi Kosmo!

Danke für den Tip, habe das jetzt mal schnell überflogen mit dem HWBE.

Wenn ich mit obigem Code in den Bootloader springe, dann passiert nichts 
mehr, sprich, das System friert ein.
Meine Applikation steuert die LEDs auf dem STK525 für ein paar 
rudimentäre Statusausgaben an und man kann erkennen, dass meine SYS-LED, 
die durch den Taskmanager getoggelt wird, einfach ihren Stand beibehält. 
Es wird also nichts mehr ausgeführt.

Ich versuche gerade mal in den LST files herum zu suchen, was aus meinem 
Code an dieser Stelle gemacht wird. Aber ich sehe halt nur meinen Code 
und die Adresse 0x1E000 als Ziel. Da ich auf das Demoprojekt für ein CDC 
( UART-USB-Bridge) aufsetzte muss ich das externe Makefile verwenden. 
Darin war die Ausgabe der LST files abgeklemmt und ich habe das nur 
notdürftig aktivieren können. So erhalte ich für Parameter nur dezimale 
Zahlen anstatt Hex. Muss da noch mit dem Compiler-Parametern spielen.

Gruß, Ulrich

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
schau doch mal, ob das HWBE auch die interruptvektoren ändert. ich denke 
nämlich nicht. falls dem so ist, kommt durch dein umsetzen bei einem irq 
totaler müll heraus. in dem fall am besten irq's aus, ivsel so lassen 
wie's ist und gucken, was passiert.
bye kosmo

von Ulrich P. (uprinz)


Lesenswert?

Das war mein erster Angang, einfach nach 0x1E000 springen, vorher nur 
noch _CLI(). Geht auch nicht.

Habe mir auch mal ein dump geschrieben. Kann jetzt beliebigen FLASH 
auslesen.
Meinen eigenen Code sehe ich auch, aber den Bootloader sehe ich 
nirgendwo. weder ein dump 0xe000 noch ein dump 0x1E000 noch irgendwas 
dazwischen liefert etwas anderes als 0xffff als Ausgabe. Wie gesagt, ein 
dump 0x0 funktioniert einwandfrei, ich sehe meinen eigenen Code.

Den fuses nach zu urteilen ist aber nur ein (E)SPM blockiert, ein (E)LPM 
sollte gehen, also müsste ich auch per pgm_read(_byte/_word)( addr) auf 
den bootloader lesen zugreifen können.

Der hat aber einen sehr zähen Versteckungsfaktor :)

Gruß, Ulrich

von jOsI (Gast)


Lesenswert?

Moin,

hat das jetzt schon jemand geschafft aus der app in den bootloader zu 
springen? Ich hab bis jetzt noch keine Lösung gefunden.

mfg

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Reset-Vector fuse auf boot-section stellen, in der Applikation Watchdog 
aktivieren und per Endlosschleife "zuschlagen" lassen. Methode ist 
demonstriert in der Atmel Beispielanwendung und dem Bootloader für den 
AVR Butterfly.

von Erwin R. (er-tronik)


Lesenswert?

Wenn man den Original-Bootloader von ATMEL benutzt, wird das direkte 
aufrufen egal in welcher Form nicht funktionieren. Der Bootloader wird 
ja immer nach dem Reset gestartet, hier wird getestet ob HWB auf Masse 
liegt und wenn ja, wird der Bootloader gestartet.
Ich sehe die einzige Möglichkeit, den Bootloader aus einer Anwendung zu 
starten in einer Hardwarelösung (z.B. den HWB-Pin per Portpin und 
Flipflop auf Masse legen) oder einfach einen eigenen Bootloader 
schreiben (was ich persönlich bevorzuge).

Erwin

von Ulrich P. (uprinz)


Lesenswert?

Ich habe das erst einmal nicht weiter verfolgt, da der eigentliche 
Applikationscode wichtiger war als die Option die Module auch über das 
Netz updaten zu können.

Grundsätzlich hatte ich drei Probleme bei der ganzen Bootloader 
Geschichte:

1) Memory-Defines:
Wie kann ich dem Compiler (WinAVR) klar machen, dass meine CPU nicht 32k 
FLASH hat sondern z.B. nur 31k ( weil 1k fest für den Bootloader 
vergeben ist) eines der Segmente wurde nämlich immer am Ende, also 
Top-Down im Flash abgelegt und kollidierte damit mit dem gegen schreiben 
geschützten Bootloader.

2) Wiederverwendbarkeit:
Ich möchte nicht den Code des Bootloaders in jedes Projekt eibauen. Er 
sollte als eigenständige Software funktionieren und getrennt geflasht 
werden können. Dazu müsste ich dem Compiler sagen, dass er nun einen 
Bootloader erzeugt, der nicht bei 0x0000 anfängt, sondern z.B. bei 
0xec00 und nur 0x0400 lang ist.

3) Um das ganze zu testen hatte ich den HWB doppelt genutzt. In der 
normalen Software wird der HWB Button abgefragt, und wenn er gedrückt 
ist, soll der Bootloader angesprungen werden. Wird der angesprungen, 
dann ist der HWB immer noch gedrückt und er Bootloader sollte sich 
aktivieren. Das ist mir aber nicht gelungen. Vermutlich, weil ich 1) und 
2) schon nicht lösen konnte.

Das ganze ist jetzt schon über ein Jahr her und witziger weise taucht 
die Anfrage nach einem Bootloader nun wieder auf. Ist auch logisch, weil 
man sonst an über 100 Platinen in einem großen Schrank jeweils den 
AVRISP anstöpseln müsste um die Stück für Stück zu aktualisieren. Ist 
schon komisch, dass Du diesen Thread ausgerechnet jetzt ausgräbst. Aber 
fein, ich warte zusammen mit Dir mal auf die meist sehr hilfreichen 
Ideen aus diesem Board.

Gruß, Ulrich

von jOsI (Gast)


Lesenswert?

Moin,

ich hab es jetzt endlich hin bekommen.
Ich beschreib mal kurz was ich gemacht habe.

Ich möchte über einen USB-Befehl das Device in den Bootloader versetzen, 
ohne das über die Hardware zu machen. Dazu nutze ich den Standard 
Bootloader von Atmel. Mit der Software Flip möchte ich die Firmware 
flashen. Die Fuses habe ich auf Standard stehen lassen, d.h.
"Hardware Boot Enable" kein Fuse gesetzt,
"Boot Reset vector Enable" kein Fuse gesetzt,
"Boot Flash size=4096 words start address=$F000" Fuse gesetzt.

Die Firmware muss, wie in dem HID-Codebeispiel von Atmel, um folgendes 
ergänzt werden.

void (*start_bootloader) (void)=(void (*)(void))0xf000;

if( jump_bootloader == 0x01 )
{
   Usb_detach();                    //! Detach actual generic HID 
application
   for(tempo=0;tempo<70000;tempo++);//! Wait some time before
   (*start_bootloader)();           //! Jumping to booltoader
}

Im meinem Fall ist es noch wichtig, dass die Timer-Interrupts 
deaktiviert werden müssen.
#define Disable_timer_int()      ( TIMSK0 = 0x00,\
                                   TIMSK1 = 0x00,\
                                   TIMSK2 = 0x00 )
Das war der ganze Trick.

mfg

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.