aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/lib
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2017-01-16 16:17:30 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2017-01-16 16:17:30 +0000
commit705d7269323e1d93c4fb8c7afa0aa88d4ae8f6a8 (patch)
treed0a482e5746087fb29aea826c4e41536130a9bde /os/hal/lib
parent2689848803371cc3492743b951bbe8f73ca9ac92 (diff)
downloadChibiOS-705d7269323e1d93c4fb8c7afa0aa88d4ae8f6a8.tar.gz
ChibiOS-705d7269323e1d93c4fb8c7afa0aa88d4ae8f6a8.tar.bz2
ChibiOS-705d7269323e1d93c4fb8c7afa0aa88d4ae8f6a8.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10055 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/lib')
-rw-r--r--os/hal/lib/fallback/I2C/hal_i2c_lld.c99
-rw-r--r--os/hal/lib/fallback/I2C/hal_i2c_lld.h42
2 files changed, 137 insertions, 4 deletions
diff --git a/os/hal/lib/fallback/I2C/hal_i2c_lld.c b/os/hal/lib/fallback/I2C/hal_i2c_lld.c
index 6fbdfdd6d..82b17663a 100644
--- a/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+++ b/os/hal/lib/fallback/I2C/hal_i2c_lld.c
@@ -30,6 +30,11 @@
/* Driver local definitions. */
/*===========================================================================*/
+#define CHECK_ERROR(msg) \
+ if ((msg) < (msg_t)0) { \
+ return MSG_TIMEOUT; \
+ }
+
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
@@ -66,6 +71,100 @@ I2CDriver I2CD4;
/* Driver local functions. */
/*===========================================================================*/
+static msg_t i2c_delay(I2CDriver *i2cp) {
+
+ if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), i2cp->start, i2cp->end)) {
+ return MSG_TIMEOUT;
+ }
+
+#if SW_I2C_USE_OSAL_DELAY || defined(__DOXYGEN__)
+ osalThreadSleep(i2cp->config->ticks);
+#else
+ i2cp->config->delay();
+#endif
+ return MSG_OK;
+}
+
+static msg_t i2c_write_start(I2CDriver *i2cp) {
+
+}
+
+static msg_t i2c_write_restart(I2CDriver *i2cp) {
+
+}
+
+static msg_t i2c_write_stop(I2CDriver *i2cp) {
+
+}
+
+static msg_t i2c_writebit(I2CDriver *i2cp, unsigned bit) {
+
+ palWriteLine(i2cp->config->sda, bit);
+ CHECK_ERROR(i2c_delay(i2cp));
+ palSetLine(i2cp->config->scl);
+ CHECK_ERROR(i2c_delay(i2cp));
+
+ /* Clock stretching.*/
+ while (palReadLine(i2cp->config->scl) == PAL_LOW) {
+ CHECK_ERROR(i2c_delay(i2cp));
+ }
+
+ /* Arbitration check.*/
+ if ((bit == PAL_HIGH) && (palReadLine(i2cp->config->sda) == PAL_LOW)) {
+ i2cp->errors |= I2C_ARBITRATION_LOST;
+ return MSG_RESET;
+ }
+
+ palClearLine(i2cp->config->scl);
+
+ return MSG_OK;
+}
+
+static msg_t i2c_readbit(I2CDriver *i2cp) {
+ msg_t bit;
+
+ palSetLine(i2cp->config->sda);
+ CHECK_ERROR(i2c_delay(i2cp));
+ palSetLine(i2cp->config->scl);
+
+ /* Clock stretching.*/
+ while (palReadLine(i2cp->config->scl) == PAL_LOW) {
+ CHECK_ERROR(i2c_delay(i2cp));
+ }
+
+ CHECK_ERROR(i2c_delay(i2cp));
+ bit = palReadLine(i2cp->config->sda);
+ palClearLine(i2cp->config->scl);
+
+ return bit;
+}
+
+static msg_t i2c_writebyte(I2CDriver *i2cp, uint8_t byte) {
+ uint8_t mask;
+
+ for (mask = 0x80U; mask > 0U; mask >>= 1U) {
+ CHECK_ERROR(i2c_writebit(i2cp, (byte & mask) != 0));
+ }
+
+ return i2c_readbit(i2cp);
+}
+
+static msg_t i2c_readbyte(I2CDriver *i2cp, unsigned nack) {
+ msg_t byte;
+ unsigned i;
+
+ byte = 0U;
+ for (i = 0; i < 8; i++) {
+ msg_t msg = i2c_readbit(i2cp);
+ CHECK_ERROR(msg);
+ byte = (byte << 1U) | msg;
+ }
+
+ CHECK_ERROR(i2c_writebit(i2cp, PAL_LOW));
+
+ return byte;
+}
+
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
diff --git a/os/hal/lib/fallback/I2C/hal_i2c_lld.h b/os/hal/lib/fallback/I2C/hal_i2c_lld.h
index 0bcb3dfbe..c6c4908a4 100644
--- a/os/hal/lib/fallback/I2C/hal_i2c_lld.h
+++ b/os/hal/lib/fallback/I2C/hal_i2c_lld.h
@@ -40,6 +40,16 @@
* @{
*/
/**
+ * @brief Use OSAL delays.
+ * @details If set to @p TRUE then delays are implemented using the
+ * thread-friendy delay function else a delay function must
+ * be provided extenally.
+ */
+#if !defined(SW_I2C_USE_OSAL_DELAY) || defined(__DOXYGEN__)
+#define SW_I2C_USE_OSAL_DELAY TRUE
+#endif
+
+/**
* @brief I2C1 driver enable switch.
* @details If set to @p TRUE the support for I2C1 is included.
* @note The default is @p FALSE.
@@ -95,9 +105,33 @@ typedef uint16_t i2caddr_t;
typedef uint8_t i2cflags_t;
/**
+ * @brief Type of a delay function.
+ */
+typedef void (*i2c_delay_t)(void);
+
+/**
* @brief Type of I2C driver configuration structure.
*/
typedef struct {
+ /**
+ * @brief I2C clock line.
+ */
+ ioline_t scl;
+ /**
+ * @brief I2C data line.
+ */
+ ioline_t sda;
+#if SW_I2C_USE_OSAL_DELAY || defined(__DOXYGEN__)
+ /**
+ * @brief Delay of an half bit time in system ticks.
+ */
+ systime_t ticks;
+#else
+ /**
+ * @brief Pointer to an externally defined delay function.
+ */
+ i2c_delay_t delay;
+#endif
} I2CConfig;
/**
@@ -129,13 +163,13 @@ struct I2CDriver {
#endif
/* End of the mandatory fields.*/
/**
- * @brief I2C clock line.
+ * @brief Time of operation begin.
*/
- ioline_t clk;
+ systime_t start;
/**
- * @brief I2C data line.
+ * @brief Time of operation timeout.
*/
- ioline_t data;
+ systime_t end;
};
/*===========================================================================*/