This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Write initial values to flash during production

During production we need to provision each device with some custom data that must last the life time of the device, ideally using nrfjprog. What is the best way to do this? I see there are Customer registers in UICR, but what about writing more than 32 bytes?

Parents
  • I determined that as a whole page must be erased before flash can be written, the fixed address storage size must be a multiple of the page size (0x1000).

    So far I've got, in my linker file:

    MEMORY
    {
        /* MBR_FLASH (rx)        : ORIGIN = 0x00000000, LENGTH = 0x00001000 */
        /* SOFTDEVICE_FLASH (rx) : ORIGIN = 0x00001000, LENGTH = 0x00025000 */
    
        FLASH (rx)               : ORIGIN = 0x00026000, LENGTH = 0x00051000
        RAM (rwx)                : ORIGIN = 0x20003320, LENGTH = 0x0000cce0
    
        provisioning_data (rwx)  : ORIGIN = 0x00077000, LENGTH = 0x00001000
    
        /* BOOTLOADER_FLASH (rx) : ORIGIN 0x00078000, LENGTH = 0x00006000 */
    }
    
    SECTIONS
    {
      .provisioning_data_block 0x00077000 :
      {
        KEEP(*(.provisioning_data_sect))
      } > provisioning_data
    }
    
    ...

    Here I reduced the size of the application flash by 0x1000 and added a new block of data at the end of the application flash. Then I define the section.

    As I'm using FDS, I needed to reserve the flash from being used by FDS in sdk_config.h:

    #define FDS_VIRTUAL_PAGES_RESERVED 1

    Then, in my code:

    uint8_t __attribute__((section (".provisioning_data_sect"))) m_provisioning_data[0x1000] __attribute__((used));
    const uint32_t provisioningStart = 0xA55A5AA5;
    
    ...
    
    if(*(uint32_t *)m_provisioning_data != provisioningStart) {
        nrf_nvmc_page_erase(m_provisioning_data);
        nrf_nvmc_write_word(m_provisioning_data, provisioningStart);
    }
    
    nrf_nvmc_write_byte(m_provisioning_data + 4, 0xBA);
    
    NRF_LOG_INFO("0x%08X", m_provisioning_data);
    NRF_LOG_HEXDUMP_INFO(m_provisioning_data, 5)

    Is this correct so far?

    Is this sufficient to protect the flash from being overwritten by the bootloader etc? I would assume not, since I have not modified any sizes in the (DFU BLE) bootloader. What would I need to modify?

Reply
  • I determined that as a whole page must be erased before flash can be written, the fixed address storage size must be a multiple of the page size (0x1000).

    So far I've got, in my linker file:

    MEMORY
    {
        /* MBR_FLASH (rx)        : ORIGIN = 0x00000000, LENGTH = 0x00001000 */
        /* SOFTDEVICE_FLASH (rx) : ORIGIN = 0x00001000, LENGTH = 0x00025000 */
    
        FLASH (rx)               : ORIGIN = 0x00026000, LENGTH = 0x00051000
        RAM (rwx)                : ORIGIN = 0x20003320, LENGTH = 0x0000cce0
    
        provisioning_data (rwx)  : ORIGIN = 0x00077000, LENGTH = 0x00001000
    
        /* BOOTLOADER_FLASH (rx) : ORIGIN 0x00078000, LENGTH = 0x00006000 */
    }
    
    SECTIONS
    {
      .provisioning_data_block 0x00077000 :
      {
        KEEP(*(.provisioning_data_sect))
      } > provisioning_data
    }
    
    ...

    Here I reduced the size of the application flash by 0x1000 and added a new block of data at the end of the application flash. Then I define the section.

    As I'm using FDS, I needed to reserve the flash from being used by FDS in sdk_config.h:

    #define FDS_VIRTUAL_PAGES_RESERVED 1

    Then, in my code:

    uint8_t __attribute__((section (".provisioning_data_sect"))) m_provisioning_data[0x1000] __attribute__((used));
    const uint32_t provisioningStart = 0xA55A5AA5;
    
    ...
    
    if(*(uint32_t *)m_provisioning_data != provisioningStart) {
        nrf_nvmc_page_erase(m_provisioning_data);
        nrf_nvmc_write_word(m_provisioning_data, provisioningStart);
    }
    
    nrf_nvmc_write_byte(m_provisioning_data + 4, 0xBA);
    
    NRF_LOG_INFO("0x%08X", m_provisioning_data);
    NRF_LOG_HEXDUMP_INFO(m_provisioning_data, 5)

    Is this correct so far?

    Is this sufficient to protect the flash from being overwritten by the bootloader etc? I would assume not, since I have not modified any sizes in the (DFU BLE) bootloader. What would I need to modify?

Children
Related