git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10055 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2017-01-16 16:17:30 +00:00
parent 2689848803
commit 705d726932
2 changed files with 137 additions and 4 deletions

View File

@ -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. */
/*===========================================================================*/

View File

@ -39,6 +39,16 @@
* @name Configuration options
* @{
*/
/**
* @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.
@ -94,10 +104,34 @@ 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;
};
/*===========================================================================*/