Some collected thoughts on FSMs, some prompted by various comments, some just
based on experience.
First off, when you're designing your FSM there is, in my experience, no
substitute for drawing the whole FSM out on a big, perhaps bloody big, sheet
of paper. Circles for each state, big curved arrows between states labelled
with the signal/condition/input that causes a state change. If you need to
you can add things like timing constraints to the arrows - best colour coded.
When you've finished your diagram you've something you can use to visually
debug your design, code from, keep for documentation or just stick on the
wall to demonstrate your brilliance to everybody.
One problem with FSMs is that you can get to a state and hang waiting on an
event that never occurs. In turn, things that should have happened didn't.
...
All of my FPGA projects use FSMs, a LOT of FSMs, but I'm pretty sure that I
can't get stuck in a state and, so far, I have been successful. But that's
not how I would do robotics or anything like that.
There's a lot to be said for having a default 'get out of jail' condition
from each and every state in your FSM. The condition can be a watchdog timer
that's set when you enter each state, or any 'should not/cannot happen'
conditions while in that state. That condition should point to a state that
lets you recover from whatever has gone wrong. In most cases the recovery state
pointed to can just be your reset or initial state, but you can go for
subtler or more complex recovery schemes if that's to your taste.
Thanks, actually I'd like to spend some time studying FSMs as I came from hi
level programming (OOP, events) and I'd like to face the limits of FMSs.
A mathematical aside. The limits of FSMs are surprisingly high. Many types of
finite computation can be computed by an FSM limited only by the usual
time/space constraints and some rather abstruse mathematics. It's well known
(or at least ought to be) that a Turing Machine can can compute anything
computable including computations involving infinities. A class of machines
called push-down automata is the next most computationally capable type of
machine and FSMs are the next class of machines out from those.
If you're into linguistic computation those three classes of machine are exactly
the classes of machine required to parse context-sensitive, context-free and regular
language grammars respectively. This leads to the true but initially rather implausible
conclusion that you could use the lex (or flex) scanner generator to specify and code
an FSM in C. Having used lex and flex quite a lot, I wouldn't recommend it.
I'm sure that I missed something I thought of yesterday and meant to add but I've run out of steam.
Just remembered it (after posting, naturally).
As far as priorities, avoiding deadlock, priority inversion and the like there is a very useful set of
techniques known as wait-free or block-free algorithms. One of the aspects of these techniques is that,
used properly, they guarantee
progress for computations that use them.
They are not generally well known and some aspects of them are definitely current research
projects for the computer science community but there are practical algorithms and applications
out there. You are more likely to find details reading papers rather than textbooks.