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

System Reset after UICR Erase and write leads to System Off.

Hello,

I am using a custom board NRF52382, Softdevice 132_v2.0, SDK 11. Two power supply options are given, battery and USB.

I tried to rewrite UICR register with two implementation
 
    1st.

    uint32_t err_code = sd_softdevice_disable();
	APP_ERROR_CHECK(err_code);
	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
	nrf_delay_ms(100);
	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	nrf_delay_ms(100);
	*(uint32_t *)0x100010E4 = var_register[0] ;
	*(uint32_t *)0x100010E8 = var_register[1] ;
	*(uint32_t *)0x100010EC = var_register[2] ;
	*(uint32_t *)0x100010F0 = var_register[3] ;
	nrf_delay_ms(100);
	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	NVIC_SystemReset();

 2nd

uint32_t err_code = sd_softdevice_disable();
	APP_ERROR_CHECK(err_code);
	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
	nrf_delay_ms(100);
	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	NRF_NVMC->ERASEUICR = 1;
	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	nrf_delay_ms(100);
	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
	nrf_delay_ms(100);
	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	nrf_delay_ms(100);
	*(uint32_t *)0x100010E4 = var_register[0] ;
	*(uint32_t *)0x100010E8 = var_register[1] ;
	*(uint32_t *)0x100010EC = var_register[2] ;
	*(uint32_t *)0x100010F0 = var_register[3] ;
	nrf_delay_ms(100);
	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	NVIC_SystemReset();

 The first implementation was not allowing me to rewrite UICR register either some corrupted data or previously stored data were coming.

In the Second implementation, I first erased UICR register then rewrite those register, it works fine for me. 

ISSUE). With the Second implementation, System is not resetting it is going in power off. Only possible way to do a reset is plug in USB, not working on battery independently and also causing problems if I try to do the soft reset.

I then have to erase the chip, program hex with DFU bootloader and do a firmware update over the air to see a soft reset is working.

This just explains that either soft device is forgetting that bootloader is present or erasing UICR register is erasing bootloader.
I tried to check also NRFFW register which is showing value 0xFFFFFFFF, in both scenarios.

From the first implementation, everything works fine but not rewrite of UICR register.

Need some explanation and how to move forward.

Thanks,

  • Hi, I know this is old... But I think there's a bug on line 13 where it says i < sizeof(uicr_buffer). this is i < 236

    It should say 

    for(int i = 0; i<(sizeof(uicr_buffer) / sizeof(uicr_buffer[0])); i++)

    or just for(int i = 0; i<59; i++)

    I changed the code to this (My code increments a reboot counter in CUSTOMER[0] every reboot, whereas yours was updating the bootloader address)

    void    increment_reboot_count()  
    { 
    //Must be done before SoftDevice init
    //This code modified from https://devzone.nordicsemi.com/f/nordic-q-a/34262/system-reset-after-uicr-erase-and-write-leads-to-system-off
    
        static uint32_t temp_uicr_NRFFW[sizeof(NRF_UICR->NRFFW) / sizeof (NRF_UICR->NRFFW[0])] = {0x00000000};
        static uint32_t temp_uicr_NRFHW[sizeof(NRF_UICR->NRFHW) / sizeof (NRF_UICR->NRFHW[0])] = {0x00000000};
        static uint32_t temp_uicr_CUSTOMER[sizeof(NRF_UICR->CUSTOMER) / sizeof (NRF_UICR->CUSTOMER[0])] = {0x00000000};
    
        static uint32_t temp_pselreset_0        = 0x00000000;
        static uint32_t temp_pselreset_1        = 0x00000000;
        static uint32_t temp_approtect          = 0x00000000;
        static uint32_t temp_nfcpins            = 0x00000000;
    
        CRITICAL_REGION_ENTER();
    
        //Read everything into temp buffers prior to erase
        for (int i = 0; i < (sizeof(temp_uicr_NRFFW) / sizeof(temp_uicr_NRFFW[0])); i++)
        {
          temp_uicr_NRFFW[i] = NRF_UICR->NRFFW[i];
          while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
        }
    
        for (int i = 0; i < (sizeof(temp_uicr_NRFHW) / sizeof(temp_uicr_NRFHW[0])); i++)
        {
          temp_uicr_NRFHW[i] = NRF_UICR->NRFHW[i];
          while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        }
    
        for (int i = 0; i < (sizeof(temp_uicr_CUSTOMER) / sizeof(temp_uicr_CUSTOMER[0])); i++)
        {
          temp_uicr_CUSTOMER[i] = NRF_UICR->CUSTOMER[i];
          while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        }
      
        temp_pselreset_0 = NRF_UICR->PSELRESET[0];
        temp_pselreset_1 = NRF_UICR->PSELRESET[1];
        temp_approtect   = NRF_UICR->APPROTECT;
        temp_nfcpins     = NRF_UICR->NFCPINS;
        
        //increment my variable
        reboot_count = temp_uicr_CUSTOMER[0] + 1;
        temp_uicr_CUSTOMER[0] = reboot_count;
    
        // Enable Erase mode
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos; //0x02; 
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        
        // Erase the UICR registers
        NRF_NVMC->ERASEUICR = NVMC_ERASEUICR_ERASEUICR_Erase << NVMC_ERASEUICR_ERASEUICR_Pos; //0x00000001;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        
        // Enable WRITE mode
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; //0x01;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        
    
        //Write everything back
        for (int i = 0; i < (sizeof(temp_uicr_NRFFW) / sizeof(temp_uicr_NRFFW[0])); i++)
        {
          if (temp_uicr_NRFFW[i] != 0xFFFFFFFF)
          {
            //printf("writing temp_uicr_NRFFW[%d] = %x\n", i, temp_uicr_NRFFW[i]);
            NRF_UICR->NRFFW[i] = temp_uicr_NRFFW[i];
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
          }
        }
    
        for (int i = 0; i < (sizeof(temp_uicr_NRFHW) / sizeof(temp_uicr_NRFHW[0])); i++)
        {
          if (temp_uicr_NRFHW[i] != 0xFFFFFFFF)
          {
            //printf("writing temp_uicr_NRFHW[%d] = %x\n", i, temp_uicr_NRFHW[i]);
            NRF_UICR->NRFHW[i] = temp_uicr_NRFHW[i];
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
          }
        }
    
        for (int i = 0; i < (sizeof(temp_uicr_CUSTOMER) / sizeof(temp_uicr_CUSTOMER[0])); i++)
        {
          if (temp_uicr_CUSTOMER[i] != 0xFFFFFFFF)
          {
            //printf("writing temp_uicr_CUSTOMER[%d] = %x\n", i, temp_uicr_CUSTOMER[i]);
            NRF_UICR->CUSTOMER[i] = temp_uicr_CUSTOMER[i];
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
          }
        }
      
        NRF_UICR->PSELRESET[0] = temp_pselreset_0; 
        NRF_UICR->PSELRESET[1] = temp_pselreset_1; 
        NRF_UICR->APPROTECT    = temp_approtect; 
        NRF_UICR->NFCPINS      = temp_nfcpins;
    
    
        CRITICAL_REGION_EXIT();
    }
    
    

Related