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

How can I properly debug my custom Buttonless DFU application?

I am attempting to create a custom Buttonless DFU application by building on top of the default example from the SDK. Specifically, I am merging the Buttonless DFU app with the BLE UART app and the TWI sensor reading app. Among those 2 other apps, I have made various changes for my custom device (not using the DK).

I have successfully been able to follow this tutorial and I can get the Nordic_Buttonless DFU app to work as expected. However, when I program my custom Buttonless DFU app to my device via nRF Connect (iOS), the new application code is never able to start and so it never advertises. On the nRF Connect app, everything works as it should: the .zip package is written and it even prints a  "Successful DFU!" notification when its done. But the code on the device never starts.

In order to debug this I have tried the following 2 things, without many results:

  1. Standard SEGGER Embedded Studio debugger
    • Connect to Target and "Erase All"
    • Open the DFU secure_bootloader example code (pca10040_s132_ble_debug), build and download to device
    • Then open the ble_app_buttonless_dfu example that I modified, build, then use the output .hex file to generate the .zip package to be sent using nRF Connect DFU on my iPhone
    • With this buttonless_dfu project open in SES, and the device in DFU mode, I click "Attach Debugger"
    • Then in the nRF Connect app, select the .zip package from before and perform the DFU
    • This is when the Debugger halts at the function 'errata_136(void)' in the file 'system_nrf52.c'. There is nothing printed in the Debug Terminal.
    • The code does not advertise itself after this, but I can reset the power and hold the button to re-enter DFU mode
  2. Embedded Studio debugger + bootloader settings with nrfutil/nrfjprog
    • Device is now back in DFU mode
    • I generate bootloader settings: nrfutil settings generate --family NRF52 --application myButtonless.hex --application-version 1 --bootloader-version 1 --bl-settings-version 2 settings.hex
    • With my custom Buttonless DFU project open in SES, I select "Attach Debugger"
    • Then I try to run the following commands:
    • nrfjprog -e
      nrfjprog --program "softdevice.hex" --verify
      nrfjprog --program "bootloader.hex" --verify
      nrfjprog --program myButtonless.hex --verify 
      nrfjprog --program settings.hex --verify
      nrfjprog --reset
    • This is when the Debugger halts at the function 'errata_136(void)' in the file 'system_nrf52.c'. There is nothing printed in the Debug Terminal.
      • I notice that it halts on the first command 'nrfjprog -e'
    • The code does not advertise itself after this, but I can reset the power and hold the button to re-enter DFU mode

I have added DEBUG to my preprocessor definitions and I have disabled optimizations. I have enabled NRF_LOG and NRF_LOG_BACKEND_RTT. Is this way of debugging correct? What should I do instead to produce a more informative debugging session? In the file 'system_nrf52.c', I found the following code:

/* Workaround for Errata 136 "System: Bits in RESETREAS are set when they should not be" found at the Errata document
       for your device located at https://infocenter.nordicsemi.com/index.jsp  */
    if (errata_136()){
        if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){
            NRF_POWER->RESETREAS =  ~POWER_RESETREAS_RESETPIN_Msk;
        }
    }

This led me to this link, which says:

// Apply the following code after any reset:
 
if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){
    NRF_POWER->RESETREAS =  ~POWER_RESETREAS_RESETPIN_Msk;
}

Any advice on where I should specifically put this IF STATEMENT in my Buttonless DFU app code? Thanks for the help :)

Parents
  • , the new application code is never able to start and so it never advertises. On the nRF Connect app, everything works as it should: the .zip package is written and it even prints a  "Successful DFU!" notification when its done. But the code on the device never starts.

     This we don't know. Probably, the application starts, but it doesn't start advertising because of an error, My guess is an APP_ERROR_CHECK(err_code); receiving an err_code != 0 before it starts advertising. This will cause a reset, and it will run into the same error, and hence you never see the advertisements. 

    Regarding your approach 2:

    Can you please try to run your commands (nrfjprog) first, and then attach the SES project, set a breakpoint in the start of main.c, and then reset the device using the UI:

    Is the breakpoint reached then?

    If so, what happens when you press resume again?

    Do you see anything in the debug terminal? If not, what is your NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED in your application's sdk_config.h? Can you try to set it to 0? If you need to perform this change, remember to generate the bootloader settings file again after you have compiled.

  • Hey Edvin,

    I did what you mentioned and I cannot get the device to reach the Breakpoint at the beginning of main.c. I have included my code that programs the device for reference.

    Regardless of which nrfutil settings generate function I use (between the commented and uncommented options in the code snippet below), whenever I Attach Debugger in SES, I am brought to the file 'nrf_log_frontend.c', specifically to the func: int32_t nrf_log_backend_add(nrf_log_backend_t const * p_backend, nrf_log_severity_t severity).

    When I click the RESTART button to restart the Debugger, it never goes to the Breakpoints that I set in main.c and just goes straight to nrf_log_backend_add(). Nothing is printed to the Debug Terminal.

    Setting NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED = 0 didnt make any difference that I was able to detect. 

    #! /bin/bash
    
    ## Compile bootloader and application:
    #boot_make='../nrf-sdk/examples/dfu/secure_bootloader/pca10040_s132_ble/armgcc/'
    boot_make='../nrf-sdk/examples/dfu/secure_bootloader/pca10040_s132_ble_debug/armgcc/'
    boot=${boot_make}_build/nrf52832_xxaa_s132.hex
    softdevice='../nrf-sdk/components/softdevice/s132/hex/s132_nrf52_7.0.1_softdevice.hex'
    app_make='../nrf-sdk/examples/ble_peripheral/ble_app_buttonless_dfu/pca10040/s132/armgcc/'
    app=${app_make}_build/nrf52832_xxaa.hex
    
    make -C "$boot_make"
    make -C "$app_make"
    
    nrfutil settings generate --family NRF52 --application "$app" --application-version 1 --bootloader-ve    rsion 1 --bl-settings-version 2 settings.hex
    
    #nrfutil settings generate --family NRF52 --application "$app" --application-version 1 --bootloader-v    ersion 1 --bl-settings-version 2 --softdevice "$softdevice" --key-file private.key settings.hex
    
    nrfjprog -e
    nrfjprog --program "$softdevice" --verify
    nrfjprog --program "$boot" --verify
    nrfjprog --program "$app" --verify
    nrfjprog --program settings.hex --verify
    
    nrfjprog --reset   

    Any advice?

Reply
  • Hey Edvin,

    I did what you mentioned and I cannot get the device to reach the Breakpoint at the beginning of main.c. I have included my code that programs the device for reference.

    Regardless of which nrfutil settings generate function I use (between the commented and uncommented options in the code snippet below), whenever I Attach Debugger in SES, I am brought to the file 'nrf_log_frontend.c', specifically to the func: int32_t nrf_log_backend_add(nrf_log_backend_t const * p_backend, nrf_log_severity_t severity).

    When I click the RESTART button to restart the Debugger, it never goes to the Breakpoints that I set in main.c and just goes straight to nrf_log_backend_add(). Nothing is printed to the Debug Terminal.

    Setting NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED = 0 didnt make any difference that I was able to detect. 

    #! /bin/bash
    
    ## Compile bootloader and application:
    #boot_make='../nrf-sdk/examples/dfu/secure_bootloader/pca10040_s132_ble/armgcc/'
    boot_make='../nrf-sdk/examples/dfu/secure_bootloader/pca10040_s132_ble_debug/armgcc/'
    boot=${boot_make}_build/nrf52832_xxaa_s132.hex
    softdevice='../nrf-sdk/components/softdevice/s132/hex/s132_nrf52_7.0.1_softdevice.hex'
    app_make='../nrf-sdk/examples/ble_peripheral/ble_app_buttonless_dfu/pca10040/s132/armgcc/'
    app=${app_make}_build/nrf52832_xxaa.hex
    
    make -C "$boot_make"
    make -C "$app_make"
    
    nrfutil settings generate --family NRF52 --application "$app" --application-version 1 --bootloader-ve    rsion 1 --bl-settings-version 2 settings.hex
    
    #nrfutil settings generate --family NRF52 --application "$app" --application-version 1 --bootloader-v    ersion 1 --bl-settings-version 2 --softdevice "$softdevice" --key-file private.key settings.hex
    
    nrfjprog -e
    nrfjprog --program "$softdevice" --verify
    nrfjprog --program "$boot" --verify
    nrfjprog --program "$app" --verify
    nrfjprog --program settings.hex --verify
    
    nrfjprog --reset   

    Any advice?

Children
  • Hi,

    cor10 said:
    I did what you mentioned and I cannot get the device to reach the Breakpoint at the beginning of main.c

    This may be because of a small but important detail when debugging with a bootloader. The bootloader will check the integrity of the application, and only start it if it is valid  (hash remains the same). So if you want to keep the bootloader in place but debug while modifying the application code, you need to change the bootloader so that it does not check the application hash. I recommend you simply modify crc_on_valid_app_required() in <SDK>/components/libraries/bootloader/nrf_bootloader.c so that it always returns false and flash that bootloader. Then you can debug your application as expected even though the bootloader is present and runs first. Note that you still need to flash a bootloader settings page initially or do an initial DFU update to flag that a valid app is present, though.

  • Hi there Einar, thanks for your help with this. I finally was able to Debug and found the point at which my program is breaking! THANK YOU! In general, should I keep the changes made to nrf_bootloader.c for future development/debugging? Or should that quick fix be undone moving forward?

    I know that this following information is not really appropriate on this ticket, but for reference I will include a summary of my bug (I can make a new ticket, or research previous tickets, so no need to provide a solution, unless its an easy one for you). The error I get is ERROR 7 [NRF_ERROR_INVALID_PARAM] and it comes from calling ble_advertising_init(). Following the Debugger through this call to ble_advertising_init(), I am taken to ble_advdata_encode(). In this function, there is the if-statement:

        // Encode 'complete' uuid list.
        if (p_advdata->uuids_complete.uuid_cnt > 0)
        {
            err_code = uuid_list_encode(&p_advdata->uuids_complete,
                                        BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
                                        BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
                                        p_encoded_data,
                                        p_len,
                                        max_size);
            VERIFY_SUCCESS(err_code);
        }

    The SES Debugger then steps into the above execution of uuid_list_encode() and then again it steps into uuid_list_sized_encode() (for 16bit UUIDs). In uuid_list_sized_encode(), there is a for-loop that iterates through the UUIDs provided by the application, and my app successfully handles the first UUID, which is the default Buttonless DFU UUID provided by the NRF SDK Buttonless DFU example (this is expected since I got the default example to work perfectly). During the second iteration of this for-loop, aka during the processing of my newly added NUS UUID (which I believe I have added erroneously), the whole system breaks when it tries to run VERIFY_SUCCESS() on the output of sd_ble_uuid_encode().

    It seems to me that there is some issue with the way I am adding the NUS Service UUID to the default Buttonless DFU app. For reference, here is the code that introduces this UUID in my application:

    static ble_uuid_t m_adv_uuids[]         = 
    {
        {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
        {BLE_UUID_NUS_SERVICE, 0x02} //NUS_SERVICE_UUID_TYPE}
    };

    I wonder if there is something obviously incorrect with this array, or if there are other crucial steps I need to take to add this UUID properly. For reference, I made sure NRF_SDH_BLE_VS_UUID_COUNT is set to 2 for each UUID in this app.

    Following other posts online, I made an edit to my code to call services_init() before calling advertising_init() and this produced a different error. This time the errors produced when I follow the same Debugging path as above switch between SOFTDEVICE: INVALID MEMORY ACCESS and NRF_ERROR_INVALID_ADDR (Invalid pointer supplied) when trying to execute sd_ble_uuid_encode(). And this time around, the error occurs on the first iteration of the for-loop in uuid_list_sized_encode(), meaning its breaking with the default UUID.

Related