boot_program_page Bug auf ATMega8

OP #2559265
Lesenswert?
• ▲
▼
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;
}
Gast #2559542
Lesenswert?
• ▲
▼
> 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
}
OP #2559761
Lesenswert?
• ▲
▼
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.
Gast #2560495
Lesenswert?
• ▲
▼
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.
Angehängte Dateien:
Gast #2560526
Lesenswert?
• ▲
▼
>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.
OP #2560768
Lesenswert?
• ▲
▼
> 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.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.