Hallo liebes Forum,
ich schreibe gerade einen Bootloader für meinen Roboter.
Die Software läuft auf einem ATmega2560.
Die Fuses habe ich auf:
- Boot Flash section size: 4096
- Boot Reset vector enabled
gesetzt.
Bei der Ausführung des Bootloaders tritt leider das folgende Problem
auf:
Über USB (RS232) sende ich ein hex file an den uC, der Bootloader
dekodiert das hex file und flasht den uC. Anschliessend schaltet der
Bootloader die Interrupt Vektoren auf die Anwendung und startet die
Anwendung jmp 0x0000.
Die Interrupt Vektoren werden mit den folgenden Befehlen umgesetzt:
MCUCR = (1<<IVCE); // Enable change of Interrupt Vectors
MCUCR = (0<<IVSEL); // Move interrupts to Application
Der Disassembler im AVR Studio zeigt, dass das Programm korrekt ins
Flash geschrieben wurde (vergleich des Assemblercodes an willkürlichen
Stellen).
Es scheint so, als ob immer noch die Interruptvektortabelle des
Bootloaders verwendet wird und nicht die der Applikation.
Hat jemand vieleicht ein ähnliches Problem oder einen Hinweis was ich
falsch gemacht haben könnte?
Vielen Dank im voraus!
MCUCR=(0<<IVSEL);// Move interrupts to Application
kann man nicht gezielt ein Bit löschen.
Eine 0 kannst du beliebige oft nach links schieben, es
bleibt immer noch eine 0.
Deine Schreibweise ist im Grunde nur eine verschleierte
Form für
1
MCUCR=0;
und das wirst du wohl kaum so haben wollen.
Um 1 Bit gezielt auf 0 zu setzen:
Hallo Karl Heinz,
da war ich wohl mit Blindheit geschlagen! Vielen Dank!
Leider startet die Applikation immer noch nicht korrekt. Wie es scheint
landet der uC immer noch in den Interrupttabellen des Bootloaders obwohl
die Anwendung schon läuft!!!
Mein Code sieht jetzt so aus:
1
// Auf die Interrupttabelle der Applikation umschalten
Aus einem mir immer noch unerklärlichem Grund landet der uC jedoch immer
wieder im Bootloader nach dem jmp 0x0000.
Eine Kleinigkeit habe ich wohl noch übersehen.
Also so wie es aussieht, führt der uC kurz nachdem er die Applikation
anspringt einen erneuten reset durch und landet wieder im Bootloader.
Ist mir im Moment leider unerklärlich. Die Anwendung selbst habe ich
bereits getestet. Die läuft einwandfrei.
Im assembler sieht das umschalten der Interruptvektortabellen so aus:
487: MCUCR = (1<<IVCE); // Enable change of Interrupt Vectors
5
+0001F427: E001 LDI R16,0x01 Load immediate
6
+0001F428: BF05 OUT 0x35,R16 Out to I/O location
7
488: MCUCR &= moveApplication; // Move interrupts to Application
8
+0001F429: B705 IN R16,0x35 In from I/O location
9
+0001F42A: 2108 AND R16,R8 Logical AND
10
+0001F42B: BF05 OUT 0x35,R16 Out to I/O location
11
492: void (*applicationPointer)( void ) = 0x0000; // Set up function pointer to RESET vector
12
+0001F42C: E000 LDI R16,0x00 Load immediate
13
+0001F42D: E010 LDI R17,0x00 Load immediate
14
+0001F42E: E020 LDI R18,0x00 Load immediate
15
+0001F42F: 0128 MOVW R4,R16 Copy register pair
16
+0001F430: 2E62 MOV R6,R18 Copy register
17
493: applicationPointer();
18
+0001F431: 01F2 MOVW R30,R4 Copy register pair
19
+0001F432: BE6C OUT 0x3C,R6 Out to I/O location
20
+0001F433: 9519 EICALL Extended indirect call to (Z)
21
+0001F434: CD54 RJMP PC-0x02AB Relative jump
Bei der IN Anweisung bin ich mir nicht ganz sicher aber ich denke, die
benötigt auch nur einen Takt. Daher sollten beim Umschalten die 4 Takte
eigentlich eingehalten werden.
Hallo Jan,
ich habe ein ähnliches Phänomen beobachtet (sowohl mit ATmega168er als
auch mit ATmega128) und hab's bisher so umgangen, dass ich im Bootloader
keine Interrupts verwende. Dazu habe ich den Empfang von Zeichen über
den UART auf Polling umgestellt.
Genauere Untersuchungen zur eigentlichen Ursache habe ich noch nicht
angestellt.
Tschüss
Torsten
Hallo Torsten,
dann bist Du schon der Zweite, der mir von diesem Phänomen berichtet.
Ich werde dann wohl oder übel auf Polling der RS232 Schnittstelle
umstellen müssen.
Mittlerweile sitze ich hier schon seit zwei Tagen und versuche dieses
Problem in den Griff zu bekommen.
Vieleicht weiss noch jemand wie man es umgeht?
Vielen Dank!
Gruss
Jan
Ich habe einen Bootloader für Mega8 geschrieben der auch Interrupts
verwendet. Da klappt das Umschalten. Die Interrupts sollten zu dem
Zeitpunkt natürlich disabled sein, mit cli() ode so.
Von wegen landet wieder im Bootloader: Schlägt da vielleicht aus
irgendwelchen Gründen der Watchdog zu?
Gibt es noch Fuses, die dabei eine Rolle spielen können?
Hallo Jörg,
die Interrupts habe ich vorher disabled => cli(). Sorry habe wegen der
Übersichtlichkeit nicht alles gepostet.
Bei den Fuses gibt es eine Option "Watchdog Timer always on" die habe
ich aber ausgeschaltet.
Wenn ich die Applikation mit dem AVR Studio direkt auf den 2560 brenne,
läuft sie ohne Probleme nur wenn ich mit dem Bootloader das Programm
aufspiele, springt er zum Anfang des Bootloaders "0x1F000 so ca. nach 4
Sekunden.
Merkwürdig...
Jan Raddatz wrote:
> Wenn ich die Applikation mit dem AVR Studio direkt auf den 2560 brenne,> läuft sie ohne Probleme nur wenn ich mit dem Bootloader das Programm> aufspiele, springt er zum Anfang des Bootloaders "0x1F000 so ca. nach 4> Sekunden.
Nun, daß hat aber nichts mit der Interruptvektortabelle zu tun.
Da ist irgendwas faul in Deinem Programm und es rennt irgendwann hinten
über auf 0x0000.
Und ohne den Bootloader hinten dran merkst Du das bloß nicht.
Peter
hmm ich geb's ja ungern zu aber mir scheint, dass Du recht hast.
Die Interrupts werden jetzt schonmal richtig angesprungen! Immerhin!
Es scheint aber noch ein Problem bei der Initialisierung der Anwendung
zu geben. Mal gucken!
Auch wenn der Beitrag schon ein wenig älter ist:
Für die Forumleser, die auf ein ähnliches Phänomen stoßen wie Guile
Lampert (sphinx): Dieses Problem tritt immer dann auf, wenn Interrupts
verwendet werden, deren Sprungadressen jedoch nicht definiert sind.
Generell gilt: Stets alle ISR definieren - andernfalls springt der IRQ
im Wald umher.
Gruß,
AnnoDazumaL