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

Avoid first OTA DFU

I am adding a bootloader with BLE OTA upgrades. I am using SDK 11.0.0 and I based my bootloader in examples\dfu\bootloader. I can only fit a single bank upgrade (I upgrade FW, SD and bootloader, alltogether) so I am using the dfu_single_bank.c file. The example bootloader checks the first byte in BOOTLOADER_SETTINGS_ADDRESS to know whether there is a valid application loaded in the flash and whether to start it or not. That byte is not initialized so by default is 0 and the bootloader starts in DFU mode.

I did as suggsted in an answer here and I changed the following line:

 uint8_t  m_boot_settings[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS))) __attribute__((used)) ;

to:

uint8_t  m_boot_settings[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS))) __attribute__((used)) = {BANK_VALID_APP};

That way I can flash the SD, bootloader and application with nRFGO and the first time the bootloader boots it starts the application.

The problem now is that DFU never actually starts. When I try it from the Android app, the phone connects. But when DFU starts, my device resets and the application on the nrf52832 starts (I guess the bootloader starts and then it starts the application).

I have no further information as I am still trying to undestand it fully. Anyway has anyone came accross this problem and is there any better way to avoid this first OTA DFU so that when the app+bootloader are flashed from nRFGO the application starts straight away?

  • Could you debug your bootloader and check the value of the dfu_start variable when you reach the

    if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START)))
    

    statement? It should be set to true if you enter the bootloader via your application, i.e. you write to the GPREGRET register in your application and then branch to the bootloader. In the bootloader the dfu_start variable is set as follows

    dfu_start  = app_reset;
    app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START);
    
  • I think I figured it out. By changing the lines above, every time the bootloader starts the startup code writes 0x1 at m_boot_settings[CODE_PAGE_SIZE]. At some point the bootloader writes a value on that position and restarts and then, the old value is lost as the startup code writes a 0x1 there again.

    Instead of doing that, now I use nrfjprog.exe to write a 0x1 there right after I flash the application. Something like this:

    SET APP_VALID_ADDRESS=0x0007F000
    SET APP_VALID_VALUE=0x1
    nrfjprog.exe --family NRF52 --memwr %APP_VALID_ADDRESS% --val %APP_VALID_VALUE%
    

    Now the bootloader works all right (except by the fact I don't have the device manager enabled, but that's another story).

    Could anyone confirm what I said?

  • Hello Bjorn. thanks for your answer. I can't debug the bootloader. I found some docs explaining how to do it but I didn't go through them yet. Anyway it appears I figured out a solution, please see the answer below

  • Hi Genis, the method you describe here is correct. The method described in your question, i.e. setting

    uint8_t  m_boot_settings[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS))) __attribute__((used)) = {BANK_VALID_APP};
    

    should also work. The bootloader will start the application if the BANK_APP_VALID flag is set or enter bootloader mode i.e. start advertising as DfuTarg and wait for commands from the DFU controller.

  • For some reason I can't understand the code above did not work for me and I saw the behavior I described. Maybe there is some side problem, I do not know. Anyway I need to write some other values when I flash the device (device name, initial configuration, etc.) so it is all right to me to do it with nrfjproj. Please feel free to delete the question if you think it may be misleading.

Related