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

Trying to Integrate DFU and now encountering bootloops due to sd_softdevice_enable()

I've been going off of the Buttonless DFU example to integrate DFU functionality into an existing project on a custom board. While I seem to have added the necessary includes and code to compile without errors, my board bootloops when it executes the code. After stepping through the code in debug mode in Eclipse, it appears that the hard fault occurs at the sd_softdevice_enable_request(), in particular when it makes the SVCALL to sd_softdevice_enable(). I'm unable to see what the actual signal returns to induce the failure.

I modified my linker script to match the memory layout of the buttonless DFU example. I also added relevant DFU configuration code to sdk_config.h, and then integrated the appropriate methods for initializing DFU from the example (app_shutdown_handler, ble_dfu_evt_handler, pm_evt_handler, peer_manager_init, delete_bonds, advertising_start) as well as necessary additions to services_init() and ble_init().

The curious thing is that all of these additions occur after the call to sd_softdevice_enable_request(). This makes me suspect that the problem has to do with changes to sdk_config.h, or changes to my Makefile. The biggest changes to sdk_config.h appear to be changing PEER_MANAGER_ENABLED from 0 to 1, PM_CENTRAL_ENABLED from 1 to 0, NRF_SDH_BLE_GAP_EVENT_LENGTH 7 to 3, NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247 to 23, NRF_SDH_BLE_SERVICE_CHANGED 0 to 1.

For the Makefile, the memory layout was altered from

MEMORY
{
  FLASH (rx) : ORIGIN = 0x23000, LENGTH = 0x5D000
  RAM (rwx) :  ORIGIN = 0x20002A68, LENGTH = 0xD598
  
}

to

MEMORY
{
  FLASH (rx) : ORIGIN = 0x23000, LENGTH = 0x55000
  RAM (rwx) :  ORIGIN = 0x20002180, LENGTH = 0xde80
  
}

with an additional section:

  .svc_data :
  {
    PROVIDE(__start_svc_data = .);
    KEEP(*(.svc_data))
    PROVIDE(__stop_svc_data = .);
  } > FLASH

I can include any additional files or sections of code. I realize this isn't very much to go off of, but I'm scratching my head over this, seeing as the bootloop is occurring at a point in the code in which things have not been altered prior to attempting to integrate the DFU code.

EDIT: there is one other detail I forgot to mention that may be a major factor here: In order to resolve an Implicit Declaration error within my build, I included "nrf_sdm.h" within the file initializing my BLE stack. This wasn't included in the example code, perhaps its resulting in improper initialization of the soft device.

  • I'm on SDK 14.2

    I set the optimization flags to be -O0 and -g3 when building, set a breakpoint in app_error_handler_bare(), and ran a debug session. The breakpoint does not get triggered.

    When I step through the app, the furthest I can get is Line 310 in nrf_sdm.h:

    SVCALL(SD_SOFTDEVICE_ENABLE, uint32_t, sd_softdevice_enable(nrf_clock_lf_cfg_t const * p_clock_lf_cfg, nrf_fault_handler_t fault_handler));

    After which things seem to blow up, and I error out with the following:

    No source available for "<signal handler called>() at 0xfffffff9" 

    Via the disassembly log:

    fffffff9:   Unable to retrieve disassembly data from backend.

    Perhaps I am missing something, but I don't see what's getting returned by sd_softdevice_enable(). In my interpretation, it seems that things blow up right before something gets returned.

    The disassembly at 0x90c is the following:

  • I reckon that you have flashed the SoftDevice to the nRF52832. What LF clock configuration( nrf_clock_lf_cfg_t p_clock_lf_cfg) are you passing to the sd_softdevice_enable call? Does your custom board have the external 32kHz crystal(LFXO) on it or not? 

  • The nrf_clock_lf_cfg_t configuration is coming from nrf_sdh.c which is defined as the following (Line 217):

        nrf_clock_lf_cfg_t const clock_lf_cfg =
        {
            .source        = NRF_SDH_CLOCK_LF_SRC,
            .rc_ctiv       = NRF_SDH_CLOCK_LF_RC_CTIV,
            .rc_temp_ctiv  = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
        #ifdef S140
            .xtal_accuracy = NRF_SDH_CLOCK_LF_XTAL_ACCURACY
        #else
            .accuracy      = NRF_SDH_CLOCK_LF_XTAL_ACCURACY
        #endif
        };

    which evaluates to:

        nrf_clock_lf_cfg_t const clock_lf_cfg =
        {
            .source        = 1,
            .rc_ctiv       = 0,
            .rc_temp_ctiv  = 0,
        #ifdef S140
            .xtal_accuracy = 7
        #else
            .accuracy      = 7
        #endif
        };
    

    We do have a 32.768kHz external crystal in place.

  • Do you see any change in the behaviour if you switch to the internal RC, i.e. 

    #define NRF_CLOCK_LFCLKSRC      {.source        = NRF_CLOCK_LF_SRC_RC,            \
                                     .rc_ctiv       = 16,                                \
                                     .rc_temp_ctiv  = 2,                                \
                                     .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM}

  • I realized I made a bit of an error - I did have a NRF_CLOCK_LFCLKSRC defined in my custom_board.h file, which used to be defined to be the following:

    #define NRF_CLOCK_LFCLKSRC      {.source       = NRF_CLOCK_LF_SRC_XTAL,      \
                                     .rc_ctiv      = 0,                          \
                                     .rc_temp_ctiv = 0,                          \
                                     .accuracy     = NRF_CLOCK_LF_ACCURACY_20_PPM}

    When I replaced this block with the one you provided (effectively altering the values of rc_ctiv from 0 to 16, and rc_temp_ctiv from 0 to 2), I find that I still see the exact same behavior.

    What's curious, is that when I look at the values of clock_lf_cfg in nrf_sdh.c via the debugger when stepping through the code, rc_ctiv and rc_temp_ctiv are both set to 0. So I suspect that my definition is being overwritten, though I'm unsure of where this is occurring.

    Do I need to modify sdk_config.h as well?

    // <o> NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval.
    #ifndef NRF_SDH_CLOCK_LF_RC_CTIV
    #define NRF_SDH_CLOCK_LF_RC_CTIV 0
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature.
    // <i> How often (in number of calibration intervals) the RC oscillator shall be calibrated
    // <i>  if the temperature has not changed.
    
    #ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV
    #define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0

    (altering relevant values to 2 and 16 still sees a failure at initialization of the softdevice, though I don't believe I'm bootlooping anymore)

    Thanks for all the help so far. If it would make things easier, I could open a private ticket with my full project enclosed.

Related