Hallo, bei meinen Versuchen den Flash eines ATMega8 über einen Bootloader zu beschreiben, bin ich über folgendes Phänomen gestossen: Die Funktion "boot_program_page" wie sie in der WinAVR-Doku beschrieben ist, funktioniert erst richtig, wenn zuvor die Funktion "boot_page_erase" mit einer beliebigen Page aufgerufen wurde. So zum Beispiel steht nach einem Aufruf von memset( data, 0, SPM_PAGESIZE ); boot_program_page( 0, data ) in den ersten 64 Bytes des Flashs immernoch "0xFF". Wobei dieser Aufruf: boot_page_erase(64); boot_program_page( 0, data ); in den ersten 64 Bytes die korrekten Nullen reinschreibt. Ganz kurios ist die Tatsache, dass sich die Page, die das erste Mal mit "boot_page_erase" bearbeitet wurde, nicht mehr beschreiben lässt, d.h. der Aufruf: boot_page_erase(0); boot_program_page( 0, data ); liefert immernoch "0xff" in der Page. Als Workaround nehmen ich momentan immer die nicht existierende Page "-1": boot_page_erase(-1); boot_program_page( 0, data ); Hatte einer von euch schonmal dasselbe Problem? Ich benutze das AVRStudio 4 mit der WinAVR Version vom 10.01.2010 (die Version 10.06.2008 hab ich auch getestet). Anbei der follständige Code (Bootloader ist 2k groß, Fuses sind auf dem ATMega8 entsprechen gesetzt): #include <avr/io.h> #include <avr/interrupt.h> #include <avr/boot.h> void boot_program_page(uint32_t page, uint8_t* buf) { uint16_t i; uint8_t sreg; /* Disable interrupts.*/ sreg = SREG; cli(); eeprom_busy_wait(); boot_page_erase(page); boot_spm_busy_wait(); /* Wait until the memory is erased. */ for (i=0; i<SPM_PAGESIZE; i+=2) { /* Set up little-endian word. */ uint16_t w = *buf++; w += (*buf++) << 8; boot_page_fill(page + i, w); } boot_page_write(page); /* Store buffer in flash page. */ boot_spm_busy_wait(); /* Wait until the memory is written.*/ /* Reenable RWW-section again. We need this if we want to jump back */ /* to the application after bootloading. */ boot_rww_enable(); /* Re-enable interrupts (if they were ever enabled). */ SREG = sreg; } int main() { uint16_t page; /* Interrupt Vektoren des bootloaders verwenden */ char sregtemp = SREG; cli(); temp = GICR; GICR = temp | (1<<IVCE); GICR = temp | (1<<IVSEL); SREG = sregtemp; sei(); /* boot_program_page funktioniert erst korrekt nach einem Aufruf von boot_page_erase */ boot_page_erase(-1); uint8_t data[SPM_PAGESIZE]; memset( data, 0, SPM_PAGESIZE ); boot_program_page( 0, data ); /* Interrupt Vektoren der Applikation verwenden */ cli(); temp = GICR; GICR = temp | (1<<IVCE); GICR = temp & ~(1<<IVSEL); return 0; }
Lesen bildet: Wichtige Regeln - erst lesen, dann posten! Wenn Du willst, daß sich das jemand anguckt, benutze die Formatierung oder poste die Source als Anhang. Peter
> Wenn Du willst, daß sich das jemand anguckt, benutze die Formatierung > oder poste die Source als Anhang. Bevor die fehlende Formatierung noch mehr potentielle Antworter abschreckt: Hier mit Formatierung :-)
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <avr/boot.h> |
4 | |
5 | void boot_program_page(uint32_t page, uint8_t* buf) { |
6 | uint16_t i; |
7 | uint8_t sreg; |
8 | |
9 | /* Disable interrupts.*/
|
10 | sreg = SREG; |
11 | cli(); |
12 | |
13 | eeprom_busy_wait(); |
14 | |
15 | boot_page_erase(page); |
16 | boot_spm_busy_wait(); /* Wait until the memory is erased. */ |
17 | |
18 | for (i=0; i<SPM_PAGESIZE; i+=2) { |
19 | /* Set up little-endian word. */
|
20 | uint16_t w = *buf++; |
21 | w += (*buf++) << 8; |
22 | |
23 | boot_page_fill(page + i, w); |
24 | }
|
25 | boot_page_write(page); /* Store buffer in flash page. */ |
26 | boot_spm_busy_wait(); /* Wait until the memory is written.*/ |
27 | |
28 | /* Reenable RWW-section again. We need this if we want to jump back */
|
29 | /* to the application after bootloading. */
|
30 | boot_rww_enable(); |
31 | |
32 | /* Re-enable interrupts (if they were ever enabled). */
|
33 | SREG = sreg; |
34 | }
|
35 | |
36 | int main() { |
37 | uint16_t page; |
38 | |
39 | /* Interrupt Vektoren des bootloaders verwenden */
|
40 | char sregtemp = SREG; |
41 | cli(); |
42 | temp = GICR; |
43 | GICR = temp | (1<<IVCE); |
44 | GICR = temp | (1<<IVSEL); |
45 | SREG = sregtemp; |
46 | sei(); |
47 | |
48 | /* boot_program_page funktioniert erst korrekt nach einem Aufruf von boot_page_erase */
|
49 | boot_page_erase(-1); |
50 | |
51 | uint8_t data[SPM_PAGESIZE]; |
52 | memset( data, 0, SPM_PAGESIZE ); |
53 | boot_program_page( 0, data ); |
54 | |
55 | /* Interrupt Vektoren der Applikation verwenden */
|
56 | cli(); |
57 | temp = GICR; |
58 | GICR = temp | (1<<IVCE); |
59 | GICR = temp & ~(1<<IVSEL); |
60 | |
61 | return 0; |
62 | }
|
Flash-Speicher muss immer zuerst gelöscht werden (sprich auf 0xFF zurückgesetzt werden) bevor etwas rein geschrieben werden kann (Schreiben im Flash geht nur in eine Richtung von 1 nach null)
Ja, der Flash Speicher wird in der Funktion "boot_program_page" vor jedem Schreiben gelöscht. In meinem Fall muss ich jedoch zuerst die Funktion "boot_page_erase" mit einer beliebigen Seite beim Starten einmal ausführen damit das Schreiben überhaupt funktioniert.
Leider kann ich das Problem nicht nachstellen bzw. bei mir funktioniert alles mit WinAVR-20100110 (und auch mit AVR-Toolchain-4.7.0-2012-02-19) Die wesentlichen Dateien sind im Anhang. Die Batchfiles sind nur zur Anschauung und bei mir für die AVR Fuses "2K Bootloader" (Linker Option -Ttext=0x1800) "Atmega8 bei 12 MHz externer Quarz" und stk200 Programmieradapter an lpt1 eingestellt.
>in den ersten 64 Bytes des Flashs immernoch "0xFF". Gelöschtes Flash hat in den Zellen ja auch 0xFF. Das ist völlig in Ordnung. >Wobei dieser Aufruf: > >boot_page_erase(64); >boot_program_page( 0, data ); > >in den ersten 64 Bytes die korrekten Nullen reinschreibt. Dann ist das Flash nicht gelöscht sondern mit Null programmiert. Dein Problem ist also keins.
> Gelöschtes Flash hat in den Zellen ja auch 0xFF. > Das ist völlig in Ordnung. Ich hab auch nichts anderes behauptet. > Dann ist das Flash nicht gelöscht sondern mit Null programmiert. Da hab ich auch geschrieben, dass das korrekt ist. Mein Problem ist der initiale Aufruf von boot_page_erase auf IRGENDEINE Page beim Starten des Controllers damit ich dann eine ANDERE Seite korrekt Löschen und beschreiben kann. @Krapao: Danke für deine Recherche. Mit deinen HEX-Files hab ich den gleichen Effekt. So langsam glaube ich, dass mein Controller defekt ist. Ich werd das mal mit einem neuen testen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.