From 0738591b023a4e2c6cacebadebfef08aafea4d6e Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 7 Dec 2011 17:57:42 +0000 Subject: I2C. Switch to synchronous model. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3570 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 85 +++------------------------------------- os/hal/platforms/STM32/i2c_lld.c | 36 +++++++++-------- os/hal/platforms/STM32/i2c_lld.h | 15 +------ os/hal/src/i2c.c | 21 +--------- 4 files changed, 29 insertions(+), 128 deletions(-) (limited to 'os') diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 1923742c7..8cfd97e75 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -66,13 +66,6 @@ #define I2C_USE_MUTUAL_EXCLUSION TRUE #endif -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__) -#define I2C_USE_WAIT TRUE -#endif - /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ @@ -98,57 +91,11 @@ typedef enum { #include "i2c_lld.h" -/** - * @brief I2C notification callback type. - * @details This callback invoked when byte transfer finish event occurs, - * no matter if sending or reading. - * - * @param[in] i2cp pointer to the @p I2CDriver object triggering the - * callback - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the - * callback - */ -typedef void (*i2ccallback_t)(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg); - -/** - * @brief I2C error notification callback type. - * - * @param[in] i2cp pointer to the @p I2CDriver object triggering the - * callback - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the - * callback - */ -typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp, - const I2CSlaveConfig *i2cscfg); - -/** - * @brief Structure representing an I2C slave configuration. - * @details Each slave device has its own config structure with input and - * output buffers for temporally storing data. - */ -struct I2CSlaveConfig{ - /** - * @brief Callback pointer. - * @note Transfer finished callback. Invoke when all data transferred. - * If set to @p NULL then the callback is disabled. - */ - i2ccallback_t id_callback; - /** - * @brief Callback pointer. - * @note This callback will be invoked when error condition occur. - * If set to @p NULL then the callback is disabled. - */ - i2cerrorcallback_t id_err_callback; -#if defined(I2C_SLAVECONFIG_EXT_FIELDS) - I2C_SLAVECONFIG_EXT_FIELDS -#endif -}; /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ -#if I2C_USE_WAIT || defined(__DOXYGEN__) /** * @brief Waits for operation completion. * @details This function waits for the driver to complete the current @@ -186,60 +133,40 @@ struct I2CSlaveConfig{ chSysUnlockFromIsr(); \ } \ } -#else /* !I2C_USE_WAIT */ -#define _i2c_wait_s(i2cp) -#define _i2c_wakeup_isr(i2cp) -#endif /* !I2C_USE_WAIT */ /** * @brief Common ISR code. * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. + * - Waiting thread wakeup. * - Driver state transitions. * * @note This macro is meant to be used in the low level drivers * implementation only. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object * * @notapi */ #define _i2c_isr_code(i2cp, i2cscfg) { \ - if(((i2cp)->id_slave_config)->id_callback) { \ - ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ - (i2cp)->id_state = I2C_READY; \ - } \ - else{ \ - (i2cp)->id_state = I2C_READY; \ - } \ + (i2cp)->id_state = I2C_READY; \ _i2c_wakeup_isr(i2cp); \ } /** * @brief Error ISR code. * @details This code handles the portable part of the ISR code: - * - Error callback invocation. - * - Waiting thread wakeup, if any. + * - Waiting thread wakeup. * - Driver state transitions. * * @note This macro is meant to be used in the low level drivers * implementation only. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object * * @notapi */ #define _i2c_isr_err_code(i2cp, i2cscfg) { \ - if(((i2cp)->id_slave_config)->id_err_callback) { \ - ((i2cp)->id_slave_config)->id_err_callback(i2cp, i2cscfg); \ - (i2cp)->id_state = I2C_READY; \ - } \ - else{ \ - (i2cp)->id_state = I2C_READY; \ - } \ + (i2cp)->id_state = I2C_READY; \ _i2c_wakeup_isr(i2cp); \ } @@ -254,11 +181,11 @@ extern "C" { void i2cObjectInit(I2CDriver *i2cp); void i2cStart(I2CDriver *i2cp, const I2CConfig *config); void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, + void i2cMasterTransmit(I2CDriver *i2cp, uint8_t slave_addr, uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes); - void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, + void i2cMasterReceive(I2CDriver *i2cp, uint8_t slave_addr, uint8_t *rxbuf, size_t rxbytes); void i2cMasterStart(I2CDriver *i2cp); void i2cMasterStop(I2CDriver *i2cp); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index f3291f819..1345c847b 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -185,8 +185,6 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) - ; _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -205,8 +203,6 @@ static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp){ dmaStreamDisable(i2cp->dmarx); i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) - ; _i2c_isr_code(i2cp, i2cp->id_slave_config); } @@ -227,7 +223,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp){ * @param[in] i2cp pointer to the @p I2CDriver object */ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - i2cflags_t flags; + i2cflags_t errors; I2C_TypeDef *reg; chSysLockFromIsr(); @@ -239,43 +235,41 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { chSysUnlockFromIsr(); reg = i2cp->id_i2c; - flags = I2CD_NO_ERROR; + errors = I2CD_NO_ERROR; if(reg->SR1 & I2C_SR1_BERR) { /* Bus error */ reg->SR1 &= ~I2C_SR1_BERR; - flags |= I2CD_BUS_ERROR; + errors |= I2CD_BUS_ERROR; } if(reg->SR1 & I2C_SR1_ARLO) { /* Arbitration lost */ reg->SR1 &= ~I2C_SR1_ARLO; - flags |= I2CD_ARBITRATION_LOST; + errors |= I2CD_ARBITRATION_LOST; } if(reg->SR1 & I2C_SR1_AF) { /* Acknowledge fail */ reg->SR1 &= ~I2C_SR1_AF; reg->CR1 |= I2C_CR1_STOP; /* setting stop bit */ - while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) - ; - flags |= I2CD_ACK_FAILURE; + errors |= I2CD_ACK_FAILURE; } if(reg->SR1 & I2C_SR1_OVR) { /* Overrun */ reg->SR1 &= ~I2C_SR1_OVR; - flags |= I2CD_OVERRUN; + errors |= I2CD_OVERRUN; } if(reg->SR1 & I2C_SR1_PECERR) { /* PEC error */ reg->SR1 &= ~I2C_SR1_PECERR; - flags |= I2CD_PEC_ERROR; + errors |= I2CD_PEC_ERROR; } if(reg->SR1 & I2C_SR1_TIMEOUT) { /* SMBus Timeout */ reg->SR1 &= ~I2C_SR1_TIMEOUT; - flags |= I2CD_TIMEOUT; + errors |= I2CD_TIMEOUT; } if(reg->SR1 & I2C_SR1_SMBALERT) { /* SMBus alert */ reg->SR1 &= ~I2C_SR1_SMBALERT; - flags |= I2CD_SMB_ALERT; + errors |= I2CD_SMB_ALERT; } - if(flags != I2CD_NO_ERROR) { /* send communication end signal */ + if(errors != I2CD_NO_ERROR) { /* send communication end signal */ chSysLockFromIsr(); - i2cAddFlagsI(i2cp, flags); + i2cAddFlagsI(i2cp, errors); chSysUnlockFromIsr(); _i2c_isr_err_code(i2cp, i2cp->id_slave_config); } @@ -523,6 +517,10 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint8_t slave_addr, dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); dmaStreamSetMode(i2cp->dmarx, ((i2cp->dmamode) | mode)); + /* wait stop bit from previouse transaction*/ + while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN; i2cp->id_i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; } @@ -561,6 +559,10 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint8_t slave_addr, dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); dmaStreamSetMode(i2cp->dmatx, ((i2cp->dmamode) | mode)); + /* wait stop bit from previouse transaction*/ + while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN; i2cp->id_i2c->CR1 |= I2C_CR1_START; } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 2ca6b872a..4e9051e39 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -273,11 +273,6 @@ typedef struct { */ typedef struct I2CDriver I2CDriver; -/** - * @brief Type of a structure representing an I2C slave config. - */ -typedef struct I2CSlaveConfig I2CSlaveConfig; - /** * @brief Structure representing an I2C driver. */ @@ -287,12 +282,11 @@ struct I2CDriver{ */ i2cstate_t id_state; -#if I2C_USE_WAIT /** * @brief Thread waiting for I/O completion. */ Thread *id_thread; -#endif /* I2C_USE_WAIT */ + #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) #if CH_USE_MUTEXES || defined(__DOXYGEN__) /** @@ -308,10 +302,6 @@ struct I2CDriver{ * @brief Current configuration data. */ const I2CConfig *id_config; - /** - * @brief Current slave configuration data. - */ - const I2CSlaveConfig *id_slave_config; __IO size_t txbytes; /*!< @brief Number of bytes to be transmitted. */ __IO size_t rxbytes; /*!< @brief Number of bytes to be received. */ @@ -341,8 +331,7 @@ struct I2CDriver{ (i2cp->id_i2c->SR2 & I2C_SR2_BUSY) -/* Wait until BUSY flag is reset: a STOP has been generated on the bus - * signaling the end of transmission. Normally this wait function +/* Wait until BUSY flag is reset. Normally this wait function * does not block thread, only if slave not response it does. */ #define i2c_lld_wait_bus_free(i2cp) { \ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 4b9160a68..996343104 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -75,11 +75,7 @@ void i2cObjectInit(I2CDriver *i2cp) { i2cp->id_config = NULL; i2cp->rxbuf = NULL; i2cp->txbuf = NULL; - i2cp->id_slave_config = NULL; - -#if I2C_USE_WAIT i2cp->id_thread = NULL; -#endif /* I2C_USE_WAIT */ #if I2C_USE_MUTUAL_EXCLUSION #if CH_USE_MUTEXES @@ -147,7 +143,6 @@ void i2cStop(I2CDriver *i2cp) { * hardware restrictions. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2C slave config * @param[in] slave_addr Slave device address (7 bits) without R/W bit * @param[in] txbuf pointer to transmit buffer * @param[in] txbytes number of bytes to be transmitted @@ -156,24 +151,19 @@ void i2cStop(I2CDriver *i2cp) { * you want transmit only */ void i2cMasterTransmit(I2CDriver *i2cp, - const I2CSlaveConfig *i2cscfg, uint8_t slave_addr, uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes) { - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ + chDbgCheck((i2cp != NULL) &&\ (slave_addr != 0) &&\ (txbytes > 0) &&\ (txbuf != NULL) &&\ ((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))), "i2cMasterTransmit"); - /* init slave config field in driver */ - i2cp->id_slave_config = i2cscfg; - - // TODO: remove this loop. Do only 1 check because mutual exclusion resolve collisions i2c_lld_wait_bus_free(i2cp); chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out"); @@ -191,27 +181,21 @@ void i2cMasterTransmit(I2CDriver *i2cp, * hardware restrictions. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2C slave config * @param[in] slave_addr slave device address (7 bits) without R/W bit * @param[in] rxbytes number of bytes to be received * @param[in] rxbuf pointer to receive buffer */ void i2cMasterReceive(I2CDriver *i2cp, - const I2CSlaveConfig *i2cscfg, uint8_t slave_addr, uint8_t *rxbuf, size_t rxbytes){ - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ + chDbgCheck((i2cp != NULL) &&\ (slave_addr != 0) &&\ (rxbytes > 1) && \ (rxbuf != NULL), "i2cMasterReceive"); - /* init slave config field in driver */ - i2cp->id_slave_config = i2cscfg; - - // TODO: remove this loop. Do only 1 check because mutual exclusion resolve collisions i2c_lld_wait_bus_free(i2cp); chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out"); @@ -298,7 +282,6 @@ void i2cReleaseBus(I2CDriver *i2cp) { chDbgCheck(i2cp != NULL, "i2cReleaseBus"); #if CH_USE_MUTEXES - (void)i2cp; chMtxUnlock(); #elif CH_USE_SEMAPHORES chSemSignal(&i2cp->id_semaphore); -- cgit v1.2.3