Embedded development
Jump to navigation
Jump to search
Pits
Race condition when reading twice a status register
Embedded devices have usually status register for various components (like I2C status bits).
When testing bits in these register, do not read several times the same register. Doing so will create a race condition. For instance:
while (R_I2C_STAT & (C_I2C_OVERFLOW | C_I2C_BUS_ERROR | C_I2C_STOP | C_I2C_ADDRESS_MATCH | C_I2C_ARBITRATION_LOSS)) {
if (R_I2C_STAT & C_I2C_RX_NOT_EMPTY) {
// Read the byte
}
}
This code has two problems:
- First, don't read twice the R_I2C_STAT. Doing so will create a race condition.
- We might miss a byte if the STOP event occurs at the same time as RX_NOT_EMPTY event.
A better implementation:
int i2c_stat = 0;
while (stat & (C_I2C_OVERFLOW | C_I2C_BUS_ERROR | C_I2C_STOP | C_I2C_ADDRESS_MATCH | C_I2C_ARBITRATION_LOSS)) {
if ((i2c_stat = R_I2C_STAT) & C_I2C_RX_NOT_EMPTY) {
// Read the byte
}
}
- We read the register only once.
- We first test the RX_NOT_EMPTY.