aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbarthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-01-06 11:49:21 +0000
committerbarthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-01-06 11:49:21 +0000
commit8fbd1c95e060821ad43d2d2b0ffca04a6d72bfeb (patch)
tree49d5c3cc66feacb08694548154026fedc52eb095
parentc56e9ea70a9a8e79f00fb70fb4278b9bd7bf3ae7 (diff)
downloadChibiOS-8fbd1c95e060821ad43d2d2b0ffca04a6d72bfeb.tar.gz
ChibiOS-8fbd1c95e060821ad43d2d2b0ffca04a6d72bfeb.tar.bz2
ChibiOS-8fbd1c95e060821ad43d2d2b0ffca04a6d72bfeb.zip
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
-rw-r--r--os/hal/platforms/STM32/i2c_lld.c17
1 files 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.*/