I2C API proposal.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3684 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
gdisirio 2011-12-29 18:03:49 +00:00
parent 40a709f42f
commit b30ba31603
2 changed files with 99 additions and 152 deletions

View File

@ -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);

View File

@ -132,111 +132,132 @@ void i2cStop(I2CDriver *i2cp) {
chSysUnlock();
}
/**
* @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 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_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 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) {