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);
}
0x1FFFF7E8+0x08
(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.
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
if they can generate programmed eprom/efuse then a serial number can’t a problem.
srp
Can’t remember it for certain though.
#define U_ID ((const unsigned short *) 0x1FFFF7E8) //U_ID95..0, referenced via U_ID[0], ..., U_ID[5]
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.
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?
It is normal in that they are wide spread. It is not normal in that they are not in compliance with the datasheet.
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.
[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);
}
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);
Cheers Steve.
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();
}

