Forum: Mikrocontroller und Digitale Elektronik Seltsames Verhalten von avrdude für EEprom Programmierung


von Karl-Heinz K. (kubi48)


Lesenswert?

Bei der Umstellung und Erweiterung des optiboot Bootloaders bin ich auf 
ein seltsames Verhalten des Programms avrdude aufmerksam geworden.
Die Adresse der zu beschreibenden EEproms wird bei einem ATmega8 anders 
übermitteelt als beim ATmega328.
Hier ist der Mitschnitt der Kommunikation von avrdude für einen mega8:
> /dev/ttyUSB3 55 00 00 20                                      U..
#                 ^^
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 48 65 6C 6C 20                       d..EHell
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 04 00 20                                      U..
#                 ^^
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 6F 20 57 6F 20                       d..Eo Wo
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 08 00 20                                      U..
#                 ^^
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 72 6C 64 20 20                       d..Erld
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 0C 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 66 72 6F 6D 20                       d..Efrom
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 10 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 20 45 45 70 20                       d..E EEp
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 14 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 72 6F 6D 21 20                       d..Erom!
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 18 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 00 FF FF FF 20                       d..E....
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 00 00 20                                      U..
......
< /dev/ttyUSB4 0A 0D                                            ..
< /dev/ttyUSB4 57 61 74 63 68 2D 64 6F 67 20 49 6E 74 65 72 72 
Watch-dog Interr
         75 70 74 0A 0D                                   upt..
< /dev/ttyUSB4 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 66 72 6F 6D  Hello 
World from
               20 46 6C 61 73 68 21 0A 0D 
Flash!..
< /dev/ttyUSB4 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 66 72 6F 6D  Hello 
World from
               20 45 45 70 72 6F 6D 21 0A 0D 
EEprom!..
< /dev/ttyUSB4 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 77 69 74 68  Hello 
World with
               20 73 74 72 69 6E 67 21 0A 0D 
string!..

Die entsprechende Stelle der Adresse habe ich mit der
#                 ^^
Zeile gekennzeichnet. Hier werden immer 4 Bytes blockweise übermittelt 
und
die Adresse ist eine Byte Adresse!
Jetzt die Übermittelung der gleichen Daten für einen mega328:
> /dev/ttyUSB3 55 00 00 20                                      U..
#                 ^^
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 48 65 6C 6C 20                       d..EHell
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 02 00 20                                      U..
#                 ^^
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 6F 20 57 6F 20                       d..Eo Wo
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 04 00 20                                      U..
#                 ^^
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 72 6C 64 20 20                       d..Erld
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 06 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 66 72 6F 6D 20                       d..Efrom
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 08 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 20 45 45 70 20                       d..E EEp
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 0A 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 72 6F 6D 21 20                       d..Erom!
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 0C 00 20                                      U..
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 64 00 04 45 00 FF FF FF 20                       d..E....
< /dev/ttyUSB4 14 10                                            ..
> /dev/ttyUSB3 55 00 00 20                                      U..

......
< /dev/ttyUSB4 0A 0D                                            ..
< /dev/ttyUSB4 57 61 74 63 68 2D 64 6F 67 20 49 6E 74 65 72 72 
Watch-dog Interr
               75 70 74 0A 0D                                   upt..
< /dev/ttyUSB4 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 66 72 6F 6D  Hello 
World from
               20 46 6C 61 73 68 21 0A 0D 
Flash!..
< /dev/ttyUSB4 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 66 72 6F 6D  Hello 
World from
               20 45 45 70 72 6F 6D 21 0A 0D 
EEprom!..
< /dev/ttyUSB4 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 77 69 74 68  Hello 
World with
               20 73 74 72 69 6E 67 21 0A 0D 
string!..


Hier werden genau wie beim Mega8 die EEprom Daten als 4-Byte Block 
übertragen, die Adresse steigt aber nur um den Wert 2!!!
Es wird hier also wie bei den Flash-Daten eine Wortadresse übermittelt.

Nun meine Frage dazu:
Für welche Prozessoren gilt die Byte-Adresse und für welche die 
Wort-Adresse? Leider habe ich keinen ATmega16 und ATmega32 zur 
Verfügung,
um meine Vermutung zu bestätigen, dass für diese beiden Prozessoren auch 
die Byte-Adresse gilt wie für den Mega8.
Die aktuelle Version meiner optiboot Assembler-Version ist derzeit auf
dem SVN Archiv des Transistortester-Projekts im Unterverzeichnis 
bootloaders/optiboot geparkt. Eine PDF Dokumentation ist im 
Unterverzeichnis bootloaders/Doku/german (bootloader.pdf) in Deutsch und 
im Unterverzeichnis bootloaders/Doku/english in Englisch zu finden.
Da die Anpassung an die verschiedenen Architekturen, Flashgrößen 
automatisch erfolgt, ist ein Linux-System oder das Vorhandensein 
entsprechender Programmwerkzeuge (bc, cat, cut, echo, grep und tr) 
Voraussetzung.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mit deinen „Bytewürsten“ (;-) kann ich gerade nicht so viel anfangen.

Was für einen programmer type (-c) benutzt du denn?

Kannst du AVRDUDE mal mit -vvvv starten und dann die relevanten Teile
hier zitieren (also die beiden Stellen, an denen der EEPROM jeweils
adressiert wird)?

p.s.: Habe noch schnell nachgesehen, die EEPROM pagesize ist sowohl
beim ATmega8 als auch ATmega328 gleich 4.

: Bearbeitet durch Moderator
von Karl-Heinz K. (kubi48)


Lesenswert?

Jörg W. schrieb:
> Was für einen programmer type (-c) benutzt du denn?

Es handelt sich hier um den seriellen Download. Auf dem ATmega ist die 
Assembler-Version des Optiboot Bootloaders installiert.
Als Programmer-Typ wird arduino und als Port /dev/ttyACM0 oder 
/dev/ttyUSB0 verwendet.
Die serielle Schnittstelle wird von einem USB-seriell Wandler 
angesteuert.
In diesem Fall hier mit der Baudrate 19200.

Ein Ausschnitt  Protokoll von avrdude für den ATmega8:
avrdude: writing eeprom (25 bytes):
1
Writing |                                                    | 0% 0.00savrdude: Send: U [55] . [00] . [00]   [20] 
2
avrdude: Recv: . [14] 
3
avrdude: Recv: . [10] 
4
avrdude: Send: d [64] . [00] . [04] E [45] H [48] e [65] l [6c] l [6c]   [20] 
5
avrdude: Recv: . [14] 
6
avrdude: Recv: . [10] 
7
Writing | #######                                            | 14% 0.04savrdude: Send: U [55] . [04] . [00]   [20] 
8
avrdude: Recv: . [14] 
9
avrdude: Recv: . [10] 
10
avrdude: Send: d [64] . [00] . [04] E [45] o [6f]   [20] W [57] o [6f]   [20] 
11
avrdude: Recv: . [14] 
12
avrdude: Recv: . [10] 
13
Writing | ##############

Für den ATmega328:
1
avrdude: writing eeprom (25 bytes):
2
3
Writing |                                                    | 0% 0.00savrdude: Send: U [55] . [00] . [00]   [20] 
4
avrdude: Recv: . [14] 
5
avrdude: Recv: . [10] 
6
avrdude: Send: d [64] . [00] . [04] E [45] H [48] e [65] l [6c] l [6c]   [20] 
7
avrdude: Recv: . [14] 
8
avrdude: Recv: . [10] 
9
Writing | #######                                            | 14% 0.02savrdude: Send: U [55] . [02] . [00]   [20] 
10
avrdude: Recv: . [14] 
11
avrdude: Recv: . [10] 
12
avrdude: Send: d [64] . [00] . [04] E [45] o [6f]   [20] W [57] o [6f]   [20] 
13
avrdude: Recv: . [14] 
14
avrdude: Recv: . [10] 
15
Writing | ##############                                     | 28% 0.04savrdude: Send: U [55] . [04] . [00]   [20]

Die Memory Details für den ATmega8:
1
                                  Block Poll               Page                       Polled
2
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
3
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
4
           eeprom         4    20   128    0 no        512    4      0  9000  9000 0xff 0xff

und für den ATmega328p
1
                                  Block Poll               Page                       Polled
2
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
3
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
4
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff

Auch hier sieht man wieder das unterschiedliche Verhalten des avrdude.
Beim Mega8 steigen die Byteaddressen um 4, beim Mega328p um 2 !
Ich habe das optiboot Programm entsprechend angepasst, deswegen laufen 
beide Testprogramme, wie man
aus dem 1. Protokoll entnehmen kann (Ausgabe Hallo World from EEprom!).
Das erste Protokoll habe ich mit zwei separaten USB-seriell Wandlern 
mitgeschrieben, die jeweils an TX und RX angeschlossen waren.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hmpf, das ist hornalter STK500v1-Code.  Den habe ich nie selbst
angefasst, davon habe ich schlicht keine Ahnung.

Arduino und Optiboot dürften die letzten sein, die dieses Relikt aus
dem vorigen Jahrtausend noch benutzen.  Alle anderen sind mal
irgendwann auf STK500v2 gegangen.

Der Dreh- und Angelpunkt dürfte das hier sein:
1
  if ((m->op[AVR_OP_LOADPAGE_LO]) || (m->op[AVR_OP_READ_LO]))
2
    a_div = 2;
3
  else
4
    a_div = 1;
5
6
// ...
7
  for (; addr < n; addr += block_size) {
8
    // MIB510 uses fixed blocks size of 256 bytes
9
    if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0) {
10
      block_size = 256;
11
    } else {
12
      if (n - addr < page_size)
13
        block_size = n - addr;
14
      else
15
        block_size = page_size;
16
    }
17
// ...
18
    stk500_loadaddr(pgm, m, addr/a_div);

page_size ist 4, das ist zugleich der Erhöhungsschritt für jede
Iteration.  Wenn eine der beiden obigen Operationen (Loadpage Lo
oder Read Lo) definiert ist für den Speicherbereich, dann wird
nur die halbe Adresse ausgegeben.

Ich vermute, dass die Halbierung der Adresse für das Beschreiben
des Flashs erforderlich ist.  Brian Deans Logeintrag für die
entsprechenden Revisions ist recht allgemein:
1
r162 | bsd | 2002-12-01 16:05:56 +0100 (Sun, 01 Dec 2002) | 4 lines
2
3
The STK500 can perform paged read/write operations even on standard
4
"non-paged" parts.  Take advantage of that and use the faster internal
5
routines of the STK500 for those parts as well.
6
7
r161 | bsd | 2002-12-01 07:35:18 +0100 (Sun, 01 Dec 2002) | 8 lines
8
9
Optimize reading and writing for the STK500 programmer if the part
10
supports paged reads and writes.  This greatly decreases the
11
program/verify time from about 4.5 minutes down to about 10 seconds in
12
a 12K program size test case.
13
14
Print out the hardware and firmware version for the STK500 if verbose
15
is enabled.

Man müsste die Unterscheidung zwischen Flash und EEPROM wohl besser
anhand des Namens des Speicherbereichs vornehmen.  Das passiert
etwas weiter oben ohnehin schon:
1
  if (strcmp(m->desc, "flash") == 0) {
2
    memtype = 'F';
3
  }
4
  else if (strcmp(m->desc, "eeprom") == 0) {
5
    memtype = 'E';
6
  }
7
  else {
8
    return -2;
9
  }

Das könnte man dann auch gleich so zusammenfassen:
1
  if (strcmp(m->desc, "flash") == 0) {
2
    memtype = 'F';
3
    a_div = 2;
4
  }
5
  else if (strcmp(m->desc, "eeprom") == 0) {
6
    memtype = 'E';
7
    a_div = 1;
8
  }
9
  else {
10
    return -2;
11
  }

Bitte eröffne mal einen Bugreport:

https://savannah.nongnu.org/bugs/?func=additem&group=avrdude

Ich würde den dann als Anlass nehmen, mit Brian mal das, was ich
hier geschrieben habe, zu diskutieren.

von Karl-Heinz K. (kubi48)


Lesenswert?

Jörg W. schrieb:
> Bitte eröffne mal einen Bugreport:

Das habe ich hier gemacht:
https://savannah.nongnu.org/bugs/?48131

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Danke, ich habe den Report mal an Brian Dean weitergereicht (und ihm
noch privat eine Mail dazu als Erläuterung geschrieben).

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.