1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-15 12:25:20 +03:00

Merge pull request #10631 from klutvott123/fix-i2c-timeout

Fix I2C timeout
This commit is contained in:
Michael Keller 2021-03-25 01:49:44 +13:00 committed by GitHub
commit 828fed5103
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 43 deletions

View file

@ -115,9 +115,9 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t data)
HAL_StatusTypeDef status;
if (reg_ == 0xFF)
status = HAL_I2C_Master_Transmit(pHandle ,addr_ << 1, &data, 1, I2C_DEFAULT_TIMEOUT);
status = HAL_I2C_Master_Transmit(pHandle ,addr_ << 1, &data, 1, I2C_TIMEOUT_SYS_TICKS);
else
status = HAL_I2C_Mem_Write(pHandle ,addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT, &data, 1, I2C_DEFAULT_TIMEOUT);
status = HAL_I2C_Mem_Write(pHandle ,addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT, &data, 1, I2C_TIMEOUT_SYS_TICKS);
if (status != HAL_OK)
return i2cHandleHardwareFailure(device);
@ -170,9 +170,9 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t
HAL_StatusTypeDef status;
if (reg_ == 0xFF)
status = HAL_I2C_Master_Receive(pHandle ,addr_ << 1, buf, len, I2C_DEFAULT_TIMEOUT);
status = HAL_I2C_Master_Receive(pHandle ,addr_ << 1, buf, len, I2C_TIMEOUT_SYS_TICKS);
else
status = HAL_I2C_Mem_Read(pHandle, addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT,buf, len, I2C_DEFAULT_TIMEOUT);
status = HAL_I2C_Mem_Read(pHandle, addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT,buf, len, I2C_TIMEOUT_SYS_TICKS);
if (status != HAL_OK) {
return i2cHandleHardwareFailure(device);

View file

@ -25,9 +25,8 @@
#include "drivers/io_types.h"
#include "drivers/rcc_types.h"
#define I2C_SHORT_TIMEOUT ((uint32_t)0x1000)
#define I2C_LONG_TIMEOUT ((uint32_t)(10 * I2C_SHORT_TIMEOUT))
#define I2C_DEFAULT_TIMEOUT I2C_SHORT_TIMEOUT
#define I2C_TIMEOUT_US 10000
#define I2C_TIMEOUT_SYS_TICKS (I2C_TIMEOUT_US / 1000)
#define I2C_PIN_SEL_MAX 4

View file

@ -182,7 +182,7 @@ bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_,
return false;
}
uint32_t timeout = I2C_DEFAULT_TIMEOUT;
timeUs_t timeoutStartUs = microsISR();
state->addr = addr_ << 1;
state->reg = reg_;
@ -196,9 +196,11 @@ bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_,
if (!(I2Cx->CR2 & I2C_IT_EVT)) { // if we are restarting the driver
if (!(I2Cx->CR1 & I2C_CR1_START)) { // ensure sending a start
while (I2Cx->CR1 & I2C_CR1_STOP && --timeout > 0) {; } // wait for any stop to finish sending
if (timeout == 0)
while (I2Cx->CR1 & I2C_CR1_STOP) { // wait for any stop to finish sending
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cHandleHardwareFailure(device);
}
}
I2C_GenerateSTART(I2Cx, ENABLE); // send the start for the new job
}
I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, ENABLE); // allow the interrupts to fire off again
@ -220,11 +222,13 @@ bool i2cBusy(I2CDevice device, bool *error)
bool i2cWait(I2CDevice device)
{
i2cState_t *state = &i2cDevice[device].state;
uint32_t timeout = I2C_DEFAULT_TIMEOUT;
timeUs_t timeoutStartUs = microsISR();
while (state->busy && --timeout > 0) {; }
if (timeout == 0)
while (state->busy) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cHandleHardwareFailure(device) && i2cWait(device);
}
}
return !(state->error);
}
@ -250,7 +254,7 @@ bool i2cReadBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, u
return false;
}
uint32_t timeout = I2C_DEFAULT_TIMEOUT;
timeUs_t timeoutStartUs = microsISR();
state->addr = addr_ << 1;
state->reg = reg_;
@ -264,9 +268,11 @@ bool i2cReadBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, u
if (!(I2Cx->CR2 & I2C_IT_EVT)) { // if we are restarting the driver
if (!(I2Cx->CR1 & I2C_CR1_START)) { // ensure sending a start
while (I2Cx->CR1 & I2C_CR1_STOP && --timeout > 0) {; } // wait for any stop to finish sending
if (timeout == 0)
while (I2Cx->CR1 & I2C_CR1_STOP) { // wait for any stop to finish sending
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cHandleHardwareFailure(device);
}
}
I2C_GenerateSTART(I2Cx, ENABLE); // send the start for the new job
}
I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, ENABLE); // allow the interrupts to fire off again

View file

@ -32,6 +32,7 @@
#include "drivers/io.h"
#include "drivers/io_impl.h"
#include "drivers/rcc.h"
#include "drivers/time.h"
#include "drivers/bus_i2c.h"
#include "drivers/bus_i2c_impl.h"
@ -44,8 +45,6 @@
#define I2C_GPIO_AF GPIO_AF_4
static uint32_t i2cTimeout;
static volatile uint16_t i2cErrorCount = 0;
const i2cHardware_t i2cHardware[I2CDEV_COUNT] = {
@ -144,10 +143,12 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data)
addr_ <<= 1;
timeUs_t timeoutStartUs;
/* Test on BUSY Flag */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -156,9 +157,9 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data)
I2C_TransferHandling(I2Cx, addr_, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
/* Wait until TXIS flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -167,10 +168,9 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data)
I2C_SendData(I2Cx, (uint8_t) reg);
/* Wait until TCR flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TCR) == RESET)
{
if ((i2cTimeout--) == 0) {
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TCR) == RESET) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -179,9 +179,9 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data)
I2C_TransferHandling(I2Cx, addr_, 1, I2C_AutoEnd_Mode, I2C_No_StartStop);
/* Wait until TXIS flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -190,9 +190,9 @@ bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t data)
I2C_SendData(I2Cx, data);
/* Wait until STOPF flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_STOPF) == RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -217,10 +217,12 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t len, uint8_t*
addr_ <<= 1;
timeUs_t timeoutStartUs;
/* Test on BUSY Flag */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -229,9 +231,9 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t len, uint8_t*
I2C_TransferHandling(I2Cx, addr_, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
/* Wait until TXIS flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -240,9 +242,9 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t len, uint8_t*
I2C_SendData(I2Cx, (uint8_t) reg);
/* Wait until TC flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TC) == RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -253,9 +255,9 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t len, uint8_t*
/* Wait until all data are received */
while (len) {
/* Wait until RXNE flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_RXNE) == RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}
@ -270,9 +272,9 @@ bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg, uint8_t len, uint8_t*
}
/* Wait until STOPF flag is set */
i2cTimeout = I2C_LONG_TIMEOUT;
timeoutStartUs = microsISR();
while (I2C_GetFlagStatus(I2Cx, I2C_ISR_STOPF) == RESET) {
if ((i2cTimeout--) == 0) {
if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
return i2cTimeoutUserCallback();
}
}