Forum: Mikrocontroller und Digitale Elektronik EEPROM lesen funktioniert nicht


von Melanie (Gast)


Lesenswert?

Hallo,

ich habe ein Problem. Ich möchte Daten im EEPROM ablegen und per ISP 
aufspielen. Das klappt auch soweit. Ich definiere einen Array mit 5 
Bytes, die .eep hat diese auch.
Im Programm lade ich mir die Daten aus dem EEPROM in eine Variable aus 
dem Flash. Leider übernimmt diese Variable die Werte aus dem EEPROM 
nicht. Wieso?
Ich lase mir die Werte mit einer LED anzeigen. Das abgespeckte Programm 
ist anbei.
Wenn ich vom meinem Programm aus eeprom_write_block() benutze, übernimmt 
das EEPROM die Werte. Wenn ich diese dann wieder lese aus dem EEPROM und 
in meine Flash Variable schreibe mit eeprom_read_block() liegen diese 
auch richtig in der Flash Variable. Nur zu Beginn liest er mir die Werte 
aus dem EEPROM nicht in die Flash Variable ein... bin ratlos.
1
#ifndef F_CPU
2
#define F_CPU           9600000UL                   // processor clock frequency 9,6Mhz
3
#endif
4
5
#include <avr/io.h>
6
#include <util/delay.h>
7
#include <avr/eeprom.h>
8
#include <avr/interrupt.h>
9
#include <inttypes.h>      // Makros für int Datentypen                      
10
11
//Define für EEPROM
12
#ifndef EEMEM
13
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
14
#define EEMEM __attribute__ ((section (".eeprom")))
15
#endif
16
17
18
19
// ------------------------------------------------------------------------------------------
20
// Variabelen im EEPROM
21
// ------------------------------------------------------------------------------------------
22
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };
23
24
25
uint8_t Array[5] = { 0 };  // Flash Variable
26
27
     
28
// main prog
29
int main(void)
30
{
31
  eeprom_read_block(Array,eeArray,sizeof(Array));
32
  
33
    // Ports initialisieren
34
  init();   
35
36
  while (1)
37
  {
38
  // hier erfolgt eine Ausgabe von Array
39
  } 
40
}
41
 /* 
42
 * Funktion init(): Initialisierung des µC 
43
 */ 
44
void init(void) 
45
{
46
  DDRB = 0; 
47
  return;
48
}

von Melanie (Gast)


Lesenswert?

Folgendes Neues habe ich herausgefunden.
Angenommen ich beschreibe das EPPROM manuell über eeprom_write_block() 
in den eeArray mit den Werten { 2,2,1,1,1 }. Danach lese ich das EPPROM 
über ISP aus.
Ich lösche den µC und spiele das ausgelesene EPROM ein. Das Programm 
funktioniert.
Irgendwie stimmt die Adresse der Zuweisung
1
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };
 nicht mit dem später zugegriffenen EPPROM Stelle überein. Daher liest 
mir das zunächst wohl nur "Schrott" aus.

Das ausgelesene EEPROM Image entspricht nicht dem, was mir der Compiler 
aus der Zuweisung erzeugt: der Zuweisung
1
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };
 die HEX-Datei oder die .eep Datei sind unterschiedlich.
Hat einer eine Idee wieso?

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Bist du sicher, dass die Initialisierung so funktioniert:
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };

Wird das wirklich beim Start des Programms in das EEPROM geschrieben?

uint8_t Array[5] = { 0 };  // Flash Variable
Das liegt im Ram, nicht im Flash, ist aber nur ein Fehler im Kommentar.

Grüße,

Peter

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Soweit ich das verstehe, muss man die Initialisierung des EEPROMS immer 
selber machen, also vom Compiler ein eep. file erzeugen lassen, in dem 
die Initialisierungswerte stehen und das nach der Programmierung des 
Programmspeichers separat programmieren. Nur so stehen die 
Initialisierungswerte korrekt im EEPROM.

Grüße,

Peter

von Melanie (Gast)


Lesenswert?

Hallo Peter,

ja, das macht der Compiler auch.
Dieses EEPROM File spiele auch per ISP auf den µC. Nur wenn ich das 
generierte EEPROM File auspiele, stehen dort nicht die Werte drin.

Programmiere ich das EEPROM aber über die Funktion eeprom_write_block() 
direkt im Programm mit gleichen Werten und lese dann die EEPROM Datei 
per ISP aus. Danach lösche ich den µC und spiele die ausgelesene Datei 
auf und das ganze funktioniert.

Kann es damit zusammenhängen, dass bei der direkt vom Compiler erzeugten 
.eep Datei die Werte bei der ersten Adresse im EEPROM anfangen?
Wenn ich die vom Compiler erzeugte Datei lade ist der erste Wert in 
Bascom 3A.
Lade ich mir die ausgelesen durch eeprom_write_block() in Bascom, so 
steht in der ersten Adresse ein 00.
Ich habe nämlich im Tutorial gelesen, dass die erste Adresse nicht 
beschrieben werden sollte, aber scheinbar macht der Compiler das. Kann 
es sein, dass dort der Wurm sich versteckt? Und wenn ja, wie erzeuge ich 
dann direkt vom Compiler eine Datei, die nicht direkt bei der ersten 
Adresse beginnt?

von Melanie (Gast)


Lesenswert?

Melanie schrieb:
> Hallo Peter,
>
> ja, das macht der Compiler auch.
> Dieses EEPROM File spiele auch per ISP auf den µC. Nur wenn ich das
> generierte EEPROM File auspiele, stehen dort nicht die Werte drin.

bzw. die Werte stehen bestimmt drin, bloß er liest nicht nicht korrekt 
aus bzw. die Stelle wird wohl nicht stimmen.

von MWS (Gast)


Lesenswert?

Dir ist klar, daß es die EESave Fuse bei einigen Controllern gibt, die 
das Löschen des EEProms beim Flashen steuert ? Es wäre doch immerhin 
möglich, daß der Compiler zuerst das EEProm beschreibt, dann das Flsah 
und dabei wieder das EEProm gelöscht wird.

von Melanie (Gast)


Lesenswert?

Die Funktion besagt ja nur, wenn ich den Chip lösche, ob das EEPROM mit 
gelöscht wird oder nicht.
Da ich den Chip lösche, das Flash aufspiele und dann die EEPROM Datei, 
spielt das keine Rolle.
Es wäre nur relevant, wenn ich die EEPROM Datei nicht neu immer auspiele 
und ständig ein geändertes Programm in den Flash schiebe.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Das bedeutet, der Compiler erwartet die Daten im EEPROM an einer anderen 
Adresse als er sie in der eep. Datei hinlegt?

Das ist schon seltsam.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>Wenn ich die vom Compiler erzeugte Datei lade ist der erste Wert in
>Bascom 3A.
>Lade ich mir die ausgelesen durch eeprom_write_block() in Bascom, so
>steht in der ersten Adresse ein 00.


Das ist aber doch beides falsch?

Nach der Initialisierung:
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };

sollte doch an der ersten Adresse 2 stehen.

von MWS (Gast)


Lesenswert?

> Es wäre nur relevant, wenn ich die EEPROM Datei nicht neu immer auspiele
> und ständig ein geändertes Programm in den Flash schiebe.

Kommt darauf an, wie das Aufspielen des Codes und des EEproms im 
Einzelnen vor sich geht. Das Beschreiben des EEProms und das Flashen des 
Codes sind zwei unterschiedliche Prozesse, das passiert nicht auf 
einmal. Deswegen einfach mal die Fuse ändern und sehen was passiert ;-)

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Wenn man die Programmierschritte manuell ausführt, sollte die Fuse kein 
Problem sein. Nur beim automatischen Programmierablauf wird der 
Masserase automatisch durchgeführt.

Ich würde mir mal gerne das map-file anschauen, kannst du mal schnell 
eins erzeugen?

von MWS (Gast)


Lesenswert?

> Wenn man die Programmierschritte manuell ausführt, sollte die Fuse kein
> Problem sein. Nur beim automatischen Programmierablauf wird der
> Masserase automatisch durchgeführt.

Das wäre logisch. Nur ist's ein kleiner Klick und schon weis man, ob's 
daran hängt.

von Melanie (Gast)


Lesenswert?

Im MAP File steht bezüglich des EEPROMS folgendes:

.eeprom         0x00810000        0x5
 *(.eeprom*)
 .eeprom        0x00810000        0x5 attiny13.o
                0x00810000                eeArray
                0x00810005                __eeprom_end = .

von Melanie (Gast)


Angehängte Dateien:

Lesenswert?

Hier noch die beiden EEPROMS im Vergleich.
Einmal das direkt vom Compiler erzeugte und einmal, wenn ich das EEPROM 
mit gleichen Werten mauell über eeprom_write_block() beschreibe.

von Melanie (Gast)


Lesenswert?

MWS schrieb:
> Das wäre logisch. Nur ist's ein kleiner Klick und schon weis man, ob's
> daran hängt.

Das habe ich auch versucht, bringt leider keine Änderung.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Stell mal bitte die beiden fraglichen eep files online, das was da im 
Bild zu sehen ist, ist völliger Unsinn.

von Melanie (Gast)


Angehängte Dateien:

Lesenswert?

Das attiny13.eep ist das vom Compiler erzeugte.
Das eeprom.HEX ist das von mir ausgelesene nach eeprom_write_block() mit 
gleichen Werten.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Also, das stimmt mit dem überein, was deine Programmiersoftware anzeigt.

Aber es passt nicht zum Mapfile und auch nicht zum Quelltext.

Kannst du das ganze Projekt hochladen?

von MWS (Gast)


Lesenswert?

Also ich seh' die Sequenz "2,2,1,1,1" nirgends in diesen Dateien, 
genauso wenig wie auf den Bascom Programmer Screenshots.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Sag ich doch, passt nicht zum Quelltext...
Und zum Mapfile auch nicht, welches behauptet, dass die section 5 byte 
lang ist.

von Melanie (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

so, ich habe das Program mal wirklich auf ein absolutes Minimum 
reduziert und wie folgt geschrieben:
1
#ifndef F_CPU
2
#define F_CPU           9600000UL                   // processor clock frequency 9,6Mhz
3
#endif
4
5
#include <avr/io.h>
6
#include <util/delay.h>
7
#include <avr/eeprom.h>
8
#include <avr/interrupt.h>
9
#include <inttypes.h>      // Makros für int Datentypen                      
10
11
// ------------------------------------------------------------------------------------------------
12
// DEFINES
13
// ------------------------------------------------------------------------------------------------
14
15
//Define für EEPROM
16
#ifndef EEMEM
17
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
18
#define EEMEM __attribute__ ((section (".eeprom")))
19
#endif
20
21
void init(void);
22
// ------------------------------------------------------------------------------------------
23
// Variabelen im EEPROM
24
// ------------------------------------------------------------------------------------------
25
uint8_t eeArray[] EEMEM = { 0,0,1,1,1 }; // Vorgabe Code im EEPROM
26
27
28
     
29
// main prog
30
int main(void)
31
{
32
    // Ports und Interrupts initialisieren
33
  init();   
34
  
35
    while (1)
36
  {
37
  
38
  }
39
40
}
41
 /* 
42
 * Funktion init(): Initialisierung des µC 
43
 */ 
44
void init(void) 
45
{
46
  // --------------------------------------------------------------------------------------------
47
  // PORTB konfigurieren
48
  //
49
  // --------------------------------------------------------------------------------------------
50
  DDRB = 0; 
51
  DDRB |= (1 << PB1) | (1 << PB2) ;    
52
  PORTB |= (1<<PB2) | (1 << PB4);      
53
    
54
55
  // --------------------------------------------------------------------------------------------
56
  // Timer 0 (8-Bit) 
57
  // --------------------------------------------------------------------------------------------
58
  TCCR0A |= (1<<WGM01);   // CTC Mode OC0A
59
  TCCR0B |= (1<<CS01);  // Prescaler 8
60
  TIMSK0 |= (1<<OCIE0A);  // Enable Compare Match A des Timers
61
  OCR0A = 149;      // Compare Register
62
   TCNT0 = 0;         // Counter auf 0 initialisieren
63
 
64
  
65
   sei();          // setzt globales Interrupt Enable Bit
66
  return;
67
}

Das Programm enthält lediglich die Initialisierng meiner benötigten 
Register, sowie die Vorbelegung des EEPROMS Array eeArray mit 5 Werten 
{0,0,1,1,1}.
Die erzeugte EEPROM .eep Datei enthält diese Werte jedoch nicht.
Anbei das Program in in einer .c Datei, die entstandene .eep Datei und 
das Makefile.

Ich hoffe jemand kann helfen.

von Karl H. (kbuchegg)


Lesenswert?

Melanie schrieb:

> Das Programm enthält lediglich die Initialisierng meiner benötigten
> Register, sowie die Vorbelegung des EEPROMS Array eeArray mit 5 Werten
> {0,0,1,1,1}.
> Die erzeugte EEPROM .eep Datei enthält diese Werte jedoch nicht.

Wie kommst du da drauf?
1
:050000000000010101F8
2
:00000001FF

sieht doch gut aus!

:05           Anzahl der Daten-Bytes, stimmt auffallend mit deinen
              Daten überein

00 00 00      dann kommen 3 Bytes, von denen 2 die Startadresse
              im EEPROM darstellen. Allesamt 0, d.h. auf jeden Fall
              mal Startadresse 0.
              Wo das 3.te Byte hingehört weiß ich jetzt nicht auswendig
              kann auch sein, dass das eigentlich zum Bytezähler
              gehört (das erste der 3). Kann aber auch sein, dass das
              letzte der Bytes so was wie eine Recordtyp Kennung ist,
              denn immerhin ist dieses Byte im anderen Datensatz 1
              und nicht wie hier 0.
              die 0 könnte also "Daten" bedeuten, während die 1 im
              anderen Datensatz "End of File" bedeutet.
              Ist aber nicht soooooo wichtig, das jetzt genau
              auzuschlüsseln

00 00 01 01 01  und hier sind sie: Deine Datenbytes aus dem Source Code

F8            noch eine Prüfsumme drüber und fertig ist der Datensatz



Aber:
Wenn wir uns mal deinen Screenshot ansehen, dann stellen wir fest, dass 
das Programmiertool mit dem EEP File nichts anzufangen wusste. Das hat 
das ganze als stink normales ASCII Textfile eingelesen.
Benutz doch bitte eine vernünftige Programmiersoftware, die auch weiß, 
dass ein EEP File einfach nur ein INTEL-Hex File mit einer anderen 
Dateiendung ist.

von Melanie (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Aber:
> Wenn wir uns mal deinen Screenshot ansehen, dann stellen wir fest, dass
> das Programmiertool mit dem EEP File nichts anzufangen wusste. Das hat
> das ganze als stink normales ASCII Textfile eingelesen.
> Benutz doch bitte eine vernünftige Programmiersoftware, die auch weiß,
> dass ein EEP File einfach nur ein INTEL-Hex File mit einer anderen
> Dateiendung ist.

Dann wird das wohl der Fehler sein. Das Programm ist dann wohl in 
Ordnung, nur die Programmiersoftware ist für diesen Zweck Müll. Dann 
werde ich wohl auf PonyProg umsteigen...

Danke.

von Jobst M. (jobstens-de)


Lesenswert?

Karl heinz Buchegger schrieb:
> Kann aber auch sein, dass das
> letzte der Bytes so was wie eine Recordtyp Kennung ist

Record-Type - Korrekt!


Gruß

Jobst

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>Wenn wir uns mal deinen Screenshot ansehen, dann stellen wir fest, dass
>das Programmiertool mit dem EEP File nichts anzufangen wusste.

Mist, das ist mir auch nicht aufgefallen, gleicher Fehler, bloß nicht 
mit Bascom, sondern mit dem Galep.

Lösung: Die .eep-Datei in .hex umbenennen.

Für weitere Verwirrung hat gesorgt, dass sich die Initialisierung von

uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };

nach

uint8_t eeArray[] EEMEM = { 0,0,1,1,1 }; // Vorgabe Code im EEPROM

geändert hat.


Grüße,

Peter

von MWS (Gast)


Lesenswert?

> Das Programm ist dann wohl in Ordnung, nur die Programmiersoftware ist für
> diesen Zweck Müll

Naja, Bascom weis schon was es mit dem von ihm selbst erzeugten EEP File 
anzufangen hat, denn es wird dort als Binärddatei erzeugt und im 
Programmer auch so (richtig) geschrieben. Diese Info ist u.A. unter 
$EEPROMHEX zu finden, hättest halt mal auch Hilfe zu Bascom lesen 
sollen, bevor Du es einsetzt.

Versteh' allerdings auch nicht wieso Du Bascom verwendest, wenn Du C 
programmieren willst. Für C würde ich das AVR Studio zum Programmieren 
nehmen, das reicht locker und man braucht kein Pony-Prog, außer 
vielleicht für exotische Programmer-HW.

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.