From 20870dc3e3d7b19ea414914c6737aa20282687b0 Mon Sep 17 00:00:00 2001 From: true Date: Sun, 28 Jul 2024 16:49:17 -0700 Subject: [PATCH] i2c.c: added timeouts added timeouts to all the polling functions in the i2c code. hopefully if something hangs this gets it going again. timeouts are not added on the data transfer portion, only on the initial setup portion. need to test if this is good enough. --- code/firmware/user/src/i2c.c | 75 ++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/code/firmware/user/src/i2c.c b/code/firmware/user/src/i2c.c index 3620857..767c46f 100644 --- a/code/firmware/user/src/i2c.c +++ b/code/firmware/user/src/i2c.c @@ -15,7 +15,10 @@ -#define I2C_TIMEOUT 0xffff; +#define I2C_TIMEOUT 0xffff +#define I2C_TIMEOUT_ACK_POLL 0x180 + +static uint32_t timeout; void i2c_init() @@ -42,25 +45,36 @@ void i2c_init() /* * reads data from devices which use a single-byte address */ -void i2c_read_addr1b(uint8_t devaddr, uint8_t addr, uint8_t *data, uint8_t len) +int8_t i2c_read_addr1b(uint8_t devaddr, uint8_t addr, uint8_t *data, uint8_t len) { - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET); + timeout = I2C_TIMEOUT; + while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--); + if (!timeout) return -1; + I2C_GenerateSTART(I2C1, ENABLE); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--); + if (!timeout) return -2; - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devaddr, I2C_Direction_Transmitter); - - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && timeout--); + if (!timeout) return -3; I2C_SendData(I2C1, addr); - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) && timeout--); + if (!timeout) return -4; I2C_GenerateSTART(I2C1, ENABLE); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--); + if (!timeout) return -5; - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devaddr, I2C_Direction_Receiver); - - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) && timeout--); + if (!timeout) return -6; while (len) { while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET) { @@ -74,20 +88,30 @@ void i2c_read_addr1b(uint8_t devaddr, uint8_t addr, uint8_t *data, uint8_t len) I2C_GenerateSTOP(I2C1, ENABLE); } } + + return 0; } -void i2c_write_addr1b(uint8_t devaddr, uint8_t addr, uint8_t *data, uint8_t len) +int8_t i2c_write_addr1b(uint8_t devaddr, uint8_t addr, uint8_t *data, uint8_t len) { - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET); + timeout = I2C_TIMEOUT; + while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--); + if (!timeout) return -1; + I2C_GenerateSTART(I2C1, ENABLE); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--); + if (!timeout) return -2; - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devaddr, I2C_Direction_Transmitter); - - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && timeout--); + if (!timeout) return -3; I2C_SendData(I2C1, addr); - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) && timeout--); + if (!timeout) return -4; while (len) { while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) != RESET) { @@ -98,20 +122,29 @@ void i2c_write_addr1b(uint8_t devaddr, uint8_t addr, uint8_t *data, uint8_t len) } I2C_GenerateSTOP(I2C1, ENABLE); + + return 0; } int8_t i2c_ack_poll(uint8_t devaddr) { int8_t addr_match = 0; - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET); + timeout = I2C_TIMEOUT; + while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--); + if (!timeout) return -1; + I2C_GenerateSTART(I2C1, ENABLE); + timeout = I2C_TIMEOUT; + while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--); + if (!timeout) return -2; - while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devaddr, I2C_Direction_Receiver); - - if (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) - addr_match = -1; + timeout = I2C_TIMEOUT_ACK_POLL; + while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) && timeout--); + if (!timeout) { + addr_match = -128; + } I2C_GenerateSTOP(I2C1, ENABLE);