Unique device ID (and flash size)

RogerClark
Wed May 27, 2015 1:02 am
Guys,

This code may be useful to someone .

Its possible to read the size of the Flash memory and more interestly a unique device ID

void setup() {
Serial.begin(115200);
}

void loop() {
uint16 *flashSize = (uint16 *) (0x1FFFF7E0);
uint16 *idBase0 = (uint16 *) (0x1FFFF7E8);
uint16 *idBase1 = (uint16 *) (0x1FFFF7E8+0x02);
uint32 *idBase2 = (uint32 *) (0x1FFFF7E8+0x04);
uint32 *idBase3 = (uint32 *) (0x1FFFF7E8+0x08);

Serial.print("Flash size is ");
Serial.print(*flashSize );
Serial.println("k");

Serial.print("Unique ID is ");
Serial.print(*(idBase0),HEX);
Serial.print(*(idBase1),HEX);
Serial.print(*(idBase2),HEX);
Serial.println(*(idBase3),HEX);

delay(500);
}


keshavadk
Mon Jul 25, 2016 7:00 am
Can i know why device ID starts from address 0x1FFFF7E8 and why it should be incremented with 2 for four times. like 0x1FFFF7E8+0x02, 0x1FFFF7E8+0x04, 0x1FFFF7E8+0x04
0x1FFFF7E8+0x08

RogerClark
Mon Jul 25, 2016 7:36 am
Everything is normally documented in the STM32F103 reference manual RM0008 page 1079

(Google for it)

Unique device ID register (96 bits)

You probably could read this as three 32 bit reads,. I’m not sure why the example code read the first register in two 16 bit chunks
However, the reference manual says it can be read in single bytes or 16 bits at a time if required.


madias
Mon Jul 25, 2016 12:31 pm
Hm. My first thinking about an unique ID is setting up a NRF24L01 network and every node is the ID, so you wont have to think about different node names. I just hope that “our” STM32F01 are really *unique* and not chinese clones with the same ID :)

ahull
Mon Jul 25, 2016 12:33 pm
madias wrote:Hm. My first thinking about an unique ID is setting up a NRF24L01 network and every node is the ID, so you wont have to think about different node names. I just hope that “our” STM32F01 are really *unique* and not chinese clones with the same ID :)

RogerClark
Mon Jul 25, 2016 9:43 pm
Andy

I agree, those registers are probably writable, but you would need to know what other registers to access in order to make them writable. They are likely just to be a private block of Flash that may also contain other info that its not accessible outside of the MCU.

The MCU must have special blocks of flash to hold the internal bootloader, though I suppose those could be part of the die; But if I was designing a MCU with its own internal SW, I would be very tempted to put that code in some private flash.

Of course that would mean each chip needs to be flashed, but I presume each chip needs to have its ID set, unless it has some magic first run code that samples environmental data to generate the ID – and that sounds fraught with problems unless the device contains a dedicated random number generator based on a noisy resistor etc


zmemw16
Mon Jul 25, 2016 9:52 pm
couldn’t you just do it at the wafer level?
if they can generate programmed eprom/efuse then a serial number can’t a problem.

srp


ahull
Mon Jul 25, 2016 10:01 pm
The unique ID is probably programmed during the testing phase. After all, all of the other elements of the system need tested (ram, flash, peripherals etc.) so an additional routine to set a serial number would not significantly impact on the testing time.

RogerClark
Mon Jul 25, 2016 11:02 pm
ahull wrote:The unique ID is probably programmed during the testing phase. After all, all of the other elements of the system need tested (ram, flash, peripherals etc.) so an additional routine to set a serial number would not significantly impact on the testing time.

ahull
Tue Jul 26, 2016 7:09 am
RogerClark wrote:ahull wrote:The unique ID is probably programmed during the testing phase. After all, all of the other elements of the system need tested (ram, flash, peripherals etc.) so an additional routine to set a serial number would not significantly impact on the testing time.

simonf
Tue Jul 26, 2016 4:52 pm
madias wrote:Hm. My first thinking about an unique ID is setting up a NRF24L01 network and every node is the ID, so you wont have to think about different node names. I just hope that “our” STM32F01 are really *unique* and not chinese clones with the same ID :)

alexandros
Sat Oct 07, 2017 9:26 pm
can the unique device ID be changed programmatically? i mean replaced-overwritten

martinayotte
Sun Oct 08, 2017 2:30 pm
Nope !

alexandros
Sun Oct 08, 2017 10:10 pm
Great!

victor_pv
Sun Oct 08, 2017 11:43 pm
If I remember right there is some write once bytes, so you can program your own ID.
Can’t remember it for certain though.

dannyf
Mon Oct 09, 2017 11:58 am
I use a macro to do it all:

#define U_ID ((const unsigned short *) 0x1FFFF7E8) //U_ID95..0, referenced via U_ID[0], ..., U_ID[5]


alexandros
Sat Oct 14, 2017 11:02 am
Hey Good day to ya all

Id like to ask something about the flashSize of STM32F103CB
based on the demo code Roger Provided in first post , i got a size of 64K Flash

Now the funny part.
(i set into the arduino IDE variant:STM43F103CB 64K as i should)

I got a sketch that uses 97% of Flash size. , i pushed some extra nonse code to get to the maximum size so i got this beautiful msg
region `rom’ overflowed by 5604 bytes

SO i changed the arduino IDE variant:STM32F103CB FROM 64K TO 128K and i gave it a shot
And it worked. :shock: :shock: :o

I also test it with a very large Array with values that checked one by one in a loop and returned me the correct results..

The question is : Is this normal dehavior? does the chip include 128K flash ?? and why i got 64K from the demo code?


dannyf
Sat Oct 14, 2017 1:42 pm
This has been discussed to the nth degree. Many of those chips have more flash, more eeprom, more features than those specified in the datasheet and by the on device registers.

It is normal in that they are wide spread. It is not normal in that they are not in compliance with the datasheet.


victor_pv
Sat Oct 14, 2017 7:03 pm
In fact if the MCU is “STM32F103CB” as you wrote, that should have 128KB according to the specs.
The STM32F103C8 (note is a number 8 not upper case b) is supposed to have only 64KB.

So if you have a CB with 128KB, you are exactly within specs.
If you have a C8 with 128Kb, then as Dannyf pointed is common.


Alois
Thu Mar 29, 2018 5:40 pm
[keshavadk – Mon Jul 25, 2016 7:00 am] –
Can i know why device ID starts from address 0x1FFFF7E8 and why it should be incremented with 2 for four times. like 0x1FFFF7E8+0x02, 0x1FFFF7E8+0x04, 0x1FFFF7E8+0x04
0x1FFFF7E8+0x08

I compared the serial number of a ST-Link clone based on STM32F103C8T6 and the Unique ID.
The Unique ID is FF4966E5549896667164724 and the ST-Link serial number is 49FF6E066689495524471667.
It’s the same number but in a another format.

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}

void PrintHex8(uint8_t data) // prints 8-bit data in hex with leading zeroes
{
if (data < 0x10) {
Serial.print("0");
}
Serial.print(data, HEX);
}

void loop() {
// put your main code here, to run repeatedly:
uint16 *flashSize = (uint16 *) (0x1FFFF7E0);
uint16 *idBase0 = (uint16 *) (0x1FFFF7E8);
uint16 *idBase1 = (uint16 *) (0x1FFFF7E8 + 0x02);
uint32 *idBase2 = (uint32 *) (0x1FFFF7E8 + 0x04);
uint32 *idBase3 = (uint32 *) (0x1FFFF7E8 + 0x08);

Serial.print("Flash size is ");
Serial.print(*flashSize );
Serial.println("k");

Serial.print("Unique ID is ");
Serial.print(*(idBase0), HEX);
Serial.print(*(idBase1), HEX);
Serial.print(*(idBase2), HEX);
Serial.println(*(idBase3), HEX);

Serial.print("Device ID is ");
byte* bytes = (byte*) idBase0;
for (int i = 0; i < 12; i++) {
PrintHex8(bytes[i]);
}
Serial.print(" -> ");
for (int i = 0; i < 11; i++) {
PrintHex8(bytes[i]);
Serial.print("-");
}
PrintHex8(bytes[11]);
Serial.println();

Serial.println();
delay(5000);
}


zoomx
Fri Mar 30, 2018 5:34 pm
It seems that every couple of bytes are swapped.

victor_pv
Fri Mar 30, 2018 10:32 pm
I bet one of them is read byte by byte, and the other as uint16_t and uint32_t so due to the endianness, the first two pairs are swapped, and then the next two groups or four are swapped.
And to swap the bytes you can use the arm REV instruction. Now, I didn’t know there is a built in for REV, but just checked if there was a built in, and apparently there is:

Serial.print("Unique ID is ");
Serial.print(__builtin_bswap16(*(idBase0)), HEX);
Serial.print(__builtin_bswap16(*(idBase1)), HEX);
Serial.print(__builtin_bswap32(*(idBase2)), HEX);
Serial.println(__builtin_bswap32(*(idBase3)), HEX);


efftek
Sat Aug 25, 2018 5:05 pm
I’m wanting several modules connecting to my pc via Ethernet. Although I won’t be using the MAC address, I still have to create one. Could I possibly use 48 bytes from this ID number as a MAC address rather than having to invent them? I know I’d still have to assign individual ip addresses.

Cheers Steve.


MoDu
Thu Aug 30, 2018 11:01 am
Yes, especially if you hash the Id in a consistent fashion which outputs your required number of digits for the MAC.

efftek
Sat Sep 01, 2018 8:21 pm
I have found that I can use the ID number as a mac providing I set the first byte to something like 0xEA. If I dont, then it doesnt work.

This is my code
#include <Ethernet_STM32.h>
#include <SPI.h>

byte *id5 = (byte *) (0x1FFFF7EC);
byte *id4 = (byte *) (0x1FFFF7EC+0x01);
byte *id3 = (byte *) (0x1FFFF7EC+0x02);
byte *id2 = (byte *) (0x1FFFF7EC+0x03);
byte *id1 = (byte *) (0x1FFFF7EC+0x04);
byte mac[] = { 0xEA, *id1, *id2, *id3, *id4, *id5 };

unsigned int localPort = 5000;
EthernetServer server(localPort);
SPIClass mSpi(2); //USING SPI2 PB12-PB15

void setup()
{
Serial.begin(115200);
delay(1000);
Ethernet.init(mSpi, PB12);
Ethernet.begin(mac);
Serial.print("IP Address assigned ");
Serial.println(Ethernet.localIP());

Serial.print("MAC assigned ");
for(int i=0; i<5; i++)
{
Serial.print(mac[i], HEX);
Serial.print("-");
}
Serial.println(mac[5], HEX);
server.begin();
}


Leave a Reply

Your email address will not be published. Required fields are marked *