I want to update some data stored in UICR CUSTOMER area on an nrf52832.
Code to do this works fine, as long as the areas are already erased (0xFFFFFFFF).
However, if they have already had a value written, and I want to update it, I understand I need to erase the UICR area first as its flash.
My process is
- copy out the non-CUSTOMER registers, to save them
- enable erase in the NVMC CONFIG
- ask the NVMC to erase by writing 1 to ERASEUICR register
- enable writing
- write back the saved registers
- go back to read mode
(and then do my usual writing code)
However, as soon as I start the process the MCU hangs (no logs, no crash, just hung).
Here is my code : I never see any of the logs probably coz the UART doesn't manage to get the bytes out!
static void _erase_uicr() { // Preserve nordic registers. Note RESERVED fields can be ignored uint32_t nrffw[15]; uint32_t nrfhw[12]; uint32_t pselreset0; uint32_t pselreset1; uint32_t approtect; uint32_t nfcpins; log_info("ERASE UICR"); for (int i=0;i<15;i++) { nrffw[i] = NRF_UICR->NRFFW[i]; } for (int i=0;i<12;i++) { nrfhw[i] = NRF_UICR->NRFHW[i]; } approtect = NRF_UICR->APPROTECT; pselreset0 = NRF_UICR->PSELRESET[0]; pselreset1 = NRF_UICR->PSELRESET[1]; nfcpins = NRF_UICR->NFCPINS; log_info("SAVED UICR info"); // Enable erasing NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een; // erase enabled while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} log_info("ENABLED ERASE UICR"); // Must erase UICR first NRF_NVMC->ERASEUICR = 0x00000001; while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} log_info("ERASED UICR"); NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; // write enabled while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} log_info("ENABLED WRITE UICR"); // Write back the copies for (int i=0;i<15;i++) { NRF_UICR->NRFFW[i] = nrffw[i]; } for (int i=0;i<12;i++) { NRF_UICR->NRFHW[i] = nrfhw[i]; } NRF_UICR->APPROTECT = approtect; NRF_UICR->PSELRESET[0] = pselreset0; NRF_UICR->PSELRESET[1] = pselreset1; NRF_UICR->NFCPINS = nfcpins; log_info("REWROTE NON-CUSTOMER UICR"); NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; // RO while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} log_info("BACK TO RO UICR"); }
Any ideas what I'm doing wrong?
Thanks