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!