Read values of UICR in Application

Hi, 

I am trying to read the value of the UICR register CUSTOMER[4] during the runtime of the application. Therefore, I am using the following code:

nrf_fstorage_read(&m_fs, (0x10001090), &destination, 32);

Where m_fs is the storage instance and destination is initialized as a char array.

My two questions are: 

- Is it correct to use nrf_fstorage_read for this purpose?

- Which address do I need to use, as my call is returning error 16: NRF_ERROR_INVALID_ADDR

Thanks, 

Simon

Parents
  • Are you using Zephyr? Here is how I did it in Zephyr. Hopefully it helps some.

    I have an enum to easily select which UICR value I want to interact with:

    typedef enum flash_uicr_register {
        fur_01,
        fur_02,
        ...
        fur_30,
        fur_31,
        fur_32,
    } flash_uicr_register_t;

    Then I wrote a simple helper function to easily compute the offsets:

    static off_t compute_uicr_offset(const flash_uicr_register_t uicr_register)
    {
        //
        // The UICR base address is 0x10001000
        // The UICR registers start at 0x080
        //
        // This calculation calculates the offset based off of the passed in register ordinal.
        //
        // Examples:
        //     fur_01: 0x10001000 + (0x080 + (0 << 2)) = 0x10001080 (0x080)
        //     fur_02: 0x10001000 + (0x080 + (1 << 2)) = 0x10001084 (0x084)
        //     fur_nn: ...
        //     fur_31: 0x10001000 + (0x080 + (30 << 2)) = 0x100010F8 (0x0F8)
        //     fur_32: 0x10001000 + (0x080 + (31 << 2)) = 0x100010FC (0x0FC)
        //
        // See: https://infocenter.nordicsemi.com/topic/ps_nrf52840/uicr.html
        //
    
        return (off_t)NRF_UICR + (0x080 + (uicr_register << 2));
    }
     

    Then I use the Zephyr's flash driver to interact with it. Here is a simplified version:

    uint32_t flash_read_uicr(const flash_uicr_register_t uicr_register)
    {
        __ASSERT_NO_MSG(uicr_register >= fur_01 && uicr_register <= fur_32);
    
        static uint32_t value = 0;
    
        int error = flash_read(mDevice, compute_uicr_offset(uicr_register), &value, sizeof(uint32_t));
    
        if (error != 0)
        {
            LOG_FLASH_E("Error reading from the UICR (Error: %d - %s)", error, errno_to_str(error));
            return false;
        }
    
        return value;
    }
    
    bool flash_write_uicr(const flash_uicr_register_t uicr_register, const uint32_t value)
    {
        __ASSERT_NO_MSG(uicr_register >= fur_01 && uicr_register <= fur_32);
    
        int error = flash_write(mDevice, compute_uicr_offset(uicr_register), &value, sizeof(uint32_t));
    
        if (error != 0)
        {
            LOG_FLASH_E("Error writing to the UICR (Error: %d - %s)", error, errno_to_str(error));
            return false;
        }
    
        return true;
    }
    
    bool flash_write_verify_uicr(const flash_uicr_register_t uicr_register, const uint32_t value)
    {
        return flash_write_uicr(uicr_register, value) &&
               flash_read_uicr(uicr_register) == value;
    }
    
    bool flash_erase_uicr(void)
    {
        int error = flash_erase(mDevice, (off_t)NRF_UICR, sizeof(*NRF_UICR));
    
        if (error != 0)
        {
            LOG_FLASH_E("Error erasing the UICR memory (Error: %d - %s)", error, errno_to_str(error));
            return false;
        }
    
        return true;
    }

    Here is what mDevice is:

    const struct device *const mDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));

  • Hi, 

    I'm sorry, I'm still using the old framework, nrf5 sdk for thread and zigbee which in our case is used together with FreeRTOS

Reply Children
Related