Forum: Mikrocontroller und Digitale Elektronik XMega: Applikation springt zum Bootloader, danach keine IRQ´s mehr verfügbar


von T. F. (n3ssaja)


Lesenswert?

Hallo zusammen,

ich habe wahrscheinlich ein sehr simples Problem, aber es treibt mich 
seit zwei Tagen zur Verzweifelung :-(

Ich habe einen Bootloader für den AtXMega32A4. Wenn dieser läuft kann 
ich über I2C/TWI von einem anderen Mikrocontroller die neue Applikation 
flashen. Soweit so gut.

Um während des Betriebes eine neue Firmware auf den XMega zu schreiben, 
habe ich die Möglichkeit mit einem Jump Befehl den Bootloader zu 
starten:
1
 void (*bootloader)( void ) = (void*) 0x4000;

Nachdem der Bootloader gestartet ist, stehen mir keine Interrupts mehr 
zur Verfügung. Das habe ich herausgefunden da zum einen die 
Kommunikation über I2C/TWI bzw externe IRQ Eingangspins nicht mehr 
funktionieren.


Wenn ich den Bootloader jedoch einzeln starte, funktioniert alles. Nur 
wenn er aus der Applikation aus angesprungen wird, geht nichts mehr.

Wodran kann das liegen?  Gibt es bei den XMega auch einen eine ISR 
VectorTable die in den Bootloaderbereich umgesetzt werden muss?

von Karol B. (johnpatcher)


Lesenswert?

Bei der Ausgangslage wird dir kaum jemand eine konkrete Hilfestellung 
geben können. Was heißt "es stehen dir keine Interrupts zur Verfügung"? 
"Willkürlicher" Reset? Von welchen Interrupts sprechen wir? überhaupt? 
Denjenigen der Anwendung, oder benutzt du diese auch im Bootloader? Ggf. 
musst du die Adresse der Vektoren verschieben. Details hierzu finden 
sich im Datenblatt. Außerdem musst du sicherstellen, dass alles richtig 
gelinkt wird.

Noch etwas grundsätzliches zum Thema Bootloader: Ich persönlich 
implementiere so etwas immer "anders" herum, d.h. bei einem Reset wird 
der Bootloader angesprungen (von der Hardware), welcher dann nach einem 
Timeout (oder wann auch immer du Lust hast) in die Hauptapplikation 
(0x0000) springt. Um aus der Hauptapplikation heraus zum Bootloader zu 
gelangen, reicht dann ein gewöhnlicher Watchdog Reset.

Dies hat den Vorteil, dass du im Bootloader einen wohldefinierten 
Zustand hast (nach Reset), und diesen dem Anspringen der 
Hauptapplikation wieder herstellen kannst. Prinzipiell kannst du 
natürlich auch in deiner Anwendung dafür sorgen, dass benutzte 
Peripherie und Register entsprechend zurückgesetzt werden. In der Praxis 
ist das aber weitaus schwieriger umzusetzen, zu mal ein Fehler in der 
Anwendung dich ggf. nicht mehr zum Bootloader kommen lässt. Da man die 
Anwendung i.d.R. öfter ändert und flasht, den Bootloader aber nur 
selten, ist das "sicherer".

Mit freundlichen Grüßen,
Karol Babioch

von Jan K. (pit1)


Lesenswert?

IVSEL im I/O CTRL-Register des Interrupt-Controllers schaltet die 
Adresse der Vektortabelle zwischen App- und Bootloaderbereich um.

von T. F. (n3ssaja)


Lesenswert?

Vielen Dank für eure schnellen Antworten.

@Karol Babioch
Ich fasse alles nochmal zusammen:

- Bei den IRQ´s, die mir nach einen Jump von der Applikation in den 
Bootloader nicht mehr zur Verfügung stehen, handelt es sich um die IRQs 
des I2C/TWI Bus an Port PC0 und PC1.

- Ich benutze den TWI Bus sowohl im Bootloader als auch in der 
Applikation.   Beide mit der selben Initialisierungsroutine für den TWI 
Slave. Zusätzlich verwende ich bei der Applikation auch den TWI Master 
sowie den TWI Bus an Port Pe0 und PE1.

- Die Adresse der Vektoren verschiebe ich jeweils am Start des Programs 
mit:
1
void PMIC_SetVectorLocationToBoot(void)
2
{
3
  uint8_t temp = PMIC.CTRL | PMIC_IVSEL_bm;
4
  CCP = CCP_IOREG_gc;
5
  PMIC.CTRL = temp;
6
}
7
8
void PMIC_SetVectorLocationToApplication(void)
9
{
10
  uint8_t temp = PMIC.CTRL & ~PMIC_IVSEL_bm;
11
  CCP = CCP_IOREG_gc;
12
  PMIC.CTRL = temp;
13
}


- Ich habe mein Programm jetzt angepasst, dass auch bei mir zunächst der 
Bootloader angesprungen wird. Liegt eine Applikation vor, dann springt 
der Bootloader unmittelbar dahin.

- Um von der Applikation in den Bootloader zu kommen darf ich keinen 
Watchdog Reset benutzen, da der XMega zeitgleich Spannungen steuert, die 
für die Versorgung des TWI Devices sind, dass mit dem XMega 
kommuniziert. DAS TWI device darf nicht reseten.

- Aus dem Grund ist es wichtig das ich entsprechende Register 
neuinitialisiere. An der Stelle liegt wahrscheinlich auch das Problem.


Gibt eine Möglichkeit die TWI Busse komplett zu reseten und danach neu 
zu initialisieren?

Noch eine Allgemeine Frage: Im DAtenblatt des AtXMega32A4 steht nicht 
die Bootloaderstartadresse. Ist es richtig das die bei 0x4000 liegt?

: Bearbeitet durch User
von Sascha W. (sascha-w)


Lesenswert?

T. F. schrieb:
> Vielen Dank für eure schnellen Antworten.
>
> Gibt eine Möglichkeit die TWI Busse komplett zu reseten und danach neu
> zu initialisieren?
>
ja - TWI über das entsprechende Controlregister ausschalten und danach 
wieder einschalten.

Hast du vor dem Sprung zum Bootloader / Umschaltung IVSEL die Interrupts 
mit cli deaktiviert?

Sascha

von Karol B. (johnpatcher)


Lesenswert?

T. F. schrieb:
> Noch eine Allgemeine Frage: Im DAtenblatt des AtXMega32A4 steht nicht
> die Bootloaderstartadresse. Ist es richtig das die bei 0x4000 liegt?

Halte ich für ein Gerücht ;). Schaue dir Kapitel 7 ("Memories") genauer 
an. Je nach Mikrocontroller ist die Größe der Bootloadersektion auch 
noch per Fueses in der Größe verstellbar, sodass sich das Ansprungsziel 
je nach Fuseeinstellungen ändert. Ein Grund mehr also warum man per 
Watchdog resetten sollte.

Wenn das in deinem Fall nicht anders geht, dann musst du tatsächlich an 
eine fest vorgegebene Adresse springen - mit den damit verbundenen 
"Risiken".

Mit freundlichen Grüßen,
Karol Babioch

von Timmo H. (masterfx)


Lesenswert?

T. F. schrieb:
> Noch eine Allgemeine Frage: Im DAtenblatt des AtXMega32A4 steht nicht
> die Bootloaderstartadresse. Ist es richtig das die bei 0x4000 liegt?
Ja. Würde aber wegen Portabilität die Adresse aus dem Header nehmen:
1
void (*bootloader)( void ) = (void*) (BOOT_SECTION_START/2);

von T. F. (n3ssaja)


Lesenswert?

Hi zusammen,

ich habe den Fehler gefunden. Es lag in der Tat daran, dass ich vor dem 
Umsetzen des IVSEL  Registers, die Interrupts nicht mit cli() 
deaktiviert habe.

Also vielen Dank euch allen nochmal für die Guten Tips!

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.