DFU for external BLE Sensor

Hi,

  I have a current project that is based on the nRf52840.  This project acts both as a peripheral and a central.  I have a need to update the firmware on a remote BLE sensor using DFU, i.e., I need to do exactly what the nRfConnect application does when it updates a peripheral firmware via DFU.  My thought was to use the nRf52840 dongle and develop this code on my PC and then port it to my embedded system.  I also thought the best starting point would be the source code for the nRfConnect application which I would port it but I see from user comments that nordic did not release the source code for this.  Is it possible to get this source code or is there another example that demonstrates what I need to accomplish?

Thanks!

Parents
  • Hi,

      I am a bit confused and am hoping that you can help.  I have a Laird BT610 sensor and when I connect to it it does not show a Secure DFU service; however, I can do an over the air update of this sensor using nRfConnect and a proper firmware.bin file for this sensor. The sensor does advertise the SMP Serviice.  Is nRfConnect using this service to perform the firmware update?

    Thanks,

    Dave

  • Hi Dave,

    I am sorry for the confusion. I assumed your FW was based on our nRF5 SDK which uses a different DFU protocol.  So my initial reply does not apply to your case. As you may know, the nRF connect SDK is relying on the DFU protocol from MCUmgr for FW updates over BLE.

    Here are the MCUmgr libraries we use for our ios and android apps:

    https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager

    https://github.com/NordicSemiconductor/IOS-nRF-Connect-Device-Manager

    Best regards,

    Vidar

  • Nevermind, I solved it.  My project has a queue dir that contained the QUEUE files nrf_queue.h and nrf_queue.c from the earlier SDK.  I copied those files from the 17.1SDK and the code now builds.

    Thanks,

    Dave

  • Hi,

    I am having 2 very weird problems, one seems like it may be compiler related.  The other one I am clueless about.  I will explain both below.

    *************************    PROBLEM #1    ********************************

    See the code below:

    BLE_NUS_C_DEF(m_ble_nus_c);
    
    uint32_t ble_nus_c_init(ble_nus_c_t * p_ble_nus_c, ble_nus_c_init_t * p_ble_nus_c_init)
    {
        uint32_t      err_code;
        ble_uuid_t    uart_uuid;
        ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;
    
        VERIFY_PARAM_NOT_NULL(p_ble_nus_c);
        VERIFY_PARAM_NOT_NULL(p_ble_nus_c_init);
    
        err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_ble_nus_c->uuid_type);
        VERIFY_SUCCESS(err_code);
    
        uart_uuid.type = p_ble_nus_c->uuid_type;
        uart_uuid.uuid = BLE_UUID_NUS_SERVICE;
    
        p_ble_nus_c->conn_handle           = (uint16_t)0x1111;
        p_ble_nus_c->conn_handle           = BLE_CONN_HANDLE_INVALID;
        p_ble_nus_c->evt_handler           = p_ble_nus_c_init->evt_handler;
        p_ble_nus_c->handles.nus_tx_handle = (uint16_t)0x2222;
        p_ble_nus_c->handles.nus_tx_handle = BLE_GATT_HANDLE_INVALID;
        p_ble_nus_c->handles.nus_status_handle = BLE_GATT_HANDLE_INVALID;
        p_ble_nus_c->handles.nus_buffer_handle = BLE_GATT_HANDLE_INVALID;
        p_ble_nus_c->handles.nus_rx_handle = BLE_GATT_HANDLE_INVALID;
    
    	print_trace("ble_nus_c_init(1) p_ble_nus_c->conn_handle: %d", p_ble_nus_c->conn_handle);
        err_code = ble_db_discovery_evt_register(&uart_uuid);
    	print_trace("ble_nus_c_init(2) p_ble_nus_c->conn_handle: %d", p_ble_nus_c->conn_handle);
    
    	return err_code;
    }
    
    /**@brief Function for initializing the Nordic UART Service (NUS) client. */
    static void nus_c_init(void)//FA191118
    {
    	ret_code_t  err_code;
    	ble_nus_c_init_t init;
    
    	init.evt_handler = ble_nus_c_evt_handler;
    
    	err_code = ble_nus_c_init(&m_ble_nus_c, &init);
    	APP_ERROR_CHECK(err_code);
    }
    
    void main(void)
    {
        nus_c_init();
    }

    What is happening is that when I run this line of code:  p_ble_nus_c->conn_handle = (uint16_t)0x1111; it does not set the conn_handle to 0x1111, it sets it to 0x0011 and also sets part of the nus_tx_handle when this instruction is executed.  I have attached a screen shot of the debugger showing this.

    This started happening after I pulled the SMP implementation from the dev board project to our real project.  Our real project was based on a SDK that did not contain the GAT QUEUE stuff, i.e., nrf_ble_gq.c and nrf_ble_gq.h.  I therefore copied these file from the 17.1SDK into our real project.  I then had to replace the nrf_queue.c and nrf_queue.h in our real project with the files from the 17.1SDK to get the project to build.  The SMP service stuff is now working in our real project.

    *************************    PROBLEM #2    ********************************

    I can no longer initialize the watchdog.  Here is the code:

    static void watchdog_init(void)
    {
    	uint32_t err_code = NRF_SUCCESS;
    	//Configure WDT.
    	nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
    	err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
    	APP_ERROR_CHECK(err_code);
    	err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
    	APP_ERROR_CHECK(err_code);
    	nrf_drv_wdt_enable();
    }
    
    int main(void)
    {
        watchdog_init();
    }

    It is crashing inside watchdog_init() at this line:  err_code = nrf_drv_wdt_init(&config, wdt_event_handler);

    Look at this line:  nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;

    Below is a Debug Watch showing the values:

    When I single step through the functions I get to the function below

    nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
                             nrfx_wdt_event_handler_t  wdt_event_handler)
    {
        NRFX_ASSERT(p_config);
        nrfx_err_t err_code;
    
    #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
        NRFX_ASSERT(wdt_event_handler != NULL);
        m_wdt_event_handler = wdt_event_handler;
    #else
        NRFX_ASSERT(wdt_event_handler == NULL);
        (void)wdt_event_handler;
    #endif
        if (m_state == NRFX_DRV_STATE_UNINITIALIZED)
        {
            m_state = NRFX_DRV_STATE_INITIALIZED;
        }
        else
        {
            err_code = NRFX_ERROR_INVALID_STATE;
            NRFX_LOG_WARNING("Function: %s, error code: %s.",
                             __func__,
                             NRFX_LOG_ERROR_STRING_GET(err_code));
            return err_code;
        }
    
        nrf_wdt_behaviour_set(p_config->behaviour);
    
        nrf_wdt_reload_value_set((p_config->reload_value * 32768) / 1000);
    
    #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
        NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority);
        NRFX_IRQ_ENABLE(WDT_IRQn);
    #endif
    
        err_code = NRFX_SUCCESS;
        NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }
    

    I set a breakpoint at this line:  NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority);

    And then look at the p_config variable which should be filled with NRF_DRV_WDT_DEAFULT_CONFIG but it is not.  I have attached a debug screen showing this below.

    If after entering the nrfx_wdt_init function I stop at a breakpoint and  adjust the p_config  data values to be those of NRF_DRV_WDT_DEAFULT_CONFIG Before NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority); is called then I do not get a crash.   This is similar to the first problem, the compiler seems like it is messing things up.

    I am guessing that this may have been caused by adding in the SMP stuff to our real project since it did not happen prior to that.  I have been beating my head against a wall all day trying to make sense of this.  I am really hoping that you have some ideas.

    Thanks,

    Dave Patton

  • Hi,

      I am still struggling with the integration of the SMP stuff into our real app, I detailed some issues in the last message.  The funny thing is that the SMP stuff is working in our real app now.  The addition of the SMP stuff into our real app has broken so many things now and I believe it is because our real app is based on an earlier SDK.  Is it possible to implement the SMP stuff in an earlier SDK?

  • Hi,

    I'm afraid I can't think of any obvious explanations to the 2 problems you described. Is there chance you can share this project here or in a private support ticket so I can try to review the project configuration?

    davidpatton said:
    Is it possible to implement the SMP stuff in an earlier SDK?

    Yes, but it will be more work if you use an older old SDK version. Which SDK/Softdevice are you using?

  • Hi Vidar,

      I have been unable to locate the last 3 bytes of the SHA in the image trailer.  I know what these 3 bytes are because I collected the entire OTA process between the nRFConnect android app and the Peripheral that is being updated.  I have attached both the RAW image file that contains the image header and image trailer as well as a "c" based header file that shows the HEX representation of the data in the RAW image file.  The SHA that is being sent for the files attached is:  0xD1, 0x01, 0x34

    The CBOR object that is sent with this is as follows:  char cSha[] = {0x63, 0x73, 0x68, 0x61, 0x43, 0xD1, 0x01, 0x34};

    I don't think the SHA is in the image file but if I am wrong can you point out where the SHA is inside the image file.  If the SHA is not in the image file I will need to be able to calculate the SHA myself in c code in the nRF5 SDK.  In this case can you provide some example code that performs this calculation?

    Thanks,

    Dave Patton

    480-00099-R1.27.2.1632834244_FOTA.binImage1.27.2.h

Reply
  • Hi Vidar,

      I have been unable to locate the last 3 bytes of the SHA in the image trailer.  I know what these 3 bytes are because I collected the entire OTA process between the nRFConnect android app and the Peripheral that is being updated.  I have attached both the RAW image file that contains the image header and image trailer as well as a "c" based header file that shows the HEX representation of the data in the RAW image file.  The SHA that is being sent for the files attached is:  0xD1, 0x01, 0x34

    The CBOR object that is sent with this is as follows:  char cSha[] = {0x63, 0x73, 0x68, 0x61, 0x43, 0xD1, 0x01, 0x34};

    I don't think the SHA is in the image file but if I am wrong can you point out where the SHA is inside the image file.  If the SHA is not in the image file I will need to be able to calculate the SHA myself in c code in the nRF5 SDK.  In this case can you provide some example code that performs this calculation?

    Thanks,

    Dave Patton

    480-00099-R1.27.2.1632834244_FOTA.binImage1.27.2.h

Children
Related