1
votes

I am trying to write data in the memory flash of a STM32L4 chip. This is to be done in a programming context in which I use C calls to ST-Link utility command line.

So here is an example of the flash memory :

               0             4             8             C
0x1FFF7000  FFFFFFFF     FFFFFFFF       FFFFFFFF       FFFFFFFF

So far I have been able to write only 32bits on a 64bit data space :

               0             4             8             C
0x1FFF7000  AAAAAAAF     FFFFFFFF       BBBCCCDD       FFFFFFFF

When writing on the first 32bits, the second 32bits are locked. So given the memory is in the previous state, the following writing is not allowed :

               0             4             8             C
0x1FFF7000  AAAAAAAF     00000001       BBBCCCDD       FFFFFFFF
                            ^^                            ^^
                         Not allowed                     Locked

I am only able to write data, which are size limited by 32 bits, once in a 64bits data space. I found this very peculiar since there is no reason why memory would be handled this way.

EDIT : This is only true because I want to write in the OTP, it seems to be working normally when I write elsewhere

First possible solution

This answer to a previous question of mine quoted this :

Level 2: No debug
In this level, the protection level 1 is guaranteed. In addition, the Cortex®-M4 debug port, the boot from RAM (boot RAM mode) and the boot from System memory (boot loader mode) are no more available. In user execution mode (boot FLASH mode), all operations are allowed on the Flash Main memory. ...
The level 2 cannot be removed at all: it is an irreversible operation.

Is there any way that enabling level 2 would allow me to write 32bits twice on a 64bit memory space ?

Second possible solution

Looking in the chip's documentation, I have found the flash memory programming sequence (page 102) :

  1. Check that no Flash main memory operation is ongoing by checking the BSY bit in the Flash status register (FLASH_SR).
  2. Check and clear all error programming flags due to a previous programming. If not, PGSERR is set.
  3. Set the PG bit in the Flash control register (FLASH_CR).
  4. Perform the data write operation at the desired memory address, inside main memory block or OTP area. Only double word can be programmed. – Write a first word in an address aligned with double word – Write the second word
  5. Wait until the BSY bit is cleared in the FLASH_SR register.
  6. Check that EOP flag is set in the FLASH_SR register (meaning that the programming operation has succeed), and clear it by software.
  7. Clear the PG bit in the FLASH_SR register if there no more programming request anymore.

I haven't been able to understand really what was that PG bit in step 3. but when I tried to set it, writing weren't allowed.

I use the ST-Link Utility for writing and the command -w32 which, according to the manual, should allow me to write on registers.

-w32 supports writing to Flash memory, OTP, SRAM and R/W registers

Also, step 4. seem to describe the exact issue I am fighting against, but I can't understand the solution it proposes.

Any hint regarding how to solve the problem with any solution would be a bless. Also, since I am not very familiar with the embedded, low-level vocabulary, don't hesitate editing my question to make it more clear.

1

1 Answers

5
votes

The reason you observe this behavior is the following (from STM32L4x5 STM32L4x6 RM):

1 Kbyte (128 double word) OTP (one-time programmable) bytes for user data. The OTP area is available in Bank 1 only. The OTP data cannot be erased and can be written only once. If only one bit is at 0, the entire double word cannot be written anymore, even with the value 0x0000 0000 0000 0000.

This means that OTP area is organized as 64-bit values and writes to it should be "atomic", meaning you write all 64 bits at once. Setting 0 at any of the 64 bits locks the entire double word for further writes. In your example this means, that if you tried writing the value in 8-bit batches by using -w8 you would only be able to write the first byte out of 8 in given double word (64 bits).

In turn that means that even if the ST-Link Utility manual states that -w32 allows programming the OTP area, it only means that it is possible to specify OTP as a target address to write to and not necessarily that you would be able to properly program all bits of each double word. This looks like an oversight, although there's not much you can do about it.

What I would personally try would be to program it using the -P command:

Description: Loads binary, Intel Hex or Motorola S-record file into device memory without
verification. For hex and srec format, the address is relevant.
Syntax: -P <File_Path> [<Address>]
Examples: -P C:\file.srec
-P C:\file.bin 0x08002000
-P C:\file.hex

I haven't tested it myself, but currently to me that appears to be the only possibility that may allow you to "atomically" program 64-bit values into OTP through ST-Link.