Embedded development

From miki
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.