aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-04-02 17:28:18 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-04-02 17:28:18 +0000
commit675296b85232a6139da384f63bb829f9182029da (patch)
tree1e76f98b20021a0f0e4bf365111bc07943046c77 /os
parentb8f6224a68c710efb260d8591d59e6247e20ee1a (diff)
downloadChibiOS-675296b85232a6139da384f63bb829f9182029da.tar.gz
ChibiOS-675296b85232a6139da384f63bb829f9182029da.tar.bz2
ChibiOS-675296b85232a6139da384f63bb829f9182029da.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5536 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/include/i2c.h5
-rw-r--r--os/hal/platforms/STM32/I2Cv1/i2c_lld.c84
2 files changed, 47 insertions, 42 deletions
diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h
index b3a9ffdff..2e45450ee 100644
--- a/os/hal/include/i2c.h
+++ b/os/hal/include/i2c.h
@@ -48,7 +48,10 @@
#define I2CD_ARBITRATION_LOST 0x02 /**< @brief Arbitration Lost. */
#define I2CD_ACK_FAILURE 0x04 /**< @brief Acknowledge Failure. */
#define I2CD_OVERRUN 0x08 /**< @brief Overrun/Underrun. */
-#define I2CD_TIMEOUT 0x10 /**< @brief Hardware timeout. */
+#define I2CD_PEC_ERROR 0x10 /**< @brief PEC Error in
+ reception. */
+#define I2CD_TIMEOUT 0x20 /**< @brief Hardware timeout. */
+#define I2CD_SMB_ALERT 0x40 /**< @brief SMBus Alert. */
/** @} */
/*===========================================================================*/
diff --git a/os/hal/platforms/STM32/I2Cv1/i2c_lld.c b/os/hal/platforms/STM32/I2Cv1/i2c_lld.c
index 9e8b5ef86..fbf1c1f71 100644
--- a/os/hal/platforms/STM32/I2Cv1/i2c_lld.c
+++ b/os/hal/platforms/STM32/I2Cv1/i2c_lld.c
@@ -65,16 +65,24 @@
#define I2C_EV5_MASTER_MODE_SELECT \
((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_SB))
+
#define I2C_EV6_MASTER_TRA_MODE_SELECTED \
((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA) << 16) | \
I2C_SR1_ADDR|I2C_SR1_TXE))
+
#define I2C_EV6_MASTER_REC_MODE_SELECTED \
((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR))
+
#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \
((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \
I2C_SR1_BTF | I2C_SR1_TXE))
+
#define I2C_EV_MASK 0x00FFFFFF
+#define I2C_ERROR_MASK \
+ ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \
+ I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT))
+
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@@ -380,57 +388,45 @@ 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] sr content of the SR1 register to be decoded
*
* @notapi
*/
-static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
- i2cflags_t errors;
+static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) {
/* Clears interrupt flags just to be safe.*/
- chSysLockFromIsr();
dmaStreamDisable(i2cp->dmatx);
dmaStreamDisable(i2cp->dmarx);
- chSysUnlockFromIsr();
- errors = I2CD_NO_ERROR;
+ i2cp->errors = I2CD_NO_ERROR;
- if (dp->SR1 & I2C_SR1_BERR) { /* Bus error. */
- dp->SR1 &= ~I2C_SR1_BERR;
- errors |= I2CD_BUS_ERROR;
- }
- if (dp->SR1 & I2C_SR1_ARLO) { /* Arbitration lost. */
- dp->SR1 &= ~I2C_SR1_ARLO;
- errors |= I2CD_ARBITRATION_LOST;
- }
- if (dp->SR1 & I2C_SR1_AF) { /* Acknowledge fail. */
- dp->SR1 &= ~I2C_SR1_AF;
- dp->CR2 &= ~I2C_CR2_ITEVTEN;
- dp->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */
- errors |= I2CD_ACK_FAILURE;
- }
- if (dp->SR1 & I2C_SR1_OVR) { /* Overrun. */
- dp->SR1 &= ~I2C_SR1_OVR;
- errors |= I2CD_OVERRUN;
- }
- if (dp->SR1 & I2C_SR1_PECERR) { /* PEC error. */
- dp->SR1 &= ~I2C_SR1_PECERR;
- errors |= I2CD_PEC_ERROR;
- }
- if (dp->SR1 & I2C_SR1_TIMEOUT) { /* SMBus Timeout. */
- dp->SR1 &= ~I2C_SR1_TIMEOUT;
- errors |= I2CD_TIMEOUT;
- }
- if (dp->SR1 & I2C_SR1_SMBALERT) { /* SMBus alert. */
- dp->SR1 &= ~I2C_SR1_SMBALERT;
- errors |= I2CD_SMB_ALERT;
+ if (sr & I2C_SR1_BERR) /* Bus error. */
+ i2cp->errors |= I2CD_BUS_ERROR;
+
+ if (sr & I2C_SR1_ARLO) /* Arbitration lost. */
+ i2cp->errors |= I2CD_ARBITRATION_LOST;
+
+ if (sr & I2C_SR1_AF) { /* Acknowledge fail. */
+ i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN;
+ i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */
+ i2cp->errors |= I2CD_ACK_FAILURE;
}
+ if (sr & I2C_SR1_OVR) /* Overrun. */
+ i2cp->errors |= I2CD_OVERRUN;
+
+ if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */
+ i2cp->errors |= I2CD_TIMEOUT;
+
+ if (sr & I2C_SR1_PECERR) /* PEC error. */
+ i2cp->errors |= I2CD_PEC_ERROR;
+
+ if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */
+ i2cp->errors |= I2CD_SMB_ALERT;
+
/* 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);
- }
}
/*===========================================================================*/
@@ -456,10 +452,12 @@ CH_IRQ_HANDLER(I2C1_EV_IRQHandler) {
* @brief I2C1 error interrupt handler.
*/
CH_IRQ_HANDLER(I2C1_ER_IRQHandler) {
+ uint16_t sr = I2CD1.i2c->SR1;
CH_IRQ_PROLOGUE();
- i2c_lld_serve_error_interrupt(&I2CD1);
+ I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
+ i2c_lld_serve_error_interrupt(&I2CD1, sr);
CH_IRQ_EPILOGUE();
}
@@ -486,10 +484,12 @@ CH_IRQ_HANDLER(I2C2_EV_IRQHandler) {
* @notapi
*/
CH_IRQ_HANDLER(I2C2_ER_IRQHandler) {
+ uint16_t sr = I2CD2.i2c->SR1;
CH_IRQ_PROLOGUE();
- i2c_lld_serve_error_interrupt(&I2CD2);
+ I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
+ i2c_lld_serve_error_interrupt(&I2CD2, sr);
CH_IRQ_EPILOGUE();
}
@@ -516,10 +516,12 @@ CH_IRQ_HANDLER(I2C3_EV_IRQHandler) {
* @notapi
*/
CH_IRQ_HANDLER(I2C3_ER_IRQHandler) {
+ uint16_t sr = I2CD3.i2c->SR1;
CH_IRQ_PROLOGUE();
- i2c_lld_serve_error_interrupt(&I2CD3);
+ I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
+ i2c_lld_serve_error_interrupt(&I2CD3, sr);
CH_IRQ_EPILOGUE();
}