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
   176   177   178   179   180   181   182   183   184   185   186