aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/hal/include/i2c.h97
-rw-r--r--os/hal/src/i2c.c154
2 files changed, 99 insertions, 152 deletions
diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h
index 31dcb53d5..1053712d0 100644
--- a/os/hal/include/i2c.h
+++ b/os/hal/include/i2c.h
@@ -51,7 +51,7 @@
#define I2CD_OVERRUN 0x08 /**< @brief Overrun/Underrun. */
#define I2CD_PEC_ERROR 0x10 /**< @brief PEC Error in
reception. */
-#define I2CD_TIMEOUT 0x20 /**< @brief Timeout Error. */
+#define I2CD_TIMEOUT 0x20 /**< @brief Hardware timeout. */
#define I2CD_SMB_ALERT 0x40 /**< @brief SMBus Alert. */
/** @} */
@@ -91,85 +91,10 @@ typedef enum {
#include "i2c_lld.h"
-
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
-/**
- * @brief Waits for operation completion.
- * @details This function waits for the driver to complete the current
- * operation.
- * @pre An operation must be running while the function is invoked.
- * @note No more than one thread can wait on a I2C driver using
- * this function.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define _i2c_wait_s(i2cp, timeout, rdymsg) { \
- chDbgAssert((i2cp)->id_thread == NULL, \
- "_i2c_wait(), #1", "already waiting"); \
- chSysLock(); \
- (i2cp)->id_thread = chThdSelf(); \
- rdymsg = chSchGoSleepTimeoutS(THD_STATE_SUSPENDED, timeout); \
- chSysUnlock(); \
-}
-
-/**
- * @brief Wakes up the waiting thread.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define _i2c_wakeup_isr(i2cp) { \
- if ((i2cp)->id_thread != NULL) { \
- Thread *tp = (i2cp)->id_thread; \
- (i2cp)->id_thread = NULL; \
- chSysLockFromIsr(); \
- chSchReadyI(tp); \
- chSysUnlockFromIsr(); \
- } \
-}
-
-/**
- * @brief Common ISR code.
- * @details This code handles the portable part of the ISR code:
- * - 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
- *
- * @notapi
- */
-#define _i2c_isr_code(i2cp, i2cscfg) { \
- (i2cp)->id_state = I2C_READY; \
- _i2c_wakeup_isr(i2cp); \
-}
-
-/**
- * @brief Error ISR code.
- * @details This code handles the portable part of the ISR code:
- * - 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
- *
- * @notapi
- */
-#define _i2c_isr_err_code(i2cp, i2cscfg) { \
- (i2cp)->id_state = I2C_READY; \
- _i2c_wakeup_isr(i2cp); \
-}
-
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@@ -181,16 +106,16 @@ extern "C" {
void i2cObjectInit(I2CDriver *i2cp);
void i2cStart(I2CDriver *i2cp, const I2CConfig *config);
void i2cStop(I2CDriver *i2cp);
- msg_t i2cMasterTransmit(I2CDriver *i2cp,
- uint8_t slave_addr,
- uint8_t *txbuf, size_t txbytes,
- uint8_t *rxbuf, size_t rxbytes,
- i2cflags_t *errors, systime_t timeout);
- msg_t i2cMasterReceive(I2CDriver *i2cp,
- uint8_t slave_addr,
- uint8_t *rxbuf, size_t rxbytes,
- i2cflags_t *errors, systime_t timeout);
-
+ i2cflags_t i2cGetErrors(I2CDriver *i2cp);
+ msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
+ i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ systime_t timeout);
+ msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
+ i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ systime_t timeout);
#if I2C_USE_MUTUAL_EXCLUSION
void i2cAcquireBus(I2CDriver *i2cp);
void i2cReleaseBus(I2CDriver *i2cp);
diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c
index c67f3a8c6..28dd99762 100644
--- a/os/hal/src/i2c.c
+++ b/os/hal/src/i2c.c
@@ -133,110 +133,131 @@ void i2cStop(I2CDriver *i2cp) {
}
/**
+ * @brief Returns the errors mask associated to the previous operation.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @return The errors mask.
+ *
+ * @api
+ */
+i2cflags_t i2cGetErrors(I2CDriver *i2cp) {
+
+ chDbgCheck(i2cp != NULL, "i2cGetErrors");
+
+ return i2c_lld_get_errors(i2cp);
+}
+
+/**
* @brief Sends data via the I2C bus.
* @details Function designed to realize "read-through-write" transfer
* paradigm. If you want transmit data without any further read,
* than set @b rxbytes field to 0.
*
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @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
- * @param[in] rxbuf pointer to receive buffer
- * @param[in] rxbytes number of bytes to be received, set it to 0 if
- * you want transmit only
- * @param[in] errors pointer to variable to store error code, zero means
- * no error.
- * @param[in] timeout operation timeout
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] 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
+ * @param[in] rxbuf pointer to receive buffer
+ * @param[in] rxbytes number of bytes to be received, set it to 0 if
+ * you want transmit only
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ *
+ * @return The number of received bytes or an exit code.
+ * @retval RDY_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval RDY_TIMEOUT if a timeout occurred before operation end.
*
- * @return timeout status
- * @retval RDY_OK if timeout not reached
- * @retval RDY_TIMEOUT if a timeout occurs
+ * @api
*/
-msg_t i2cMasterTransmit(I2CDriver *i2cp,
- uint8_t slave_addr,
- uint8_t *txbuf,
- size_t txbytes,
- uint8_t *rxbuf,
- size_t rxbytes,
- i2cflags_t *errors,
- systime_t timeout) {
+msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
+ i2caddr_t addr,
+ const uint8_t *txbuf,
+ size_t txbytes,
+ uint8_t *rxbuf,
+ size_t rxbytes,
+ systime_t timeout) {
msg_t rdymsg;
- chDbgCheck((i2cp != NULL) && (slave_addr != 0) &&
+ chDbgCheck((i2cp != NULL) && (addr != 0) &&
(txbytes > 0) && (txbuf != NULL) &&
((rxbytes == 0) || ((rxbytes > 0) && (rxbuf != NULL))) &&
- (timeout > TIME_IMMEDIATE) && (errors != NULL),
- "i2cMasterTransmit");
+ (timeout != TIME_IMMEDIATE),
+ "i2cMasterTransmitTimeout");
- i2c_lld_wait_bus_free(i2cp);
- i2cp->errors = I2CD_NO_ERROR; /* clear error flags from previous run */
chDbgAssert(i2cp->id_state == I2C_READY,
- "i2cMasterTransmit(), #1", "not ready");
+ "i2cMasterTransmitTimeout(), #1", "not ready");
+ chSysLock();
+ i2cp->errors = I2CD_NO_ERROR;
i2cp->id_state = I2C_ACTIVE_TRANSMIT;
- i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes);
- _i2c_wait_s(i2cp, timeout, rdymsg);
-
- *errors = i2cp->errors;
-
+ rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes,
+ rxbuf, rxbytes, timeout);
+ i2cp->id_state = I2C_READY;
+ chSysUnlock();
return rdymsg;
}
/**
* @brief Receives data from the I2C bus.
*
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @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
- * @param[in] errors pointer to variable to store error code, zero means
- * no error.
- * @param[in] timeout operation timeout
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] 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
+ * @param[in] errors pointer to variable to store error code, zero means
+ * no error.
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
*
- * @return timeout status
- * @retval RDY_OK if timeout not reached
- * @retval RDY_TIMEOUT if a timeout occurs
+ * @return The number of received bytes or an exit code.
+ * @retval RDY_OK if the function succeeded.
+ * @retval RDY_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval RDY_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
*/
-msg_t i2cMasterReceive(I2CDriver *i2cp,
- uint8_t slave_addr,
- uint8_t *rxbuf,
- size_t rxbytes,
- i2cflags_t *errors,
- systime_t timeout){
+msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
+ i2caddr_t slave_addr,
+ uint8_t *rxbuf,
+ size_t rxbytes,
+ systime_t timeout){
msg_t rdymsg;
- chDbgCheck((i2cp != NULL) && (slave_addr != 0) &&
+ chDbgCheck((i2cp != NULL) && (addr != 0) &&
(rxbytes > 0) && (rxbuf != NULL) &&
- (timeout > TIME_IMMEDIATE) && (errors != NULL),
- "i2cMasterReceive");
+ (timeout != TIME_IMMEDIATE),
+ "i2cMasterReceiveTimeout");
- i2c_lld_wait_bus_free(i2cp);
- i2cp->errors = I2CD_NO_ERROR; /* clear error flags from previous run */
chDbgAssert(i2cp->id_state == I2C_READY,
"i2cMasterReceive(), #1", "not ready");
+ chSysLock();
+ i2cp->errors = I2CD_NO_ERROR;
i2cp->id_state = I2C_ACTIVE_RECEIVE;
- i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes);
- _i2c_wait_s(i2cp, timeout, rdymsg);
-
- *errors = i2cp->errors;
-
+ rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout);
+ i2cp->id_state = I2C_READY;
+ chSysUnlock();
return rdymsg;
}
-
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
- * @brief Gains exclusive access to the I2C bus.
- * @details This function tries to gain ownership to the I2C bus, if the bus
+ * @brief Gains exclusive access to the I2C bus.
+ * @details This function tries to gain ownership to the SPI bus, if the bus
* is already being used then the invoking thread is queued.
+ * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
+ * must be enabled.
*
* @param[in] i2cp pointer to the @p I2CDriver object
*
- * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION
- * option is set to @p TRUE.
+ * @api
*/
void i2cAcquireBus(I2CDriver *i2cp) {
@@ -250,12 +271,13 @@ void i2cAcquireBus(I2CDriver *i2cp) {
}
/**
- * @brief Releases exclusive access to the I2C bus.
+ * @brief Releases exclusive access to the I2C bus.
+ * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
+ * must be enabled.
*
* @param[in] i2cp pointer to the @p I2CDriver object
*
- * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION
- * option is set to @p TRUE.
+ * @api
*/
void i2cReleaseBus(I2CDriver *i2cp) {