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

calling fds_write within a ble_evt_handler gets the SD or app stuck

I'm modifying the DFU example app in SDK 15.3, for the nRF52840.

attempting to call fds_record_update or fds_record_write within the context of app/main.c ble_evt_handler(), gets the system stuck.

Calling it elsewhere, for example from main(), works fine, and the internal flash gets updated correctly.

more specifically, my application captures a BLE_WRITE event, and then attempts to write a record to flash using fds_record_write or fds_record_update (depends if the record key already exists or not).

this attempt fails, since the FDS callback is never called, and the call waits indefinitely for the write operation to complete.

The FDS callback works correctly, if the FDS functions are called from main().

Parents
  • It sounds to me like you have a problem with your code. Executing blocking code in event handlers is not a good idea, you need to use flags or to schedule function calls to be executed in the main context.

    My guess is that the interrupt priority of the FDS module is lower than the BLE priority in your code. 

    1. fds_record_write is async and non-blocking. It causes a callback to be called when the write is complete
    2. after calling fds_record_write, I wait in a sleep-loop (not busy-loop) using
          while (fds_write_in_progress)
          {
              nrf_pwr_mgmt_run();
          }
          
          // or
          
          while(fds_write_in_progress)
          {
          #ifdef SOFTDEVICE_PRESENT
              (void) sd_app_evt_wait();
          #else
              __WFE();
          #endif
          }

    If there is only 1 task in the SoftDevice, which is responsible for handling ble_evt_handler and the fds event handler, then it will indeed block, since it will not get the chance to respond to the fds event.
    But, since my write operation is short (several bytes, which take a few microseconds which I believe the SD can spare), and I would like to keep my code simple, I hope there is a way to create a 2nd thread, one that will be coupled with the fds events and other non-BLE hardware events (ADC, I2C, and such).

  • Well, what's the benefit of having non-blocking APIs if you're wrapping them in while loops and waiting for the operation to finish? You're effectively converting the non-blocking code into blocking code.

    Also, I'm not sure if I understood correctly, but I think you have those while loops in the ble_evt_handler. As I said, if the interrupt priority of the FDS module is lower than the BLE priority, the FDS event won't ever preempt the BLE event, and therefore the flag won't ever be set. You would just be stuck in a while loop in the BLE event handler forever, and since you're already in the event handler, no other events can be processed.

    Lastly, you don't know how long the write operation is going to take. That's up to the softdevice to decide and it depends on how busy it is.

Reply
  • Well, what's the benefit of having non-blocking APIs if you're wrapping them in while loops and waiting for the operation to finish? You're effectively converting the non-blocking code into blocking code.

    Also, I'm not sure if I understood correctly, but I think you have those while loops in the ble_evt_handler. As I said, if the interrupt priority of the FDS module is lower than the BLE priority, the FDS event won't ever preempt the BLE event, and therefore the flag won't ever be set. You would just be stuck in a while loop in the BLE event handler forever, and since you're already in the event handler, no other events can be processed.

    Lastly, you don't know how long the write operation is going to take. That's up to the softdevice to decide and it depends on how busy it is.

Children
Related