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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren