How to read the ATMEL unique ID

i was checking the data sheet to see if there is any unique id which i can use to identify the different boards
at the data sheet
SAM Cortex M3 datasheet

i found at page 39

9.1.3.7 Unique Identifier
Each device integrates its own 128-bit unique identifier. These bits are factory configured and
cannot be changed by the user. The ERASE pin has no effect on the unique identifier.

i also found this

Unique identifier example

but how can i read it. from my code.

Kind regards

Johan Lieshout

Maybe this link helps? https://github.com/emagii/at91sam3s/blob/master/examples/eefc_uniqueid/main.c

Yes sort of. I can read it. but i want to read it in a ino

because my complete project is in a ino and i cannot import the asf librarys

This seems to work - well its reading something.

__attribute__ ((section (".ramfunc")))
void _EEFC_ReadUniqueID( unsigned int * pdwUniqueID )
{
    unsigned int status ;
  
    /* Send the Start Read unique Identifier command (STUI) by writing the Flash Command Register with the STUI command.*/
    EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
    do
    {
        status = EFC1->EEFC_FSR ;
    } while ( (status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY ) ;

    /* The Unique Identifier is located in the first 128 bits of the Flash memory mapping. So, at the address 0x400000-0x400003. */
    pdwUniqueID[0] = *(uint32_t *)IFLASH1_ADDR;
    pdwUniqueID[1] = *(uint32_t *)(IFLASH1_ADDR + 4);
    pdwUniqueID[2] = *(uint32_t *)(IFLASH1_ADDR + 8);
    pdwUniqueID[3] = *(uint32_t *)(IFLASH1_ADDR + 12);

    /* To stop the Unique Identifier mode, the user needs to send the Stop Read unique Identifier
       command (SPUI) by writing the Flash Command Register with the SPUI command. */
    EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI ;

    /* When the Stop read Unique Unique Identifier command (SPUI) has been performed, the
       FRDY bit in the Flash Programming Status Register (EEFC_FSR) rises. */
    do
    {
        status = EFC1->EEFC_FSR ;
    } while ( (status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
}

void setup ()
{
    Serial.begin (57600) ;

    unsigned int adwUniqueID[5] ;
    WDT_Disable( WDT ) ;

    Serial.println("Reading 128 bits unique identifier \n\r" ) ;
    _EEFC_ReadUniqueID( adwUniqueID ) ;

    Serial.print ("ID: ") ;
    for (byte b = 0 ; b < 4 ; b++)
      Serial.print ((unsigned int) adwUniqueID [b], HEX) ;
    Serial.println () ;
}



void loop() {
  // put your main code here, to run repeatedly:

}

I had to select EFC1, as EFC0 doesn’t seem to work, ditto IFLASH1_ADDR.

I note the result is ASCII, which is encouraging (not machine code), but I don’t
know how to interpret it (endianness).

My Due gives:

Reading 128 bits unique identifier 


ID: 52323020333034373130312037323039

Thanx Mark,

I just figured it out myself.
Funny to see the differences in our solution with the same result.

#define FLASH_ACCESS_MODE_128    0
#define EFC       (0x400E0A00U)

uint32_t ul_rc;
	uint32_t unique_id[4];

typedef enum flash_rc {
	FLASH_RC_OK = 0,        //!< Operation OK
	FLASH_RC_YES = 1,       //!< Yes
	FLASH_RC_NO = 0,        //!< No
	FLASH_RC_ERROR = 0x10,  //!< General error
	FLASH_RC_INVALID,       //!< Invalid argument input
	FLASH_RC_NOT_SUPPORT = 0xFFFFFFFF    //!< Operation is not supported
} flash_rc_t;
typedef unsigned long UL;
void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
Serial.println(" Arduino IDE" );
ul_rc = efc_init(EFC, FLASH_ACCESS_MODE_128, 4);
if (ul_rc != 0) {
Serial.println(" FOUT" );
	}

Serial.println("-I- Reading 128 bits Unique Identifier\r");
ul_rc = flash_read_unique_id(unique_id, 4);

Serial.print(" ID = " );
Serial.print((UL)unique_id[0]);Serial.print(",");
Serial.print((UL)unique_id[1]);Serial.print(",");
Serial.print((UL)unique_id[2]);Serial.print(",");
Serial.println((UL)unique_id[3]);


}
void loop() {
  // put your main code here, to run repeatedly:

}

uint32_t flash_read_unique_id(uint32_t *pul_data, uint32_t ul_size)
{
	uint32_t uid_buf[4];
	uint32_t ul_idx;

	if (FLASH_RC_OK != efc_perform_read_sequence(EFC, EFC_FCMD_STUI,
			EFC_FCMD_SPUI, uid_buf, 4)) {
		return FLASH_RC_ERROR;
	}

	if (ul_size > 4) {
		/* Only 4 dword to store unique ID */
		ul_size = 4;
	}

	for (ul_idx = 0; ul_idx < ul_size; ul_idx++) {
		pul_data[ul_idx] = uid_buf[ul_idx];
	}

	return FLASH_RC_OK;
}

MarkT: My Due gives:

Reading 128 bits unique identifier 

ID: 52323020333034373130312037323039

That looks consistent with values I have seen elsewhere, the OpenOCD debugger prints out the ID.

Do you need to disable interrupts while reading the ID, if the Flash is "offline" so to speak?

Does anyone know if the unique ID has a standard format? mine reads " 1 D8FPN 8011030\030\070" so it appears to be ASCII, I would like to shorten this to a 8-10 byte string and was keen to know which part changes within this family as I expect it is grouped by processor / family ect and think only part will change for other SAM3S chips.

i Have two applications dedicated with approaved due's so i don't run the wrong code on the wrong due's and some are approaved in both because they are not connected.

unsigned int uid1[]={1395798304,1395798304,1379021088,1395798304,1395798304,1395798304,1379021088}; unsigned int uid2[]={959920181,825504566,892745783,825504566,825504566,925905974,892745783}; unsigned int uid3[]={825243680,825241905,808466865,842019378,842019378,842019616,825243953}; unsigned int uid4[]={2956013625,892350517,892481590,858796080,858796080,959459382,942813237};

unsigned int uid1[] = {1379021088,1395798304, 1379021088, 1379021088, 1395798304, 1395798304,1379021088}; unsigned int uid2[] = {892745783,825504566, 892745783, 892745783, 925905974, 825504566,423179575}; unsigned int uid3[] = {825242930,842019378, 808466865, 825243953, 825242912, 825241905,825242417}; unsigned int uid4[] = {842084406,858796080, 892481590, 942813237, 842018868, 892350517,892481590};