Hallo die Herren,
leider ist mein letzter Beitrag auf wenig Aufmerksamkeit gestoßen.
War zugegeben auch schon etwas unübersichtlich.
Ich würde gerne einen Bootloader in Codevison schreiben, soweit klappt
auch alles bis auf die Befüllung des "temporary page buffers".
Zum Debuggen möchte ich nur die ersten 2 Words der ersten Page befüllen
und ins Flash schreiben.
1
#pragma regalloc- /* Deaktivierung der automatischen Vergabe von Adressen an Variablen*/
2
registerunsignedintdaten@0x0002;
3
unsignedcharPAGE_BUFFER[128]@0x008A;
4
registerunsignedintdaten@0x0002;
5
registerunsignedintCurrentAdress@0x0006;//CurrentAdress in Register 6 speichern
6
#pragma regalloc+ /* Aktivierung der automatischen Vergabe von Adressen an Variablen*/
7
8
PAGE_BUFFER[0]=0x0C;
9
PAGE_BUFFER[1]=0x94;
10
PAGE_BUFFER[2]=0x68;
11
PAGE_BUFFER[3]=0x00;
12
13
voidDO_SPM(void)
14
{
15
#asm
16
WAIT_SPM:
17
inr16,0x37;//SPMCR in Register r16 einlesen 37= Address von SPMCR, passt für ATmega32
18
sbrcr16,0x01;//Skip if Bit in Register is Cleared
19
//The SPMEN bit will auto-clear upon completion of an SPM instruction,
20
//or if no SPM instruction is executed within four clock cycles. During page erase and page write,
21
//the SPMEN bit remains high until the operation is completed.
22
rjmpWAIT_SPM;
23
out0x37,r17;//schreibe in SPMCR-Register und führe aus
24
spm;
25
#endasm
26
}
27
28
29
voidRAM_2_TEMP_PAGE(void)
30
{
31
CurrentAdress=0;
32
#asm ("movw r30,r6"); //move CurrentAddress to Z pointer
33
34
daten=PAGE_BUFFER[0]+256*PAGE_BUFFER[0+1];
35
#asm("movw r0,r2"); //kopiert wert r3+r2 in r1+r0
36
#asm("ldi r17,0x01"); //If only SPMEN is written, the following SPM instruction will store the value in R1:R0 in the temporary page buffer addressed by the Z-pointer.
37
DO_SPM();
38
39
CurrentAdress=2;
40
#asm ("movw r30,r6");
41
daten=PAGE_BUFFER[2]+256*PAGE_BUFFER[2+1];
42
#asm("movw r0,r2");
43
#asm("ldi r17,0x01");
44
DO_SPM();
45
46
}
Meines Erachtens sollte das Programm nun folgendes machen:
1.) z-Pointer auf Adresse 0 setzten
2.) PAGE_BUFFER[0] und PAGE_BUFFER[1] in R0 bzw. R1 übernehmen
3.) R0 bzw. R1 in den "temporary page buffer" ab Adresse 0 schreiben
4.) zPointer auf Adresse 2 setzten
5.) PAGE_BUFFER[2] und PAGE_BUFFER[3] in R0 bzw. R1 übernehmen
6.) R0 bzw. R1 in den "temporary page buffer" ab Adresse 2 schreiben
Wenn ich nun aber nach dem Schreiben der Page den Flash Speicher auslese
stehen die an ganz anderen Adressen. Siehe Anhang Bild1.
Ich versteh einfach nicht was ich falsch mache.
Bitte um Tipps wo der Fehler liegen könnte. Danke
Hast du schon mal geschaut, ob es unter codevision eine
bootloader-unterstützung gibt. vielleicht mußt du gar nicht alles selbst
machen, vielleicht gibt es schon funktionen dafür.
Meinst du mit Disassembler-Listing dies hier, falls ja muss ich mich
erstmal einlesen. Davon hab ich noch wenig Ahnung.
Falls es sich beim Disassembler-Listing um etwas anders handelt bitte um
Aufklärung.
1
;void RAM_2_TEMP_PAGE(void)
2
; 0000 017D {
3
_RAM_2_TEMP_PAGE:
4
; 0000 017E CurrentAdress =0;
5
CLR R6
6
CLR R7
7
; 0000 017F #asm ("movw r30,r6"); //move CurrentAddress to Z pointer
; 0000 0182 #asm("movw r0,r2"); //kopiert wert r3+r2 in r1+r0
19
movw r0,r2
20
; 0000 0183 #asm("ldi r17,0x01"); //If only SPMEN is written, the following SPM instruction will store the value in R1:R0 in the temporary page buffer addressed by the Z-pointer.
Mark schrieb:> Meinst du mit Disassembler-Listing dies hier
Ja.
Und da siehst du auch schon, wo der Pfeffer im Hasen liegt.
1
; 0000 017E CurrentAdress =0;
2
CLR R6
3
CLR R7
4
; 0000 017F #asm ("movw r30,r6"); //move CurrentAddress to Z pointer
5
movw r30,r6
Damit willst du den Z-Zeiger vorbereiten. Du hast aber die Rechnung
ohne den Wirt, ähem, den Compiler gemacht, denn:
1
__GETB1HMN _PAGE_BUFFER,1
2
LDI R30,LOW(0)
3
ADD R30,R26
4
ADC R31,R27
5
MOVW R2,R30
6
; 0000 0182 #asm("movw r0,r2"); //kopiert wert r3+r2 in r1+r0
7
movw r0,r2
... der zerpopelt dir danach deinen Z-Zeiger wieder für seine eigenen
Berechnungen.
Ich glaube, mit dieser Art Inline-Assembler bist du da aufgeschmissen,
da du dem Compiler nicht genau genug mitteilen kannst, wie sich dein
Assemblercode in die C-Umgebung einfügen soll ("constraining").
Vielleicht kannst du ja eine ganze Funktion stattdessen in Assembler
implementieren und mit dazu linken.
1
; 0000 0186 CurrentAdress =2;
2
LDI R30,LOW(2)
3
LDI R31,HIGH(2)
4
MOVW R6,R30
5
; 0000 0187 #asm ("movw r30,r6");
6
movw r30,r6
Mit ein paar ordentlichen constraints beim Inline-Assembler hätte man
sich auch diese Hin- und Herschubserei sparen können.
Recht Herzlichen Danke für die Unterstützung Jörg.
Mit diesen Informationen hat es dann geklappt.
Kann jetzt prinzipiell die Daten auf die entsprechende Seite im Falsh
schreiben.
Nun muss ich nur noch den Ablauf des Bootloaders schreiben.
Die einzelnen Funktionen funktionieren mal alle. JUHU
Anbei noch ein Foto meines ersten richtigen Mikrocontroller Projektes.
Bin ja schon ein klein wenig stolz darauf.
Bin selbst gespannt mit welchen Problem ich als nächster komme. (-:
mfg
Mark
Hallo die Herren,
Habe nun mit Hilfe des Beitrages:
http://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung
den Ablauf meines Bootloaders geschrieben.
Dies funktioniert auch alles soweit. Er empfängt die Daten, bildet
Checksummen, schreibt die erste Flash Seite.
Danach geht es aber nicht mehr weiter, weil er über die RS232 falsche
Daten empfängt -> dadurch Checksummenfehler.
Nach dem Aufruf des folgendem Programmabschnitt funktioniert die
Kommunikation nicht mehr richtig.
#asm ("movw r30,r6"); //move CurrentAddress to Z pointer
24
#asm("ldi r17,0x01"); //If only SPMEN is written, the following SPM instruction will store the value in R1:R0 in the temporary page buffer addressed by the Z-pointer.
25
DO_SPM();
26
}
27
CurrentAdress=page;
28
PAGE_WRITE();/* Store buffer in flash page. */
29
30
31
/* Reenable RWW-section again. We need this if we want to jump back */
32
/* to the application after bootloading. */
33
REENABLE_RWW();
34
35
/* Re-enable interrupts (if they were ever enabled). */
36
SREG=sreg;
37
38
}
39
40
41
42
voidPAGE_WRITE(void)
43
{
44
#asm
45
movwr30,r6;//move CurrentAddress to Z pointer
46
ldir17,0x05;//Bit 0 – SPMEN: Store Program Memory Enable, Bit 2 – PGWRT: Page Write
47
#endasm
48
DO_SPM();
49
}
Wenn ich das PAGE_WRITE (); auskommentiere,
empfängt er wieder alle Daten richtig.
Woran könnte dies liegen?
Mark schrieb:> program_page((unsigned int)flash_page, flash_data);>> void program_page (unsigned long int page, unsigned char buf[SPM_PAGESIZE])
Warum wird flash_page auf unsigned int gecastet, wenn die Funktion doch
ein unsigned long int erwartet? Wieso ist flash_page nicht gleich als
unsigned long int definiert, wenn dieser Typ nötig ist?
Hast Du geprüft, dass flash_page auch beim 2. Aufruf die richtige
Adresse enthält? Wenn nicht, schreibst Du vielleicht irgendwo in den
Flashspeicher, was erklären könnte, warum dein Programm anschließend
nicht mehr funktioniert - es wurde überschrieben.
#asm("ldi r17,0x11"); //Bit 0 – SPMEN: Store Program Memory Enable, Bit 4 – RWWSRE: Read-While-Write Section Read Enable
4
DO_SPM();
5
}
6
7
voidDO_SPM(void)
8
{
9
#asm
10
WAIT_SPM:
11
inr16,0x37;//SPMCR in Register r16 einlesen 37= Address von SPMCR, passt für ATmega32
12
sbrcr16,0x01;//Skip if Bit in Register is Cleared
13
//The SPMEN bit will auto-clear upon completion of an SPM instruction,
14
//or if no SPM instruction is executed within four clock cycles. During page erase and page write,
15
//the SPMEN bit remains high until the operation is completed.
16
rjmpWAIT_SPM;
17
out0x37,r17;//schreibe in SPMCR-Register und führe aus
18
spm;
19
#endasm
20
}
Irgntwie verschluckt er mir 5 Zeilen aus der HEX Datei.
Nach dem Aufruf schreiben der ersten Flash Seite.
Andreas schrieb:> Wenn nicht, schreibst Du vielleicht irgendwo in den>> Flashspeicher, was erklären könnte, warum dein Programm anschließend>> nicht mehr funktioniert - es wurde überschrieben.
Mein Bootlader Programm wird nicht überschrieben. Funktioniert auch
weiterhin.