Go Down

Topic: How to change a chip signature? (Read 7314 times) previous topic - next topic

nickgammon

This may be helpful...
http://www.avrfreaks.net/comment/165751#comment-165751
I read that a few times, but couldn't quite see what he was getting at. Plus I think that was a different chip.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Coding Badly


Yeah, that's a bit jumbled.

There is some stuff I can sort-of remember that may have not been in any of the links I found.  My memory works best when there is a concrete goal so ... Are you going to try manipulating the signature bytes of a processor?  Which processor?



Coding Badly

#17
Aug 16, 2015, 12:30 am Last Edit: Aug 16, 2015, 12:35 am by Coding Badly

Ah ha!  I think That post is in reference to the t13 processor / serial high-voltage programming.

His description of how to modify the Chip Erase command lines up with the datasheet...

Quote
To erase the signature and calibration rows, modify your programming software so that bit7 of the first instruction byte of chiperase is set. That is, the sdi/sii pairs
80,CC 00,64 00,6C
By his nomenclature, the Chip Erase command is 80,4C 00,64 00,6C.


nickgammon

#18
Aug 16, 2015, 01:27 am Last Edit: Aug 16, 2015, 01:27 am by Nick Gammon
Let's put it like this. In my HV programmer sketch, this erases the chip:

Code: [Select]
void eraseMemory ()
  {
  HVprogram (ACTION_LOAD_COMMAND, CMD_CHIP_ERASE);

  digitalWrite (WR, LOW);  // pulse WR to erase chip
  digitalWrite (WR, HIGH);
   
  pollUntilReady ();
  clearPage();  // clear temporary page
  }  // end of eraseMemory


Given:

Code: [Select]
// high-voltage programming commands we can send (when action is LOAD_COMMAND)
  enum {
        CMD_CHIP_ERASE       = 0b10000000,
        CMD_WRITE_FUSE_BITS  = 0b01000000,
        CMD_WRITE_LOCK_BITS  = 0b00100000,
        CMD_WRITE_FLASH      = 0b00010000,
        CMD_WRITE_EEPROM     = 0b00010001,
        CMD_READ_SIGNATURE   = 0b00001000,
        CMD_READ_FUSE_BITS   = 0b00000100,
        CMD_READ_FLASH       = 0b00000010,
        CMD_READ_EEPROM      = 0b00000011,
        CMD_NO_OPERATION     = 0b00000000,
        }; // end of commands

  // when XTAL1 is pulsed the settings in XA1 and XA0 control the action
  enum {
       ACTION_LOAD_ADDRESS,
       ACTION_LOAD_DATA,
       ACTION_LOAD_COMMAND,
       ACTION_IDLE
       };    // end of actions



Quote
By his nomenclature, the Chip Erase command is 80,4C 00,64 00,6C.
I can see the 0x80 there (CMD_CHIP_ERASE) but I don't see what the other bytes are.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon

Are you going to try manipulating the signature bytes of a processor?  Which processor?
I read somewhere it couldn't be done, so I want to prove them wrong. ;)

Any reasonable processor that I have to hand and don't mind having to replace, eg. ATmega328P, ATtiny85.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Coding Badly


Well, I just cannot see enough overlap between high voltage parallel programming (the code you posted) and high voltage serial programming (the byte sequences I posted).  I assume the command would be the same (CMD_CHIP_ERASE) and DATA would be something other than 0b10000000.  You could try DATA = 0b01000000.  But that would truly be taking a shot in the dark.

I assume you do not have code for high voltage serial programming (appropriate for ATtiny processors).

I believe I had crossed paths with someone who had used (low voltage) serial programming (ISP) to manipulate the signature bytes.  Does that capture your interest?  I don't have time tonight to continue the search but I should tomorrow.


nickgammon

Quote
I believe I had crossed paths with someone who had used (low voltage) serial programming (ISP) to manipulate the signature bytes.  Does that capture your interest?
Yes, but I can believe that it would be HV programming that lets you do it. Quite possibly the Atmel production line has to put the signatures there somehow.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Paul__B

Quite possibly the Atmel production line has to put the signatures there somehow.
Well, if the die is the same ...

john1993

#23
Aug 16, 2015, 06:01 pm Last Edit: Aug 16, 2015, 06:09 pm by john1993
over the years there have been a couple instances of these being altered by accident but some years back i also changed signature bytes in some tiny on purpose as described in the freaks thread linked above. since it was a scientific experiment and not particularly useful i did not bother to document but similar to that procedure:

Quote from: KKP
This is via the HV programming logic; If someone maps it out on the other methods, I would like to learn too.

To erase the signature and calibration rows, modify your programming software so that bit7 of the first instruction byte of chiperase is set. That is, the sdi/sii pairs
80,CC 00,64 00,6C
Will erase the signature and calibration rows.

Before attempting this, read out ALL 16+16 bytes of signature and calibration. The documentation states that 2 bits in the second pair of read_sig_byte are address bits; This is untrue, there are 4 address bits for T13. Likewise for read_cal_byte, the second pair has 4 address bits.

After you have erased the signature and calibration rows, load the flash programming instruction, followed by 16 words of data as one usually would for programming flash. Then, instead of executing flash_load_high_address_page_program, load
sdi 1xx1 x011 0000 0000 0000 0000
sii 0101 0101 0100 0101 0011 0101
instead (let's call it sig_page_program).
The low bytes end up in signature, the high bytes end up in calibration.

And the calibration value written here IS used after reset. The higher undocumented sig/cal bytes may or may not have interesting control functions :-)

The method employed for this was brute force; I had a program fire off one random sequence after another, checking the chip state after each sequence. It spat out a number of interesting patterns, and I then had to figure out what part of the pattern was significant. Beware: Like the documented keep_eeprom_during_chiperase fuse, there is also an undcumented bit somewhere, 'keep signature rows during chiperase'; During some of my experimentation I managed to erase it on one of my devices and I haven't been able to find it, thus every time I do a normal chiperase the signature of this particular device is erased too.

edit: my bit patterns are given without 0_ and _00 padding.
i was able to alter several different chips but with no real application put little effort into saving the utilities or hardware (couple npn). now wish i did. a friend of mine also managed it but im not sure he still has more details. i will check.


Coding Badly

#24
Aug 16, 2015, 11:11 pm Last Edit: Aug 16, 2015, 11:13 pm by Coding Badly

Some code to go with this thread...
http://www.avrfreaks.net/forum/undocumented-signature-row-contents

Code: [Select]

#include <avr/boot.h>

static char const Nibbles[] =
    {
      '0', '1', '2', '3', '4', '5', '6', '7',
      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };

static void PrintHex1( uint8_t const Value )
{
  Serial.write( Nibbles[(Value >> 4) & 0x0F] );
  Serial.write( Nibbles[(Value >> 0) & 0x0F] );
}

static void PrintHex2( uint16_t const Value )
{
  Serial.write( Nibbles[(Value >> 12) & 0x0F] );
  Serial.write( Nibbles[(Value >>  8) & 0x0F] );
  Serial.write( Nibbles[(Value >>  4) & 0x0F] );
  Serial.write( Nibbles[(Value >>  0) & 0x0F] );
}

void setup()
{
  Serial.begin( 115200 );
 
  Serial.println();
  Serial.print( F( "SPM_PAGESIZE = " ) );
  Serial.print( SPM_PAGESIZE );
  Serial.println();
  Serial.println();

  bool NeedAddress;
  uint16_t NextPage;
  uint16_t NextGap;
  uint16_t NextLine;
  uint16_t Address;
  uint8_t Value;
  char AsChar[17];
  uint8_t i1;
  uint8_t Page;

  NeedAddress = true;
  NextPage = SPM_PAGESIZE;
  NextGap = 8;
  NextLine = 16;
  Address = 0;
  AsChar[16] = 0;
  i1 = 0;
  Page = 0;

  do
  {
    if ( NeedAddress )
    {
      PrintHex2( Address );
      Serial.print( F( "  " ) );
      NeedAddress = false;
    }

    Value = boot_signature_byte_get( Address );

    if ( Value >= 32 && Value <= 127 )
    {
      AsChar[i1] = Value;
    }
    else
    {
      AsChar[i1] = '.';
    }

    ++i1;

    PrintHex1( Value );
   
    Serial.write( ' ' );
   
    ++Address;

    if ( Address >= NextGap )
    {
      Serial.write( ' ' );
      NextGap += 16;
    }

    if ( Address >= NextLine )
    {
      Serial.print( F( "  |" ) );
      Serial.print( AsChar );
      Serial.print( F( "|" ) );
      Serial.println();
      NeedAddress = true;
      NextLine += 16;
      i1 = 0;
    }

    if ( Address >= NextPage )
    {
      Serial.println();
      NextPage += SPM_PAGESIZE;
      ++Page;
    }
  }
  //while ( Address != 0 );
  //while ( Address != SPM_PAGESIZE );
  while ( Page < 3 );
}

void loop()
{
}


The code is uploaded to the target.  It dumps the contents of the target's signature data to Serial.  It is "well tested" in the sense that I ran it on a single Uno and some stuff showed up in Serial Monitor.  At Address = 0xFE00 zeros were read.  At Address = 0xFF70 the code went haywire.  The output wrapped at SPM_PAGESIZE (128).

This sketch (or something like it) could be used to make a backup of the signature data.

This is the dump from my Uno...

Code: [Select]


SPM_PAGESIZE = 128

0000  1E 98 95 FF 0F CD FF 26  FF 0C FF 17 FF FF 55 32   |.......&......U2|
0010  36 33 38 31 FF 04 05 09  17 01 12 05 13 05 FF FF   |6381............|
0020  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 2F 87   |............../.|
0030  8E 56 11 65 63 8F 97 48  03 74 04 10 DA 0B CC 10   |.V.ec..H.t......|
0040  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0050  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0060  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0070  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 5C 1C   |..............\.|

0080  1E 98 95 FF 0F CD FF 26  FF 0C FF 17 FF FF 55 32   |.......&......U2|
0090  36 33 38 31 FF 04 05 09  17 01 12 05 13 05 FF FF   |6381............|
00A0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 2F 87   |............../.|
00B0  8E 56 11 65 63 8F 97 48  03 74 04 10 DA 0B CC 10   |.V.ec..H.t......|
00C0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
00D0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
00E0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
00F0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 5C 1C   |..............\.|

0100  1E 98 95 FF 0F CD FF 26  FF 0C FF 17 FF FF 55 32   |.......&......U2|
0110  36 33 38 31 FF 04 05 09  17 01 12 05 13 05 FF FF   |6381............|
0120  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 2F 87   |............../.|
0130  8E 56 11 65 63 8F 97 48  03 74 04 10 DA 0B CC 10   |.V.ec..H.t......|
0140  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0150  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0160  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0170  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 5C 1C   |..............\.|

nickgammon

Very interesting, thanks! You seem to have forgotten to post the "boot_signature_byte_write" function. :P
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Coding Badly

#26
Aug 16, 2015, 11:43 pm Last Edit: Aug 16, 2015, 11:43 pm by Coding Badly

Ha!  Funny you should mention that.  There is a hint in the m328 datasheet that a boot_signature_byte_write function is possible.

Quote
26.3 Register Description
26.3.1 SPMCSR - Store Program Memory Control and Status Register
Bit 5 - SIGRD: Signature Row Read
...
An SPM instruction within four cycles after SIGRD and SPMEN are set will have no effect.  This operation is reserved for future use and should not be used.
But if it has no effect, why include that second sentence?


john1993

#27
Aug 17, 2015, 03:17 pm Last Edit: Aug 17, 2015, 03:47 pm by john1993
it is trivial to read fuse and signature with lpm. however afaik nobody has proven to alter them with spm or regular spi. some cases using hv programming and many accidentally via vcc or other voltage abuse. i do have two chips here that can only be flashed using -F because of this.

mestek123

Some code to go with this thread...
http://www.avrfreaks.net/forum/undocumented-signature-row-contents

Code: [Select]

#include <avr/boot.h>

static char const Nibbles[] =
    {
      '0', '1', '2', '3', '4', '5', '6', '7',
      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };

static void PrintHex1( uint8_t const Value )
{
  Serial.write( Nibbles[(Value >> 4) & 0x0F] );
  Serial.write( Nibbles[(Value >> 0) & 0x0F] );
}

static void PrintHex2( uint16_t const Value )
{
  Serial.write( Nibbles[(Value >> 12) & 0x0F] );
  Serial.write( Nibbles[(Value >>  8) & 0x0F] );
  Serial.write( Nibbles[(Value >>  4) & 0x0F] );
  Serial.write( Nibbles[(Value >>  0) & 0x0F] );
}

void setup()
{
  Serial.begin( 115200 );
 
  Serial.println();
  Serial.print( F( "SPM_PAGESIZE = " ) );
  Serial.print( SPM_PAGESIZE );
  Serial.println();
  Serial.println();

  bool NeedAddress;
  uint16_t NextPage;
  uint16_t NextGap;
  uint16_t NextLine;
  uint16_t Address;
  uint8_t Value;
  char AsChar[17];
  uint8_t i1;
  uint8_t Page;

  NeedAddress = true;
  NextPage = SPM_PAGESIZE;
  NextGap = 8;
  NextLine = 16;
  Address = 0;
  AsChar[16] = 0;
  i1 = 0;
  Page = 0;

  do
  {
    if ( NeedAddress )
    {
      PrintHex2( Address );
      Serial.print( F( "  " ) );
      NeedAddress = false;
    }

    Value = boot_signature_byte_get( Address );

    if ( Value >= 32 && Value <= 127 )
    {
      AsChar[i1] = Value;
    }
    else
    {
      AsChar[i1] = '.';
    }

    ++i1;

    PrintHex1( Value );
   
    Serial.write( ' ' );
   
    ++Address;

    if ( Address >= NextGap )
    {
      Serial.write( ' ' );
      NextGap += 16;
    }

    if ( Address >= NextLine )
    {
      Serial.print( F( "  |" ) );
      Serial.print( AsChar );
      Serial.print( F( "|" ) );
      Serial.println();
      NeedAddress = true;
      NextLine += 16;
      i1 = 0;
    }

    if ( Address >= NextPage )
    {
      Serial.println();
      NextPage += SPM_PAGESIZE;
      ++Page;
    }
  }
  //while ( Address != 0 );
  //while ( Address != SPM_PAGESIZE );
  while ( Page < 3 );
}

void loop()
{
}


The code is uploaded to the target.  It dumps the contents of the target's signature data to Serial.  It is "well tested" in the sense that I ran it on a single Uno and some stuff showed up in Serial Monitor.  At Address = 0xFE00 zeros were read.  At Address = 0xFF70 the code went haywire.  The output wrapped at SPM_PAGESIZE (128).

This sketch (or something like it) could be used to make a backup of the signature data.

This is the dump from my Uno...

Code: [Select]


SPM_PAGESIZE = 128

0000  1E 98 95 FF 0F CD FF 26  FF 0C FF 17 FF FF 55 32   |.......&......U2|
0010  36 33 38 31 FF 04 05 09  17 01 12 05 13 05 FF FF   |6381............|
0020  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 2F 87   |............../.|
0030  8E 56 11 65 63 8F 97 48  03 74 04 10 DA 0B CC 10   |.V.ec..H.t......|
0040  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0050  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0060  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0070  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 5C 1C   |..............\.|

0080  1E 98 95 FF 0F CD FF 26  FF 0C FF 17 FF FF 55 32   |.......&......U2|
0090  36 33 38 31 FF 04 05 09  17 01 12 05 13 05 FF FF   |6381............|
00A0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 2F 87   |............../.|
00B0  8E 56 11 65 63 8F 97 48  03 74 04 10 DA 0B CC 10   |.V.ec..H.t......|
00C0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
00D0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
00E0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
00F0  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 5C 1C   |..............\.|

0100  1E 98 95 FF 0F CD FF 26  FF 0C FF 17 FF FF 55 32   |.......&......U2|
0110  36 33 38 31 FF 04 05 09  17 01 12 05 13 05 FF FF   |6381............|
0120  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 2F 87   |............../.|
0130  8E 56 11 65 63 8F 97 48  03 74 04 10 DA 0B CC 10   |.V.ec..H.t......|
0140  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0150  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0160  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF FF FF   |................|
0170  FF FF FF FF FF FF FF FF  FF FF FF FF FF FF 5C 1C   |..............\.|


yes i have tested the code and it works

but have u changed signature values in another code or just this for dumping it

nickgammon

I was interested in how to change the signature. I can read it OK.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Go Up