~ruther/qmk_firmware

608404f8742f01d1821a74c5a107e0c62b046423 — Daniel Kao 3 years ago be42c5f
Fix AVR I2C master 1ms timeout (#17174)

* avr i2c_master: Fix 1ms timeout

i2c_start() produces a minimum time_slice of 1ms for use as timeout
value.
The timer granularity is 1ms, it is entirely possible for timer_count
to tick up immediately after the last timer read and falsely trigger
timeout with a '>= 1' comparison.

* avr/drivers/i2c_master: Use timer_elapsed()
1 files changed, 6 insertions(+), 6 deletions(-)

M platforms/avr/drivers/i2c_master.c
M platforms/avr/drivers/i2c_master.c => platforms/avr/drivers/i2c_master.c +6 -6
@@ 64,7 64,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {

    uint16_t timeout_timer = timer_read();
    while (!(TWCR & (1 << TWINT))) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
            return I2C_STATUS_TIMEOUT;
        }
    }


@@ 81,7 81,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {

    timeout_timer = timer_read();
    while (!(TWCR & (1 << TWINT))) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
            return I2C_STATUS_TIMEOUT;
        }
    }


@@ 102,7 102,7 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
    i2c_status_t status;
    do {
        status = i2c_start_impl(address, time_slice);
    } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout)));
    } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) <= timeout)));
    return status;
}



@@ 114,7 114,7 @@ i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {

    uint16_t timeout_timer = timer_read();
    while (!(TWCR & (1 << TWINT))) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
            return I2C_STATUS_TIMEOUT;
        }
    }


@@ 132,7 132,7 @@ int16_t i2c_read_ack(uint16_t timeout) {

    uint16_t timeout_timer = timer_read();
    while (!(TWCR & (1 << TWINT))) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
            return I2C_STATUS_TIMEOUT;
        }
    }


@@ 147,7 147,7 @@ int16_t i2c_read_nack(uint16_t timeout) {

    uint16_t timeout_timer = timer_read();
    while (!(TWCR & (1 << TWINT))) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
        if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
            return I2C_STATUS_TIMEOUT;
        }
    }