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

ble_dfu_init() crashes on SDK12.3

I am adding dfu capabilities to my app on SDK12.3.

For that, I took the example on sdk12.3/examples/ble_peripheral/experimental_ble_app_buttonless_dfu and copied the relevant parts to my app,

When running ble_dfu_init() on my app, it crashes with the error:

SDH:WARNING:sd_ble_enable: RAM start should be adjusted to 0x20001ff8
SDH:WARNING:RAM size should be adjusted to 0x6008 
:INFO:running nrf_dfu_settings_init
:INFO:!!!!!!!!!!!!!!! Resetting bootloader settings !!!!!!!!!!!
:INFO:Erasing old settings at: 0x0003fc00
:INFO:Erasing: 0x0003fc00, num: 1
:INFO:Erase failed: 1
:ERROR:Erasing from flash memory failed.
APP_ERROR:ERROR:Fatal

Although most likely unrelated, I also included the warning messages, as the values suggested for RAM_START and RAM_SIZE are actually the ones I already have. Is there something I can do to fix this warning?

This is the call stack for ble_dfu_init(): ble_dfu_init() -> nrf_dfu_settings_init() -> nrf_dfu_settings_write() -> rf_dfu_flash_erase() -> fs_erase(), which then returns "FS_ERR_NOT_INITIALIZED"

nrf_dfu_flash_erase() is from the nrf_dfu_buttonless.c, that is part of the "experimental_ble_app_buttonless_dfu" example from sdk12.3.

Looks like the CRC is wrong and the app goes into reset mode, which makes sense because I haven't yet flashed the bootloader config, so there isn't any valid CRC information yet.

Questions:

1. How can I run the app with the buttonless dfu in debug mode, when I still don't know what the crc of the app will be?

2. How can I make it work in release mode when the bootloader settings are actually loaded with the correct information on the device?

3. How can I make sure fs_init() is called, so that in the event of a legitimate CRC check failure, the app is actually deleted?

Best regards,

Ricardo

Parents
  • I actually made some progress. The problem was a missing bootloader settings.hex file (More info can be found on case 256364).

    I  can currently get the bootloader to check my app with the CRC from the settings file, and run it.

    So now I get my app running and advertising the the "Experimental Buttonless DFU Service" characteristic. Next I just need to figure out how to use it.

    There must be something missing, because when I use the nordic nrfconnect android app, and click the "DFU" button on top, it gets stuck on "Starting the bootloader".

    I have read that to have the app booting to the DFU, we need to write 0x1 to the dfu service, which I assume is written to the characteristic and not the service. I also assume that that is what the android app is doing.

    So, if the android app is getting stuck, maybe my nrf app is either not detecting this value being written, or it is not being able to write the flag to tell the bootloader to boot into dfu mode, or the request for booting is failing.

    Are there any configurations I should include in my nfr project? How to approach this issue?

    Best regard,

    Ricardo

Reply
  • I actually made some progress. The problem was a missing bootloader settings.hex file (More info can be found on case 256364).

    I  can currently get the bootloader to check my app with the CRC from the settings file, and run it.

    So now I get my app running and advertising the the "Experimental Buttonless DFU Service" characteristic. Next I just need to figure out how to use it.

    There must be something missing, because when I use the nordic nrfconnect android app, and click the "DFU" button on top, it gets stuck on "Starting the bootloader".

    I have read that to have the app booting to the DFU, we need to write 0x1 to the dfu service, which I assume is written to the characteristic and not the service. I also assume that that is what the android app is doing.

    So, if the android app is getting stuck, maybe my nrf app is either not detecting this value being written, or it is not being able to write the flag to tell the bootloader to boot into dfu mode, or the request for booting is failing.

    Are there any configurations I should include in my nfr project? How to approach this issue?

    Best regard,

    Ricardo

Children
  • A bit more info:

    Am running my app, and using the android nrfconnect to write to the Experimental Buttonless DFU. The app provides an option to request the booting to the bootloader.

    1) When I issue this request from the android app (either the default action, or in advanced if I select "request"), on my nrf app i see that it executes the code I copied from the experimental buttonless dfu example.

    it calls: ble_dfu_on_ble_evt()->on_rw_authorize_req()->on_ctrlpt_write()

    which then calls sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply)

    and returns BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR.

    On ble_gatt.h, where this value is defined, it is stated that there is a configuration error on the client characteristic.

    On the hopes that it could be related with permissions, as the nordic example code I copied has the read and write permissions set to SEC_SIGNED, i tried changing them both to SEC_OPEN but got the same result

        //dfus_init.ctrl_point_security_req_write_perm        = SEC_SIGNED;
        //dfus_init.ctrl_point_security_req_cccd_write_perm   = SEC_SIGNED;
        dfus_init.ctrl_point_security_req_write_perm        = SEC_OPEN;
        dfus_init.ctrl_point_security_req_cccd_write_perm   = SEC_OPEN;

    2) If on the android app, I select advanced and the "Command", it calls instead:

    it calls: ble_dfu_on_ble_evt()->on_write(), because evt_id is BLE_GATTS_EVT_WRITE, but then fails because  p_evt_write->handle != p_dfu->control_point_char.cccd_handle.

    p_evt_write->handle is 0x16

    p_dfu->control_point_char.cccd_handle is 0x17

    3) If on the android app, I select instead the notify option, the same code if run than on case 2), the notifications for this characteristic are enabled, but still no booting to the boot loader happens.

    4) If I enable notifications, and then I execute the same as in case 1), then the call to sd_ble_gatts_rw_authorize_reply() succeeds. (Looks like progress Slight smile)

    But still, a bit down the road, there is a call to resp_send(), and immediately after, the condition on the if statement where the enter_bootloader() call is, fails.

    p_evt_write->data[0] == BLE_DFU_ENTER_BOOTLOADER is true

    but rsp_code == BLE_DFU_ENTER_BOOTLOADER is false, because it was set to DFU_RSP_SUCCESS, a few lines before:

        // reply to the write authorization
        do {
            err_code = sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply);
        } while (err_code == NRF_ERROR_BUSY);
    
    
        if (write_authorize_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS)
        {
            return;
        }
    
        // Start executing the control point write action
    
        switch (p_evt_write->data[0])
        {
            case BLE_DFU_ENTER_BOOTLOADER:
                rsp_code = DFU_RSP_SUCCESS;
                break;
    
             // Unrecognized Op Code
            default:
                rsp_code = DFU_RSP_OP_CODE_NOT_SUPPORTED;
                break;
        }
    
        resp_send(p_dfu, (ble_dfu_buttonless_op_code_t)p_evt_write->data[0], rsp_code);
    
        if (rsp_code == BLE_DFU_ENTER_BOOTLOADER
            && p_evt_write->data[0] == BLE_DFU_ENTER_BOOTLOADER)
        {
            enter_bootloader(p_dfu);
        }

    Is this a bug on the ble_dfu.c code from the example on SDK12.3, or am I still missing something?

    Best regards,

    Ricardo

  • More progress, but still not there yet.

    I changed the if statement on on_ctrlpt_write() to:

        //if (rsp_code == BLE_DFU_ENTER_BOOTLOADER
        if (rsp_code == DFU_RSP_SUCCESS
            && p_evt_write->data[0] == BLE_DFU_ENTER_BOOTLOADER)
        {
            enter_bootloader(p_dfu);
        }

    And then enabled notifications on the "Experimental Buttonless DFU" characteristic, and then pressed the write button and sent a "Request".

    This actually calls the enter_bootloader() function and produces the following log:

    APP:INFO:Indication for BLE_DFU is enabled
    APP:INFO:Device is entering bootloader mode!
    :INFO:Erasing old settings at: 0x0003fc00
    :INFO:Erasing: 0x0003fc00, num: 1
    :INFO:Erase failed: 1
    :ERROR:Erasing from flash memory failed.

    0x3fc00 is the location for the bootloader settings .hex.

    It makes sense that erasing this block and then restarting would bring the device into DFU mode, as the signature can't be verified.

    looking into the call to enter_bootloader(), it calls:

    nrf_dfu_settings_write(), which then calls nrf_dfu_flash_erase(), which returns with FS_ERR_NOT_INITIALIZED.

    So, it loks like what is stopping the erasing of the settings, is the fs not being initialized. How can this be done?

    Best regards,

    Ricardo

  • Yet another reply to my own posts:

    I added the fs_init() call to the enter_bootloader() function:

    static void enter_bootloader(ble_dfu_t * p_dfu)
    {
        if (p_dfu->evt_handler != NULL)
        {
            ble_dfu_evt_t evt;
    
            evt.type = BLE_DFU_EVT_ENTERING_BOOTLOADER;
    
            p_dfu->evt_handler(p_dfu, &evt);
        }
    
        s_dfu_settings.enter_buttonless_dfu = true;
    
        // NOTE: was added by me
        fs_init();
    
        (void)nrf_dfu_settings_write(flash_callback);
    
        /*
        TODO:
         - Save bond data
        */
    }

    And am also printing the err_code after the call to nrf_dfu_flash_erase().

    Now, when running the subscribe notifications + write "request", I get the following log:

    APP:INFO:Device is entering bootloader mode!
    :INFO:Erasing old settings at: 0x0003fc00
    :INFO:Erasing: 0x0003fc00, num: 1
    :INFO:Erase failed: 5
    :ERROR:Erasing from flash memory failed 5.
    

    Error code 5 corresponds to FS_ERR_INVALID_ADDR (Error: Address out of bounds).

    So, why is this address invalid? It looks like I am just missing some small setting somewhere.

    Can you please help?

    Also, what is the best place to call fs_init()?

    Many thanks and sorry for the long thread. I should have made all of this debugging and discovery in silence Slight smile

    Best regards,

    Ricardo

  • Since I have made some progress, and it looks like the almost everything is working, I will now close this case and suggest following up with case 256478, where I explain my latest road-block with getting the device to reboot after a successful request to go into DFU mode.

Related