AVR (ATmega644) Signatur & Serialnummer auslesen

Gast #7311699
Lesenswert?

Hallo zusammen,

ich möchte aus meinem ATmega644 während dem Betrieb die Signatur UND die Seriennummer auslesen.

Dafür habe ich das Datenblatt durchforstet und bin auf verschiedene REGISTER unterhalb 0x20 gestoßen. Daraus habe ich einen kleinen C Quellcode gebastelt. Nun meine Frage: Ist dieser korrekt? Besonders bei der Seriennummer kann ich schlecht feststellen ob die zurückgegebenen Werte wirklich die Seriennummer sind oder etwas anderes.

Falles es eine bessere Lösung zum Auslesen gibt, würde ich mich über Kommentare freuen.

1
void cpu_get_sig(uint8_t *sigarray) //muss 3 Bytes haben
2
{
3
  *sigarray[2] = SIGNATURE_2
4
  *sigarray[1] = SIGNATURE_1
5
  *sigarray[0] = SIGNATURE_0.
6
}
7

8
void cpu_get_sn(uint8_t *idarray) //muss 10 Bytes haben
9
{
10
  idarray[1] = boot_signature_byte_get(0x0E); //SN 2
11
  idarray[0] = boot_signature_byte_get(0x0F); //SN 1
12
  idarray[3] = boot_signature_byte_get(0x10); //SN 4
13
  idarray[2] = boot_signature_byte_get(0x11); //SN 3
14
  idarray[5] = boot_signature_byte_get(0x12); //SN 6
15
  idarray[4] = boot_signature_byte_get(0x13); //SN 5
16
  idarray[6] = boot_signature_byte_get(0x14); //Reserved
17
  idarray[7] = boot_signature_byte_get(0x15); //Wafer Number
18
  idarray[8] = boot_signature_byte_get(0x16); //Y-coordinate
19
  idarray[9] = boot_signature_byte_get(0x17); //X-coordinate  
20
}
#7311716
Lesenswert?

Hm. Da du doch schon das Datenblatt gelesen hast...

Cybers schrieb:

void cpu_get_sig

ist Unsinn. SIGNATURE_0 .. _2 ,kannst du im Programm nicht addressieren, die machen was ganz anderes.

https://www.nongnu.org/avr-libc/user-manual/group__avr__signature.html

Cybers schrieb:

void cpu_get_sn(uint8_t *idarray) //muss 10 Bytes haben { idarray[1] = boot_signature_byte_get(0x0E); //SN 2 idarray[0] = boot_signature_byte_get(0x0F); //SN 1 idarray[3] = boot_signature_byte_get(0x10); //SN 4 idarray[2] = boot_signature_byte_get(0x11); //SN 3 idarray[5] = boot_signature_byte_get(0x12); //SN 6 idarray[4] = boot_signature_byte_get(0x13); //SN 5 idarray[6] = boot_signature_byte_get(0x14); //Reserved idarray[7] = boot_signature_byte_get(0x15); //Wafer Number idarray[8] = boot_signature_byte_get(0x16); //Y-coordinate idarray[9] = boot_signature_byte_get(0x17); //X-coordinate }

Das ist prinzipiell nicht verkehrt, nur hat der ATMega644 als Vertreter der Steinzeit-Megas solch neumodischen Kram wie eine Seriennummer gar nicht. Der hat nur 3 Byte Signature, und ein Byte "RC Oscillator Calibration Byte", sonst nix. ("Nix" nennt sich im Datenblatt: "reserved for future use.")

Oliver

Gast #7311736
Lesenswert?

Oliver S. schrieb:

ist Unsinn. SIGNATURE_0 .. _2 ,kannst du im Programm nicht addressieren, die machen was ganz anderes.

ok, dann doch eher so:

1
void cpu_get_sig(uint8_t *sigarray) //muss 4 Bytes haben
2
{ 
3
  *sigarray[0] = boot_signature_byte_get(0x0000); //SigByte 1
4
  *sigarray[1] = boot_signature_byte_get(0x0002); //SigByte 2
5
  *sigarray[2] = boot_signature_byte_get(0x0004); //SigByte 3
6
  *sigarray[3] = boot_signature_byte_get(0x0001); //RC Oszillator Byte
7
}

Das sollte funktionieren oder?

Oliver S. schrieb:

Das ist prinzipiell nicht verkehrt, nur hat der ATMega644 als Vertreter der Steinzeit-Megas solch neumodischen Kram wie eine Seriennummer gar nicht. Der hat nur 3 Byte Signature, und ein Byte "RC Oscillator Calibration Byte", sonst nix. ("Nix" nennt sich im Datenblatt: "reserved for future use.")

Da bin ich mir nicht sicher. Im Datenblatt vom ATmega644P auf Seite 368 steht:

28.3. - Signature Bytes All Atmel microcontrollers have a three-byte signature code which identifies the device. This code can be read in both serial and parallel mode, also when the device is locked. The three bytes reside in a separate address space. For the device the signature bytes are given in the following table.

Table 28-9. Device and JTAG ID Signature Bytes Address 0x000 | 0x001 | 0x002 0x1E | 0x96 | 0x0A

28.4. - Calibration Byte The device has a byte calibration [...] Calibrated Internal RC Oscillator on page 49

28.5. - Serial Number Each individual part has a specific serial number. This can be used to identify a specify part while it is in the field. The serial number consists of nine bytes which can be accessed from the signature address space.

Gast #7311825
Lesenswert?

Cybers schrieb:

ATmega644P/V - Rev.B - 08/2016

Komisch. Das aktuelle Datenblatt zum ATmega644P/V bei Microchip (Rev. A - 10/2018) listet in der Versionsgeschichte gar keine Rev. B von 08/2016 auf. In diesem gibt es unter 24.3 allerdings auch nur Signature Bytes, aber keine Seriennummer. Laut Datenblatt gibt es die nicht. Und unterhalb von 0x20 befindet sich laut 5.3 doch nur die Register File.

Gast #7311828
Lesenswert?

Die Signatur von meinen beiden ATmega644P-20PU, beide von 0741 (also ziemlich alt):

1
0000  1E59 96FF 0AFF FFFF EDFF FFF7 FFFF 4837
2
0008  3130 3536 FF12 0E0A 1701 1201 1301 FFFF
3
0010  FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
4
0018  FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
5

6
0000  1E8D 96FF 0AFF FFFF EDFF FFF7 FFFF 4837
7
0008  3130 3536 FF16 0B0B 1701 1201 1301 FFFF
8
0010  FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
9
0018  FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF

Ob da in der zweiten Zeile so etwas wie eine Seriennummer steht - keine Ahnung.

Gast #7311839
Lesenswert?

Interessant, in der aktuellen Vesion von 2018 (https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/ATmega164P-324P-644P-Data-Sheet-40002071A.pdf) und den älteren von Atmel ist davon nichts zu lesen. Da die 2016er Versionen (ich hab ne 07 und ne 08 gefunden) ne komplett überarbeitet Version ist in der die der Prozessoren 164/324 und 644 getrennt wurden, die Von Microchip nicht wieder erwähnt wurden, kann man wohl von einem Fehler oder einem geplaten Feature ausgehen.

Gast #7311998
Lesenswert?

Sieht für mich gut aus und könnte funktionieren, wenn

SIGNATURE_0, SIGNATURE_1, SIGNATURE_2, boot_signature_byte_get

die Zugriffskonventionen zum Signatur Speicher einhalten.

Falls Deine Idee nicht funktioniert, lies Abschnitt

27.8.10. Reading the Signature Row from Software

27.9.1. SPMCSR - Store Program Memory Control and Status Register

in Deinem Datenblatt.

Auf Signatur Speicher zugreifen:

  1. Adresse in Z-Pointer schreiben
  2. Bits in SPMCSR setzen
  3. LPM innerhalb drei CPU-Zyklen ausführen!

Z.B. in Assembler, weil nur drei CPU-Zyklen zwischen SPMCSR und LPM erlaubt sind:

.INCLUDE "m644pdef.inc"

ldi r0, 0b00100001 ;SIGRD, SPMEN Bitmaske für SPMCSR

ldi r31, 0 ;ZH

ldi r30, 0 ;ZL=0 für Signature Byte 1 in r1

out SPMCSR, r0

lpm r1, Z

ldi r30, 2 ;ZL=2 für Signature Byte 2 in r2

out SPMCSR, r0

lpm r2, Z

ldi r30, 4 ;ZL=4 für Signature Byte 3 in r3

out SPMCSR, r0

lpm r3, Z

Moderator Persönliche Seite #7312010
Lesenswert?

S. Landolt schrieb:

1056?

Ah - jetzt - ja: ASCII&umstellen 1.-2.Byte!: 1056 <-> 0165

Ja, die Byte-Reihenfolge ist natürlich nicht sofort ersichtlich. Ich sah nur 3130 3536, was erstmal sofort das "ASCII Flag" im Gehirn klingeln ließ. ;-)

Wahrscheinlich ist dann der erste Chip von der Scheibe #18, X-Position 14, Y-Position 10, der zweite von der Scheibe #24 (dürfte die letzte im Los sein, wenn man bei 0 anfängt), X- und Y-Position 11.

avr schrieb:

Z.B. in Assembler

Braucht man nicht, genau dafür gibt's ja dieses boot_signature_byte_get().

Gast #7312303
Lesenswert?

Jörg W. schrieb:

Cybers schrieb:

Gibt es sie also doch? ;)

Nur eben nicht bei allen. Siehst du ja auch an obigen Dumps. Die Losnummer, Scheibennummer und X/Y-Position dagegen scheint zumindest schon sehr lange beim Test mit einprogrammiert zu werden. Die habe ich auch schon bei anderen AVRs so gesehen.

Ok, bei dem Dump verstehe ich die Adresse nur nicht so ganz. Jeder Block ist 2 Bytes, aber die zweite Zeile fängt bei 08 an. Wenn ich die Blöck aber durchzähle komme ich auf: 0x000F also 16.

Gast #7313590
Lesenswert?

Da ich gerade nichts anderes zu Hand habe, hatte ich versucht bei einem ATmega32-16PU nur die Signature Bytes auszulesen.

1
void cpu_get_sig(uint8_t *sigarray) //muss 4 Bytes haben
2
{ 
3
  uint8_t tmp;
4
  tmp = SREG;
5
  cli();
6
  SPMCR |= (1<< SPMEN);
7
  sigarray[0] = boot_signature_byte_get(0x0000); //SigByte 1
8
  sigarray[1] = boot_signature_byte_get(0x0002); //SigByte 2
9
  sigarray[2] = boot_signature_byte_get(0x0004); //SigByte 3
10
  sigarray[3] = boot_signature_byte_get(0x0001); //RC Oszillator Byte
11
  SREG = tmp;
12
}

Raus kommt nur irgendein bullshit. Gibt es noch etwas zu beachten. Intern wird die Funktion (bzw. Makro) folgenermaßen umgesetzt:

1
#define boot_signature_byte_get   (       addr  )   \
2
(__extension__({                      \
3
      uint8_t __result;                         \
4
      __asm__ __volatile__                      \
5
      (                                         \
6
        "sts %1, %2\n\t"                        \
7
        "lpm %0, Z" "\n\t"                      \
8
        : "=r" (__result)                       \
9
        : "i" (_SFR_MEM_ADDR(__SPM_REG)),       \
10
          "r" ((uint8_t)(__BOOT_SIGROW_READ)),  \
11
          "z" ((uint16_t)(addr))                \
12
      );                                        \
13
      __result;                                 \
14
}))
Gast #7313603
Lesenswert?

avr schrieb:

und SIGRD setzt!

Ich hatte mich zu früh ans testen gemacht! Beim ATmega32 kann per Firmware die Signature Bytes nicht ausgelesen werden. Das ist nur mit einem Programmer möglich. Bei einem ATmega644P sollte dies aber funktionieren. Dann muss ich wohl eine kleine Bestellung machen. Danach kann ich das erst testen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren