Design Ideas: July 18, 1996
Microprocessor peripheral devices with multibyte
registers often harbor a subtle bug that can bite the unwary software engineer.
If your program reads the peripheral device's registers at the same time that
the device is updating those registers, the program can obtain a mixed result.
One or more of the bytes could be left over from a previous reading, not having
been updated yet (
Figure
1). A simple, high-level technique ensures that processing does not proceed
until the peripheral device emits stable readings. The key element in the
routine "DMACount" in Listing 1 is the do-while loop.
| Listing 1Stabilization routine for hardware registers |
|---|
unsigned DMACount ( void ) // Func to get current DMA count
{ unsigned wDL1,wDL2; // Buffers for reads of DMA count
unsigned wDH1,wDH2; // " " " " " "
do { //
wDL1 = inport ( SAR0L ); // General-purpose input function
wDH1 = inport ( SAR0H ); // "inport" reads DMA count
wDL2 = inport ( SAR0L ); // twice from 2-byte register
wDH2 = inport ( SAR0H ); // "SAR0"
}
while ((wDL1!=wDL2) || (wDH1!=wDH2));
// "while" compares successive readings, looking for a match
return (wDH1<<8) | wDL1; // Return 32[CHS6]-bit composite count
}
|
The do-while loop repeatedly reads the hardware register twice, comparing the two successive reads until they match or stabilize. The portion of the routine that actually reads the hardware registers is peculiar to the DMA counter of the Z180 µP, SAR0. But the argument of the while expression is a simple, general-purpose method for determining when a reading is stable. You can easily extend the technique to hardware registers holding any number of bytes. (DI #1893)