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

OTA fail after set the public address

Hi,

I'm using the nRF5_sdk V11.0 and S130 on nRF51822, we need to write a 6 bytes address to the CUSTOMER register(address is 0x100010f8) of the UICR when mass production, then I will read it out to use sd_ble_gap_address_set function change the gap address. The code as follow:

   static void Mac_Addr_Set(void)
{
	 uint8_t i = 0;
	 uint8_t mac_addr[8];
	 uint32_t err_code;
	 ble_gap_addr_t gap_addr;
	 const uint8_t *addr = (uint8_t *)0x100010f8;
	
	 for(i=0;i<8;i++)
	 {
			mac_addr[i] = (uint8_t)*(addr);
			addr++;
	 }	
	 if(((mac_addr[0]!=0)&&(mac_addr[1]!=0)&&(mac_addr[2]!=0)&&(mac_addr[3]!=0)&&(mac_addr[4]!=0)&&(mac_addr[5]!=0))||
			((mac_addr[0]!=0xFF)&&(mac_addr[1]!=0xFF)&&(mac_addr[2]!=0xFF)&&(mac_addr[3]!=0xFF)&&(mac_addr[4]!=0xFF)&&(mac_addr[5]!=0xFF)))
	 {
			gap_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
			memcpy(gap_addr.addr, mac_addr, 6); 			
	 
			err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &gap_addr);
			APP_ERROR_CHECK(err_code);				        
	 }

But I found that, OTA fails if I read the address out to set the public address,the APP stops at "Enabling DFU bootloader...". OTA is good if I don't call the Mac_Addr_Set() function to set gap address. what is more strange, when the OTA fail, I do OTA again and then is OK. Than is to say, I need to do twice OTA so that it can update the firmware.

Also I use the heart rate example(s130_with_dfu) to test, it meets the same problem. Could anyone give me some advice? Thanks.

Best regards, Alice

Parents
  • Hi Alice,

    The problem is that when we reset to the OTA bootloader, the softdevice is reinitialized, therefore the address used here is the original one. Not the one you set in your application. Therefore the app on the phone won't be able to find the DFU bootloader to do DFU update since the address is changed.

    So what you need to do is to also set the address to the address you saved in UICR in the bootloader.

    Note that inside dfu_transport_update_start() we do an address change if there is no re-bond required, we increase the address by 1 to make the DFU look like a new device, just to make sure it's not cached by the peer device, or the peer device try to re-bond with the DFU bootloader. The app do search for both the device address and the device address + 1 to do a re-connect.

  • I also encountered the same problem. The chip I used is NRF52832. I set a public address in the application and saved it in the NRF_UICR register to read the address when bootloader dfu starts. But there is a serious and unsolvable problem here. My phone keeps reminding me of connection timeout when performing DUF. Through simulation, I found that the application did not start the DFU process. If I do not set a public address, the DFU process is successful. Through low-power analysis of the current, I determined that the application did not enter the bootloader at all because the DFU process restarts and the current tends to decrease. However, the problem I encountered did not involve a restart. The routine I used was ble_uart, and I have no way to solve this problem. I am saddened

Reply
  • I also encountered the same problem. The chip I used is NRF52832. I set a public address in the application and saved it in the NRF_UICR register to read the address when bootloader dfu starts. But there is a serious and unsolvable problem here. My phone keeps reminding me of connection timeout when performing DUF. Through simulation, I found that the application did not start the DFU process. If I do not set a public address, the DFU process is successful. Through low-power analysis of the current, I determined that the application did not enter the bootloader at all because the DFU process restarts and the current tends to decrease. However, the problem I encountered did not involve a restart. The routine I used was ble_uart, and I have no way to solve this problem. I am saddened

Children
  • Hi 

    If you are using SDK v12 or newer what you describe should work fine, as long as you make sure to write your data to one of the CUSTOMER registers in the UICR. 

    If you're still having issues with this please open a new ticket, and share the details of what you have tried and which problems you are experiencing. Then we can have a look. 

    Best regards
    Torbjørn

  • The initial mobile system I used was Android 10 but couldn't be upgraded. Later, I used Android 14, but it couldn't be upgraded the first time. If I try to use a program that can be upgraded to insert nrf52832 and perform DFU upgrade on it, then erase all the programs and burn my program, then I can upgrade using my phone, but when I change the public MAC address, I cannot upgrade again

    Here are the functions for me to change the public MAC and write to the UICR register

    void load_dvc_mac(void)
    {
    
        uint32_t err_code = 0;
        ble_gap_addr_t addr;
        err_code = sd_ble_gap_addr_get(&addr);
        APP_ERROR_CHECK(err_code);
    
        //  LOG("mac:%X:%X:%X:%X:%X:%X",dvc_ble_info.ble_mac[0],dvc_ble_info.ble_mac[1],dvc_ble_info.ble_mac[2], dvc_ble_info.ble_mac[3],dvc_ble_info.ble_mac[4],dvc_ble_info.ble_mac[5]);
    
        addr.addr[0] = dvc_ble_info.ble_mac[5];
        addr.addr[1] = dvc_ble_info.ble_mac[4];
        addr.addr[2] = dvc_ble_info.ble_mac[3];
        addr.addr[3] = dvc_ble_info.ble_mac[2];
        addr.addr[4] = dvc_ble_info.ble_mac[1];
        addr.addr[5] = dvc_ble_info.ble_mac[0];
    
        addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; // 公共类型的广播地址;  如果是静态随机,最高2位需要为11:  addr[5]|0xC0
    
        if (addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_STATIC)
        {
            addr.addr[5] = (addr.addr[5] | 0xC0);
        }
        // LOG("<%d-%d-%x>\n", addr.addr_id_peer, addr.addr_type, addr.addr[5]);
    
        err_code = sd_ble_gap_addr_set(&addr);
    
        APP_ERROR_CHECK(err_code);
    
    }
    

    void Save_mac_to_UICR(void)
    {
    
        NRF_UICR_Type t_uicr = {0};
        memcpy((uint8_t *)&t_uicr, (uint8_t *)NRF_UICR, sizeof(NRF_UICR_Type));
        memcpy((uint8_t *)&t_uicr.UNUSED0, &dvc_ble_info.ble_mac[0], 6);
    
        nrf_nvmc_page_erase((uint32_t)&NRF_UICR->UNUSED0); // 一次擦除连续写入
        nrf_nvmc_write_bytes((uint32_t)&NRF_UICR->UNUSED0, (uint8_t *)&t_uicr, sizeof(NRF_UICR_Type));
    
    }

  • My problem has been resolved because the version of the nrf connect software I am using is too low. I switched to the latest version 4.28 and everything has been resolved

  • Very good to hear. The best of luck with your project Slight smile

Related