I2C API proposal.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3684 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
40a709f42f
commit
b30ba31603
|
@ -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);
|
||||
|
|
154
os/hal/src/i2c.c
154
os/hal/src/i2c.c
|
@ -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) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue