git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10055 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
2689848803
commit
705d726932
|
@ -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. */
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
Loading…
Reference in New Issue