From a2623677baafdf2be87f41b69e8449aac3625630 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Thu, 14 Jan 2016 20:14:15 +0000 Subject: [PATCH] [i2c-bb] Add timeout and error code return if slave fails to ack --- firmware/inc/i2c_bb.h | 9 +++++++-- firmware/src/i2c_bb.c | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/firmware/inc/i2c_bb.h b/firmware/inc/i2c_bb.h index ed61a44..e911555 100644 --- a/firmware/inc/i2c_bb.h +++ b/firmware/inc/i2c_bb.h @@ -27,8 +27,13 @@ #include "samd20.h" -void i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length); -void i2c_bb_write(uint8_t address, uint8_t* data, uint8_t data_length); +typedef enum { + I2C_BB_SUCCESS, + I2C_BB_SLAVE_NO_ACK, +} i2c_bb_result_t; + +i2c_bb_result_t i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length); +i2c_bb_result_t i2c_bb_write(uint8_t address, uint8_t* data, uint8_t data_length); void i2c_bb_init(void); #endif /* I2C_BB_H */ diff --git a/firmware/src/i2c_bb.c b/firmware/src/i2c_bb.c index 23f368c..1822730 100644 --- a/firmware/src/i2c_bb.c +++ b/firmware/src/i2c_bb.c @@ -25,6 +25,7 @@ #include "samd20.h" #include "hw_config.h" #include "system/port.h" +#include "i2c_bb.h" #define SDA I2C_SERCOM_SDA_PIN #define SCL I2C_SERCOM_SCL_PIN @@ -133,13 +134,23 @@ void i2c_bb_ack(void) /** * Waits to receive a slave ack. SDA is already released */ -void i2c_bb_get_ack(void) +i2c_bb_result_t i2c_bb_get_ack(void) { + uint8_t i; + i2c_bb_write_pin(SCL, 1); - while (i2c_bb_read_pin(SDA)); /* wait for SDA=0 */ + for (i = 0; i < 10; i++) { /* 10 attempts to */ + if (i2c_bb_read_pin(SDA) == 0) { break; } /* wait for SDA=0 */ + } i2c_bb_write_pin(SCL, 0); + + if (i == 10) { /* fail */ + return I2C_BB_SLAVE_NO_ACK; /* no ack */ + } + + return I2C_BB_SUCCESS; } /** @@ -147,13 +158,17 @@ void i2c_bb_get_ack(void) * * address is the full read address like 0xEF */ -void i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length) +i2c_bb_result_t i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length) { + i2c_bb_result_t result; + address |= 1; /* set read flag */ i2c_bb_start(); /* start. claim both */ i2c_bb_put_byte(address); /* address. claim and relase SDA */ - i2c_bb_get_ack(); /* slave acks */ + if ((result = i2c_bb_get_ack()) != I2C_BB_SUCCESS) { /* slave acks */ + return result; + } for (uint8_t n = 0; n < data_length; n++) { @@ -164,27 +179,37 @@ void i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length) } i2c_bb_stop(); /* stop. release both */ + + return I2C_BB_SUCCESS; } /** * I2C Write. * * address is the full write address like 0xEE */ -void i2c_bb_write(uint8_t address, uint8_t* data, uint8_t data_length) +i2c_bb_result_t i2c_bb_write(uint8_t address, uint8_t* data, uint8_t data_length) { + i2c_bb_result_t result; + address &= ~1; /* clear read flag */ i2c_bb_start(); /* start. claim both */ i2c_bb_put_byte(address); /* address. claim and release SDA */ - i2c_bb_get_ack(); /* slave acks */ + if ((result = i2c_bb_get_ack()) != I2C_BB_SUCCESS) { /* slave acks */ + return result; + } for (uint8_t n = 0; n < data_length; n++) { i2c_bb_put_byte(data[n]); /* data. claim and release SDA */ - i2c_bb_get_ack(); /* slave acks */ + if ((result = i2c_bb_get_ack()) != I2C_BB_SUCCESS) { /* slave acks */ + return result; + } } i2c_bb_claim_pin(SDA, 0); /* claim SDA again */ i2c_bb_stop(); /* stop */ + + return I2C_BB_SUCCESS; }