From 6419a7a3aac4632b70dcf623e6099628a29d6826 Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Thu, 20 Jun 2019 16:28:23 +0200 Subject: [PATCH 1/2] cpu/kinetis/i2c: Fix false positive for expected EIO during i2c write This fixes the positive result when master write data is NACKed. This false positive occurs when the write frame is finished but a data nack occurred. The AF check should occur first. --- cpu/kinetis/periph/i2c.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpu/kinetis/periph/i2c.c b/cpu/kinetis/periph/i2c.c index 2e5eeb0f78..2c6f4d25f6 100644 --- a/cpu/kinetis/periph/i2c.c +++ b/cpu/kinetis/periph/i2c.c @@ -471,21 +471,21 @@ static void i2c_irq_mst_tx_handler(I2C_Type *i2c, i2c_state_t *state, uint8_t S) assert(len != 0); /* This only happens if this periph driver is broken */ --len; state->tx.bytes_left = len; - if (len == 0) { + if (S & I2C_S_RXAK_MASK) { + /* NACK */ + /* Abort master transfer */ + DEBUG("i2c: NACK\n"); + bit_clear8(&i2c->C1, I2C_C1_MST_SHIFT); + state->active = 0; + state->retval = -EIO; + i2c_irq_signal_done(i2c, state->pid); + } + else if (len == 0) { /* We are done, NACK on the last byte is OK */ DEBUG("i2c: TX done\n"); i2c_irq_signal_done(i2c, state->pid); } else { - if (S & I2C_S_RXAK_MASK) { - /* NACK */ - /* Abort master transfer */ - DEBUG("i2c: NACK\n"); - bit_clear8(&i2c->C1, I2C_C1_MST_SHIFT); - state->active = 0; - state->retval = -EIO; - i2c_irq_signal_done(i2c, state->pid); - } /* transmit the next byte */ /* Increment first, datap points to the last byte transmitted */ ++state->tx.datap; From ec62f1cccee4ff2ca53ba5ba33724a98ff183ce7 Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Fri, 21 Jun 2019 11:03:12 +0200 Subject: [PATCH 2/2] cpu/kinetis/i2c: Suppress cppcheck unreadVariable warning On cppcheck 1.82 it throws a warning. Since it costs cycles and does nothing the ++dummy is (void)dummy. A warning suppression is added so the CI is happy. --- cpu/kinetis/periph/i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpu/kinetis/periph/i2c.c b/cpu/kinetis/periph/i2c.c index 2c6f4d25f6..defb9f4457 100644 --- a/cpu/kinetis/periph/i2c.c +++ b/cpu/kinetis/periph/i2c.c @@ -380,8 +380,10 @@ int i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t fla /* Initiate master receive mode by reading the data register once when * the C1[TX] bit is cleared and C1[MST] is set */ volatile uint8_t dummy; + /* cppcheck-suppress unreadVariable + * (reason: needed to empty D register) */ dummy = i2c->D; - ++dummy; + (void)dummy; /* Wait until the ISR signals back */ TRACE("i2c: read C1=%02x S=%02x\n", (unsigned)i2c->C1, (unsigned)i2c->S); thread_flags_t tflg = thread_flags_wait_any(THREAD_FLAG_KINETIS_I2C | THREAD_FLAG_TIMEOUT);