From 46bdcb1c8ec12e6e69f1420dcb2e50549ef28d64 Mon Sep 17 00:00:00 2001 From: emlsyx Date: Sun, 18 Jul 2021 20:19:19 +0800 Subject: [PATCH] fix imxrt i2c drives read failure bug --- bsp/imxrt/libraries/drivers/drv_i2c.c | 101 +++++--------------------- 1 file changed, 19 insertions(+), 82 deletions(-) diff --git a/bsp/imxrt/libraries/drivers/drv_i2c.c b/bsp/imxrt/libraries/drivers/drv_i2c.c index 117b29f3d3..3ad48de112 100644 --- a/bsp/imxrt/libraries/drivers/drv_i2c.c +++ b/bsp/imxrt/libraries/drivers/drv_i2c.c @@ -8,6 +8,7 @@ * 2017-08-08 Yang the first version * 2018-03-24 LaiYiKeTang add hardware iic * 2019-04-22 tyustli add imxrt series support + * 2021-07-18 emlsyx fix read failure bug * */ @@ -126,81 +127,24 @@ static rt_err_t imxrt_lpi2c_configure(struct imxrt_i2c_bus *bus, lpi2c_master_co LPI2C_MasterInit(bus->I2C, cfg, LPI2C_CLOCK_FREQUENCY); return RT_EOK; } - -status_t LPI2C_MasterCheck(LPI2C_Type *base, uint32_t status) +static rt_err_t imxrt_lpi2c_wait_fifo_empty(LPI2C_Type *base) { - status_t result = kStatus_Success; + size_t tx_count = 0xFFU; + size_t rx_count = 0xFFU; - /* Check for error. These errors cause a stop to automatically be sent. We must */ - /* clear the errors before a new transfer can start. */ - status &= 0x3c00; - if (status) + /* Check master tx FIFO empty or not */ + LPI2C_MasterGetFifoCounts(base, &rx_count, &tx_count); + while (tx_count || rx_count) { - /* Select the correct error code. Ordered by severity, with bus issues first. */ - if (status & kLPI2C_MasterPinLowTimeoutFlag) - { - result = kStatus_LPI2C_PinLowTimeout; - } - else if (status & kLPI2C_MasterArbitrationLostFlag) - { - result = kStatus_LPI2C_ArbitrationLost; - } - else if (status & kLPI2C_MasterNackDetectFlag) - { - result = kStatus_LPI2C_Nak; - } - else if (status & kLPI2C_MasterFifoErrFlag) - { - result = kStatus_LPI2C_FifoError; - } - else - { - assert(false); - } - - /* Clear the flags. */ - LPI2C_MasterClearStatusFlags(base, status); - - /* Reset fifos. These flags clear automatically. */ - base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK; + LPI2C_MasterGetFifoCounts(base, &rx_count, &tx_count); } - return result; -} - -/*! - * @brief Wait until the tx fifo all empty. - * @param base The LPI2C peripheral base address. - * @retval #kStatus_Success - * @retval #kStatus_LPI2C_PinLowTimeout - * @retval #kStatus_LPI2C_ArbitrationLost - * @retval #kStatus_LPI2C_Nak - * @retval #kStatus_LPI2C_FifoError - */ -static status_t LPI2C_MasterWaitForTxFifoAllEmpty(LPI2C_Type *base) -{ - uint32_t status; - size_t txCount; - - do + /* Check communicate with slave successful or not */ + if (LPI2C_MasterGetStatusFlags(base) & kLPI2C_MasterNackDetectFlag) { - status_t result; - - /* Get the number of words in the tx fifo and compute empty slots. */ - LPI2C_MasterGetFifoCounts(base, NULL, &txCount); - - /* Check for error flags. */ - status = LPI2C_MasterGetStatusFlags(base); - result = LPI2C_MasterCheck(base, status); - if (result) - { - return result; - } + return RT_EEMPTY; } - - while (txCount); - - return kStatus_Success; + return RT_EOK; } static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, @@ -221,17 +165,14 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, { if (imxrt_i2c->msg[i].flags & RT_I2C_RD) { - if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Write) != kStatus_Success) + if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) { i = 0; break; } - while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) - { - } - - if (LPI2C_MasterRepeatedStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) + /* Check communicate with slave successful or not */ + if (RT_EOK != imxrt_lpi2c_wait_fifo_empty(imxrt_i2c->I2C)) { i = 0; break; @@ -251,17 +192,14 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, break; } - while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) - { - } - - if (LPI2C_MasterSend(imxrt_i2c->I2C, imxrt_i2c->msg[i].buf, imxrt_i2c->msg[i].len) != kStatus_Success) + /* Check communicate with slave successful or not */ + if (RT_EOK != imxrt_lpi2c_wait_fifo_empty(imxrt_i2c->I2C)) { i = 0; break; } - if (LPI2C_MasterWaitForTxFifoAllEmpty(imxrt_i2c->I2C) != kStatus_Success) + if (LPI2C_MasterSend(imxrt_i2c->I2C, imxrt_i2c->msg[i].buf, imxrt_i2c->msg[i].len) != kStatus_Success) { i = 0; break; @@ -351,7 +289,6 @@ int rt_hw_i2c_init(void) return 0; } - -INIT_DEVICE_EXPORT(rt_hw_i2c_init); +INIT_BOARD_EXPORT(rt_hw_i2c_init); #endif /* BSP_USING_I2C */ -- Gitee