How to obtain and use the STM32 96-bit UID
- January 30, 2024
- 8 replies
- 34715 views
Introduction
Some STM32 MCUs embed two unique identifiers: a unique 96-bit unique identifier and device ID. This article shows how to both obtain these values in your code, and describe some possible use cases for them.
1. 96-bit unique ID
This 96-bit UID is unique for every STM32 ever made. These 96-bit unique IDs are created as a combination of unique fabrication parameters:
- UID[31:0]: X and Y coordinates on the wafer expressed in BCD format
- UID[63:40]: LOT_NUM[23:0] Lot number (ASCII encoded)
- UID[39:32]: WAF_NUM[7:0] Wafer number (8-bit unsigned number)
- UID[95:64]: LOT_NUM[55:24] Lot number (ASCII encoded)
It is common to use this UID as a serial number or as a key for secure applications.
2. Obtaining the UID
The HAL libraries provide a way to read the three words of the 96-bit UID.
uint32_t uid[3];
uid[0] = HAL_GetUIDw0();
uid[1] = HAL_GetUIDw1();
uid[2] = HAL_GetUIDw2();
If you are not using HAL, then the CMSIS device header provides a definition for the address of the UID. Even without HAL, you have a uniform way to obtain the UID.
uint32_t uid[3];
uid[0] = *(uint32_t *)UID_BASE;
uid[1] = *(uint32_t *)(UID_BASE + 4);
uid[2] = *(uint32_t *)(UID_BASE + 8);
As a validation, you can check the 2nd and 3rd bytes of the UID, which are mostly ascii encoded. Reading these values as bytes, you should be able to see the ascii encoding of the lot numbers:
uint8_t lot1[4];
uint8_t lot2[4];
uint8_t *ptr;
ptr = (uint8_t *)&uid[1];
for (uint8_t i = 0; i < 4; i++) {
lot1[i] = ptr[i];
}
ptr = (uint8_t *)&uid[2];
for (uint8_t i = 0; i < 4; i++) {
lot2[i] = ptr[i];
}

2.1 STM32H5 specific issue
When trying to read the UID for the H5, you will run into a hard fault if you have ICACHE enabled. Furthermore, if you have not set up an MPU region for the address of the UID. Unlike other STM32, the UID address is located in the range of the USER flash.
#define UID_BASE (0x08FFF800UL) /*!< Unique device ID register base address */
According to the reference manuals RM0492 and RM0481 section 7.3.2: "By default, all the AHB memory range is cacheable. For regions where caching is not practical (OTP, RO, data area), MPU must be used to disable local cacheability." Since the above address is in the AHB memory range, it is necessary to create an MPU region to remove the cacheability of this region. The screenshots below are the STM32CubeMX configuration of the MPU:
- Start by creating new Attributes Settings:
- Configure the Parameters Settings - start by setting the Region Limit Address to 0x08FFFFFF and then configure the Region Base Address to 0x08FFF800:

- Upon code generation, the MPU_Config() looks like this:
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
MPU_Attributes_InitTypeDef MPU_AttributesInit = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region 0 and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x08FFF800;
MPU_InitStruct.LimitAddress = 0x08FFFFFF;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RO;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Attribute 0 and the memory to be protected
*/
MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER0;
MPU_AttributesInit.Attributes = MPU_DEVICE_nGnRnE;
HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
Conclusion
Using either the HAL libraries or standard CMSIS definitions, in most cases it is simple to obtain the STM32's 96-bit unique identifier. The ID is guaranteed to be unique for all STM32, so it is useful for applications that need a serial number for a product, or need a key that can be used for security applications. If you run into a hard fault while trying to obtain the UID on devices with ICACHE, be sure to check the reference manual for your particular STM32 to see if you need to configure the MPU to disable cacheability for the memory address containing the UID.
Related links
Reference manual RM0492: STM32H503 line Arm®-based 32-bit MCUs
Reference manual RM0481: STM32H563/H573 and STM32H562 Arm®-based 32-bit MCUs