Forum: Mikrocontroller und Digitale Elektronik Atmega64C1 Bootloader schreibt nicht in Flash


von Rene Strophff (Gast)



Lesenswert?

Guten Tag!

Ich arbeite hier gerade mit einem Bootloader auf einem Automotive 
Atmega64C1. Leider konnte ich bisher beim Schreiben in den Flash keine 
Erfolge verzeichnen. Da der ursprüngliche Code eher komplex ist, habe 
ich ein einfaches Projekt aufgesetzt, das einfach nur eine Seite des 
Flashspeichers mit einem Text beschreiben soll. Auch da zeigt sich 
leider kein Erfolg.

Den Code der Funktion boot_program_page habe ich direkt dem Beispiel in 
der boot.h entnommen. Eigentlich hätte ich angenommen, dass dieser 
Beispielcode anstandslos das tut, was er verspricht. Aber wenn ich den 
Flash nach Durchlaufen des Codes auslese, findet sich von den zu 
schreibenden Daten keine Spur.

Die Fuses sollten korrekt gesetzt sein. Das Textsegment habe ich in den 
Linkereinstellungen an die Adresse 0x3800 verschoben, wo der Bootloader 
entprechend der Fuses (Byteadresse 0x7000) liegen sollte.

Als Entwicklungsumgebung nutze ich Atmel Studio 7 mit GCC.

Hier der Code:
1
#include <stdint.h>
2
#include <inttypes.h>
3
#include <avr/io.h>
4
#include <avr/wdt.h>
5
#include <avr/interrupt.h>
6
#include <avr/boot.h>
7
#include <avr/pgmspace.h>
8
9
#include "typedefs.h"
10
#include "driver/can/can_drv.h"
11
#include "driver/can/reduced_can_lib.h"
12
13
14
void boot_program_page (uint32_t page, uint8_t *buf)
15
{
16
   uint16_t i;
17
   uint8_t sreg;
18
19
   // Disable interrupts.
20
21
   sreg = SREG;
22
   cli();
23
   
24
   eeprom_busy_wait ();
25
26
   boot_page_erase (page);
27
   boot_spm_busy_wait ();      // Wait until the memory is erased.
28
29
   for (i=0; i<SPM_PAGESIZE; i+=2)
30
   {
31
      // Set up little-endian word.
32
33
      uint16_t w = *buf++;
34
      w += (*buf++) << 8;
35
      
36
      boot_page_fill (page + i, w);
37
   }
38
39
   boot_page_write (page);     // Store buffer in flash page.
40
   boot_spm_busy_wait();       // Wait until the memory is written.
41
42
   // Reenable RWW-section again. We need this if we want to jump back
43
   // to the application after bootloading.
44
45
   boot_rww_enable ();
46
47
   // Re-enable interrupts (if they were ever enabled).
48
49
   SREG = sreg;
50
}
51
52
int main(void)
53
{
54
   uint8_t TextToPage[] = {"It is a period of civil war. Rebel spaceships, striking from a hidden base, have won their first victory against the evil Galactic Empire. ..."}; //Text zum Posten hier gekürzt
55
   
56
   cli();
57
   wdt_disable();
58
59
60
   boot_program_page (1, TextToPage);
61
   
62
   while (1) 
63
   {
64
   }
65
}

Angehängt habe ich einen Screenshot der Einstellungen der Fuse Bits und 
einen Screenshot eines Disassemblys, das zeigt, dass der Code 
tatsächlich im angestrebten Adressbereich ausgeführt wird.

Für kompetente Hilfe wäre ich gerade sehr dankbar :)

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Rene Strophff schrieb:
> Das Textsegment habe ich in den
> Linkereinstellungen an die Adresse 0x3800 verschoben, wo der Bootloader
> entprechend der Fuses (Byteadresse 0x7000) liegen sollte.

die Byte-Adresse stimmt nicht. 0x3800 * 2 = 0x7600
d.h. (falls es kein Schreibfehler ist) der Bootloader liegt an der 
falschen Stelle, dann kann er nicht in den Flash schreiben.

PS: genau das selbe hatte ich auch schon. Auch bei mir war der 
Bootloader an der falschen Stelle

von Rene Strophff (Gast)


Lesenswert?

0x3800 * 2 ergibt durchaus 0x7000

Allerdings ergibt 3800 dezimal multipliziert mit 2 schon 7600 dezimal.
Die Adressen sind aber in hex angegeben. Zugegebnermaßen habe ich beide 
Werte mit dem Windows Taschenrechner ausgerechnet, gehe aber davon aus, 
dass dieser korrekt rechnet.
Im vom Compiler erzeugten .hex File liegt der Code ebenfalls auf Adresse 
0x7000. Ebenso liest es sich im .map File.

Die Tatsache, dass der Code ausgeführt wird (verifiziert über eine 
Ausgabe auf den CAN Bus) spricht auch stark dafür, dass der Code auf dem 
entsprechenden Vektor liegt.

Trotzdem danke für die Antwort :)

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Asche auf mein Haupt!!

Man nehme den Windows Taschenrechner, stelle ihn auf Programmierer um, 
und vergesse trotzdem auf hex zu stellen.

Also daran liegts nicht.

Möglicherweise ist irgendwo trotzdem ein Adressproblem...

von Stefan E. (sternst)


Lesenswert?

Rene Strophff schrieb:
> Das Textsegment habe ich in den
> Linkereinstellungen an die Adresse 0x3800 verschoben, wo der Bootloader
> entprechend der Fuses (Byteadresse 0x7000) liegen sollte.

Nö, das 0x7000 ist die Wortadresse.

von Rene Strophff (Gast)


Lesenswert?

Stefan E. schrieb:
> Nö, das 0x7000 ist die Wortadresse.

Das hat den Trick gemacht. Danke!

Ich hatte es auch vorher schon mit 0x7000 als Wortadresse probiert, muss 
mich dabei aber wohl irgendwie vertippt haben, denn dabei hat mir der 
Linker einen Fehler ausgegeben und ich habe den Gedanken, dass das die 
Wortadresse sein könnte verworfen.

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
Noch kein Account? Hier anmelden.