Forum: Mikrocontroller und Digitale Elektronik ATTiny85 und avrdude: EEPROM auslesen nur jedes zweite Byte


von Simon E. (eingehirner)


Lesenswert?

Hallo zusammen,

ich hab ein kleines Problem bzw. eine Frage und hab dazu hier oder im 
Datenblatt nichts gefunden... was nicht heisst, dass da kein Brett vorm 
Kopf sein kann ;-)

Ich schreibe ein Programm, das Daten im EEPROM des ATTiny85 speichern 
und bei Gelegenheit wieder auslesen soll. So weit, so primitiv. Hab den 
Beispielcode aus dem Datenblatt kopiert, leicht angepasst, ein 
Testscript geschrieben und lösche beim Aufspielen des Flash auch gleich 
das EEPROM auf 0x00 (weil 0xFF als Default im Programm zu Problemen 
führen würde).

Dann mache ich folgendes:
200x ein Byte Daten hintereinander ins EEPROM speichern
--> EEPROM sollte so aussehen: 0x00,0x01,0x02,0x03...,0xc7, dann nur 
noch Nullen
200x diese EEPROM-Daten Byte für Byte auslesen, als Code bitweise auf 
LED ausgeben, in die nächsten 200 EEPROM-Speicherplätze schreiben
--> EEPROM sollte so aussehen: 
0x00,0x01,0x02,0x03...,0xc7,0x00,0x01,0x02...

Die Bytes werden von der LED sehr nett ausgegeben, stimmen alle mit der 
Erwartung überein. Der Code scheint also genau das zu machen, was er 
soll.

ABER wenn ich jetzt das EEPROM mit avrdude auslese:
avrdude -c avr910 -p t85 -P /dev/ttyUSB0 -U eeprom:r:IR_RemoteData.hex:h

dann sieht das File IR_RemoteData.hex so aus:
0x00,0x01,0x00,0x03,0x00,0x05...,0xc7,0x00,0x00,0x02,0x00,0x04,0x00,0x06 
...

Das heisst, es wird nur jedes zweite Byte ausgelesen. Ich sehe auch hier 
am "Frameshift" von erster zu zweiter Sequenz, dass die Daten da sind 
(sonst könnte das 0x02 von der zweiten Sequenz nicht da sein, es wurde 
ja direkt von der ersten Sequenz kopiert), aber eben - jedes zweite Byte 
fehlt.

Das ist sowohl beim Format Hex (Format-Code h) als auch bei Intel Hex 
(Format-Code i) der Fall, daran liegt's nicht...

Diese Situation ist fürs Debugging blöd und ich würde die Daten auch aus 
Interesse gern auslesen... Weiss jemand, was hier schiefgeht?

Viele Grüsse und danke schonmal,
Simon

von PZ (Gast)


Lesenswert?

Zeig mal deinen Code...

von Andreas B. (bitverdreher)


Lesenswert?

Meine Glaskugel sagt, daß Du als "byte" int16 definiert hast.

von Peter D. (peda)


Lesenswert?

Code in Prosa, wie kommt man nur darauf?
Glaskugel sagt, Du speicherst als int.

von Simon E. (eingehirner)


Lesenswert?

Hallo zusammen,

es geht hier gar nicht um den Code. Wie gesagt: Die Daten werden korrekt 
ins EEPROM geschrieben, korrekt ausgelesen und neu geschrieben (jeweils 
mit LED überprüft). Was nicht klappt, ist das Auslesen mittels avrdude.

Ich programmiere in Assembler, habe also keine Probleme mit den 
Datentypen...

Viele Grüsse,
Simon

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> es geht hier gar nicht um den Code
Nun ja, so steht es im Betreff: "... avrdude ...".

> Daten werden korrekt ins EEPROM geschrieben, korrekt ausgelesen
Avrdude kenne ich nicht, gebe aber zu bedenken, dass es noch eine andere 
Möglichkeit gibt, dass nämlich der 'Assembler-Code' sowohl beim 
Schreiben wie beim Lesen den selben Versatz hat. Also wäre das Programm 
vielleicht doch von Interesse, zumindest solange nicht ein 
Avrdude-Kenner das Fehlverhalten bestätigt.

von Andreas B. (bitverdreher)


Lesenswert?

Simon E. schrieb:
> Ich programmiere in Assembler, habe also keine Probleme mit den
> Datentypen...

Na gut, dann schau Dir mal Zeile 42 an.

von Uwe D. (monkye)


Lesenswert?

...und in welchem Format wird denn in den EEPROM geschrieben?

1 Byte?? Oder 2 Byte??

Fragen über Fragen - die alle hier schon gestellt wurden, nur mit 
anderen Worten. Und mit dem avrdude hat das erstmal herzlich wenig zu 
tun.

von Simon E. (eingehirner)


Lesenswert?

Problem gelöst - danke an S. Landolt für den entscheidenden Hinweis!

Fürs Protokoll: Ich lag mit meiner Analyse daneben, der avrdude 
funktioniert einwandfrei. Asche auf mein Haupt und ja, es wäre schneller 
gegangen, wenn ich den Code einkopiert hätte... auch wenn ich nach wie 
vor nicht weiss, was genau logisch/mathematisch falsch war. Hab eine (in 
meinen Augen funktional identische) Alternative ausprobiert und 
schwupps, klappt alles.

Vielleicht weiss das ja jemand? (Diesmal mit Code.)

Ich habe in r17 den Wert, der ins EEPROM soll, in r18 und r19 die 
low/high-Bytes der Adressen (und nein, sie sind nicht vertauscht).

Ich inkrementiere die Adresse in jedem Schritt so (Snippet aus dem alten 
Code):
1
ldi r16, 0   ; dummy zero for adding with carry
2
inc r18      ; low byte ==> das ist offenbar schon ein Fehler, weil inc kein Carry setzt (laut Datenblatt nur Z,N,V), aber da ich nur von 0-200 zähle, sollte ein nicht gesetztes Carry keinen Unterschied machen (hätte ich gedacht). Falsch ist es trotzdem. Sollte subi r18, -1 sein, denke ich.
3
adc r19, r16 ; high byte, add carry

Das führt dazu, dass jedes ZWEITE Byte an die richtige Stelle im EEPROM 
geschrieben wird und jedes ANDERE ZWEITE Byte sehr viel weiter hinten 
(oberhalb von Position 256, nicht exakt - die genaue Stelle weiss ich 
nicht mehr). r18/r19 scheinen also immer hin und her zu springen. Ich 
verstehe nicht warum.

Alternativ hab ich folgendes probiert, das einwandfrei funktioniert:
1
  ldi ZH, 0  ; low(EEPROM address)
2
  ldi ZL,  0 ; high(EEPROM address)
3
  ldi r17, 1 ; Data to be written to EEPROM
4
5
  ; Write data to first 200 bytes in EEPROM
6
  DLoop1:
7
    rcall EEPROM_write  ; Write r17 to EEPROM address H:L r19:r18
8
    adiw Z, 1           ; Increment address
9
    mov r18, ZL
10
    mov r19, ZH
11
    inc r17             ; Increment data to be written
12
    cpi r17, 200        ; Stop after 200 writes
13
    brne DLoop1
14
15
  ; Verify data in first 200 bytes of EEPROM by reading them and writing them to second 200 bytes
16
  ldi r20, 200
17
  ldi ZH, 0 ; Reset EEPROM address
18
  ldi ZL, 0
19
  DLoop2:
20
    mov r18, ZL
21
    mov r19, ZH
22
    rcall EEPROM_read   ; Read EEPROM data from H:L r19:r18 into r17
23
24
;    rcall DEBUGr17 ; Ausgabe von r17 (Data von EEPROM) als Blinken auf LED
25
26
    adiw Z, 50          ; Go to address x+200 - adiw accepts only values <60??? Found nothing about this in datasheet.
27
    adiw Z, 50          ; Go to address x+200
28
    adiw Z, 50          ; Go to address x+200
29
    adiw Z, 50          ; Go to address x+200
30
    mov r18, ZL
31
    mov r19, ZH
32
    rcall EEPROM_write  ; Store r17 here
33
34
    sbiw Z, 49          ; Increment to next address
35
    sbiw Z, 50
36
    sbiw Z, 50
37
    sbiw Z, 50
38
    dec r20             ; Count down, do this 200x

Nach dieser Erkenntnis wäre es vermutlich sinnvoll, wenn ich meinen 
EEPROM_write und EEPROM_read auf die Nutzung von ZH/ZL umschreiben 
würde, dann spar ich mir die Kopiererei...

Weiss jemand, wo das mit der Werte-Obergrenze beim adiw dokumentiert 
ist?

Viele Grüsse,
Simon

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

> Weiss jemand, wo das mit der Werte-Obergrenze
> beim adiw dokumentiert ist?

Na, im 'AVR® Instruction Set Manual'.

von S. Landolt (Gast)


Lesenswert?

Übrigens ist im vorliegenden Fall subi plus sbci sinnvoll - deutlich 
kürzer und schneller.

von Simon E. (eingehirner)


Lesenswert?

Stimmt. Danke!

von S. Landolt (Gast)


Lesenswert?

Mir ist ohnehin nicht klar, was sich Atmel bei den Befehlen adiw und 
sbiw gedacht hat - nie schneller als subi sbci, und nur im Fall 0..63 
kürzer.

von c-hater (Gast)


Lesenswert?

S. Landolt schrieb:

> Mir ist ohnehin nicht klar, was sich Atmel bei den Befehlen adiw und
> sbiw gedacht hat - nie schneller als subi sbci, und nur im Fall 0..63
> kürzer.

Naja, früher(tm) gab es die Instruktionen überhaupt nur für den 
Immediate-Bereich 0..63. Ist das heute anders?

Und der Vorteil der adiw, subiw war natürlich wirklich die Ersparnis von 
Flashspace. Das, was die C-ler als "Zeigerarithmetik" betiteln, läßt 
sich damit bezüglich des Platzbedarfs wirklich ganz ordentlich 
eindampfen, aber auch der Zugriff auf Datenstrukturen im Flash, denn 
leider gibt es für (e)lpm ja keine indizierte Adressierung mit Offset, 
da ist man zur exzessiven Nutzung von "Zeigerarithmetik" von Haus aus 
gezwungen.

von S. Landolt (Gast)


Lesenswert?

Ihr erster Absatz ist mir völlig unverständlich.

"Datenstrukturen im Flash": wenn ich solche wirklich umfangreich nutzen 
wollte, würde ich sie innerhalb von 256-Byte-Blöcken anordnen und mit 
subi ZL arbeiten (was auch noch jeweils 1 Takt spart).

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.