[i2c-bb] Add timeout and error code return if slave fails to ack

main-solar-only
Richard Meadows 2016-01-14 20:14:15 +00:00
rodzic 132b178f9d
commit a2623677ba
2 zmienionych plików z 39 dodań i 9 usunięć

Wyświetl plik

@ -27,8 +27,13 @@
#include "samd20.h" #include "samd20.h"
void i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length); typedef enum {
void i2c_bb_write(uint8_t address, uint8_t* data, uint8_t data_length); 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); void i2c_bb_init(void);
#endif /* I2C_BB_H */ #endif /* I2C_BB_H */

Wyświetl plik

@ -25,6 +25,7 @@
#include "samd20.h" #include "samd20.h"
#include "hw_config.h" #include "hw_config.h"
#include "system/port.h" #include "system/port.h"
#include "i2c_bb.h"
#define SDA I2C_SERCOM_SDA_PIN #define SDA I2C_SERCOM_SDA_PIN
#define SCL I2C_SERCOM_SCL_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 * 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); 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); 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 * 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 */ address |= 1; /* set read flag */
i2c_bb_start(); /* start. claim both */ i2c_bb_start(); /* start. claim both */
i2c_bb_put_byte(address); /* address. claim and relase SDA */ 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++) { 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 */ i2c_bb_stop(); /* stop. release both */
return I2C_BB_SUCCESS;
} }
/** /**
* I2C Write. * I2C Write.
* *
* address is the full write address like 0xEE * 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 */ address &= ~1; /* clear read flag */
i2c_bb_start(); /* start. claim both */ i2c_bb_start(); /* start. claim both */
i2c_bb_put_byte(address); /* address. claim and release SDA */ 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++) { for (uint8_t n = 0; n < data_length; n++) {
i2c_bb_put_byte(data[n]); /* data. claim and release SDA */ 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_claim_pin(SDA, 0); /* claim SDA again */
i2c_bb_stop(); /* stop */ i2c_bb_stop(); /* stop */
return I2C_BB_SUCCESS;
} }