Hallo,
ich versuche gerade, diesen Bootloader
http://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung
auf meinem ATmega168 zum Laufen zu bringen.
Ich hänge allerdings schon am "Hallo Welt" - Bootloader fest. Dieser
funktioniert zwar einigermaßen, wenn ich ihn an Adresse 0x0000 schreibe,
aber wenn ich ihn an die Bootloader-Adresse 0x3800(mithilfe der
Linker-Option -Ttext=0x3800) schreibe, passiert nichts.
Hier nochmal der Code:
Jürgen schrieb:> wenn ich ihn an die Bootloader-Adresse 0x3800(mithilfe der>> Linker-Option -Ttext=0x3800)
Wo trägst du die denn ein?
Im Makefile wäre das so richtig.
In die AVR-Studio-Options kommt die Wordadresse:
0x3800 / 2 = 0x1c00
mfg.
Ich benutze die Optimierungseinstellung -Os und ich setze in den
AVR-Studio options die Linker option -Ttext=0x3800, sodass dann im
Makefile folgendes erscheint:
Schau mal ins Hexfile, sind dort die Adressen 0x38xx sichtbar? Die
zweite Zeile sollte etwa mit :1003800 beginnen.
Setzt du F_CPU richtig? Sonst ist die Baudrate total verwurstelt...
Im Hex file beginnt die 2. Zeile mit :103810000C945...
Die F_CPU sollte richtig sein, da ich von der seriellen Schnittstelle
einwandfreie Zeichenketten bekomme wenn ich das Programm nicht im
Boot-Bereich starte.
Ich habe jetzt mithilfe der StatusLED herausgefunden, dass der
Mikrocontroller in uart.c hängen bleibt. Ich verwende die
Implementierung der seriellen Schnittstelle von Peter Fluery(siehe
Anhang). An der durch den Pfeil markierten Stelle läuft das Programm nun
nicht weiter:
Hmm sieht für mich alles ok aus. Vielleicht fällt ja jmd anders was auf?
Der Passus aus der uart.c passt (ich wundere mich, dass der Compiler
hier das Z-Register verwendet, wo ein lds/ori/sts genügt):
1
+00001D6E: ECE1 LDI R30,0xC1 Load immediate
2
+00001D6F: E0F0 LDI R31,0x00 Load immediate
3
+00001D70: 8180 LDD R24,Z+0 Load indirect with displacement
4
+00001D71: 6280 ORI R24,0x20 Logical OR with immediate
5
+00001D72: 8380 STD Z+0,R24 Store indirect with displacement
6
+00001D73: 9508 RET Subroutine return
In deiner "boot.txt" sieht die Vektoren-Tabelle okay aus; zumindest sind
Rx complete und DRE umgesetzt:
Das Verschieben der Tabelle erfüllt auch die Bedingung, dass das Setzen
von IVCE und IVSEL innerhalb von 4 Zyklen (gem. Wiki-Aritkel) geschehen
muss. Stack wird auch für den 168er passend gesetzt (0x4FF), deswegen
knallt's auch nicht. Auch hier fällt mir wieder die Verwendung des Z
Registers auf, mein Compiler macht das anders (avr-gcc 4.3.3).
Hab mal den C Code reingemischt:
1
char sregtemp = SREG;
2
3
+00001C6B: B72F IN R18,0x3F In from I/O location
4
5
cli();
6
7
+00001C6C: 94F8 CLI Global Interrupt Disable
8
9
temp = MCUCR;
10
11
+00001C6D: E5E5 LDI R30,0x55 Load immediate
12
+00001C6E: E0F0 LDI R31,0x00 Load immediate
13
+00001C6F: 8180 LDD R24,Z+0 Load indirect with displacement
14
+00001C70: 2F98 MOV R25,R24 Copy register
15
16
MCUCR = temp | (1<<IVCE);
17
18
+00001C71: 6091 ORI R25,0x01 Logical OR with immediate
19
+00001C72: 8390 STD Z+0,R25 Store indirect with displacement
20
21
MCUCR = temp | (1<<IVSEL);
22
23
+00001C73: 6082 ORI R24,0x02 Logical OR with immediate
24
+00001C74: 8380 STD Z+0,R24 Store indirect with displacement
Tom M. schrieb:> Hmm sieht für mich alles ok aus. Vielleicht fällt ja jmd anders was auf?
Ich bezweifle, dass das Disassembly tatsächlich von obigen Source-Code
stammt, denn dieser Teil
ist dort doppelt drin, und zwar vor und nach dem Verschieben der
Vektoren. Und das vor dem Verschieben ist natürlich tötlich.
Tom M. schrieb:> Der Passus aus der uart.c passt (ich wundere mich, dass der Compiler> hier das Z-Register verwendet, wo ein lds/ori/sts genügt):
Was mich ebenfalls an dem -Os zweifeln lässt.
erscheint wie bereits erwähnt 2 mal. Diesen hatte ich zu Debugzwecken an
der Anfang geschoben. Ich habe hier nun nochmal das richtige file,
kompiliert mit -Os, das genausowenig funktioniert.
Also ich habe mittlerweile eine andere Implementierung für sie serielle
Kommunikation genommen und jetzt klappt auch fast alles, nur das ich
scheinbar nicht in den Flash speicher schreiben kann. Ich benutze die
Funktion
1
voidboot_program_page(uint32_tpage,uint8_t*buf)
aus dem Bootloader Tutorial(s.o). Ich habe testweise einfach mal
versucht, irgendetwas an den Anfang des Speichers zu schreiben:
1
for(inti=0;i<SPM_PAGESIZE;i++)
2
{
3
flash_data[i]=0x01;
4
}
5
boot_page_erase(64);
6
program_page((uint16_t)0,flash_data);
Jedoch ohne Erfolg. Hat vielleicht jemand eine Idee?