Skip to main content
Visitor II
January 24, 2024
Solved

Algorithm to derive USB-DFU DeviceDescriptor.iSerialNumber from UnigueDeviceID?

  • January 24, 2024
  • 3 replies
  • 2400 views

I have a device with STMF412 processor.

This device has UniqueDeviceID [1F 00 23 00 09 51 37 35 31 37 37 36 ]
- Contents of the register "Unique device ID register: (96 bits) at address UID_BASE 0x1FFF7A10UL

---------------------------------

When I boot into the application (USB-CDC communication was generated in CubeIde)
and I connect the device to the PC, so I read the following DeviceDescriptor for the USB-CDC device

Device Descriptor:
  bcdUSB:                     0x0201
  bDeviceClass:            0x02
  bDeviceSubClass:      0x02
  bDeviceProtocol:        0x00
  bMaxPacketSize0:     0x40 (64)
  idVendor:                    0x0483 (STMicroelectronics)
  idProduct:                   0x5740
  bcdDevice:                 0x0200
  iManufacturer:            0x01 0x0409: "STMicroelectronics"
  iProduct:                     0x02 0x0409: "STM32 Virtual ComPort"
  iSerialNumber:           0x03 0x0409: "365A37503537"
  bNumConfigurations: 0x01

The serial number is calculated in the file usdd_desc.c by the function Get_SerialNum()
static void Get_SerialNum(void)
{
    uint32_t deviceserial0, deviceserial1, deviceserial2;

    deviceserial0 = *(uint32_t *) DEVICE_ID1;       // [1F 00 23 00] 0x0023001F
    deviceserial1 = *(uint32_t *) DEVICE_ID2;       // [09 51 37 35] 0x35375109
    deviceserial2 = *(uint32_t *) DEVICE_ID3;       // [31 37 37 36] 0x36373731

    deviceserial0 += deviceserial2; // 0x0023001F+0x36373731 = 0x365A3750

    if (deviceserial0 != 0)
    {
      IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);   "36 5A 37 50"
      IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); "35 37"
    }
}

---------------------------------

When I boot into DFU
and connect the device to the PC, I read the following DeviceDescriptor for the USB-DFU device

Device Descriptor:
  bcdUSB:                    0x0100
  bDeviceClass:           0x00
  bDeviceSubClass:     0x00
  bDeviceProtocol:        0x00
  bMaxPacketSize0:     0x40 (64)
  idVendor:                    0x0483 (STMicroelectronics)
  idProduct:                   0xDF11
  bcdDevice:                  0x2200
  iManufacturer:             0x01 0x0409: "STMicroelectronics"
  iProduct:                      0x02 0x0409: "STM32 BOOTLOADER"
  iSerialNumber:            0x03 0x0409: "365A375A3537"
  bNumConfigurations:  0x01

---------------

Does anyone know how to derive the DFU-bootloader from the UniqueDeviceID [1F 00 23 00 09 51 37 35 31 37 37 36 ]
that serial number "365A375A3537" ? Which, unlike the CubeIde serial number, has the value "5A" instead of "50"?

( "365A37503537" vs "365A375A3537")

    This topic has been closed for replies.
    Best answer by Tesla DeLorean

    The F411 looks to have an algorithm like you describe. Are you sure you read the UID correctly?

    3 replies

    ST Employee
    January 25, 2024

    I guess the DFU-bootloader uses a bit different Get_SerialNum() implementation than the usdd_desc.c implementation for STM32F412.

    Visitor II
    January 25, 2024

    It is clear to me that DFU-bootloader uses a slightly different implementation of Get_SerialNum() than usdd_desc.c for STM32F412.

    But which one? The source code for the bootloader is not public, so I don't have a chance to see what the function looks like, how the serial number is created.

    But ST should have the source code. It would help me a lot if you could publish the way the serial number is created.

    Graduate II
    January 25, 2024

    The F411 looks to have an algorithm like you describe. Are you sure you read the UID correctly?

    Visitor II
    January 25, 2024

    Yes, I read the UID correctly.
    I tried comparing the serial number in DFU mode and CDC mode for multiple processors and it was different each time

                                              STM32F412VETX STM32F412VETX STM32F412VGT6
    "STM32 BOOTLOADER"  "3547363D3536"   "333FB6473132"   "B837B94C3231"
    "STM32 Virtual ComPort"  "354736333536"   "333FB63D3132"   "B837B9423231"

    Super User
    January 27, 2024

    Looks like the bootloader simply adds 10 to the 2nd byte before converting it to the UCS-2 string. I have no idea what made ST to do that.

    While the bootloader sources are not available, you still can run the bootloader with debugger attached, place a data breakpoint ("watchpoint") to the UniqueID, and single-step in asm to see what happens with it (should be quite straighforward).

    Of course, there's no guarantee for this to remain the same when the bootloader changes - rarely, but they do, if an error is discovered, see versions in AN2606.

    JW

    Graduate II
    January 27, 2024

    I looked at the F411 to hand, and that didn't add the 10, it was the usual computation.

    Can you dump the ROM from 0x1FFF0000..0x1FFF7FFF, and I'll take a look at the binary.

    Thanks, -Clive