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
Meine Glaskugel sagt, daß Du als "byte" int16 definiert hast.
Code in Prosa, wie kommt man nur darauf? Glaskugel sagt, Du speicherst als int.
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
> 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.
Simon E. schrieb: > Ich programmiere in Assembler, habe also keine Probleme mit den > Datentypen... Na gut, dann schau Dir mal Zeile 42 an.
...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.
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
> Weiss jemand, wo das mit der Werte-Obergrenze > beim adiw dokumentiert ist? Na, im 'AVR® Instruction Set Manual'.
Übrigens ist im vorliegenden Fall subi plus sbci sinnvoll - deutlich kürzer und schneller.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.