Hallo,
ich will mal einen Bootloader schreiben. Nun will ich erstmal verstehen,
was ich überhaupt tun muss.
Ich habe das mal versucht zusammen zu schreiben und würde mich freuen,
wenn ihr mich korrigieren könntet, wenn etwas falsch ist.
Für den Atmega16M1 mit einer Boot size von 2048 words.
Dh. der Bootloader hat 4096 Byte platz und liegt im flash 0x1800 bis
0x1FFF
Die eigetliche Applikation liegt im falsh von 0x0000 bis 0x17FF
Nun müsste doch die erste Page bei der Adresse 0x0000 und die nächste
bei 0x0400 und die darauf nächste 0x0800 liegen usw. (Sprich 128*8*n mit
n = 0,1,2...) Und jede Page 4096/32 = 128 Byte groß sein...? Dh. ich
muss 128 Byte sammeln und kann dann eine Page beschreiben.
Meine Idee, da ich immer nur 8 Nutzdaten (Plus Ext ID) verschicken kann
und es sein könnte, dass mal eine Nachricht verloren geht, das ganze zu
zählen. (Oder hält das jemand für übertrieben?)
Ich würde also immer Abschnittsweise versenden. Jeder Abschnitt hat 32
Nachrichten und somit 256 Byte (Dh. beim 16M1 und 32M1 könnten zwei
pages und beim 64M1 eine page beschrieben werde) Nachdem der letzte
Abschnitt gesendet wurde, schicke ich eine weitere Nachricht um dem MCU
zu sagen, er soll in die Applikation springen.
Bei welcher Nachricht des Abschnitts ich bin, würde ich in die CAN ID
(Nutze 29Bit) unterbringen.
Nun ist mir das mit dem Sammeln der Date noch nicht ganz klar. Wie macht
man das am besten? Man muss ja erstmal 128 Byte sammeln, um überhaupt
eine Page komplett schreiben zu können. Macht man das am besten mit
memcpy() oder gibt es auch andere, sparsammere Varianten?
Ich habe auch noch nicht ganz raus, was man mit dem Read While Write
Speicher macht, der im Datenblatt im Bootloader Bereich genannt wird.
Und dann als letzte Frage: Wie kommt man am geschicktesten vom
Bootloader wieder in die soeben geschriebene Applikation? Ich habe
einige Varianten online gefunden, verstehe davon aber meist nicht all zu
viel...
1 | void boot_jump_to_application(void)
|
2 | {
|
3 | // Das verändern des Int Vektors ist noch klar
|
4 | uint8_t reg = MCUCR & ~((1 << IVCE) | (1 << IVSEL));
|
5 | MCUCR = reg | (1 << IVCE);
|
6 | MCUCR = reg;
|
7 |
|
8 | // Könnte mir das hier jemand erklären?
|
9 | #if FLASHEND > 0xffff
|
10 | __asm__ __volatile__(
|
11 | "push __zero_reg__" "\n\t"
|
12 | "push __zero_reg__" "\n\t"
|
13 | "push __zero_reg__" "\n\t");
|
14 | #else
|
15 | __asm__ __volatile__(
|
16 | "push __zero_reg__" "\n\t"
|
17 | "push __zero_reg__" "\n\t");
|
18 | #endif
|
19 | }
|
Könnte mir das jemand erklären?