ERASEUICR not erasing UICR

I have a problem erasing data written to the NRF_UICR->CUSTOMER registers.

I want to store the hardware version and serial number in these registers, but the serial number may change once in the lifetime of the product. Thus I would like to be able to update it.

The function I've written works on the NRF52832 chip, but doesn't seem to work on the NRF52840.

The infocenter says that when the erase bit in the confic register is set, I could erase all customer registers.

But I cannot get this to work on the NRF52840.

I've also disabled the protection registers using;

NRF_APPROTECT->DISABLE = APPROTECT_DISABLE_DISABLE_SwDisable;

But that doesn't seem to help.

Any help would be appreciated.

The function in question;

                uint8_t total_flash_size = ROUND_UP(HARDWARE_VERSION_SZ + HARDWARE_KEYWORD_SZ + SERIAL_NUMBER_SZ + SERIAL_KEYWORD_SZ, 4);
                uint32_t flash_copy_array[(total_flash_size / 4)];
                serial_number_t serial_number;
                uint32_t *pversion_flash = HARDWARE_VERSION_PTR; //Hardware version is first so use that as origin
               
                //Get data from flash
                memcpy((uint8_t*)flash_copy_array, (uint8_t*)pversion_flash, total_flash_size);
               
                //Put new data in temp stuct
                memcpy(serial_number.u.data, data, SERIAL_NUMBER_SZ);
                serial_number.keyword = SERIAL_NUMBER_KEYWORD;
//
                //HardwareVersionPointer is the first address, so this is used to calculate the offset for the array
                memcpy(&((uint8_t*)flash_copy_array)[SERIAL_NUMBER_PTR - HARDWARE_VERSION_PTR], (uint8_t*)&serial_number, SERIAL_NUMBER_SZ + SERIAL_KEYWORD_SZ);
               
                __disable_irq();
                //Configure for erase
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
                while(NRF_NVMC->READY == NVMC_READY_READY_Busy){;}
                NRF_NVMC->ERASEUICR = NVMC_ERASEUICR_ERASEUICR_Erase << NVMC_ERASEUICR_ERASEUICR_Pos;

                //Wait for erase to complete
                while(NRF_NVMC->READY == NVMC_READY_READY_Busy){;}

                //Configure for write
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
                while(NRF_NVMC->READY == NVMC_READY_READY_Busy){;}

                //Write data to flash
                for(int i = 0; i < (total_flash_size / 4); i++)
                {
                    while(NRF_NVMC->READYNEXT == NVMC_READY_READY_Busy){;}//NRF52840 has this register, so use it. Maybe it will help? nop
                    pversion_flash[i] = flash_copy_array[i];
                }
                //memcpy(pversion_flash, flash_copy_array, sizeof(flash_copy_array));
                while(NRF_NVMC->READY == NVMC_READY_READY_Busy){;}

                //Undo configuration
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
                while(NRF_NVMC->READY == NVMC_READY_READY_Busy){;}
                __enable_irq();

                SendCMD_Data(kAck, (uint8_t*)paddr, MEMORY_ADDRESS_SIZE);
                //System reset is needed for the new UICR configuration to take effect
                k_msleep(200);
                NVIC_SystemReset();
Related