In an embedded application programmed on C on ARM7 (with portability requirements), currently using a commercial priority-based preemptive RTOS, we need to remove that RTOS and any RTOS dependency per customer mandate. We have 8 tasks using many HW interfaces, sleep statements, I2C communications. As it is, the SW makes good use of RTOS features for simplification of the code, though timing requirements would be manageable without an RTOS.
Several functions, including routines called in many places currently implement sequences of blocking (for that thread) calls to I2c driver functions, sleep statements, etc. Based on the premise that polling on I2C calls / sleep is not acceptable for customers, such calls must then be non-blocking and return. The issue of course is to "come back" to the "statement", possibly 4 calls down from top-level task entry, when I2C completes or sleep time has elapsed.
I'm converging towards a hierarchical state machine design for each task, with a simple scheduler on top. But handling several routines, which used to make sequences of then-blocking calls and now become each a state machine, which can get called in several places and at different function call depths, seems to necessitate an explicit stack feature for each task, so that each time I start a sub-state-machine, I can allocate the states for that process and push them on the "state-stack" of that task, so that the next scheduler call to that task will be able to go down all the hierarchical states to continue processing where it "left off".
Can you see other design architectures applicable to the issue, considerations for fast porting of the code to a non-preemptive paradigm, or point to thought-enriching resources and discussions about "RTOS-removal" techniques and designs?
The three answers all together paint a good picture of state machine-based development relevancy and the associated tools to avoid re-inventing the wheel. Our customers won't take any kind of license, including GPL. From the answers it seems that there is no way around caching states if one wants to use hierarchical state machines without RTOS and with polling calls prohibited. As hierarchical SM help a lot porting the existing code by conserving its structure (function calls to routines become invocation of sub-state machines), I will go that way, using the provided tools as good examples. - Thanks.