aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-04-01 15:38:17 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-04-01 15:38:17 +0000
commit0ebb7959d58256bea8e65b2cbed282e840297880 (patch)
tree246ce57e45451aae72e8fbb367ac6ca9e216c9e1
parent0e39ecd8bfa36d89ca1fead2ae43068d9bdc9516 (diff)
downloadChibiOS-0ebb7959d58256bea8e65b2cbed282e840297880.tar.gz
ChibiOS-0ebb7959d58256bea8e65b2cbed282e840297880.tar.bz2
ChibiOS-0ebb7959d58256bea8e65b2cbed282e840297880.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5525 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--os/hal/platforms/STM32/I2Cv2/i2c_lld.c118
-rw-r--r--testhal/STM32F37x/I2C/main.c26
2 files changed, 91 insertions, 53 deletions
diff --git a/os/hal/platforms/STM32/I2Cv2/i2c_lld.c b/os/hal/platforms/STM32/I2Cv2/i2c_lld.c
index 82b5ed13b..6668c212f 100644
--- a/os/hal/platforms/STM32/I2Cv2/i2c_lld.c
+++ b/os/hal/platforms/STM32/I2Cv2/i2c_lld.c
@@ -56,7 +56,7 @@
/*===========================================================================*/
#define I2C_MASTER_TC \
- ((uint32_t)(I2C_ISR_BUSY|I2C_ISR_TC))
+ ((uint32_t)(I2C_ISR_BUSY | I2C_ISR_TC))
#define I2C_ERROR_MASK \
((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \
@@ -155,13 +155,14 @@ static void i2c_lld_safety_timeout(void *p) {
* @brief I2C shared ISR code.
*
* @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] isr content of the ISR register to be decoded
*
* @notapi
*/
-static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t status) {
+static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) {
I2C_TypeDef *dp = i2cp->i2c;
- if (status & I2C_MASTER_TC) {
+ if (isr & I2C_ISR_TC) {
uint8_t rxbytes = dmaStreamGetTransactionSize(i2cp->dmarx);
if (rxbytes > 0) {
/* Enable RX DMA */
@@ -179,6 +180,10 @@ static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t status) {
wakeup_isr(i2cp, RDY_OK);
}
}
+ else if (isr & I2C_ISR_NACKF) {
+ i2cp->errors |= I2CD_ACK_FAILURE;
+ wakeup_isr(i2cp, RDY_RESET);
+ }
}
/**
@@ -231,48 +236,31 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
* @brief I2C error handler.
*
* @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] isr content of the ISR register to be decoded
*
* @notapi
*/
-static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t status) {
- i2cflags_t errors;
+static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) {
/* Clears interrupt flags just to be safe.*/
dmaStreamDisable(i2cp->dmatx);
dmaStreamDisable(i2cp->dmarx);
- errors = I2CD_NO_ERROR;
+ if (isr & I2C_ISR_BERR)
+ i2cp->errors |= I2CD_BUS_ERROR;
- if (status & I2C_ISR_BERR) { /* Bus error. */
- status &= ~I2C_ISR_BERR;
- errors |= I2CD_BUS_ERROR;
- }
- if (status & I2C_ISR_ARLO) { /* Arbitration lost. */
- status &= ~I2C_ISR_ARLO;
- errors |= I2CD_ARBITRATION_LOST;
- }
- if (status & I2C_ISR_OVR) { /* Overrun. */
- status &= ~I2C_ISR_OVR;
- errors |= I2CD_OVERRUN;
- }
- if (status & I2C_ISR_PECERR) { /* PEC error. */
- status &= ~I2C_ISR_PECERR;
- errors |= I2CD_PEC_ERROR;
- }
- if (status & I2C_ISR_TIMEOUT) { /* SMBus Timeout. */
- status &= ~I2C_ISR_TIMEOUT;
- errors |= I2CD_TIMEOUT;
- }
- if (status & I2C_ISR_ALERT) { /* SMBus alert. */
- status &= ~I2C_ISR_ALERT;
- errors |= I2CD_SMB_ALERT;
- }
+ if (isr & I2C_ISR_ARLO)
+ i2cp->errors |= I2CD_ARBITRATION_LOST;
+
+ if (isr & I2C_ISR_OVR)
+ i2cp->errors |= I2CD_OVERRUN;
+
+ if (isr & I2C_ISR_TIMEOUT)
+ i2cp->errors |= I2CD_TIMEOUT;
/* If some error has been identified then sends wakes the waiting thread.*/
- if (errors != I2CD_NO_ERROR) {
- i2cp->errors = errors;
+ if (i2cp->errors != I2CD_NO_ERROR)
wakeup_isr(i2cp, RDY_RESET);
- }
}
/*===========================================================================*/
@@ -287,35 +275,44 @@ static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t status) {
* @notapi
*/
CH_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) {
- uint32_t status = I2CD1.i2c->ISR;
+ uint32_t isr = I2CD1.i2c->ISR;
CH_IRQ_PROLOGUE();
- if (status & I2C_ERROR_MASK)
- i2c_lld_serve_error_interrupt(&I2CD1, status);
- else if (status & I2C_INT_MASK)
- i2c_lld_serve_interrupt(&I2CD1, status);
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD1, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD1, isr);
CH_IRQ_EPILOGUE();
}
#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER)
CH_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
- uint32_t status = I2CD1.i2c->ISR;
+ uint32_t isr = I2CD1.i2c->ISR;
CH_IRQ_PROLOGUE();
- i2c_lld_serve_interrupt(&I2CD1, status);
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD1, isr);
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
- uint32_t status = I2CD1.i2c->ISR;
+ uint32_t isr = I2CD1.i2c->ISR;
CH_IRQ_PROLOGUE();
- i2c_lld_serve_error_interrupt(&I2CD1, status);
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD1, isr);
CH_IRQ_EPILOGUE();
}
@@ -333,35 +330,44 @@ CH_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
* @notapi
*/
CH_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) {
- uint32_t status = I2CD2.i2c->ISR;
+ uint32_t isr = I2CD2.i2c->ISR;
CH_IRQ_PROLOGUE();
- if (status & I2C_ERROR_MASK)
- i2c_lld_serve_error_interrupt(&I2CD2, status);
- else if (status & I2C_INT_MASK)
- i2c_lld_serve_interrupt(&I2CD2, status);
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD2, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD2, isr);
CH_IRQ_EPILOGUE();
}
#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER)
CH_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
- uint32_t status = I2CD2.i2c->ISR;
+ uint32_t isr = I2CD2.i2c->ISR;
CH_IRQ_PROLOGUE();
- i2c_lld_serve_interrupt(&I2CD2, status);
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD2, isr);
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
- uint32_t status = I2CD2.i2c->ISR;
+ uint32_t isr = I2CD2.i2c->ISR;
CH_IRQ_PROLOGUE();
- i2c_lld_serve_error_interrupt(&I2CD2, status);
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD2, isr);
CH_IRQ_EPILOGUE();
}
@@ -497,8 +503,8 @@ void i2c_lld_start(I2CDriver *i2cp) {
dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR);
/* Reset i2c peripheral.*/
- dp->CR1 = i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_TCIE |
- I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN;
+ dp->CR1 = i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE |
+ I2C_CR1_TCIE | I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN;
/* Set slave address field (master mode) */
dp->CR2 = (i2cp->config->cr2 & ~I2C_CR2_SADD);
@@ -591,6 +597,9 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
chDbgCheck((rxbytes > 1), "i2c_lld_master_receive_timeout");
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2CD_NO_ERROR;
+
/* Global timeout for the whole operation.*/
if (timeout != TIME_INFINITE)
chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
@@ -682,6 +691,9 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
chDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))),
"i2c_lld_master_transmit_timeout");
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2CD_NO_ERROR;
+
/* Global timeout for the whole operation.*/
if (timeout != TIME_INFINITE)
chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
diff --git a/testhal/STM32F37x/I2C/main.c b/testhal/STM32F37x/I2C/main.c
index 52a4e889b..96295089b 100644
--- a/testhal/STM32F37x/I2C/main.c
+++ b/testhal/STM32F37x/I2C/main.c
@@ -23,6 +23,7 @@
* The timings are critical, please always refer to the STM32 Reference
* Manual before attempting changes.
*/
+#if 0
static const I2CConfig i2cconfig = {
STM32_TIMINGR_PRESC(8U) | /* 72MHz/9 = 8MHz I2CCLK. */
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
@@ -30,6 +31,14 @@ static const I2CConfig i2cconfig = {
0,
0
};
+#endif
+static const I2CConfig i2cconfig = {
+ STM32_TIMINGR_PRESC(15U) |
+ STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) |
+ STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U),
+ 0,
+ 0
+};
/*
* This is a periodic thread that does absolutely nothing except flashing
@@ -78,6 +87,23 @@ int main(void) {
* Normal main() thread activity, in this demo it does nothing.
*/
while (TRUE) {
+ unsigned i;
+ msg_t msg;
+ static const uint8_t cmd[] = {0, 0};
+ uint8_t data[16];
+
+ chThdSleepMilliseconds(10);
+ msg = i2cMasterTransmitTimeout(&I2CD2, 0x52, cmd, sizeof(cmd),
+ data, sizeof(data), TIME_INFINITE);
+ if (msg != RDY_OK)
+ chSysHalt();
+ for (i = 0; i < 256; i++) {
+ chThdSleepMilliseconds(10);
+ msg = i2cMasterReceiveTimeout(&I2CD2, 0x52,
+ data, sizeof(data), TIME_INFINITE);
+ if (msg != RDY_OK)
+ chSysHalt();
+ }
chThdSleepMilliseconds(500);
}
return 0;