add i2c timeouts

better than hanging indefinitely if something goes wrong
This commit is contained in:
Benjamin Wiegand
2025-09-01 17:46:39 -07:00
parent 611d7c54ab
commit 2ca88f97d2
4 changed files with 26 additions and 37 deletions
+2
View File
@@ -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
+13 -8
View File
@@ -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;
+9 -28
View File
@@ -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;
+2 -1
View File
@@ -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);