liam-geotab opened a new pull request, #20144:
URL: https://github.com/apache/nuttx/pull/20144

   ## Summary
   
   Add an API for OTP (one-time programmable) memory on stm32h5. There are OTP 
APIs for non-STM32 platforms. There is no other API for STM32 so far with these 
names.
   
   Implement it in stm32h563xx_flash.c since the progmem abstraction also lives 
there.
   
   ```c
   int stm32_otp_write(const uint16_t *data, uint16_t len, uint32_t offset);
   int stm32_otp_read(uint16_t *data, uint16_t len, uint32_t offset);
   ```
   
   The API allows cross-block reads/writes that don't necessarily start/end at 
block boundaries.
   The type of `data` is uint16_t * to express to the caller that the pointer 
should be 2-aligned. The natural size of OTP words is 16 bits. `len` is 
uint16_t for no strong reason. Preserve author's work.
   
   ```c
   uint32_t stm32_otp_getlockstatus(void);
   ```
   
   Get a mask of blocks that are locked. A block being locked is considered as 
being one-time programmed. In future stm32 platform support, uint32_t may not 
be sufficient to represent all blocks. This platform has 32 blocks.
   
   The user can be ignorant of the block sizes but they must be aware of the 
full size of the OTP area and there is no define for it in a public header. If 
the user writes half of a block, the unwritten half still gets locked, so the 
user cannot e.g. write the whole OTP area one word at a time, so they actually 
do need to be aware of the block size.
   
   If these issues are unacceptable, changes should be requested by reviewers. 
I am favoring preserving the author's work by default.
   
   ## Impact
   
   If the new STM32 OTP API is bad, there will be a breaking change later (e.g. 
when OTP is added for other STM32 platforms) to improve it.
   
   The other impact worth noting is that this permanently sets a device's OTP 
contents irreversibly, if that wasn't clear.
   
   ## Testing
   
   `nucleo-h563zi:nsh` with `CONFIG_STM32_PROGMEM` enabled.
   
   ```diff
   diff --git a/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c 
b/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c
   index 2cfb962226..57100f0975 100644
   --- a/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c
   +++ b/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c
   @@ -42,10 +42,53 @@
    #  include "stm32_wdg.h"
    #endif
    
   +#include "stm32_flash.h"
   +
    
/****************************************************************************
     * Pre-processor Definitions
     
****************************************************************************/
    
   +#define BLOCK_SIZE   64
   +#define BLOCK        5    /* block to write */
   +
   +static const uint8_t block_data[BLOCK_SIZE] = 
"\xff\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33\xab\xcd\xef\x33";
   +
   +static uint16_t otp_block[BLOCK_SIZE / 2];
   +
   +static int dump_otp(void)
   +{
   +  int ret;
   +  uint8_t *otp_block_u8 = (uint8_t *)otp_block;
   +
   +  uint32_t lock_bits = stm32_otp_getlockstatus();
   +  printf("OTP lock bits: 0x%08"PRIx32"\n", lock_bits);
   +
   +  for (int i = 0; i < 32; i++)
   +    {
   +      printf("OTP block %2d (offset %4d):", i, i * BLOCK_SIZE);
   +
   +      if (((1 << i) & lock_bits) == 0)
   +        {
   +          printf(" not programmed\n");
   +          continue;
   +        }
   +
   +      ret = stm32_otp_read(otp_block, BLOCK_SIZE, i * BLOCK_SIZE);
   +      if (ret < 0)
   +        {
   +          syslog(LOG_ERR, "ERROR: Failed to read OTP: %d\n", ret);
   +          return ret;
   +        }
   +      for (int j = 0; j < BLOCK_SIZE; j++)
   +        {
   +          printf(" %02"PRIx8, otp_block_u8[j]);
   +        }
   +      printf("\n");
   +    }
   +
   +  return OK;
   +}
   +
    
/****************************************************************************
     * Public Functions
     
****************************************************************************/
   @@ -177,6 +220,35 @@ int stm32_bringup(void)
        }
    #endif
    
   +  ret = dump_otp();
   +  if (ret < 0)
   +    {
   +      return ret;
   +    }
   +
   +  if (((1 << BLOCK) & stm32_otp_getlockstatus()) == 0)
   +    {
   +      printf("writing block %d\n", BLOCK);
   +
   +      memcpy(otp_block, block_data, BLOCK_SIZE);
   +      ret = stm32_otp_write(otp_block, BLOCK_SIZE, BLOCK * BLOCK_SIZE);
   +      if (ret < 0)
   +        {
   +          syslog(LOG_ERR, "ERROR: Failed to write OTP: %d\n", ret);
   +          return ret;
   +        }
   +
   +      ret = dump_otp();
   +      if (ret < 0)
   +        {
   +          return ret;
   +        }
   +    }
   +  else
   +    {
   +      printf("block %d is already written\n", BLOCK);
   +    }
   +
      UNUSED(ret);
      return OK;
    }
   ```
   
   ```
   ABCG
   OTP lock bits: 0x00000001
   OTP block  0 (offset    0): ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 
ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd 
ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33
   OTP block  1 (offset   64): not programmed
   OTP block  2 (offset  128): not programmed
   OTP block  3 (offset  192): not programmed
   OTP block  4 (offset  256): not programmed
   OTP block  5 (offset  320): not programmed
   OTP block  6 (offset  384): not programmed
   OTP block  7 (offset  448): not programmed
   OTP block  8 (offset  512): not programmed
   OTP block  9 (offset  576): not programmed
   OTP block 10 (offset  640): not programmed
   OTP block 11 (offset  704): not programmed
   OTP block 12 (offset  768): not programmed
   OTP block 13 (offset  832): not programmed
   OTP block 14 (offset  896): not programmed
   OTP block 15 (offset  960): not programmed
   OTP block 16 (offset 1024): not programmed
   OTP block 17 (offset 1088): not programmed
   OTP block 18 (offset 1152): not programmed
   OTP block 19 (offset 1216): not programmed
   OTP block 20 (offset 1280): not programmed
   OTP block 21 (offset 1344): not programmed
   OTP block 22 (offset 1408): not programmed
   OTP block 23 (offset 1472): not programmed
   OTP block 24 (offset 1536): not programmed
   OTP block 25 (offset 1600): not programmed
   OTP block 26 (offset 1664): not programmed
   OTP block 27 (offset 1728): not programmed
   OTP block 28 (offset 1792): not programmed
   OTP block 29 (offset 1856): not programmed
   OTP block 30 (offset 1920): not programmed
   OTP block 31 (offset 1984): not programmed
   writing block 5
   OTP lock bits: 0x00000021
   OTP block  0 (offset    0): ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 
ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd 
ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33
   OTP block  1 (offset   64): not programmed
   OTP block  2 (offset  128): not programmed
   OTP block  3 (offset  192): not programmed
   OTP block  4 (offset  256): not programmed
   OTP block  5 (offset  320): ff cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 
ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd 
ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33
   OTP block  6 (offset  384): not programmed
   OTP block  7 (offset  448): not programmed
   OTP block  8 (offset  512): not programmed
   OTP block  9 (offset  576): not programmed
   OTP block 10 (offset  640): not programmed
   OTP block 11 (offset  704): not programmed
   OTP block 12 (offset  768): not programmed
   OTP block 13 (offset  832): not programmed
   OTP block 14 (offset  896): not programmed
   OTP block 15 (offset  960): not programmed
   OTP block 16 (offset 1024): not programmed
   OTP block 17 (offset 1088): not programmed
   OTP block 18 (offset 1152): not programmed
   OTP block 19 (offset 1216): not programmed
   OTP block 20 (offset 1280): not programmed
   OTP block 21 (offset 1344): not programmed
   OTP block 22 (offset 1408): not programmed
   OTP block 23 (offset 1472): not programmed
   OTP block 24 (offset 1536): not programmed
   OTP block 25 (offset 1600): not programmed
   OTP block 26 (offset 1664): not programmed
   OTP block 27 (offset 1728): not programmed
   OTP block 28 (offset 1792): not programmed
   OTP block 29 (offset 1856): not programmed
   OTP block 30 (offset 1920): not programmed
   OTP block 31 (offset 1984): not programmed
   
   NuttShell (NSH) NuttX-13.0.1-RC1
   nsh>
   ```
   
   (reset)
   
   ```
   ABCG
   OTP lock bits: 0x00000021
   OTP block  0 (offset    0): ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 
ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd 
ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33
   OTP block  1 (offset   64): not programmed
   OTP block  2 (offset  128): not programmed
   OTP block  3 (offset  192): not programmed
   OTP block  4 (offset  256): not programmed
   OTP block  5 (offset  320): ff cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 
ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd 
ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33 ab cd ef 33
   OTP block  6 (offset  384): not programmed
   OTP block  7 (offset  448): not programmed
   OTP block  8 (offset  512): not programmed
   OTP block  9 (offset  576): not programmed
   OTP block 10 (offset  640): not programmed
   OTP block 11 (offset  704): not programmed
   OTP block 12 (offset  768): not programmed
   OTP block 13 (offset  832): not programmed
   OTP block 14 (offset  896): not programmed
   OTP block 15 (offset  960): not programmed
   OTP block 16 (offset 1024): not programmed
   OTP block 17 (offset 1088): not programmed
   OTP block 18 (offset 1152): not programmed
   OTP block 19 (offset 1216): not programmed
   OTP block 20 (offset 1280): not programmed
   OTP block 21 (offset 1344): not programmed
   OTP block 22 (offset 1408): not programmed
   OTP block 23 (offset 1472): not programmed
   OTP block 24 (offset 1536): not programmed
   OTP block 25 (offset 1600): not programmed
   OTP block 26 (offset 1664): not programmed
   OTP block 27 (offset 1728): not programmed
   OTP block 28 (offset 1792): not programmed
   OTP block 29 (offset 1856): not programmed
   OTP block 30 (offset 1920): not programmed
   OTP block 31 (offset 1984): not programmed
   block 5 is already written
   
   NuttShell (NSH) NuttX-13.0.1-RC1
   nsh>
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to