boot_program_page Bug auf ATMega8

OP #2559265
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
> 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
}
Gast
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)
OP
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
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
>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
> 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

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

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.