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

How to avoid busy waiting on async operations and gracefully preserve code flow

In my code I am fully embracing the async way when using peripherals, but the problem is that my code is becoming more and more complex due to having to break down all operations in multiple parts with cascading callbacks. Suppose I have to implement a protocol on a peripheral that requires something like:

sendA()

sendB()

sendC()

... in sequence, maybe also handling intermediate errors. This is becoming a mess like:

sendA_async(sendA_callback)

[in sendA_callback] sendB_async(sendB_callback)

[in sendB_callback] sendC_async(sendC_callback)

The lazy obvious solution is to forget about async events and write code just like in some examples:

sendA()

while(!completed_A) {}

sendB()

...

But this increases power consumption, causes problems in IRQs. I've also seen something better like this:

sendA()

while(!completed_A) { __WFE() }

sendB()

...

But what if I am using SoftDevice, app timers, scheduler, logs, etc? In my main loop the "sleep loop" is:

for (;;) {

// Run application scheduler

app_sched_execute();

// Process logs if required

if (NRF_LOG_PROCESS() == false) {

// Manage power, sleep if required

ua_power_manage();

}

}

Can I put this code in a function and use it for waiting? I'm not so sure...

Also, going back to the original async code, using a state machine to keep track of what's going on does not make the code much more easy to handle if it's more complex than a simple example.

What's the preferred/suggested pattern for handling with async code, preserving state, avoiding resource conflicts when using multi step async code?

Thanks!