Sun Apr 24 15:49:21 EDT 2016

uC program core

- "recursive" finite state machines = tasks with finite and static
  activation records / recursion depth.

- hardware drivers = glue code to abstract state machines.

- glue code.

Components aren't hard.  The problem is the glue code, essentially the
abstraction for communication between tasks.  I.e the OS.

Communication (almost?) exclusively takes the form of writes to a
memory location or larger buffer / queue, and synchronization to an
external event in the form of an actual event (interrupt or function
call), or a logical condition change that needs to be polled.

The sequencer then orchestrates resumption of execution, possibly as
simple as a round-robin poll.

True boundless recursion is (almost?) never needed.  Activation
records can be allocated in advance for all tasks in a single nested
struct/union.  Mutually exclusive activation records (successive
function calls) can use a C union.

What about designing a language with those restrictions?  Building
applications then boils down to building state machines (finite tasks)
that cause events and wait for events to happen.  CSP or Actor model.