STM32CubeProgrammer OTP management

Applicable for STM32MP13x lines, STM32MP15x lines

STM32CubeProgrammer can be used to read and update the OTP of the device, which is seen as a partition on the device.

This page describes the format of the partition used by the embedded programming service to allow OTP access by STM32CubeProgrammer (see AN5275: USB DFU/USART protocols used in STM32MP1 Series bootloaders for protocol details).

Refer to STM32CubeProgrammer article to know how to use the STM32CubeProgrammer that is the official STMicroelectronics tool for update OTP on STM32 platforms.

1 OTP partition[edit]

The OTP partition is identified with the reserved Id 0xF2 and is exported as:

  • a specific alternate setting of the USB DFU [1].
  • a special operation: OTP write (0xF2), for UART download command (0x31) and read partition command (0x12)

This is used to access the STM32MP's on-chip one time-programmable memory by the ST32CubeProgrammer (see option -otp). It is only supported in the embedded programming service = U-Boot.

The OTP partition must be programmed without a header and have a fixed size following the structure described in chapter #Data Structure.

1.1 Access operation[edit]

For read operation, the host requests the OTP partition data, and the platform replies with all the partition content.

For write operation, the host needs to send the full structure containing one or more modifications. The platform analyses each field . First the OTP values are updated, then the OTP controls (such as lock) are updated.

After any write operation, a read must be done to update the Host information.

1.2 Data structure[edit]

The data structure version 2 is described in the table below.

For ecosystem release ≥ v4.0.0 More info.png , the same structure is used for

  • OP-TEE support with the provisioning TA
  • TF-A support with SMC when OP-TEE is not used.

The previous data structure version 1 is no more used.

Its size is 776 bytes with 96 OTP for STM32MP1 Series = (2 * 96 + 2) * 4 bytes for 32 bits word, with M = 0 to 95:

Word Field name Description
0 Version Version of this structure = 2
1 Global State bit-field with state of BSEC the OTP provider[GlobalState 1]
2 OTP[0] OTP value
  • 0x0 on read error or read lock
  • 0x0 to write with unmodified value (lock only)
3 OTP[0] status Status of OTP:
  • [0]: 1 bit read error detected: 1 = OTP value isn't valid
  • [26]: 1 bit lock error
  • [27]: 1 bit sticky programming lock
  • [28]: 1 bit shadow write sticky lock
  • [29]: 1 bit shadow read sticky lock
  • [30]: 1 bit permanent write lock
  • [31]: 1 bit prog requested an update of this OTP, value and/or status (only for write, always 0 on read)
4 OTP[1] OTP value
5 OTP[1] status Status of OTP
... ... ...
2+M*2 OTP[M] Value of OTP M
3+M*2 OTP[M] status Status of OTP M
  1. Global state: is not used during a write operation, its value should be 0 for write request
  2. Provisioning = OTP-SECURED open_device BSEC state, the secrets are not provisioned (see Life cycle for detail).
  3. Secured = OTP-SECURED closed_device BSEC state, the secrets are provisioned and protected (see Life cycle for detail).
  4. Hardware Key set bit indicates the provisioned firmware encryption key for STM32MP13x lines Warning.png, not used for STM32MP15x lines More info.png
  5. Encrypted data bit is reserved to indicate an encrypted content of OTP for read or write operation, not yet implemented.

You can write OTP without read operation by using a buffer initialized with 0x0, except the version word set to 0x2.

You can also read the current value of the OTP in a buffer and reuse the same buffer for the write operation, as bit 31 of OTP status is 0 for read.

To update an OTP, you need to update the used buffer for the modified OTP:

  • the OTP value, set at 0x0 if unmodified for lock only operation
  • the OTP status lock values for prog lock and/or read lock after OTP value update, set to 0x0 if unmodified
  • request the update: set the bit 31 of the OTP status to indicate a modification request of this OTP

The operation is interrupted on the first error.

1.2.1 Examples[edit]

With OTP[0] status bit-field values:

  • programmation request: bit31 => 0x80000000
  • permanent lock: bit 30 => 0x40000000

Some simple operations are, with the structure full of zero except:

  • write X in OTP_N
    • OTP[N] value = X
    • OTP[N] status = 0x80000000
  • prog lock OTP N
    • OTP[N] value = 0x0
    • OTP[N] status = 0xC0000000
  • write and lock OTP N
    • OTP[N] value = X
    • OTP[N] status = 0xC0000000
  • write value and sticky read+permanent lock for OTP N to N+2
    • OTP[N] value = X
    • OTP[N] status = 0xE0000000
    • OTP[N + 1] value = Y
    • OTP[N + 1] status = 0xE0000000
    • OTP[N + 2] value = Z
    • OTP[N + 2] status = 0xE0000000

2 Reference list[edit]