Page 181 - Embedded Microprocessor Systems Real World Design
P. 181
One solution to this is for the polling code to have a mask byte in RAM. The
polling loop turns bits on and off in the LED mask but never writes to the hard-
ware register. The ISR writes to the register, ORing the LED mask byte into its own
solenoid control value. This could be reversed, of course, with the polling loop con-
trolling the hardware and the ISR having a solenoid mask byte.
A related problem can occur on many peripheral ICs. The complexity of modern
peripheral parts often requires them to have a number of internal registers. Rather
than using a large block of processor address space, these parts sometimes have two
addresses: register select and data. In operation, the processor writes the number
of the internal register it wants to read or write to the peripheral’s register select
address. It then reads or writes the data address to mod+ the selected internal
register. If a process in the polling loop or in a lower-priority ISR tries to access
such a peripheral, and an interrupt occurs between register selection and data
transfer, and if the ISR also uses the peripheral IC, the original process will access
the wrong register when it regains control. This happens frequently. It is an easy
problem to overlook, and it is not always possible to avoid having the ISR and
another task access the same peripheral IC.
Race Condition
A software race condition exists when a process tries to use data before the data
really are ready. Say that a system has a process in the polling loop and a regular
interrupt ISR. The polling loop process gets data from some external device such
as an ADC or maybe commands via an RS-232 link to an external controller. The
polling loop process places the input data in a memory location, DATABYTE. It
also sets a flag (semaphore) byte, FLAGBYTE, to tell the ISR data are available.
Each time the ISR executes, if the flag byte is set, it reads the data from DATABYTE
and does something with that data, then resets the flag byte. Now look at the
following code description for the polling loop process:
1. If input data are available,
2. Set FLAGBYTE,
3. Store input data at DATABYTE.
If the interrupt occurs between Steps 2 and 3, the ISR sees the flag set and
processes the data. However, because the polling loop process has not yet written
the data, the ISR uses whatever value is in DATABYTE, which probably is the pe-
vious data value. In addition, the actual data byte is never processed because the
flag was reset by the ISR.
The simple fix for this problem is to swap lines 2 and 3 in the code description
or disable interrupts around those lines of code. Note that an optimizing compiler
(see Chapter 4) can create a race condition under the right circumstances.
162 Embedded Microprocessor Systems