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

Is there sample code for writing to an UICR register?

Hi Has anyone been able to write to the UICR NFCPINS register? I am using the following code and it i get a cpu reset

/*=============================================================================*/
/*=============================================================================*/
STATIC UWRESULTCODE
NfcPubWriteUICR_NFCPINS(
    VOID
    )
{
    UI32 nNewVal = 0xFFFFFFFE;
    
    /* Turn on flash write enable and wait until the NVMC is ready: */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    }

    NRF_UICR->NFCPINS = nNewVal;

    /* Turn off flash write enable and wait until the NVMC is ready: */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    }
    return UWRESULTCODE_SUCCESS;
}

I note that back in May 2015, someone asked for sd_flash_write() to be able to that and Nordic responded that it will be added to the wish list. Needlessly to say that in v2.0.0 of the SD132 it does not work and returns an INVALID_ADDR

And frustrating thing is that there is a sample app in examples\peripheral\uicr_config and all I see in main.c is ..

int main(void)
{
    while (true)
    {
        /* Do nothing */
    }
}

And the only file that mentions NFCPINS is system_nrf52.c and it is doing what I do above.

Which means if it works there, but not for me, it must be something to do with softdevice having been started by the time I come to calling my code.

Reason I need the 'late' call is that I need to offer a programmatic way of disabling the NFCPINS as our customers do not have a compile phase for the module we are going to provide

Look forward to hearing from anyone and thank you in advance

  • Hi,

    There is a workaround for this (I have not tried it myself).

    Disable MWU and write to UICR and then enable MWU. Then you can directly access NVMC register.

    void app_mwu_enable(void)
    {
      NRF_MWU->REGIONENSET
        = ((MWU_REGIONENSET_RGN0WA_Set << MWU_REGIONENSET_RGN0WA_Pos) | (MWU_REGIONENSET_PRGN0WA_Set << MWU_REGIONENSET_PRGN0WA_Pos));
    }
    
    void app_mwu_disable(void)
    {
      NRF_MWU->REGIONENCLR
        = ((MWU_REGIONENCLR_RGN0WA_Clear << MWU_REGIONENCLR_RGN0WA_Pos) | (MWU_REGIONENCLR_PRGN0WA_Clear << MWU_REGIONENCLR_PRGN0WA_Pos));
    }
    

    Then you can do something like this

    app_mwu_disable();
    NfcPubWriteUICR_NFCPINS();
    app_mwu_enable();
    

    Hopefully softdevice adds feature to access UICR in future releases so that we do not have to use this workaround. Just to remind you, that this might not work well along with BLE traffic.

  • You are a star. Your workaround works. Thank you so much

  • That is great, that it worked for you, in that case can you please accept this answer .

  • I spoke too soon :-( It works if I single step through the code ..

    UI32 nNewVal = 0xFFFFFFFE;
    

    #if 1

    /* MWU Enable -- This is workaround suggested by Aryan on the Nordic Developer Zone */
    NRF_MWU->REGIONENSET
        = ((MWU_REGIONENSET_RGN0WA_Set << MWU_REGIONENSET_RGN0WA_Pos) 
         | (MWU_REGIONENSET_PRGN0WA_Set << MWU_REGIONENSET_PRGN0WA_Pos));
    
    /* Turn on flash write enable and wait until the NVMC is ready: */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    /* write to the register */
    NRF_UICR->NFCPINS = nNewVal;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        
    /* Turn off flash write enable and wait until the NVMC is ready: */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        
    /* MWU Disable -- This is workaround suggested by Aryan on the Nordic Developer Zone */
    NRF_MWU->REGIONENCLR
        = ((MWU_REGIONENCLR_RGN0WA_Clear << MWU_REGIONENCLR_RGN0WA_Pos) 
         | (MWU_REGIONENCLR_PRGN0WA_Clear << MWU_REGIONENCLR_PRGN0WA_Pos));
                
    return UWRESULTCODE_SUCCESS;
    

    #endif

    But if I just run it, the firmware hangs. The only way forward is to hit reset.

  • And I can confirm that when I call that code there is no radio activity

Related