diff options
Diffstat (limited to 'drivers/avr/i2c_master.c')
| -rw-r--r-- | drivers/avr/i2c_master.c | 19 | 
1 files changed, 18 insertions, 1 deletions
| diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c index b1e4885298..2773e00778 100644 --- a/drivers/avr/i2c_master.c +++ b/drivers/avr/i2c_master.c @@ -28,8 +28,14 @@  #    define F_SCL 400000UL  // SCL frequency  #endif +#ifndef I2C_START_RETRY_COUNT +#    define I2C_START_RETRY_COUNT 20 +#endif  // I2C_START_RETRY_COUNT +  #define TWBR_val (((F_CPU / F_SCL) - 16) / 2) +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +  void i2c_init(void) {      TWSR = 0; /* no prescaler */      TWBR = (uint8_t)TWBR_val; @@ -47,7 +53,7 @@ void i2c_init(void) {  #endif  } -i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { +static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {      // reset TWI control register      TWCR = 0;      // transmit START condition @@ -86,6 +92,17 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {      return I2C_STATUS_SUCCESS;  } +i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { +    // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled. +    uint16_t     timeout_timer = timer_read(); +    uint16_t     time_slice    = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT)));  // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries +    i2c_status_t status; +    do { +        status = i2c_start_impl(address, time_slice); +    } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout))); +    return status; +} +  i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {      // load data into data register      TWDR = data; | 
