In a register that is written by the CPU, the register is write-only and a variable called REGMASK contains the current value in the register. The least significant bit of the register drives an LED, and is controlled by the interrupt service routine (ISR), which blinks the LED at a regular rate. The most significant bit is used by non-ISR code to control a relay. The remaining bits could control a stepper motor, or something similar. The non-ISR logic looks like this:
1. Read REGMASK.
2. Set/clear whatever bit needs to be changed.
3. Write result to hardware register.
4. Write result to REGMASK.
The ISR logic looks like this:
A. Read REGMASK.
B. Toggle bit 0 to blink LED.
C. Write result to hardware register.
D. Write result to REGMASK.
If the interrupt occurs between non-ISR statements 1 and 3, the non-ISR-controlled bits in REGMASK and in the hardware register will be correct, but the LED toggle will be lost. If the interrupt occurs between statements 3 and 4, a momentary pulse will occur at the output of the hardware register on the bit the non-ISR code attempted to change.
The hardware register will be left in the wrong state, but REGMASK will be correct except for the LED bit. The hardware register will be corrected the next time it is updated, with the result being a delay in changing whatever bit the non-ISR code wanted to alter.
Two fixes are possible for this problem:
- Use disable/enable pairs to protect the non-ISR code.
- Use two masks. The ISR code sets a mask for the LED, but does not update the hardware register.