Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Issues with Buttonless DFU added to existing project

Hello:

We have a BLE project running on the BMD-300 from Rigado for which we want to add BLE DFU functionality. I am basing our development on the "ble_app_buttonless_dfu" project as well as the "secure_dfu_ble" for the bootloader. We are using NRF SDK 14.0.0 and IAR for our development. I have followed the great tutorial at "https://devzone.nordicsemi.com/b/blog/posts/getting-started-with-nordics-secure-dfu-bootloader" to generate the bootloader, bootloader options for application, merge bootloader+bootloader options, generate application,and load them up (also SD) with NRF GO. I set up the RTT logger on the main application.

I erase the chip, then I program the SD, then the bootloader, and then the application, and reset power. The unit always seems to be stuck in PC 0x13d6e of SoftDevice. Since it is a Hex I have no idea what it is doing there! I always have to attach to the running target and hit reset for the device to start performing properly. 

I was having issues with the bootloader not setting the vector table correctly to the app, so when I initialized my other HW the interrupts were getting sent to the bootloader!

To remedy this, I added a call to "nrf_dfu_svci_vector_table_unset()" at the start of the program.

However, now I am getting an NRF_ERROR_INVALID_STATE error on "sd_softdevice_enable()" when I initialize the stack (on ble_stack_init() ).

How is the correct way to add the Buttonless DFU functionality to the device? Is there an order of function that I should follow? should the DFU initialization happen before the HW initialization so the code sets up the correct vector table?

If you could provide any guidance I would be very grateful! I have spend too much time on this.

Thanks!

  • I solved a minor issue, the setting for the bootloader button on the "secure_dfu_ble" example was set up incorrectly, so maybe that was the issue with the need to reset multiple times until it worked. The main issue, however, is still present!

    I tested using the "ble_app_buttonless_dfu" application to upload my application and the upload works. However it still crashes on sd_softdevice_enable() with an NRF_ERROR_INVALID_STATE  error.

    Can it be that the stack is already initialized by the bootloader and when it enters my code and initializes again I get this error?I am not sure what the issue is; I see that the "ble_app_buttonless_dfu" example initializes the BLE stack very early on and it does not de-initialize it. I am doing the same thing. 

    My code in main.c (needs some cleanup...):

      int main(void)
    {
    int32_t err_code = 0;
        int32_t task_error = 0;
       
        
        nrf_delay_ms(1000); //wait after power up
        
        err_code  = NRF_LOG_INIT(NULL);
        NRF_LOG_DEFAULT_BACKENDS_INIT();
        //nrf_dfu_svci_vector_table_unset();
        NRF_LOG_INFO("Hello!");
        NRF_LOG_FLUSH();
        SEGGER_RTT_WriteString(0, "RTT initialized\n");
         
         BLE_init(); //Chrashes inside here
         ...
         }

    Code inside BLE_Init

    int32_t BLE_init(void)
    {
        bool erase_bonds;
        uint32_t err_code;
    
        // Initialize
        ble_stack_init(); //Crashes inside here
        err_code = app_timer_init();
        //...
        }

    Crashes on "err_code = nrf_sdh_enable_request();" with a return error of NRF_ERROR_INVALID_STATE.

    Thanks

  • Another test, it seems that if I do the following I can get it to work:

    *Disable WDT on main application (Don't know as of now how to handle WDT feeding on Bootloader, will search around...)

    *Assume that SD can be already initialized: Added this code to "ble_stack_init()"

    static void ble_stack_init(void)
    {
        ret_code_t err_code;
        ble_cfg_t ble_cfg;
        if(nrf_sdh_is_enabled() == false){
          err_code = nrf_sdh_enable_request();
          APP_ERROR_CHECK(err_code);
        }else
        {
          NRF_LOG_INFO("SD is already enabled!");
        }
        ...
        }

    *Assume LF clock is already initialized (on a function after BLE initialization that sets our App's HW):

    ->Note protection of "nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_Xtal);"

    int32_t CLK_lfclk_config(void)
    {
      int32_t status = 0;
      status = nrf_drv_clock_init();
      if(status != NRF_ERROR_MODULE_ALREADY_INITIALIZED) //Assumption
      {
        nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_Xtal);
        //APP_ERROR_CHECK(err_code);
    
        nrf_drv_clock_lfclk_request(NULL);
      }else
      {
        status = 0;
      }
      
      if (status !=0)
        return ((int32_t)CLOCK_ERROR);
      else
        return (0);
    }

    I kind of understand that the BLE bootloader may initialize the SD and the LF clock, but I am worried to not understand why the "secure_dfu_ble" did not do this. I also worry that I am missing something that might come back to byte me! Is there a list of components to take care of when adding buttonless DFU? Or, am I doing something wrong and because of that I need the changes I implemented?

    Thanks!

  • Hello, 

    The bootloader disables the softdevice before branching to the main application, so it should not return invalid state when you try to re-enable it from the app. Have you made any changes to the default bootloader code that may have changed this behavior?  Also, do you have a LF crystal in your design, or are you using the internal RC oscillator? 

    *EDIT*:

    Related to nrf_sdh_enable_request() returning invalid state: are you doing any fstorage operations prior to ble_stack_init()? Looks like the fstorage softdevice backend may enable the softdevice through nrf_sdh_request_continue();

  • Thank you for your response!

    I have not made any changes to the code of the BLE DFU (Other than WDT calls to feed the WDT on the bootloader!). As you can see with the code above the main application only does NRF_LOG and RTT - related code before calling BLE_init() which in turn calls ble_stack_init(). Could you please point me to where the DFU code disables the SD so I can debug and see if it hits that place? I could not find it!

    Thanks!

Related