Erase UICR and merge Bootloader problem

Hello,

I am using NRF52832 with soft device 13.0.0 and Nordic's bootloader from the examples.

What I do is develop an application which stores some values in uicr registers 0-7 (no soft device enabled yet). Before storing the values I erase the uicr registers at device startup, using the following code. (Then the rest of the application executes)

	 SEGGER_RTT_WriteString(0, "Deleting uicr \r\n");
	 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
	 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	 NRF_NVMC->ERASEUICR = 1;
	 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	 
	SEGGER_RTT_WriteString(0, "Update  Version \r\n");

	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
	NRF_UICR->CUSTOMER[0] = hardware_version_reg;  // a uint32 value
	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}	

Everything works fine when I test the application without a bootloader.

In the next step I use the following commands to create a hex file which includes the soft device, the bootloader (DFU) and the application:

nrfutil settings generate --family NRF52 --application testing_firmware_v01.04.hex --application-version 0x0104 --bootloader-version 0x0103 --bl-settings-version 1 bootloader_setting.hex
mergehex --merge feel_bootloader_v1.3.hex bootloader_setting.hex --output Bootldr_Settings.hex
mergehex --merge Bootldr_Settings.hex s132_nrf52_4.0.2_softdevice.hex --output SoftAndBoot.hex
mergehex --merge SoftAndBoot.hex feel_testing_firmware_v01.04.hex --output FW_merged.hex

This last hex file (FW_merged) is what i use to program the device with nRFgo Studio. Up to now, during the development, everything worked fine with this procedure.

When I added the code to erase and write the uicr as mentioned above a strange problem occurred.
When I used the FW_merged file to program the device in nRFgo Studio the bootloader would not be programmed in the device. Only the softdevice and the application would be programmed. The verification also failed. If I program the bootloader separately after that, the verification succeeds and the device works ok.

After some experimentation I saw that the command  NRF_NVMC->ERASEUICR = 1; alone would cause that problem. If I comment this line then everything runs smoothly again and the bootloader is programmed properly with the hex file.

Any ideas why this might happen? 

Thank you in advance

  • Hi Dimitris, 

    When you use the bootloader you must be very careful with the UICR. This is because we store the bootloader address in the UICR. You can read about that here.

    If you have some data that need to be changed more often, I would suggest to use a dedicated flash page to store, instead of using UICR. UICR is more of something like serial number, or hard coded configuration. And please be aware and avoid the address that is used by the bootloader. 

  • Thank you for the response,

    The data that are stored in the uicr registers are connected to the hardware version of the device and some calibration values. They are stored once and remain there during the lifetime of the device. The only occasion where these registers are deleted and written again is when the device is re-calibrated.

    As for the uicr registers only the uicr customer registers are used, so I suppose it is safe to use them. I have done it in the past in another application (with a bootloader added also) and everything seemed to work fine.

    The weird thing is that when I add some code to check if the uicr customer register has data before deleting it, then the problem disappears

    if ( NRF_UICR->CUSTOMER[0] != 0xFFFFFFFF )	{
    			
    	 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
    	 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    	 NRF_NVMC->ERASEUICR = 1;
    	 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    }

    I would understand it if the deletion of the uicr caused a crash after programming the device, during run time.

    I would expect for the device to program properly and then the application or bootloader to fail, not to see a problem during the programming of the device with the hex file. 

    How is it possible for a line of code inside the application to have such an effect in the programming of the device? I checked the map file of the application and the soft device, application and bootloader areas do not overlap.

    How this line of code can create problems in the merging of the hex files, and can affect the programming of the device so that verification fails? And why programming the bootloader separately solves the problem?

    I understand these are a lot of questions but this seems like a rather strange problem to me.

  • Hi Dimitris, 

    I would not suggest to use nRFGo Studio for programming. Please use nrfjprog. 

    With nRFGo Studio the chip may not be halted between programming and verification. And if you do any flash modification in between it may result in verification failed. 

    Please try again with nrfjprog and provide us the log/screenshot. 

    Please note that even though there is part of the UICR is "reserved for customer" but when you erase the UICR the whole page is erased.You would need to make sure you back up the rest of UICR page and write it back after you erase. 

  • Hello Hung Bui,

    I tried programming the device with nrfjprog and indeed verification did succeed. However the bootloader was not programmed again. I could see that from nRFGo Studio, but also tried it in the device. We have a button that enters bootloader mode. When pressed the device just restarts and does not enter DFU.

    Here are the screenshots from nrfjprog and nRFGo Studio (after programming with nrfjprog).

    When I comment the NRF_NVMC->ERASEUICR = 1; command and repeat the same procedure, everything runs smoothly, and the when the button is pressed the device enters DFU normally.

    I tried backing up the uicr registers and rewrite them after the erase but that did not solve the problem. Here is the code I used: ( I did not back up the customer registers)

    	NRF_UICR_Type uicr_cpy = *NRF_UICR;
    	
    	for(int x=0; x<32;x++){
    		uicr_cpy.CUSTOMER[x] = 0xFFFFFFFF;
    	}
    	
    	//erase
    	 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
    	 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    	 NRF_NVMC->ERASEUICR = 1;
    	 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    		//rewrite
    
    		 
    		 *NRF_UICR = uicr_cpy;
    	

    The problem is still there. I program the device with nrfjprog and although verification succeeds (only in nrfjprog), the bootloader is not programmed properly and would not start

    The only thing that seems to work is the one I mentioned in my earlier reply, when I add this check before erasing uicr:

    if ( NRF_UICR->CUSTOMER[0] != 0xFFFFFFFF ) { erase uicr }

    and changing slightly the way I call the function which erases uicr (instead of calling 2 wrapper functions I call only one - I move the code for erasing one level up, nothing else changes)

    Although this solution works, I am really curious why this happens...

  • I don't think you can write a whole page by just calling *NRF_UICR = uicr_cpy; You need to write them word by word (32 bit) 

    Could you please check after the erase and write to the UICR; you have the correct start address of the bootloader (NRF_UICR_BOOTLOADER_START_ADDRESS) at : NRF_UICR_BASE + 0x14

    And the correct address of the MBR Param page address at NRF_UICR_BASE + 0x18

Related