add i2c timeouts
better than hanging indefinitely if something goes wrong
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
|
||||
#define BATT_I2C_ADDR 0x0b
|
||||
#define BATT_I2C_BAUD 32000
|
||||
#define BATT_I2C_TIMEOUT 200000 // in microseconds
|
||||
|
||||
|
||||
// i2c connected to laptop (as slave)
|
||||
@@ -46,6 +47,7 @@
|
||||
|
||||
#define LAPTOP_I2C_ADDR BATT_I2C_ADDR // use the same address
|
||||
#define LAPTOP_I2C_BAUD BATT_I2C_BAUD // use the same baud (for now)
|
||||
#define LAPTOP_I2C_TIMEOUT BATT_I2C_TIMEOUT
|
||||
|
||||
|
||||
// spi display
|
||||
|
||||
@@ -189,6 +189,7 @@ void init_mitm() {
|
||||
|
||||
|
||||
void mitm_loop() {
|
||||
int ret;
|
||||
i2c_dev_t* laptop = get_laptop_dev();
|
||||
i2c_dev_t* bms = get_bms_dev();
|
||||
|
||||
@@ -229,7 +230,8 @@ void mitm_loop() {
|
||||
|
||||
// write previous byte
|
||||
if (mitm_cmd_buffer_index > 0) {
|
||||
i2c_write_burst_blocking(bms->i2c, bms->address, &mitm_cmd_buffer[mitm_cmd_buffer_index - 1], 1);
|
||||
ret = i2c_write_burst_blocking(bms->i2c, bms->address, &mitm_cmd_buffer[mitm_cmd_buffer_index - 1], 1);
|
||||
if (ret < 0) printf("BATT ERROR %d!\n", ret);
|
||||
}
|
||||
|
||||
mitm_cmd_buffer[mitm_cmd_buffer_index++] = transfer->data;
|
||||
@@ -259,7 +261,8 @@ void mitm_loop() {
|
||||
i2c_write_raw_blocking(laptop->i2c, &mitm_reply_buffer[mitm_reply_buffer_index], 1);
|
||||
} else {
|
||||
// forward reply from bms
|
||||
i2c_read_burst_blocking(bms->i2c, bms->address, &mitm_reply_buffer[mitm_reply_buffer_index], 1);
|
||||
ret = i2c_read_burst_blocking(bms->i2c, bms->address, &mitm_reply_buffer[mitm_reply_buffer_index], 1);
|
||||
if (ret < 0) printf("BATT ERROR %d! - ", ret);
|
||||
i2c_write_raw_blocking(laptop->i2c, &mitm_reply_buffer[mitm_reply_buffer_index], 1);
|
||||
}
|
||||
|
||||
@@ -272,12 +275,14 @@ void mitm_loop() {
|
||||
bool aborted = transfer->event == I2C_ABORT;
|
||||
|
||||
if (previous_event == I2C_WRITE) {
|
||||
i2c_write_blocking(bms->i2c, bms->address, mitm_cmd_buffer + mitm_cmd_buffer_index - 1, 1, false);
|
||||
ret = i2c_write_timeout_us(bms->i2c, bms->address, mitm_cmd_buffer + mitm_cmd_buffer_index - 1, 1, false, bms->timeout);
|
||||
if (aborted) printf("ABORT - ");
|
||||
if (ret < 0) printf("BATT ERROR %d! - ", ret);
|
||||
printf("end of TX (%d bytes)\n", mitm_cmd_buffer_index);
|
||||
} else if (previous_event == I2C_READ) {
|
||||
i2c_stop_blocking(bms); // pay the court a fine or serve your sentence
|
||||
ret = i2c_stop_read_blocking(bms);
|
||||
if (aborted) printf("ABORT - ");
|
||||
if (ret < 0) printf("BATT ERROR %d! - ", ret);
|
||||
printf("end of RX (%d bytes)\n", mitm_reply_buffer_index);
|
||||
} else {
|
||||
if (aborted) printf("ABORT\n");
|
||||
@@ -292,11 +297,11 @@ void mitm_loop() {
|
||||
reply_override = false;
|
||||
|
||||
if (previous_event == I2C_WRITE) {
|
||||
i2c_write_blocking(bms->i2c, bms->address, mitm_cmd_buffer + mitm_cmd_buffer_index - 1, 1, true);
|
||||
ret = i2c_write_timeout_us(bms->i2c, bms->address, mitm_cmd_buffer + mitm_cmd_buffer_index - 1, 1, true, bms->timeout);
|
||||
printf("switching TX -> RX after sending (%d bytes)\n", mitm_cmd_buffer_index);
|
||||
|
||||
// apply read command overrides
|
||||
if (mitm_cmd_buffer_index == 1) { // read command
|
||||
if (ret < 0) printf("BATT ERROR %d!\n", ret);
|
||||
else if (mitm_cmd_buffer_index == 1) { // read command
|
||||
// apply read command overrides
|
||||
cmd_reply_override override = get_read_command_reply_override(mitm_cmd_buffer[0]);
|
||||
if (override != NULL) {
|
||||
reply_override = true;
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
struct i2c_dev;
|
||||
|
||||
|
||||
i2c_dev_t _i2c_bms_dev = {BATT_I2C, BATT_I2C_ADDR};
|
||||
i2c_dev_t _i2c_laptop_dev = {LAPTOP_I2C, LAPTOP_I2C_ADDR};
|
||||
i2c_dev_t _i2c_bms_dev = {BATT_I2C, BATT_I2C_ADDR, BATT_I2C_TIMEOUT};
|
||||
i2c_dev_t _i2c_laptop_dev = {LAPTOP_I2C, LAPTOP_I2C_ADDR, LAPTOP_I2C_TIMEOUT};
|
||||
|
||||
|
||||
i2c_dev_t* get_bms_dev() {
|
||||
@@ -81,27 +81,8 @@ bool validate_smbus_crc(uint8_t address, uint8_t cmd, uint8_t* reply, uint8_t le
|
||||
}
|
||||
|
||||
|
||||
void i2c_stop_blocking(i2c_dev_t* device) {
|
||||
i2c_hw_t* hw = i2c_get_hw(device->i2c);
|
||||
|
||||
i2c_get_hw(device->i2c)->enable = 0;
|
||||
i2c_get_hw(device->i2c)->tar = device->address;
|
||||
i2c_get_hw(device->i2c)->enable = 1;
|
||||
|
||||
while (!i2c_get_write_available(device->i2c)) {
|
||||
tight_loop_contents();
|
||||
}
|
||||
|
||||
hw->data_cmd = I2C_IC_DATA_CMD_STOP_LSB;
|
||||
|
||||
bool abort;
|
||||
do abort = hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_TX_ABRT_BITS;
|
||||
while (!i2c_get_read_available(device->i2c) && !abort);
|
||||
|
||||
if (abort) hw->clr_tx_abrt;
|
||||
else i2c_get_hw(device->i2c)->data_cmd;
|
||||
|
||||
device->i2c->restart_on_next = false;
|
||||
int i2c_stop_read_blocking(i2c_dev_t* device) {
|
||||
return i2c_read_timeout_us(device->i2c, device->address, NULL, 1, false, device->timeout);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +97,7 @@ int smbus_read(i2c_dev_t* device, uint8_t cmd, uint8_t* result, size_t length) {
|
||||
uint8_t crc;
|
||||
|
||||
// write command code
|
||||
ret = i2c_write_blocking(device->i2c, device->address, &cmd, 1, true);
|
||||
ret = i2c_write_timeout_us(device->i2c, device->address, &cmd, 1, true, device->timeout);
|
||||
if (ret < 0) {
|
||||
printf("failed, write returned %d\n", ret);
|
||||
return SMBUS_ERROR_DEVICE;
|
||||
@@ -130,7 +111,7 @@ int smbus_read(i2c_dev_t* device, uint8_t cmd, uint8_t* result, size_t length) {
|
||||
}
|
||||
|
||||
// read crc
|
||||
ret = i2c_read_blocking(device->i2c, device->address, &crc, 1, false);
|
||||
ret = i2c_read_timeout_us(device->i2c, device->address, &crc, 1, false, device->timeout);
|
||||
if (ret < 0) {
|
||||
printf("failed, crc read returned %d\n", ret);
|
||||
return SMBUS_ERROR_DEVICE;
|
||||
@@ -152,7 +133,7 @@ int smbus_read_block(i2c_dev_t* device, uint8_t cmd, uint8_t* result, size_t max
|
||||
uint8_t block_length, crc;
|
||||
|
||||
// write command code
|
||||
ret = i2c_write_blocking(device->i2c, device->address, &cmd, 1, true);
|
||||
ret = i2c_write_timeout_us(device->i2c, device->address, &cmd, 1, true, device->timeout);
|
||||
if (ret < 0) {
|
||||
printf("failed, write returned %d\n", ret);
|
||||
return SMBUS_ERROR_DEVICE;
|
||||
@@ -168,7 +149,7 @@ int smbus_read_block(i2c_dev_t* device, uint8_t cmd, uint8_t* result, size_t max
|
||||
if (block_length > max_length) {
|
||||
// don't truncate, crc can't be verified
|
||||
printf("block is longer than max_length! block_length = %d, max_length = %d\n", block_length, max_length);
|
||||
i2c_stop_blocking(device);
|
||||
i2c_stop_read_blocking(device);
|
||||
return SMBUS_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
@@ -180,7 +161,7 @@ int smbus_read_block(i2c_dev_t* device, uint8_t cmd, uint8_t* result, size_t max
|
||||
}
|
||||
|
||||
// read crc
|
||||
ret = i2c_read_blocking(device->i2c, device->address, &crc, 1, false);
|
||||
ret = i2c_read_timeout_us(device->i2c, device->address, &crc, 1, false, device->timeout);
|
||||
if (ret < 0) {
|
||||
printf("failed, crc read returned %d\n", ret);
|
||||
return SMBUS_ERROR_DEVICE;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
struct i2c_dev {
|
||||
i2c_inst_t* i2c;
|
||||
uint8_t address;
|
||||
uint timeout;
|
||||
};
|
||||
|
||||
typedef struct i2c_dev i2c_dev_t;
|
||||
@@ -40,7 +41,7 @@ typedef struct i2c_dev i2c_dev_t;
|
||||
i2c_dev_t* get_bms_dev();
|
||||
i2c_dev_t* get_laptop_dev();
|
||||
|
||||
void i2c_stop_blocking(i2c_dev_t* device);
|
||||
int i2c_stop_read_blocking(i2c_dev_t* device);
|
||||
int generate_smbus_crc(uint8_t address, uint8_t cmd, uint8_t* reply, uint8_t length, bool is_block, bool is_read);
|
||||
bool validate_smbus_crc(uint8_t address, uint8_t cmd, uint8_t* reply, uint8_t length, uint8_t recieved_crc, bool is_block, bool is_read);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user