From 8fbd1c95e060821ad43d2d2b0ffca04a6d72bfeb Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 6 Jan 2012 11:49:21 +0000 Subject: I2C. Fix problem with write only transactions. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3747 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index eade3bb8a..9927016a7 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -304,14 +304,15 @@ static uint32_t i2c_get_event(I2CDriver *i2cp) { * @notapi */ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; switch (i2c_get_event(i2cp)) { case I2C_EV5_MASTER_MODE_SELECT: - dp->DR = i2cp->addr; + i2cp->i2c->DR = i2cp->addr; break; case I2C_EV6_MASTER_REC_MODE_SELECTED: dmaStreamEnable(i2cp->dmarx); + /* LAST bit needs only during receive phase. */ + i2cp->i2c->CR2 |= I2C_CR2_LAST; break; case I2C_EV6_MASTER_TRA_MODE_SELECTED: dmaStreamEnable(i2cp->dmatx); @@ -324,6 +325,7 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; return; } + i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; i2cp->i2c->CR1 |= I2C_CR1_STOP; wakeup_isr(i2cp, RDY_OK); break; @@ -352,6 +354,10 @@ static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { #endif dmaStreamDisable(i2cp->dmarx); + dmaStreamClearInterrupt(i2cp->dmarx); + + i2cp->i2c->CR2 &= ~(I2C_CR2_LAST | I2C_CR2_ITEVTEN); + i2cp->i2c->CR1 &= ~I2C_CR1_ACK; i2cp->i2c->CR1 |= I2C_CR1_STOP; wakeup_isr(i2cp, RDY_OK); } @@ -375,6 +381,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { #endif dmaStreamDisable(i2cp->dmatx); + dmaStreamClearInterrupt(i2cp->dmatx); } /** @@ -407,6 +414,7 @@ static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp) { } if (i2cp->i2c->SR1 & I2C_SR1_AF) { /* Acknowledge fail. */ i2cp->i2c->SR1 &= ~I2C_SR1_AF; + i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */ errors |= I2CD_ACK_FAILURE; } @@ -668,8 +676,7 @@ void i2c_lld_start(I2CDriver *i2cp) { /* Reset i2c peripheral.*/ i2cp->i2c->CR1 = I2C_CR1_SWRST; i2cp->i2c->CR1 = 0; - i2cp->i2c->CR2 = I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | - I2C_CR2_DMAEN | I2C_CR2_LAST; + i2cp->i2c->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; /* Setup I2C parameters.*/ i2c_lld_set_clock(i2cp); @@ -785,6 +792,7 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, return RDY_TIMEOUT; /* Starts the operation.*/ + i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN; i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; /* Waits for the operation completion or a timeout.*/ @@ -868,6 +876,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, return RDY_TIMEOUT; /* Starts the operation.*/ + i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN; i2cp->i2c->CR1 |= I2C_CR1_START; /* Waits for the operation completion or a timeout.*/ -- cgit v1.2.3