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 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 source]
The OTP partition is identified by the reserved Id 0xF2 and is exported as a specific alternate setting of the USB DFU [1].
This is used to access the STM32MP's on-chip one time programmable memory, and is only supported in U-Boot.
The OTP partition must be programmed without a header and must have a fixed size of 1024 bytes = 256 words (32 bits), following the structure described in chapter #Data Structure.
1.1. Access operation[edit source]
For read operation, the host requests the OTP partition data, and the platform replies with all the partition content (1024 bytes).
For write operation, the host needs to send the full structure containing one or more modifications. Each field is analyzed by the platform. 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.1. Data structure[edit source]
1.1.1. Version 1[edit source]
The data structure for the STM32MP15x Series based on TF-A SMC is described in the table below.
Access can be RWS = Read / Write / Sticky
Word | Field name | Description | RWS |
---|---|---|---|
0 | Version | Version of this structure = 1 | R |
1 | Configuration |
|
RW |
2 | Reserved | ||
3 | Status |
|
R |
4 | General Lock conf |
|
RWS |
5 | Debug conf |
|
RW |
6 | Reserved | ||
7 | Reserved | ||
8 | Disturbed status 1 |
|
R |
9 | Disturbed status 2 |
|
R |
10 | Disturbed status 3 |
|
R |
11 | Reserved | ||
12 | Reserved | ||
13 | Reserved | ||
14 | Error status 1 |
|
R |
15 | Error status 2 |
|
R |
16 | Error status 3 |
|
R |
17 | Reserved | ||
18 | Reserved | ||
19 | Reserved | ||
20 | Permanent lock 1 |
|
RWS |
21 | Permanent lock 2 |
|
RWS |
22 | Permanent lock 3 |
|
RWS |
23 | Reserved | ||
24 | Reserved | ||
25 | Reserved | ||
26 | Programming lock 1 |
|
RWS |
27 | Programming lock 2 |
|
RWS |
28 | Programming lock 3 |
|
RWS |
29 | Reserved | ||
30 | Reserved | ||
31 | Reserved | ||
32 | Shadow write lock 1 |
|
RWS |
33 | Shadow write lock 2 |
|
RWS |
34 | Shadow write lock 3 |
|
RWS |
35 | Reserved | ||
36 | Reserved | ||
37 | Reserved | ||
38 | Shadow read lock 1 |
|
RWS |
39 | Shadow read lock 2 |
|
RWS |
40 | Shadow read lock 3 |
|
RWS |
41 | Reserved | ||
42 | Reserved | ||
43 | Reserved | ||
44 | OTP 0 | Value of OTP 0 | RW |
45 | OTP 1 | Value of OTP 1 | RW |
... | OTP ... | Value of OTP ... | RW |
139 | OTP95 | Value of OTP 95 | RW |
140 | Reserved | ||
... | Reserved | ||
251 | Reserved | ||
252 | Configuration register |
|
R |
253 | IP version |
|
R |
254 | IP ID | R | |
255 | IP_Magic_ID | R |
1.1.2. Version 2[edit source]
The data structure version 2 for the OP-TEE provisioning TA is described in the table below.
Its size is 776 bytes with 96 OTP for STM32MP15x and for STM32MP13x = (2 * 96 + 2) * 4 bytes for 32 bits word.
Word | Field name | Description |
---|---|---|
0 | Version | Version of this structure = 2 for OP-TEE TA |
1 | Global State | bitfield with state of BSEC the OTP provider (only for read request, 0 for write)
|
2 | OTP[0] | OTP value
|
3 | OTP[0] status | Status of OTP:
|
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 |
You can write OTP without other 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 a 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 indicated a modification request of this OTP
The operation is interrupted on the first error.
Global state is not used during a write operation.
The bit 31 Encrypted data is reserved to indicate an encrypted content of OTP for read or write operation.
1.1.2.1. Examples[edit source]
- 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 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
1.2. Reference list[edit source]