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

Buttonless OTA Hanging

I am using nRF52840 with SDK16 building with armgcc and trying to intergrate buttonless OTA into my project. 

App details:

  • Based on the ble_app_hrs_freertos example project
    • Peer manager disabled as it was causing issues with USB DFU
  • CDC ACM enabled

Bootloader details:

  • Based on secure_bootloader pca10056_usb
    • Configured for buttoned DFU

As far as I can tell, I have migrated the necessary code from ble_app_buttonless_ota into my app code and from secure_bootloader pca10056_ble into my bootloader. When I try and run the code, I am seeing potentially 2 issues.

  1. I get a hang on boot when calling ble_dfu_buttonless_async_svci_init() -> nrf_dfu_svci_vector_table_set()
  2. If I comment out ble_dfu_buttonless_async_svci_init(), then my app code can fully run without problem. But if I attempt to send OTA  from nRF Toolbox DFU, I seem to get stuck in a loop of attempting to enter the bootloader but instead resetting into the app code after some time. This goes on until I reprogram the app code entirely.
    1. I have used the debugger to get to where I know it is getting through the various events of ble_dfu_evt_handler(), but compared to the raw example code, I do not see my app code get to app_shutdown_handler()

Anyone have any ideas as to what is going on?

Parents
  • Hi Kyle, 

    If you remove ble_dfu_buttonless_async_svci_init() the application won't be able to call the svc function provided by the softdevice, namely nrf_dfu_set_adv_name() function. This function allow the bootloader to change the advertising name to the name desired by the application. This may not be the functionality that you need. 

    But you need to skip the call for nrf_dfu_set_adv_name() and nrf_dfu_set_adv_name_on_sys_evt in the code. 

    You may need to check your bootloader to see if it's configured the svci functions correctly. 

    But anyway, in the end of the day the only thing the application need to do to switch from application to the bootloader is to write to the GPREGRET register value BOOTLOADER_DFU_START and trigger a soft reset (please have a look at ble_dfu_buttonless_bootloader_start_finalize() function). The bootloader will read the GPREGRET register and decide to enter the DFU booting or not. 
    You may need to trigger a disconnection to the application before that, but that's not obligated (just to avoid the delay to wait for the connection timeout) 

  • Hello, 

    Thank you for your response. I confirmed that svci is configured for both the application and the bootloader.

    With more investigation today, I found that the device was successfully getting into DFU, but after some time, the nRF Toolbox App would report "Upload Failed: DFU_DEVICE_DISCONNECTED". I was able to get the device into DFU mode and see if it was advertising and saw that it was as "DfuTarg" as expected from the sdk_config. But I am confused why the advertising name was able to change from the product name since I still have ble_dfu_buttonless_async_svci_init() commented out.

    Since I also have USB DFU implemented, I attempted to disable the USB DFU functionality so that my bootloader was only configured for OTA DFU. With that version of the bootloader, I was able to perform an OTA using the "nRF Connect" app (saw in another post that it might work better).

    So now the question has evolved to why does having USB DFU functionality enabled prevent OTA from staying connected and completing? Using the "--print-memory-usage"" GCC flag, I see that the bootloader is using 45% of  the reserved 56 kB of FLASH, so it doesn't seem like a memory issue.

    Thanks!

  • Hi Kyle, 
    Sorry for late reply I was on vacation last week. 
    I don't think there is much modification between the SDK v15.2 and SDK v16. 
    I would suggest to have a look at my example and try to port the same in SDK v16. 

    If the issue persist we would need to debug the bootloader and check what caused the issue. 

  • Hello, 

    I was able to debug the bootloader and found where it was failing. After calling the transport init for BLE, I was able to step through usb_dfu_transport_init() ->  nrf_drv_power_init() and was returning NRF_ERROR_INVALID_STATE below at line 10:

    ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const* p_config)
    {
        if (m_initialized)
        {
            return NRF_ERROR_MODULE_ALREADY_INITIALIZED;
        }
    
        if (nrf_sdh_is_enabled())
        {
            return NRF_ERROR_INVALID_STATE;
        }
        
        if (p_config == NULL)
        {
            p_config = &m_drv_power_config_default;
        }
    
        ret_code_t err_code = nrfx_power_init(p_config);
        if (err_code == NRFX_SUCCESS)
        {
            m_initialized = true;
        }
        return err_code;
    }

    I tried to figure out if this was an issue with any of the sdk_config flags but had no luck. After reading https://devzone.nordicsemi.com/f/nordic-q-a/25890/ble-and-usb-can-t-work-at-the-same-time-on-nrf52840, I ended up returning SUCCESS here instead and have been able to successfully perform OTA and USB DFU.

    Does this make sense to you? I worry about whether or not this is the correct fix. I checked SDK v17 to see if this had been changed and it had not. 

  • Hi Kyle, 
    nrf_drv_power_init() should be called before the softdevice initialized. You may want to change the location that the function is called to before softdevice initialized (inside ble_stack_init() in nrf_dfu_ble.c ) 
    The main purpose for the nrf_drv_power is to handle/detect USB power event. 

  • Is the handling/detecting of USB power events to help with USB enumerating as a DFU device?

    I tried your suggestion of calling nrf_drv_power_init() before the softdevice is initialized in ble_stack_init() and reverted the changes I made to nrf_drv_power_init(). I could not get USB to enumerate as a DFU device with those changes. With a breakpoint in nrf_drv_power_init() I saw that it got called twice, once by ble_stack_init() and again by usb_dfu_transport_init().

    Falling back to my original changes, I did see it enumerate. Is there something else that I might be missing to go along with your suggestions to get USB to enumerate in DFU?

  • Hi Kyle, 
    If it's called in ble_stack_init() then you should not call it again in usb_dfu_transport_init().

    Or you can just ignore the error if you receive NRF_ERROR_MODULE_ALREADY_INITIALIZED. 

Reply Children
No Data
Related