Assessing the Super Loop architecture
Many of the features of the modern desktop OS, such as graphics capability, printing and disk access, are of little value in embedded applications, where sophisticated graphics screens, printers and disks are unavailable.
As a result, as we saw in Chapter 9, the software architecture used in many simple embedded applications is a form of SUPER LOOP (Listing 13.1).
Listing 13.1 Part of a simple Super Loop demonstration
The main advantages of the Super Loop architecture illustrated in Listing 13.1 are (1) that it is simple, and therefore easy to understand, and (2) that it consumes virtually no system memory or CPU resources.
However, we get ‘nothing for nothing’: Super Loops consume little memory or processor resources because they provide few facilities to the developer. A particular limitation with this architecture is that it is very difficult to execute Task X at precise intervals of time: as we will see, this is a very significant drawback.
For example, consider a collection of requirements assembled from a range of dif- ferent embedded projects (in no particular order):
● The current speed of the vehicle must be measured at 0.5 second intervals.
● The display must be refreshed 40 times every second.
● The calculated new throttle setting must be applied every 0.5 seconds.
● A time-frequency transform must be performed 20 times every second.
● If the alarm sounds, it must be switched off (for legal reasons) after 20 minutes.
● If the front door is opened, the alarm must sound in 30 seconds if the correct password is not entered in this time.
● The engine vibration data must be sampled 1,000 times per second.
● The frequency-domain data must be classified 20 times every second.
● The keypad must be scanned every 200 ms.
● The master (control) node must communicate with all other nodes (sensor nodes and sounder nodes) once per second.
● The new throttle setting must be calculated every 0.5 seconds.
● The sensors must be sampled once per second.
We can summarize this list by saying that many embedded systems must carry out tasks at particular instants of time. More specifically, we have two kinds of activ- ity to perform:
● Periodic tasks, to be performed (say) once every 100 ms
● One-shot tasks, to be performed once after a delay of (say) 50 ms
This is very difficult to achieve with the primitive architecture shown in Listing
13.1. Suppose, for example, that we need to start Task X every 200 ms, and that the task takes 10 ms to complete. Listing 13.2 illustrates one way in which we might adapt the code in Listing 13.1 in order to try to achieve this.
The approach illustrated in Listing 13.2 is not generally adequate, because it will only work if the following conditions are satisfied:
1 We know the precise duration of Task X
2 This duration never varies
In practical applications, determining the precise task duration is rarely straightfor- ward. Suppose we have a very simple task that does not interact with the outside world but, instead, performs some internal calculations. Even under these rather restricted circumstances, changes to compiler optimization settings – even changes to an apparently unrelated part of the program – can alter the speed at which the task executes. This can make fine-tuning the timing very tedious and error prone.
The second condition is even more problematic. Often in an embedded system the task will be required to interact with the outside world in a complex way. In these cir- cumstances the task duration will vary according to outside activities in a manner over which the programmer has very little control.