aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/include/i2c.h
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal/include/i2c.h')
-rw-r--r--os/hal/include/i2c.h201
1 files changed, 159 insertions, 42 deletions
diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h
index 5f8c971fd..f5465985b 100644
--- a/os/hal/include/i2c.h
+++ b/os/hal/include/i2c.h
@@ -34,7 +34,24 @@
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
-
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+#define I2CD_NO_ERROR 0
+/** @brief Bus Error.*/
+#define I2CD_BUS_ERROR 0x01
+/** @brief Arbitration Lost (master mode).*/
+#define I2CD_ARBITRATION_LOST 0x02
+/** @brief Acknowledge Failure.*/
+#define I2CD_ACK_FAILURE 0x04
+/** @brief Overrun/Underrun.*/
+#define I2CD_OVERRUN 0x08
+/** @brief PEC Error in reception.*/
+#define I2CD_PEC_ERROR 0x10
+/** @brief Timeout or Tlow Error.*/
+#define I2CD_TIMEOUT 0x20
+/** @brief SMBus Alert.*/
+#define I2CD_SMB_ALERT 0x40
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@@ -49,6 +66,9 @@
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
+#if I2C_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES
+#error "I2C_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES"
+#endif
/*===========================================================================*/
/* Driver data structures and types. */
@@ -58,78 +78,175 @@
* @brief Driver state machine possible states.
*/
typedef enum {
- I2C_UNINIT = 0, /**< Not initialized. */
- I2C_STOP = 1, /**< Stopped. */
- I2C_READY = 2, /**< Ready. */
- I2C_MREADY = 3, /**< START and address sent. */
- I2C_MTRANSMIT = 4, /**< Master transmitting. */
- I2C_MRECEIVE = 5, /**< Master receiving. */
- I2C_MERROR = 6 /**< Error condition. */
+ I2C_UNINIT = 0, /**< @brief Not initialized. */
+ I2C_STOP = 1, /**< @brief Stopped. */
+ I2C_READY = 2, /**< @brief Ready. */
+ I2C_ACTIVE = 3, /**< @brief In communication. */
+ I2C_COMPLETE = 4, /**< @brief Asynchronous operation complete. */
+
+ // slave part
+ I2C_SACTIVE = 10,
+ I2C_STRANSMIT = 11,
+ I2C_SRECEIVE = 12,
} i2cstate_t;
+
#include "i2c_lld.h"
-/*===========================================================================*/
-/* Driver macros. */
-/*===========================================================================*/
+/**
+ * @brief I2C notification callback type.
+ * @details This callback invoked when byte transfer finish event occurs,
+ * No matter sending or reading. This function designed
+ * for sending (re)start or stop events to I2C bus from user level.
+ *
+ * If callback function is set to NULL - driver atomaticcaly
+ * generate stop condition after the transfer finish.
+ *
+ * @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, I2CSlaveConfig *i2cscfg);
+
/**
- * @brief Read mode.
+ * @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
*/
-#define I2C_READ 1
+typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg);
+
/**
- * @brief Write mode.
+ * @brief I2C transmission data block size.
*/
-#define I2C_WRITE 0
+typedef uint8_t i2cblock_t;
+
/**
- * @brief Seven bits addresses header builder.
+ * @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, or
+ * by DMA buffer events
+ * 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;
+
+ /**
+ * @brief Receive and transmit buffers.
+ */
+ size_t txbytes;
+ size_t rxbytes;
+ i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */
+ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/
+ uint16_t slave_addr;
+ uint8_t nbit_address; /*!< Length of address (must be 7 or 10).*/
+ i2cflags_t errors;
+ i2cflags_t flags;
+ /* Status Change @p EventSource.*/
+ EventSource sevent;
+};
+
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#if I2C_USE_WAIT || defined(__DOXYGEN__)
+/**
+ * @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] addr seven bits address value
- * @param[in] rw read/write flag
+ * @param[in] i2cp pointer to the @p I2CDriver object
*
- * @return A 16 bit value representing the header, the most
- * significant byte is always zero.
+ * @notapi
*/
-#define I2C_ADDR7(addr, rw) (uint16_t)((addr) << 1 | (rw))
+#define _i2c_wait_s(i2cp) { \
+ chDbgAssert((i2cp)->thread == NULL, \
+ "_i2c_wait(), #1", "already waiting"); \
+ (i2cp)->thread = chThdSelf(); \
+ chSchGoSleepS(THD_STATE_SUSPENDED); \
+}
+/**
+ * @brief Wakes up the waiting thread.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define _i2c_wakeup_isr(i2cp) { \
+ if ((i2cp)->thread != NULL) { \
+ Thread *tp = (i2cp)->thread; \
+ (i2cp)->thread = NULL; \
+ chSysLockFromIsr(); \
+ chSchReadyI(tp); \
+ chSysUnlockFromIsr(); \
+ } \
+}
+#else /* !I2C_USE_WAIT */
+#define _i2c_wait_s(i2cp)
+#define _i2c_wakeup_isr(i2cp)
+#endif /* !I2C_USE_WAIT */
/**
- * @brief Ten bits addresses header builder.
+ * @brief Common ISR code.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
*
- * @param[in] addr ten bits address value
- * @param[in] rw read/write flag
+ * @param[in] i2cp pointer to the @p I2CDriver object
*
- * @return A 16 bit value representing the header, the most
- * significant byte is the first one to be transmitted.
+ * @notapi
*/
-#define I2C_ADDR10(addr, rw) \
- (uint16_t)(0xF000 | \
- (((addr) & 0x0300) << 1) | \
- (((rw) << 8)) | \
- ((addr) & 0x00FF))
+#define _i2c_isr_code(i2cp, i2cscfg) { \
+ (i2cp)->id_state = I2C_COMPLETE; \
+ if(((i2cp)->id_slave_config)->id_callback) { \
+ ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \
+ } \
+ _i2c_wakeup_isr(i2cp); \
+}
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
-
#ifdef __cplusplus
extern "C" {
#endif
void i2cInit(void);
void i2cObjectInit(I2CDriver *i2cp);
- void i2cStart(I2CDriver *i2cp, const I2CConfig *config);
+ void i2cStart(I2CDriver *i2cp, I2CConfig *config);
void i2cStop(I2CDriver *i2cp);
- void i2cMasterStartI(I2CDriver *i2cp,
- uint16_t header,
- i2ccallback_t callback);
- void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback);
- void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback);
- void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf,
- i2ccallback_t callback);
- void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf,
- i2ccallback_t callback);
+ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg);
+ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg);
+ void i2cMasterStart(I2CDriver *i2cp);
+ void i2cMasterStop(I2CDriver *i2cp);
+ void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask);
+
#if I2C_USE_MUTUAL_EXCLUSION
void i2cAcquireBus(I2CDriver *i2cp);
void i2cReleaseBus(I2CDriver *i2cp);