Learning to think co-operatively:Loop timeout

Loop timeout

Context
● You are developing an embedded application using one or more members of the 8051 family of microcontrollers.

● The application has a time-triggered architecture, constructed using a scheduler.

Problem

How do you ensure that your system will not ‘hang’ while waiting for a hardware operation (such as an AD conversion or serial data transfer) to complete?

Background

The Philips 8XC552 is an Extended 8051 device with a number of on-chip peripherals, including an 8-channel, 10-bit ADC. Philips provide an application note (AN93017) that describes how to use this microcontroller. This application note includes the following code:

// Wait until AD conversion finishes (checking ADCI) while ((ADCON & ADCI) == 0);

Such code is potentially unreliable, because there are circumstances under which our application may ‘hang’. This might occur for one or more of the following reasons:

● If the ADC has been incorrectly initialized, we cannot be sure that a data conver- sion will be carried out.

● If the ADC has been subjected to an excessive input voltage, then it may not operate at all.

● If the variables ADCON or ADCI were not correctly initialized, they may not oper- ate as required.

Such problems are not, of course, unique to this particular microcontroller or even to ADCs. Such code is common in embedded applications.

If your application is to be reliable, you need to be able to guarantee that no func- tion will hang in this way. Loop timeouts offer a simple but effective means of providing such a guarantee.

Solution

A loop timeout may be easily created. The basis of the code structure is a software delay, created as follows:

unsigned integer Timeout_loop = 0;

while (++Timeout_loop);

This loop will keep running until the variable Timeout_loop reaches its maxi- mum value (assuming 16-bit integers) of 65,535 and then overflows. When this happens, the program will continue. Note that, without some simulation studies or prototyping, we cannot easily determine how long this delay will be. However, we do know that the loop will, eventually, time out.

Such a loop is not terribly useful. However, if we consider again the ADC example given in ‘Background’, we can easily extend this idea. Recall that the original code was as follows:

// Wait until AD conversion finishes (checking ADCI) while ((ADCON & ADCI) == 0);

Here is a modified version of this code, this time incorporating a loop timeout:

tWord Timeout_loop = 0;

// Take sample from ADC

// Wait until conversion finishes (checking ADCI)

// – simple loop timeout

while (((ADCON & ADCI) == 0) && (++Timeout_loop != 0));

Note that this alternative implementation is also useful:

tWord Timeout_loop = 1;

// Take sample from ADC

// Wait until conversion finishes (checking ADCI)

// – simple loop timeout

while (((ADCON & ADCI) == 0) && (Timeout_loop != 0))

{

Timeout_loop++; // Disable for use in hardware simulator…

}

The advantage of this second technique is that the loop timeout may be easily commented out, if required, when executing the code on a hardware simulator.

In both cases, we now know that the loop cannot go on ‘for ever’.

Note that we can vary the duration of the loop timeout by changing the initial value loaded into loop variable. The file TimeoutL.H, reproduced in Listing 15.1 and included on the CD in the directory associated with this chapter, includes a set of constants that give, very approximately, the specified timeout values.

We give an example of how to use this file in the following sections.

Hardware resource implications

LOOP TIMEOUT does not use a timer and imposes an almost negligible CPU and memory load.

Reliability and safety implications

Using a L OOP T IMEOUT can result in a huge reliability and safety improvement at minimal cost. However, if practical, HARDW ARE TIMEOUT [page 305] is usually an even better solution.

Portability

Loop timeouts will work in any environment. However, the timings obtained will vary dramatically between microcontrollers and compilers.

Overall strengths and weaknesses

clip_image005clip_image006Much better than executing code without any form of timeout protection. Many applications use a timer for RS232 baud rate generation, and another

timer to run the scheduler. In many 8051 devices, this leaves no further

timers available to implement a HARDW ARE TIMEOUT [page 305]. In these circumstances, use of a loop is the only practical way of implementing effective timeout behaviour.

clip_image007Timings are difficult to calculate and timer values are not portable. HARDW ARE TIMEOUT is always a better solution, if you have a spare timer available.

Related patterns and alternative solutions

As mentioned under ‘Reliability and safety implications’, HARDW ARE TIMEOUT [page 305] is often a better alternative to LOOP TIMEOUT .

In addition, HARDW ARE W A TCHDOG [page 217] provides an alternative; however, it is rather crude by comparison and detects errors at the application (rather than task) level.

Example: Test program for loop timeout code

As noted, loop timeouts must be carefully hand-tuned to give accurate delay values.

The program in Listing 15.2 can be used to test such timeout code.

The program is run in the Keil hardware simulator to check the timings (Figure 15.1).

Remember: Changes in compiler optimization settings – and even apparently unconnected changes to the rest of the program – can change these timings, because they alter the way in which the compiler makes use of the available memory areas.

For a final test in the pre-production code, set a port pin high at start of the time- out and clear it at the end. Use an oscilloscope to measure the resulting delay.

Learning to think co-operatively-0286

Example: Loop timeouts in an I2C library

We discuss the I2C bus in detail in Chapter 23. Very briefly, I2C is a two-wire serial bus. The two wires are referred to as the serial data (SDA) and serial clock (SCL) lines (Figure 15.2). When the bus is free, both SCL and SDA lines are HIGH.

Here we consider how loop timeouts are used in a version of the I2C library.

At certain stages in the data transmission, we need to ‘synchronize the clocks’. This means waiting for the ‘clock’ line to be pulled high (by a slave device). Some I2C code libraries include fragments of code similar to the following to achieve this:

// Synchronize the clock while (_I2C_SCL == 0);

Of course, for all of the reasons discussed in this pattern, this is a dangerous approach.

Learning to think co-operatively-0287

The following code fragment uses a loop timeout to improve this code with a 1 ms timeout:

Learning to think co-operatively-0288

Leave a comment

Your email address will not be published. Required fields are marked *