Event-based vs polling

When designing an embedded system an important design decision is how the system should work: event-based or polling based.

The type of the connected hardware can provide a first hint. Communication interfaces and many other hardware interfaces are nowadays mostly realized event based (e.g. a CAN network interface). If binary input/output channels are the dominating interface polling can be the better choice. In case of doubts better choose the event-based design. In both system types state-machines are the right tool to model state based behavior. In event-based systems also the state-machines should be modeled state-based. I.e. the machine waits for new events, possibly changes state, perform actions as a reaction to an event and then waits for the next event. If there is no event the state machine needs not to run. In polling-based systems the state machine is executed cyclically independent if it is necessary or not. The cycle time must be chosen in a way that no relevant signal change is missed. In the following section a simple example is presented first in an event-based and then as polling-based design. The task of the machine is similar to an AND function. If one input appears the other must appear within a certain time, otherwise a fault state is entered.

Event-based model

In this model transitions are triggered by events that are sent form outside to the machine. E.g. from an interrupt service routine detecting a change of the digital inputs. The do not loose events often a queue is used. Whenever the state machine runs it looks for new events in the queue, processes them and does not consume any CPU time if there are no events. If a RTOS is used the state-machine often runs in its own thread and blocks the thread execution until a new event arrives.

Generated source code looks like this (reduced to fit in here):

/*Events which can be sent to the state-machine */ typedef enum { evAB=0U, evB, evA, evNoInput, evEnable, evTimeout, evDisable, _NO_MSG } A_EVENT_T; void event_example(A_EVENT_T msg){ switch (stateVar) { case Idle: if(msg==evEnable){ setReady(1); stateVar = Init; }else{ /* Intentionally left blank */ } break; case Init: if(msg==evA){ startTimer(); stateVar = WaitB; }else if(msg==evAB){ setOut(1); timerStop(); stateVar = AandB; } ... break; case WaitA: if(msg==evNoInput){ setReady(1); stateVar = Init; }else if(msg==evTimeout){ stateVar = Error; } ... }

Polling-based model

In this model transitions are triggered by boolean conditions. The state machine has to run cyclically. This type of state machine is often found in systems based on a big main loop. The cycle time of the main loop must be fast enough to ensure that no condition changes are lost e.g. input inA going from low to hight and low again.

Generated source code looks like this (reduced to fit in here):

void polling_example(void){ /* action code */ inA = getA(); inB = getB(); enable = getEnable(); switch (stateVar) { case Idle: if(enable){ setReady(1); stateVar = Init; }else{ /* Intentionally left blank */ } break; case Init: if(inA && !inB){ timerStart(); stateVar = WaitB; }else if(inA && inB){ setOut(1); timerStop; stateVar = AandB; } ... break; case WaitA: /* action code */ timout = isTimeout(); if(!inB){ setReady(1); stateVar = Init; }if(timeout){ stateVar = Error; } ... }

The SinelaboreRT code generator can generate both machine types for you. As you can see the overall structure looks very similar but the two run-time models - event-based vs. polling are very different.

Be aware of the different run-time models during architecture design and make a conscious decision! In case of doubts better choose the event-based model.

If you have any feedback or suggestions for improvement please send me an email.