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

Background DFU causes problem on FreeRTOS tasks

Env setup:

nrf52840 on PCA10056, SDK 16.0.0, S140, FreeRTOS, secure bootloader

Description:

I'm trying BLE background DFU in the application.

Had reference iot/background dfu code. But the final impl is porting dfu/ and ble_dfu/ under sdk/components/libraries/bootloader/ to my application.

The code works with nRF Connect and nRF Toolbox, to transfer dfu payload to flash bank1.

My application was based on ble_app_hrs_freertos/

During the porting, I need to enable the app scheduler for nrf_dfu_req_handler.c, to handler incoming payload written to flash asynchronously.

Disable the dfu timer, since the other BLE connection (e.g. heart rate) is still working

FreeRTOS tasks:

1. invoke nrf_sdh_freertos_init to create softdevice task

2. create a dfu task for consuming app scheduler

void dfu_thread(void * arg) {

    UNUSED_PARAMETER(arg);

    while (1) {

        app_sched_execute();

        osDelay(10);

    }

}

3. modify the log task, (disable the freertos idle task, not using the task suspend, wake up way), lower priority

while(1) {

    if (NRF_LOG_PROCESS()) {

        osDelay(1);

    } else {

        nrfx_gpiote_out_toggle(15);  - debug led

        osDelay(50);

    }

}

4. a log task to report alive

while(1) {

     NRF_LOG_DEBUG("alive");

    osDelay(1000);

}

Problem:

  • sometimes running the background dfu, after transfer complete, the system keeps normal running state, with "alive" message
  • sometimes running the background dfu, after transfer complete, the "alive" message won't show periodically.
    • in this situation, the debug led still blinking
    • press a button to print other log(in in_pin_handler), still working
  • sometimes running the background dfu, the transfer stuck, 
    • in this situation, debug led stopped
    • press a button to print other log, not working 
  • don't run background dfu, just BLE connect / read HRM / disconnect, repeat, the system keeps normal state

I suspect there's something wrong when running freertos with the app scheduler.

Wondering if anyone has similar setup, could share your experience and maybe some debug direction?

  • Hi,

    Things executing inside the app_scheduler could be doing something not compatible with FreeRTOS. FreeRTOS expects everything to be run in tasks and the app_scheduler is running outside the FreeRTOS control.

    I think we will need more information if you want help to debug this and probably it will be best if you open a private case and share your whole project with us so one of our FreeRTOS experts in tech support can take a look at it.

    Best regards,

    Marjeris

  • It's is FreeRTOS stack overflow.

    I'm also worry about the FreeRTOS compatibility with app_scheduler, fstorage queues, nrf_balloc, and softdevice task.

    So I did more to debug

    1. disable fstorage api, and its internal queues, always return success immediately

    2. modify the dfu, allocate 4k buffer in bss instead of nrf_balloc on every 244 bytes. and only call fstorage write every 4k data

    I still see task issues happen with both changes.

    Then I did more test,

    3. disable or re-arrange the FreeRTOS task create

    After this, sometimes device crash during dfu. This leads to the obvious reason that stack is overflow. 

    With uxTaskGetStackHighWaterMark and configCHECK_FOR_STACK_OVERFLOW, I can confirm the issue, and fix it by increase the stack size.

    One thing needs to mention,

    The task to run app_sched_execute took over 310 (x 4 bytes) units from task stack, even  larger than the softdevice task (256).

  • Monza,

    app scheduler is just a context changing API. app_sched_put will put the context into the queue and app_sched_execute will execute the context. 

    The most important thing is the context in which you are calling app_sched_execute. In your case, you are calling it inside the dfu_thread. This should work fine in terms of API usage. The app_scheduler is not probably the best API in terms of stack usage, you could probably reduce the queue buffers of the app_scheduler if you think that fits your design. 

    Second, we have not tested the usage of FreeRTOS and app_scheduler. app_scheduler is designed for someone who does not have the fancy features of the FreeRTOS. Inside FreeRTOS, normally you communicate between tasks using inter task communications like message queues or notifications. These inter-task communications are very stack friendly and use smaller stack for inter-task communication only as compared to app_scheduler.

    Lastly, what you are doing is something we have not tested, that said, it should work. the stack overflow problem is something understandable, please increase the stack size more, to get around the problem. You could phase out app_scheduler and try to port it to use FreeRTOS message queues instead.

Related