aboutsummaryrefslogtreecommitdiff
path: root/drivers/avr/i2c_master.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/avr/i2c_master.c')
-rw-r--r--drivers/avr/i2c_master.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c
index b1e488529..2773e0077 100644
--- a/drivers/avr/i2c_master.c
+++ b/drivers/avr/i2c_master.c
@@ -28,8 +28,14 @@
28# define F_SCL 400000UL // SCL frequency 28# define F_SCL 400000UL // SCL frequency
29#endif 29#endif
30 30
31#ifndef I2C_START_RETRY_COUNT
32# define I2C_START_RETRY_COUNT 20
33#endif // I2C_START_RETRY_COUNT
34
31#define TWBR_val (((F_CPU / F_SCL) - 16) / 2) 35#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
32 36
37#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
38
33void i2c_init(void) { 39void i2c_init(void) {
34 TWSR = 0; /* no prescaler */ 40 TWSR = 0; /* no prescaler */
35 TWBR = (uint8_t)TWBR_val; 41 TWBR = (uint8_t)TWBR_val;
@@ -47,7 +53,7 @@ void i2c_init(void) {
47#endif 53#endif
48} 54}
49 55
50i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { 56static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
51 // reset TWI control register 57 // reset TWI control register
52 TWCR = 0; 58 TWCR = 0;
53 // transmit START condition 59 // transmit START condition
@@ -86,6 +92,17 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
86 return I2C_STATUS_SUCCESS; 92 return I2C_STATUS_SUCCESS;
87} 93}
88 94
95i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
96 // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
97 uint16_t timeout_timer = timer_read();
98 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
99 i2c_status_t status;
100 do {
101 status = i2c_start_impl(address, time_slice);
102 } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout)));
103 return status;
104}
105
89i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { 106i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
90 // load data into data register 107 // load data into data register
91 TWDR = data; 108 TWDR = data;