STM32 parts, in all families, have a “Device Electronic Signature” block, which contains a Unique Device ID register of 96 bits. It’s burnt in to the part during manufacture, and is guaranteed to be unique for any device in any context
Now, 96 bits is fairly large, and in one application of mine, I need an 8 bit number that reliably varies between devices, and also a 48bit serial number. (Like a MAC address, or EUI48) The canonical way of doing this is to hash the large value to get a small value. I was hoping to use 48 bits of the unique id as “unique enough”
ST doesn’t provide much/any information about what goes into this 96 bit number, but there’s internet rumours that it includes things like wafer x,y position, manufacturing datecodes and so on. If I want something that reliably varies, I need to know a little bit more. I don’t have anything really conclusive, but it looks like I really will have to hash the unique id. Here’s the unique id bits from three STM32F100C8 parts purchased from mouser in the same lot. (Can’t find the order date right now)
device | uniqueid[95:64] | uniqueid[63:32] | uniqueid[31:0] |
---|---|---|---|
STM32F100C8-A | 0x43023307 | 0x36314732 | 0x06E30030 |
STM32F100C8-B | 0x43022507 | 0x36314732 | 0x06CF0030 |
STM32F100C8-C | 0x43022407 | 0x36314732 | 0x06D10030 |
STM32F100RB (STM32VL Discovery board) | 0x43172128 | 0x30345532 | 0x06B30036 |
On the STM32F0 datasheet, the bits are actually described, and there’s no real reason to assume that it ever changed. They list bits 95:64 as LOT_NUM[55:24], bits 63:40 as LOT_NUM[23:0], bits 39:32 as WAF_NUM[7:0] and bits 31:0 as X and Y coordinates on the wafer expressed in BCD format. That would imply that my three parts in the same box came from the same wafter, but different lot numbers. So, well, maybe it was a different scheme for the F1 :)
Looks like I’ll be hashing anyway then :)
Hi,
is there specific instructions you used to read the unique-IDs? could you kindly show me how could I read my STM32L unique-id in C?
Thank you!
Andrea
It’s just like reading any other register.
IDcode = DBGMCU->IDCODE;
Reference manual : Unique device ID register (96 bits)
uint32_t Unique_ID_Low;
uint32_t Unique_ID_Mid;
uint32_t Unique_ID_Hig;
uint32_t flash_read(uint32_t address)
{
return (*(__IO uint32_t*) address);
}
uint32_t Ret_Unique_ID (void)
{
FLASH_Unlock();
Unique_ID_Low = flash_read(0x1FFF7A10);
Unique_ID_Mid = flash_read(0x1FFF7A10 + 0x04);
Unique_ID_Hig = flash_read(0x1FFF7A10 + 0x08);
FLASH_Lock();
}
uint16_t Ret_Flash_Size (void)
{
return (flash_read(0x1FFF7A22));
}
Thanks for the tip! I later discovered this in stm32f0xx_ll_utils.h:
/**
* @brief Get Word0 of the unique device identifier (UID based on 96 bits)
* @retval UID[31:0]: X and Y coordinates on the wafer expressed in BCD format
*/
__STATIC_INLINE uint32_t LL_GetUID_Word0(void)
{
return (uint32_t)(READ_REG(*((uint32_t *)UID_BASE_ADDRESS)));
}
/**
* @brief Get Word1 of the unique device identifier (UID based on 96 bits)
* @retval UID[63:32]: Wafer number (UID[39:32]) & LOT_NUM[23:0] (UID[63:40])
*/
__STATIC_INLINE uint32_t LL_GetUID_Word1(void)
{
return (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE_ADDRESS + 4U))));
}
/**
* @brief Get Word2 of the unique device identifier (UID based on 96 bits)
* @retval UID[95:64]: Lot number (ASCII encoded) – LOT_NUM[55:24]
*/
__STATIC_INLINE uint32_t LL_GetUID_Word2(void)
{
return (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE_ADDRESS + 8U))));
}
/**
* @brief Get Flash memory size
* @note This bitfield indicates the size of the device Flash memory expressed in
* Kbytes. As an example, 0x040 corresponds to 64 Kbytes.
* @retval FLASH_SIZE[15:0]: Flash memory size
*/
__STATIC_INLINE uint32_t LL_GetFlashSize(void)
{
return (uint16_t)(READ_REG(*((uint32_t *)FLASHSIZE_BASE_ADDRESS)));
}
Alastair, yes, that’s what I said. The bits are defined for F0. They are _not_ defined for F1.
Have you come to a conclusion about this unique ID? I’m searching for some documentation about it for the stm32f334r8