Forum: Mikrocontroller und Digitale Elektronik Jump zum Bootloader beim XMEGA


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich verwende einen XMEGA256A3U von Atmel. Ich habe bereits einen 
Bootloader geschrieben und diesen auch in den Flash unter der 
Wordadresse 0x20000 hinterlegt. Wenn ich mit den AVRSTUDIO das BOOTRST 
Fuse auf Bootloader stelle, dann startet nicht meine Application sondern 
der Bootloader. Soweit so gut nun zu meinem Problem:

Wie kann ich den Bootloader aus der Application starten. Ich habe 
gelesen das man dies mit einem Extended Indirect Jump (eijmp) macht. 
Dies ist notwendig da ich mehr als 64kByte Flash habe.

ich habe dies im Internet bereits gefunden jedoch hat es nicht 
funktioniert:

asm volatile (
"ldi r30, 0x02" "\n\t" // set up EIND
"sts 60, r30" "\n\t"
"ldi r30,0x00" "\n\t" //indirect call address
"ldi r31,0x00" "\n\t" //16bit address z
"eijmp" "\n\t"

Ich habe daraus eine Funktion erstellet und rufe diese auf.

void Jump_To_Bootloader(void)
{
    #asm
        cli               ; Disable Interrupts
        ldi r30,0x02      ; Set Up EIND to 0x02
        sts 60,r30        ;
        ldi r30,0x00      ; Indirect call adress
        ldi r31,0x00      ; Indirect call adress
        eijmp             ; Jump to bootloader adress
    #endasm
}

Jedoch scheint da ein Fehler drin zu sein. Ich kenne mich leider nicht 
perfekt mit Assembler aus. Vielleicht kann mir jedmand ja einen Hinweis 
geben

: Gesperrt durch Moderator
von spess53 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi

>Wie kann ich den Bootloader aus der Application starten. Ich habe
>gelesen das man dies mit einem Extended Indirect Jump (eijmp) macht.
>Dies ist notwendig da ich mehr als 64kByte Flash habe.

Wieso? Ein simpler 'jmp' kann 4MWord adressieren.

MfG Spess

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wie würde das denn mit dem Jump ausehen?

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe das Gefühlt das die Speicheradresse für EIND falsch ist.

von Timmo H. (masterfx)


Bewertung
0 lesenswert
nicht lesenswert
Ich würde es mal so versuchen:
void(* jump_to_bootloader)(void) = (void (*)(void))(BOOT_SECTION_START/2+0x1FC/2);
EIND = BOOT_SECTION_START>>17;
jump_to_bootloader();

Wobei der Offset der Einsprungadresse 0x1FC natürlich von dir angepasst 
werden muss.

: Bearbeitet durch User
von Leo B. (luigi)


Bewertung
0 lesenswert
nicht lesenswert
Ich hab mich jetzt nicht sehr lange mit deinem Problem beschäftigt, aber 
bei Atmel sieht das anders aus.
http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_EIJMP.html

OUT und STS sind nicht äquivalent!

: Bearbeitet durch User
von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
:-)

Diese Zeile überfordert mich ein wenig :-)

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Coole Seite kann ich noch nicht vielen Dank für die Infos ich werde es 
gleich mal ausprobieren.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hat leider auch nicht funktioniert. Ich versuche es jetzt mal mit dem 
Debugger. Jedoch habe ich mit dem Debugger noch so meine Probleme. Ich 
downloade gerade das aktuelle AVR Studio.

von Dieter F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Genau von ARV-Praxis habe ich den Code ja auch. Jedoch funktioniert es 
bei mir nicht. Ohne den Debuger sehe  ich auch nicht wohin der PC 
springt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> :-)
>
> Diese Zeile überfordert mich ein wenig :-)

Funktioniert aber.  Ich habe mal den Einsprungoffset weggenommen
(also Einsprung direkt an den Anfang des Laders) und ein typedef
eingeführt:
#include <avr/io.h>

typedef void (*bldr_t)(void) __attribute__((noreturn));

int main(void)
{
  const bldr_t jump_to_bootloader = (bldr_t)(BOOT_SECTION_START/2);
  EIND = BOOT_SECTION_START>>17;
  jump_to_bootloader();

  return 0;
}

Das macht der Compiler draus:
.global main
        .type   main, @function
main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        ldi r24,lo8(2)
        out 0x3c,r24
        ldi r30,0
        ldi r31,0
        eicall

: Bearbeitet durch Moderator
von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke für die Info Jörg,

aber macht der eicall nicht einen Sprung und legt die Rücksprungadresse 
auf den Stack ab so das er dann wieder zurückspringt und es dann zu 
Problemen kommt?

Kannst Du vielleicht noch etwas zu diesen 2 Zeilen schreiben was diese 
genau machen?

typedef void (*bldr_t)(void) __attribute__((noreturn));

const bldr_t jump_to_bootloader = (bldr_t)(BOOT_SECTION_START/2);

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:

> aber macht der eicall nicht einen Sprung und legt die Rücksprungadresse
> auf den Stack ab

Ja, macht er.

> so das er dann wieder zurückspringt und es dann zu
> Problemen kommt?

Wer ist „er“?  Wer springt denn da wann zurück?  Dein Bootloader?
Warum sollte er?

Allerdings sollte der Bootloader den Stackpointer (re-)initialisieren.

> Kannst Du vielleicht noch etwas zu diesen 2 Zeilen schreiben was diese
> genau machen?

C-Buch, Kapitel über Zeiger?

> typedef void (*bldr_t)(void) __attribute__((noreturn));

Vereinbart einen Datentypen (namens „bldr_t“) für einen
Funktionszeiger, wobei die Funktion keinen Rückgabewert hat (void),
ja nicht einmal überhaupt zurückzukehren gedenkt (attribute noreturn),
und keine Parameter übernimmt ((void)).

> const bldr_t jump_to_bootloader = (bldr_t)(BOOT_SECTION_START/2);

Bildet einen solchen Zeiger per Typecast aus einer Konstante.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
das ist dann aber schon advance c.

In meinem Bootloader ist eine komplette Intitialisierungsroutine. Jedoch 
bin ich mir gerade nicht sicher ob ich da den Stackpointer zurücksetze 
ich versuche das nachschlagen.

Danke für die Erklärung. Mit Pointer auf Funktionen selber muste ich 
noch nicht arbeiten. Aber ich werde mich da mal im Internet belesen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> das ist dann aber schon advance c.

Nö, nur Zeiger bis zu Ende verstanden. ;-)

Allerdings gebe ich gern zu, dass das Abtrennen des Typs in einem
typedef hier wirklich sinnvoll ist.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
So den Debugger habe ich installiert nun bin ich aber wirklich mal 
gespannt :-)

von Dieter F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi,

sollte es nicht reichen, wenn Johann den Offset in sein Konstrukt 
einbaut und auf die word-address (das Teilen durch 2) umstellt - 
(0x40000 + 0x1FC) / 2 = 0x200FE:

AVR 1916:

Internal firmware request: The user application can decide to start a 
DFU session. This can be achieved by jumping to a specific address in 
the boot loader firmware. The entry point to start a DFU session 
initiated by a user application firmware jump is BOOT_SECTION_START + 
0x1FC for all devices

Also:
void Jump_To_Bootloader(void)
{
    #asm
        cli               ; Disable Interrupts
        ldi r30,0x02      ; Set Up EIND to 0x02
        sts 60,r30        ;
        ldi r30,0xFE      ; Indirect call adress
        ldi r31,0x00      ; Indirect call adress
        eijmp             ; Jump to bootloader adress
    #endasm
}

Wobei ich bei "word-address" (jetzt auf 0x20000 angepasst) auf extrem 
wackligen Boden stehe ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Dieter Frohnapfel schrieb:
> sollte es nicht reichen, wenn Johann den Offset in sein Konstrukt
> einbaut und auf die word-address (das Teilen durch 2) umstellt -
> (0x40000 + 0x1FC) / 2 = 0x200FE:

Zumindest mit dem AVR-GCC nicht: der hat nur 16 bit breite Zeiger.

> Internal firmware request: The user application can decide to start a
> DFU session. This can be achieved by jumping to a specific address in
> the boot loader firmware.

Setzt aber voraus, dass er einen DFU-Bootloader installiert hat.  Ich
habe aber den Eindruck, dass es sein eigener Bootloader ist.

von Dieter F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> Zumindest mit dem AVR-GCC nicht: der hat nur 16 bit breite Zeiger.

Ja, deswegen auch EIND oder?

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
So Jung ich habe mit dem Debugger das ganze genau untersucht. Wenn ich 
per RS232 ein Kommando an den XMEGA sende dann wird wirklich ein Sprung 
zur Adresse 0x20000 ausgeführt.

Dort steht auch mein Bootloader drin. Dieser wird aber anscheinend nicht 
richtig abgearbeitet. Ich kann mit dem Debugger die Bootsection anzeigen 
dort steht auf jedenfall etwas drin. Nur bleibt der Mikrocontroller dann 
hängen.

Wenn ich jedoch das BOOTRST Fuse auf Bootloader stelle, dann startet der 
Booloader richtig.

Ich verwende eine RS232 Interrupt um die neuen RS232 Flash Daten zu 
empfangen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> Ich verwende eine RS232 Interrupt um die neuen RS232 Flash Daten zu
> empfangen.

IVSEL gesetzt?

Ansonsten kann man einen Bootloader auch gepollt schreiben.

von Timmo H. (masterfx)


Bewertung
0 lesenswert
nicht lesenswert
Du solltest bedenken, dass wenn du von der Applikation in den Bootloader 
springst, dass alle Register so bleiben wie sie sind. Also würde ich 
vorher einen Zustand herstellen, der quasi dem Reset entspricht. Also 
alle Interrupts voher deaktivieren, RTC deaktivieren...
Arbeitest du im Bootloader mit Interrupts? Wenn ja musst du den 
ISR-Vektor noch verbiegen, das kannst du über BOOTRST und IVSEL.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Der Programm Counter bleibt bei 0x2021E stehen. Als wenn es eine 
Endlosschleife ist wie bei While(1)
;0000 009A   mikrocontroller_init();
   RCALL _mikrocontroller_init
;0000 009B 
;0000 009C   while(1)
_0x15:
;0000 009D   {
;0000 009E   }
  RJMP _0x15
;0000 009F }
_0x18:
  RJMP _0x18
;.FEND

: Bearbeitet durch Moderator
von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich arbeite in der Application Firmware und der Bootloader Firmware mit 
mit Interrupts. Ich habe natürlich nicht den Interruptverktor verbogen 
:-)

Ok dann werde ich IVSEL und BOOTRST konfigurieren.

Das ist doch alles total ... Man ist kurz vor dem Ziel und es geht 
nichts. Das ist heute wieder echt so ein Tag :-(

von Dieter F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Johann,

verwendest Du den Bootloader von dort?

http://www.avr-praxis.de/forum/showthread.php?759-Programmer-und-Developmenttool-f%FCr-Xmega-A1-USB-Mikrocontrollermodul

Dann solltest Du auch das berücksichtigen:

Die Einsprungadresse für den Bootloader ist 0x21FF0 (word address 
0x10FF8). Die Einsprungadresse bleibt für folgende Bootloaderversionen 
gleich.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ne ich habe einen eigenen geschrieben.

von Dieter F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> Ne ich habe einen eigenen geschrieben.

Dann wirst Du ja auch Deine eigene Einsprungadresse kennen ... oder?

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Meiner setzt den CLOCk auf 32MHZ konfiguriert einen RS232 Receiver 
Interrupt. In der Interruptroutine werden dann Daten empfangen.

In der RS232 Interruptroutine verwende ich noch einen Hardwaretimer. 
Diesen benutze ich zum Abbruch der RS232 Routine falls nicht genügend 
Daten kommen. Der Timer benutzt aber keine Interruptroutine.

Das Hauptprogramm ist das While(1)

Ich verstehe Atmel nicht. Ich könnte ja einfach aus der Application 
herraus das BOOTRST Fuse verändern anschließnd einen Reset auslösen und 
alles wäre wunderbar. Das hätte mich nur wenige Minuten gekostet jetzt 
glüht mein Kopf und nichts geht.

von Johann (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich dachte die Einsprungadresse ist die Adresse 0x20000? Das ist doch 
der Startbereich vom Bootloader. Ich dachte diese wird dann 
abgearbeitet.

Oder liege ich da falsch? ich habe mal meinen Bootloader angehängt

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> Ich könnte ja einfach aus der Application herraus das BOOTRST Fuse
> verändern anschließnd einen Reset auslösen und alles wäre wunderbar.

Der Sinn einer Fuse ist es aber, nun gerade nicht durch die
Applikation änderbar zu sein.

Nur, weil du gerade deine Software nicht im Griff hast, brauchst du
jetzt nicht die Schuld beim Hardwarehersteller suchen …

Es steht dir ja völlig frei, die Fuse immer zu setzen und bei Bedarf
einfach per Watchdog einen Reset zu veranlassen.  Dann hast du das
Problem halt andersrum, der Bootloader muss dann entscheiden, wann
und wie er die Applikation anspringen will.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> ich habe mal meinen Bootloader angehängt

Sourcecode wäre einfacher zu entziffern …

> Ich dachte die Einsprungadresse ist die Adresse 0x20000?

Ja, ist sie auch.

: Bearbeitet durch Moderator
von Johann (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, aber der Frust sitzt momentan sehr tief. Ich bin für jede Hilfe 
sehr dankbar

Ich habe mal das Main-File beigefügt und meine Initialisierungsroutine.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> Der Programm Counter bleibt bei 0x2021E stehen. Als wenn es eine
> Endlosschleife ist wie bei While(1)

Ist es ja auch, das ist deine while(1)-Schleife aus main().  Was
sollte denn in dieser sonst noch passieren?

Alles, was passiert, muss ja über einen Interrupt passieren.

Am Einsprungpunkt des Codes erfolgt ein Stück Initialisierung,
dann ein Sprung auf Byteadresse 0x4043a:
  …
  (Hier wird übrigens SP initialisiert)
   402a8:       ef ef           ldi     r30, 0xFF       ; 255
   402aa:       ed bf           out     0x3d, r30       ; 61
   402ac:       ef e5           ldi     r30, 0x5F       ; 95
   402ae:       ee bf           out     0x3e, r30       ; 62
   402b0:       c0 e0           ldi     r28, 0x00       ; 0
   402b2:       d0 e3           ldi     r29, 0x30       ; 48
   402b4:       1c 94 1d 02     jmp     0x4043a ;  0x4043a

Dort steht offenbar main():
   4043a:       d7 d1           rcall   .+942           ;  0x407ea
   4043c:       ff cf           rjmp    .-2             ;  0x4043c
   4043e:       ff cf           rjmp    .-2             ;  0x4043e

Die zweite Endlosschleife scheint dein Compiler (welcher auch immer
es ist, hast du uns nicht verraten) nach main() hinzuzufügen, die
erste ist deine eigene.

0x407ea ist die Init-Routine, die dein Compiler auch stur so wie
geschrieben aufdröselt:
   407ea:       2a de           rcall   .-940           ;  0x40440
   407ec:       39 de           rcall   .-910           ;  0x40460
   407ee:       7a de           rcall   .-780           ;  0x404e4
   407f0:       45 df           rcall   .-374           ;  0x4067c
   407f2:       4b df           rcall   .-362           ;  0x4068a
   407f4:       82 df           rcall   .-252           ;  0x406fa
   407f6:       a3 df           rcall   .-186           ;  0x4073e
   407f8:       78 94           sei
   407fa:       08 95           ret

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
So ich habe mir das List-File noch mal genauer angeschaut.

Dort steht in Adresse 0x020000 der Resetvector vom Bootloader. Demnach 
habe ich mir die Resetroutine angeschaut. Dort wird auf jedenfall das 
IVESL Bit 1 1 gesetzt und somit Interrupt Vector im Bootbereich 
platziert.

Durch den Debugger kann ich auch feststellen das ich im Bootloadebereich 
bin. Jedoch wenn ich ein Kommando per RS232 Sende komme ich nicht in die 
RS232 Routine vom Booloader.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> komme ich nicht in die RS232 Routine vom Booloader.

PMIC-Setup?

Ich müsste mir die Details für dieses Teil jetzt im Datenblatt
durchwälzen.  Das wäre aber potenziell ein Unterschied zwischen dem,
was dir deine Applikation beim Einsprung in den Bootloader hinterlässt
und dem, was du beim Anspringen des Bootloaders per Reset hast.

Ich würde wohl nach möglichster Möglichkeit versuchen, in einem
Bootloader nur minimal an der Hardware herumzufummeln (nur das
wirklich für den Loader nötige) und ohne Interrupts auszukommen. Ob
du nun da in einem while(1) im main() Däumchen drehst oder an der
Stelle den UART-Rx pollst, bleibt sich schließlich gleich.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> PMIC-Setup?

Lass dir doch mal die PMIC-Register dumpen einerseits wenn du die
BOOTRST-Fuse gesetzt hast und andererseits wenn dein Loader von der
Applikation aus angesprungen worden ist.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wenn mit AVR das Fuse-Bit BOOTRST veränder, so das er aus dem Bootloader 
startet (beim Power Up) dann funktioniert ja auch die RS232 
Interruptroutine. Ich kann dann auch wieder zurückspringen auf dem 
Application bereich und auch dort funktioniert dann die RS232-Routine.

Ich werde mal eine LED Toggeln wenn ich im Bootloader bin. Und eine 2 
LED einschalten wenn ich im Bootloader in die RS232 Routine kommen. --> 
Oldscool halt.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ok ich habe den Code geändert. Wenn die XMEGA Bootloader Initialisierung 
abgeschlossen ist schalte ich eine LED an. Diese leuchtet auch. Demnach 
muss der XMEGA vollständig initialisiert sein. Jedoch wenn ich einen 
RS232 Befehl sende wird die 2. LED in der USART Interruptserviceroutine 
nicht gesetzt.

Dies ist schon ein Hinweis das mit dem Interrupt etwas nicht in Ordnung 
ist. Da habe ich wenigstens etwas wo ich den Fehler suchen kann.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> Demnach muss der XMEGA vollständig initialisiert sein.

Ja klar, du bist ja schließlich in deiner while(1)-Schleife in main().

Wie ich schon schrob: guck dir den Interruptcontroller an.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich werde dann noch mal mit dem Debugger alles prüfen und hoffentlich 
den Fehler finden.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich konnte leider nichts finden.

Was mir jedoch aufgefallen ist. Wenn ich aus der Application den Jump in 
den Bootloader mache, dann komme ich auch in den Bootoader rein und eine 
LED wird angeschaltet.

Wenn ich jedoch anschließend die Betriebsspannung vom Board entferne und 
anschließend diese wieder aktiviere, dann bin ich wieder im Booloader 
und die Interruptserviceroutine von der USART funktioniert und alles 
geht :-(

Nach einen Power Up sollte doch die Applikation wieder starten und nicht 
der Bootloader. Das BOOTRST Fuse Bit steht auf Application und wird auch 
nicht von mir verändert.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
So ich HABE DEN FEHLER GEFUNDEN:

Ich habe aus der USART_INTERRUPT_SERVICE_ROUTINE den Sprung zum 
Bootloader gemacht. Das scheint so nicht zu gehen oder ich habe etwas 
nicht richtig gelöscht.

Wenn ich in der Interrupt Service Routine nur ein globales Flag setze 
und dieses in der Mainroutine abfrage und dann beim gesetzten Flag den 
Sprung zum Bootloader ausführe dann geht es auch sofort.

Mir ist jedoch aufgefallen das wenn ich im Bootloader bin und die 
Versorgungspannung ausschalte und anschließend wieder Einschalte bootet 
der Mikrocontroller immer automatisch aus dem Booloaderbereich. Ist das 
eine Sicherheitsfunktion so das ich aktive erst wieder den 
Bootloaderbereich verlassen muss?

Dies ist eigentlich sehr gut, denn wenn beim Flashen der Strom ausfällt 
könnte ich in aus der Application herraus nicht mehr in den Bootloader 
springen, da die Application ja bereits gelöscht ist und nur bis zu 
einem gewissen Prozentsatz neu geflasht wurde.

von Christian K. (the_kirsch)


Bewertung
0 lesenswert
nicht lesenswert
Solange du in einer ISR bist sind globale Interrupts aus (ISRs sind 
normalerweise nicht unterbrechbar)

Und wenn du aus der ISR einen Sprung machst, denkt der Controller das du 
immer noch in der ISR bist.
Der ASM-Befehl RETI aktiviert beim Beenden der ISR wieder die globalen 
Interrupts.

Ich kenne mich mit den XMegas nicht aus, die haben ja so ein tolles 
Eventsystem.


Bei den normalen Megas, sollte eigentlich ein sei() reichen, was du 
vermutlich in deinem Bootloadercode auch tust.

Vor deinem Sprung sollte man alle ISRs deaktivieren.


Und noch was, eigentlich ist die elegante Methode einen Reset 
auszulösen, den Watchdog ablaufen zu lassen. Danach wird der Controller 
auch Hardwareseitig komplett neu initialisiert.
Du hast ja geschrieben das bei einem Reset bei dir zuerst der Bootloader 
startet.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Christian K. schrieb:
> Ich kenne mich mit den XMegas nicht aus, die haben ja so ein tolles
> Eventsystem.

Insbesondere haben sie einen Interruptcontroller (wies ich nicht
oben ausdrücklich darauf hin?), und der denkt natürlich auch, dass
die zugehörige ISR nach wie vor in Bearbeitung ist …

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich bin davon ausgegangen das mein Resetvektor im Bootloader alles neu 
Initialisiert.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> Ich bin davon ausgegangen das mein Resetvektor im Bootloader alles neu
> Initialisiert.

Beitrag "Re: Jump zum Bootloader beim XMEGA"

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Christian K. schrieb:
> Solange du in einer ISR bist sind globale Interrupts aus (ISRs sind
> normalerweise nicht unterbrechbar)

Nicht beim XMEGA. Dort kann ein höher priorisierter Interrupt einen 
niedriger priorisierten unterbrechen. Aber Du hast schon Recht, 
irgendwann muss schon ein passendes reti kommen, um die noch laufende 
ISR abzuschließen.

von Johann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mein Resetvektor im Bootloader verbiegt ja auch die Interrupttabelle. 
Aber über welchen Befehl kann ich dann das RETI löschen so das mein 
Bootloader nicht mehr denkt das er noch im Interrupt ist?

von Christian K. (the_kirsch)


Bewertung
0 lesenswert
nicht lesenswert
Ein RETI macht das gleiche wie ein RET, oberstes Element des Stacks in 
den PC laden und zusätzlich das I-Flag im SREG setzen.

Ich konnte jetzt keine Informationen finden ob das RETI bei einem XMega 
mehr macht.

Da ein XMega ein Interrupt Controller hat, würd ich dir mal raten das 
Disassembly einer ISR anzuschauen, um zu checken ob am Ende der ISR vor 
dem RETI noch irgendwelche anderen Registerbits verändert werden.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Johann schrieb:
> Aber über welchen Befehl kann ich dann das RETI löschen so das mein
> Bootloader nicht mehr denkt das er noch im Interrupt ist?

Warum zum Geier™ tust du nicht endlich mal, was ich dir die ganze
Zeit lang predige, und guckst dir das Kapitel zum Interruptcontroller
im Datenblatt an?  Ich mein', ich klapp' das Ding auf, und es guckt
mich ein Statusregister an, bei dem sowas steht:
Bit 0 ­ LOLVLEX: Low-level Interrupt Executing
This flag is set when a low-level interrupt is executing or when the interrupt handler has been interrupted by an
interrupt from higher level or an NMI. The flag will be cleared when returning (RETI) from the interrupt handler.

von Christian K. (the_kirsch)


Bewertung
0 lesenswert
nicht lesenswert
Gut zu wissen das ein RETI bei einem XMega mehr macht.

Im Offiziellen "AVR Instruction Set Manual" und im Kapitel Instruction 
Set Summary eines XMegas-Datenblatts gibt es keinen Verweis darauf.

@Johann
Jetzt hab ich mir mal das Datenblatt vom Xmega A3U geladen, aber ich 
find die zitierte Passage nicht. Auch die Volltextsuche bring nichts.


EDIT:
Atmel hat bei den Datenblättern der XMegas outgesourced.
Im Xmega AU hab ich es gefunden.

: Bearbeitet durch User
von spess53 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi

>Jetzt hab ich mir mal das Datenblatt vom Xmega A3U geladen, aber ich
>find die zitierte Passage nicht. Auch die Volltextsuche bring nichts.

Die interessanten Sachen stehen im entsprechenden Manual:

http://www.atmel.com/Images/Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf

MfG Spess

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Die interessanten Sachen stehen im entsprechenden Manual:

Ja, diese doppelten Datenblätter sind Scheibenkleister.  Wenn sie
wenigstens im per-device datasheet dann die unnötigen Kapitel-stubs
gleich weggelassen hätten, aber so erwecken die Dinger immer noch
den Eindruck, als würden sie alles abdecken, obwohl man in Wirklichkeit
darin nur einige ganz wenige Details findet, während der große Rest im
Familien-Datenblatt steht.

Aber wenn man irgendwie ernsthaft was mit einem Xmega macht, sollte
man das eigentlich kennen.

Christian K. schrieb:
> Im Offiziellen "AVR Instruction Set Manual" und im Kapitel Instruction
> Set Summary eines XMegas-Datenblatts gibt es keinen Verweis darauf.

Es gibt auch keinen Hinweis drauf, dass bspw. ein OUT auf ein
bestimmtes Portregister ein Pin toggeln kann oder ein Interruptflag
löschen.

Spätestens, wenn man aber mal irgendwie versucht nachzudenken, wie sie
die Interruptpriorisierung gelöst haben können, wird einem klar, dass
der Interruptcontroller auf irgendeine Weise wissen muss, dass gerade
eine ISR in Bearbeitung ist, denn nur so kann er verhindern, dass bei
global zugelassenen Interrupts ein Interrupt gleicher oder niederer
Priorität die aktuelle ISR unterbricht.

: Bearbeitet durch Moderator
von Georg X. (schorsch666)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich versuche im Moment den Bootloader mit der Version 1.04 auf meinem 
AtxMega63A3U zum Laufen zu bekommen.

Ich möchte den bootloader aus meiner Applikation starten.
Die Abfrage des IOs zum Starten des Bootloaders habe ich ausgebaut.
So dass dieser starten sollte. Kompiliert habe ich mit IAR.

Die Fusebits habe ich auf die Applikaiton gestellt.

In meiner Applikation benutze ich die USB-Schnittstelle um mit dem PC zu 
kommunizieren.

Mir fehlt jetzt noch der Jump aus der Applikation in den Bootloader.
Ich habe zwar schon einiges hier gelesen aber ich kriege es nicht hin.

Hat jemand dies schon zuverlässig lösen können?

Danke.

Gruß,
Georg.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Georg X. schrieb:
> Hat jemand dies schon zuverlässig lösen können?

Bitte öffne einen eigenen Thread, dein Problem hat nur den Namen
gemeinsam mit dem Problem, welches in diesem Thread hier behandelt
worden ist (verklemmter Interruptcontroller).

Ach, und beschreibe dein Problem umfassend, insbesondere was du
im Moment tust.

: Bearbeitet durch Moderator
von Timmo H. (masterfx)


Bewertung
0 lesenswert
nicht lesenswert
Georg X. schrieb:
> Mir fehlt jetzt noch der Jump aus der Applikation in den Bootloader.
Unabhängig vom Device sollte das hier funzen:
void(* jump_to_bootloader)(void) = (void (*)(void))(BOOT_SECTION_START/2+0x1FC/2);
jump_to_bootloader();

: Bearbeitet durch User
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.