how to read atmega 32 signature row?

5.6k views Asked by At

I tried to read signature row of atmega32 with boot_signature_byte_get(0); but i get this error : 'SIGRD' undeclared (first use in this function) and it seems that it's because of we only can read the signature with the AVRs that have SIGRD bit in SPMCR (i suppose!).
Is this right? and so then how can i read signature row another way?

4

There are 4 answers

2
Toribio On BEST ANSWER

Back in 2007, there was no function in any header to read the signature byte, then it was introduced in the same year. But as it seems, it still has some problems with that.

The datasheet says:

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.

Meaning that the ATMEGA32 has read-access to this byte. Also in the datasheet, it specifies how to read this byte. And in most of their MCUs, it's read in the same way, but for some reason, the SIGRD definition number is missing in some header files, including the ATMEGA32 one.

But, as a workaround, we can define SIGRD manually. We just have to known its value. When I do some findstr (or grep) in the header files searching this definition, unanimously, its value is 5.

So, the workaround would be:

#define SIGRD 5
#include <avr/boot.h>

I compiled this successfully, but I've just tried to test the program on a simulation software, as I don't have the ATMEGA32 with me right now. It returns a byte, so now it's up to you to known if this is the correct byte...

Regarding the SPMCR thing you said, it seems that the signature row is in another address space (by my understanding, I don't know if this is right I can't confirm), and the way to get it, is using some instructions, similarly when we upload some program to the MCU.

0
martinharnevie On

The SIGRD exists and can be used in the ATmega164A/164PA/324A/324PA/644A/644PA/1284/1284P processors. The "reserved for future use" remark only applies to SPM instruction for anything else than the five lowest bits of SPMCSR, see page 285, section 26.9.1.

0
Steve H. On

I believe that the atmega32 does not support reading the signature bytes within the user program.

The atmega32 Datasheet reveales that this device has no bit called SIGRD in its register SPMCR, the fifth bit of this register is reserved and marked as read only.

The atmega640/1280/2560 processors have a similar register called spmcSr that has this bit SIGRD (Bit 5). But the datasheet explains that this Bit should not be used since this operation is reserved for future use (Nonetheless, the procedure for reading the signature is explained there).

Your compiler works correctly since the atmega32 does not have this SIGRD bit.

0
finnan On

I'd like to enhance a bit and illustrate Flávio's answer as I faced the same problem tonight.

so then how can i read signature row another way?

Flávio's workaround does the job well:

#define SIGRD 5
#include <avr/boot.h>

void read_signature_row(uint8_t sr[3])
{
  sr[0] = boot_signature_byte_get(0x0000);
  sr[1] = boot_signature_byte_get(0x0002);
  sr[2] = boot_signature_byte_get(0x0004);
}

void setup()
{
  Serial.begin(9600);
  delay(100);

  uint8_t sr[3] = {0xcc, 0xcc, 0xcc};
  read_signature_row(sr);

  char buff[100];
  snprintf(buff, sizeof buff, "Device signature: %02X %02X %02X", sr[0], sr[1], sr[2]);
  Serial.println(buff);
}

void loop()
{}

I don't have ATmega32, although this method retrieves correct signatures for my ATmega328P (1E 95 0F) and ATmega168PA (1E 94 0B).

it seems that it's because of we only can read the signature with the AVRs that have SIGRD bit in SPMCR (i suppose!). Is this right?

No, it actually sets SIGRD to SPMCR prior to call LPM as seen at avr/boot.h:

#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
#define boot_signature_byte_get(addr) \
(__extension__({                      \
      uint8_t __result;                         \
      __asm__ __volatile__                      \
      (                                         \
        "sts %1, %2\n\t"                        \
        "lpm %0, Z" "\n\t"                      \
        : "=r" (__result)                       \
        : "i" (_SFR_MEM_ADDR(__SPM_REG)),       \
          "r" ((uint8_t)(__BOOT_SIGROW_READ)),  \
          "z" ((uint16_t)(addr))                \
      );                                        \
      __result;                                 \
}))