From 5ef209c86344caedf23c09eb991e7434385cba96 Mon Sep 17 00:00:00 2001 From: Daniel Jarai Date: Thu, 19 Jul 2018 11:35:43 +0200 Subject: nanohub: stm32: i2c: always wait for the BTF event in the DmaTxDone ISR This interrupt is fired when the DMA transfer completes, ie. all bytes have been transmitted to the I2C peripheral. However, It's possible that the I2C transfer didn't finish yet, so before touching the peripheral, wait for the BTF (byte transfer finished) flag to be set. This fixes the issue where the last byte of a transfer was randomly lost, especially at higher core clock frequencies (>= 40 MHz). Change-Id: I126e43f1e9cfdc831f61d0a0a1940367440dce55 --- firmware/os/platform/stm32/i2c.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/firmware/os/platform/stm32/i2c.c b/firmware/os/platform/stm32/i2c.c index 7ba7b7ce..8ae35cf7 100644 --- a/firmware/os/platform/stm32/i2c.c +++ b/firmware/os/platform/stm32/i2c.c @@ -543,14 +543,16 @@ static void stmI2cMasterDmaTxDone(void *cookie, uint16_t bytesLeft, int err) state->tx.offset = state->tx.size - bytesLeft; state->tx.size = 0; + stmI2cDmaDisable(pdev); + + while (!(regs->SR1 & I2C_SR1_BTF)) + ; + if (err == 0 && state->rx.size > 0) { atomicWriteByte(&state->masterState, STM_I2C_MASTER_START); stmI2cStartEnable(pdev); } else { - while (!(regs->SR1 & I2C_SR1_BTF)) - ; - stmI2cStopEnable(pdev); stmI2cMasterTxRxDone(pdev, err); } -- cgit v1.2.3