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()
This commit is contained in:
Daniel Kao 2022-06-21 15:00:04 -07:00 committed by GitHub
parent be42c5fb98
commit 608404f874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -64,7 +64,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
uint16_t timeout_timer = timer_read(); uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) { 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; 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(); timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) { 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; return I2C_STATUS_TIMEOUT;
} }
} }
@ -102,7 +102,7 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
i2c_status_t status; i2c_status_t status;
do { do {
status = i2c_start_impl(address, time_slice); 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; return status;
} }
@ -114,7 +114,7 @@ i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
uint16_t timeout_timer = timer_read(); uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) { 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; return I2C_STATUS_TIMEOUT;
} }
} }
@ -132,7 +132,7 @@ int16_t i2c_read_ack(uint16_t timeout) {
uint16_t timeout_timer = timer_read(); uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) { 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; return I2C_STATUS_TIMEOUT;
} }
} }
@ -147,7 +147,7 @@ int16_t i2c_read_nack(uint16_t timeout) {
uint16_t timeout_timer = timer_read(); uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) { 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; return I2C_STATUS_TIMEOUT;
} }
} }