I2C. Driver looks working, but sometimes hangs up. I don't know, my big project cause troubles in it, or driver cause troubles in my project.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3116 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
af0e40079d
commit
ccb28114da
|
@ -218,6 +218,31 @@ struct I2CSlaveConfig{
|
|||
_i2c_wakeup_isr(i2cp); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error ISR code.
|
||||
* @details This code handles the portable part of the ISR code:
|
||||
* - Error 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] i2cp pointer to the @p I2CDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _i2c_isr_err_code(i2cp, i2cscfg) { \
|
||||
(i2cp)->id_state = I2C_COMPLETE; \
|
||||
if(((i2cp)->id_slave_config)->id_err_callback) { \
|
||||
((i2cp)->id_slave_config)->id_err_callback(i2cp, i2cscfg); \
|
||||
if((i2cp)->id_state == I2C_COMPLETE) \
|
||||
(i2cp)->id_state = I2C_READY; \
|
||||
} \
|
||||
else \
|
||||
(i2cp)->id_state = I2C_READY; \
|
||||
_i2c_wakeup_isr(i2cp); \
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
|
|
|
@ -94,20 +94,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) {
|
|||
}
|
||||
break;
|
||||
case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
|
||||
/* Disable ITEVT In order to not have again a BTF IT */
|
||||
dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN;
|
||||
/* if nothing to read then generate stop */
|
||||
if (i2cp->rxbytes == 0){
|
||||
dp->CR1 |= I2C_CR1_STOP;
|
||||
/* Disable ITEVT In order to not have again a BTF IT */
|
||||
dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN;
|
||||
/* Portable I2C ISR code defined in the high level driver,
|
||||
* note, it is a macro.*/
|
||||
_i2c_isr_code(i2cp, i2cp->id_slave_config);
|
||||
}
|
||||
else{
|
||||
/* Disable ITEVT In order to not have again a BTF IT */
|
||||
dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN;
|
||||
/* send restart and begin reading operations */
|
||||
i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes);
|
||||
chSysLockFromIsr();
|
||||
i2c_lld_master_transceive(i2cp);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -242,10 +242,10 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) {
|
|||
|
||||
if(flags != I2CD_NO_ERROR) {
|
||||
/* send communication end signal */
|
||||
_i2c_isr_code(i2cp, i2cp->id_slave_config);
|
||||
chSysLockFromIsr();
|
||||
i2cAddFlagsI(i2cp, flags);
|
||||
chSysUnlockFromIsr();
|
||||
_i2c_isr_err_code(i2cp, i2cp->id_slave_config);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,10 +539,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr,
|
|||
i2cp->txbuf = txbuf;
|
||||
i2cp->rxbuf = rxbuf;
|
||||
|
||||
/* enable ERR, EVT & BUF ITs */
|
||||
i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN);
|
||||
i2cp->id_i2c->CR1 &= ~I2C_CR1_POS;
|
||||
|
||||
if(slave_addr & 0x8000){/* 10-bit mode used */
|
||||
/* add the two msb of 10-bit address to the header */
|
||||
i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006);
|
||||
|
@ -568,9 +564,18 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr,
|
|||
// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--)
|
||||
// ;
|
||||
//#endif /* I2C_USE_WAIT */
|
||||
uint32_t timeout = 0xfffff;
|
||||
|
||||
|
||||
uint32_t timeout = I2C_START_TIMEOUT;
|
||||
while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--)
|
||||
;
|
||||
/* is timeout overflows? */
|
||||
chDbgAssert(timeout < I2C_START_TIMEOUT,
|
||||
"i2c_lld_master_transmit(), #1", "time is out");
|
||||
|
||||
/* enable ERR, EVT & BUF ITs */
|
||||
i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN);
|
||||
i2cp->id_i2c->CR1 &= ~I2C_CR1_POS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -593,11 +598,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr,
|
|||
i2cp->rxbytes = rxbytes;
|
||||
i2cp->rxbuf = rxbuf;
|
||||
|
||||
/* enable ERR, EVT & BUF ITs */
|
||||
i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN);
|
||||
i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */
|
||||
i2cp->id_i2c->CR1 &= ~I2C_CR1_POS;
|
||||
|
||||
if(slave_addr & 0x8000){/* 10-bit mode used */
|
||||
/* add the two msb of 10-bit address to the header */
|
||||
i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006);
|
||||
|
@ -633,9 +633,62 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr,
|
|||
// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--)
|
||||
// ;
|
||||
//#endif /* I2C_USE_WAIT */
|
||||
uint32_t timeout = 0xfffff;
|
||||
|
||||
|
||||
uint32_t timeout = I2C_START_TIMEOUT;
|
||||
while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--)
|
||||
;
|
||||
/* is timeout overflows? */
|
||||
chDbgAssert(timeout < I2C_START_TIMEOUT,
|
||||
"i2c_lld_master_receive(), #1", "time is out");
|
||||
|
||||
/* enable ERR, EVT & BUF ITs */
|
||||
i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN);
|
||||
i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */
|
||||
i2cp->id_i2c->CR1 &= ~I2C_CR1_POS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i2c_lld_master_transceive(I2CDriver *i2cp){
|
||||
|
||||
i2cp->flags = I2C_FLG_MASTER_RECEIVER;
|
||||
i2cp->errors = 0;
|
||||
|
||||
i2cp->slave_addr1 |= 0x01;
|
||||
|
||||
/* Only one byte to be received */
|
||||
if(i2cp->rxbytes == 1) {
|
||||
i2cp->flags |= I2C_FLG_1BTR;
|
||||
}
|
||||
/* Only two bytes to be received */
|
||||
else if(i2cp->rxbytes == 2) {
|
||||
i2cp->flags |= I2C_FLG_2BTR;
|
||||
i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */
|
||||
}
|
||||
|
||||
i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */
|
||||
|
||||
//#if !I2C_USE_WAIT
|
||||
// /* Wait until the START condition is generated on the bus:
|
||||
// * the START bit is cleared by hardware */
|
||||
// uint32_t timeout = 0xfffff;
|
||||
// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--)
|
||||
// ;
|
||||
//#endif /* I2C_USE_WAIT */
|
||||
|
||||
|
||||
uint32_t timeout = I2C_START_TIMEOUT;
|
||||
while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--)
|
||||
;
|
||||
/* is timeout overflows? */
|
||||
chDbgAssert(timeout < I2C_START_TIMEOUT,
|
||||
"i2c_lld_master_receive(), #1", "time is out");
|
||||
|
||||
/* enable ERR, EVT & BUF ITs */
|
||||
i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN);
|
||||
i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */
|
||||
i2cp->id_i2c->CR1 &= ~I2C_CR1_POS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
#define I2C_START_TIMEOUT 0xFFFF
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
|
@ -233,6 +234,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr,
|
|||
uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes);
|
||||
void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr,
|
||||
uint8_t *rxbuf, size_t rxbytes);
|
||||
void i2c_lld_master_transceive(I2CDriver *i2cp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -165,15 +165,18 @@ void i2cMasterTransmit(I2CDriver *i2cp,
|
|||
/* init slave config field in driver */
|
||||
i2cp->id_slave_config = i2cscfg;
|
||||
|
||||
//#if I2C_USE_WAIT
|
||||
// i2c_lld_wait_bus_free(i2cp);
|
||||
// if(i2c_lld_bus_is_busy(i2cp)) {
|
||||
//#ifdef PRINTTRACE
|
||||
// print("I2C Bus busy!\n");
|
||||
//#endif
|
||||
// return;
|
||||
// };
|
||||
//#endif
|
||||
#if I2C_USE_WAIT
|
||||
i2c_lld_wait_bus_free(i2cp);
|
||||
if(i2c_lld_bus_is_busy(i2cp)) {
|
||||
#ifdef PRINTTRACE
|
||||
print("I2C Bus busy!\n");
|
||||
return;
|
||||
#else
|
||||
/* the time is out */
|
||||
chDbgAssert(FALSE, "i2cMasterTransmit(), #1", "time is out");
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(i2cp->id_state == I2C_READY,
|
||||
|
@ -211,15 +214,18 @@ void i2cMasterReceive(I2CDriver *i2cp,
|
|||
/* init slave config field in driver */
|
||||
i2cp->id_slave_config = i2cscfg;
|
||||
|
||||
//#if I2C_USE_WAIT
|
||||
// i2c_lld_wait_bus_free(i2cp);
|
||||
// if(i2c_lld_bus_is_busy(i2cp)) {
|
||||
//#ifdef PRINTTRACE
|
||||
// print("I2C Bus busy!\n");
|
||||
//#endif
|
||||
// return;
|
||||
// };
|
||||
//#endif
|
||||
#if I2C_USE_WAIT
|
||||
i2c_lld_wait_bus_free(i2cp);
|
||||
if(i2c_lld_bus_is_busy(i2cp)) {
|
||||
#ifdef PRINTTRACE
|
||||
print("I2C Bus busy!\n");
|
||||
return;
|
||||
#else
|
||||
/* the time is out */
|
||||
chDbgAssert(FALSE, "i2cMasterReceive(), #1", "time is out");
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(i2cp->id_state == I2C_READY,
|
||||
|
|
|
@ -173,6 +173,14 @@
|
|||
/* I2C driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define I2C_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the mutual exclusion APIs on the I2C bus.
|
||||
*/
|
||||
|
|
|
@ -54,9 +54,9 @@ static msg_t I2CAccelThread(void *arg) {
|
|||
i2cscfg = (I2CSlaveConfig *)msg;
|
||||
|
||||
/* collect measured data */
|
||||
acceleration_x = i2cscfg->rxbuf[0] + (i2cscfg->rxbuf[1] << 8);
|
||||
acceleration_y = i2cscfg->rxbuf[2] + (i2cscfg->rxbuf[3] << 8);
|
||||
acceleration_z = i2cscfg->rxbuf[4] + (i2cscfg->rxbuf[5] << 8);
|
||||
acceleration_x = accel_rx_data[0] + (accel_rx_data[1] << 8);
|
||||
acceleration_y = accel_rx_data[2] + (accel_rx_data[3] << 8);
|
||||
acceleration_z = accel_rx_data[4] + (accel_rx_data[5] << 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -77,8 +77,6 @@ static void i2c_lis3_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
|
|||
static const I2CSlaveConfig lis3 = {
|
||||
i2c_lis3_cb,
|
||||
i2c_lis3_error_cb,
|
||||
accel_rx_data,
|
||||
accel_tx_data,
|
||||
};
|
||||
|
||||
|
||||
|
@ -106,13 +104,13 @@ int init_lis3(void){
|
|||
#define RXBYTES 0 /* set to 0 because we need only transmit */
|
||||
|
||||
/* configure accelerometer */
|
||||
lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; /* register address */
|
||||
lis3.txbuf[1] = 0b11100111;
|
||||
lis3.txbuf[2] = 0b01000001;
|
||||
lis3.txbuf[3] = 0b00000000;
|
||||
accel_tx_data[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; /* register address */
|
||||
accel_tx_data[1] = 0b11100111;
|
||||
accel_tx_data[2] = 0b01000001;
|
||||
accel_tx_data[3] = 0b00000000;
|
||||
|
||||
/* sending */
|
||||
i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, TXBYTES, RXBYTES);
|
||||
i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, TXBYTES, accel_rx_data, RXBYTES);
|
||||
chThdSleepMilliseconds(1);
|
||||
|
||||
#undef RXBYTES
|
||||
|
@ -127,9 +125,9 @@ int init_lis3(void){
|
|||
void request_acceleration_data(void){
|
||||
#define RXBYTES 6
|
||||
#define TXBYTES 1
|
||||
lis3.txbuf[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address
|
||||
accel_tx_data[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address
|
||||
i2cAcquireBus(&I2CD1);
|
||||
i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, TXBYTES, RXBYTES);
|
||||
i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, TXBYTES, accel_rx_data, RXBYTES);
|
||||
i2cReleaseBus(&I2CD1);
|
||||
#undef RXBYTES
|
||||
#undef TXBYTES
|
||||
|
|
|
@ -29,6 +29,23 @@
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* Red LEDs blinker thread, times are in milliseconds.
|
||||
*/
|
||||
static WORKING_AREA(BlinkWA, 128);
|
||||
static msg_t Blink(void *arg) {
|
||||
(void)arg;
|
||||
while (TRUE) {
|
||||
palClearPad(IOPORT3, GPIOC_LED);
|
||||
chThdSleepMilliseconds(500);
|
||||
palSetPad(IOPORT3, GPIOC_LED);
|
||||
chThdSleepMilliseconds(500);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Temperature polling thread */
|
||||
static WORKING_AREA(PollTmp75ThreadWA, 128);
|
||||
static msg_t PollTmp75Thread(void *arg) {
|
||||
|
@ -110,6 +127,8 @@ int main(void) {
|
|||
PollAccelThread,
|
||||
NULL);
|
||||
|
||||
/* Creates the blinker thread. */
|
||||
chThdCreateStatic(BlinkWA, sizeof(BlinkWA), LOWPRIO, Blink, NULL);
|
||||
|
||||
/* main loop that do nothing */
|
||||
while (TRUE) {
|
||||
|
|
|
@ -29,11 +29,12 @@ static void i2c_max1236_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg)
|
|||
/* This callback raise up when transfer finished */
|
||||
static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
|
||||
(void)*i2cp;
|
||||
(void)*i2cscfg;
|
||||
/* get ADC data */
|
||||
ch1 = ((i2cscfg->rxbuf[0] & 0xF) << 8) + i2cscfg->rxbuf[1];
|
||||
ch2 = ((i2cscfg->rxbuf[2] & 0xF) << 8) + i2cscfg->rxbuf[3];
|
||||
ch3 = ((i2cscfg->rxbuf[4] & 0xF) << 8) + i2cscfg->rxbuf[5];
|
||||
ch4 = ((i2cscfg->rxbuf[6] & 0xF) << 8) + i2cscfg->rxbuf[7];
|
||||
ch1 = ((max1236_rx_data[0] & 0xF) << 8) + max1236_rx_data[1];
|
||||
ch2 = ((max1236_rx_data[2] & 0xF) << 8) + max1236_rx_data[3];
|
||||
ch3 = ((max1236_rx_data[4] & 0xF) << 8) + max1236_rx_data[5];
|
||||
ch4 = ((max1236_rx_data[6] & 0xF) << 8) + max1236_rx_data[7];
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,8 +43,6 @@ static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
|
|||
static const I2CSlaveConfig max1236 = {
|
||||
i2c_max1236_cb,
|
||||
i2c_max1236_error_cb,
|
||||
max1236_rx_data,
|
||||
max1236_tx_data,
|
||||
};
|
||||
|
||||
#define max1236_addr 0b0110100
|
||||
|
@ -56,13 +55,13 @@ void init_max1236(void){
|
|||
/* this data we must send via IC to setup ADC */
|
||||
#define RXBYTES 0
|
||||
#define TXBYTES 2
|
||||
max1236.txbuf[0] = 0b10000011; /* config register content. Consult datasheet */
|
||||
max1236.txbuf[1] = 0b00000111; /* config register content. Consult datasheet */
|
||||
max1236_tx_data[0] = 0b10000011; /* config register content. Consult datasheet */
|
||||
max1236_tx_data[1] = 0b00000111; /* config register content. Consult datasheet */
|
||||
|
||||
|
||||
/* transmit out 2 bytes */
|
||||
i2cAcquireBus(&I2CD2);
|
||||
i2cMasterTransmit(&I2CD2, &max1236, max1236_addr, TXBYTES, RXBYTES);
|
||||
i2cMasterTransmit(&I2CD2, &max1236, max1236_addr, max1236_tx_data, TXBYTES, max1236_rx_data, RXBYTES);
|
||||
while(I2CD2.id_state != I2C_READY){
|
||||
chThdSleepMilliseconds(1);
|
||||
}
|
||||
|
@ -78,7 +77,7 @@ void read_max1236(void){
|
|||
#define RXBYTES 8
|
||||
|
||||
i2cAcquireBus(&I2CD2);
|
||||
i2cMasterReceive(&I2CD2, &max1236, max1236_addr, RXBYTES);
|
||||
i2cMasterReceive(&I2CD2, &max1236, max1236_addr, max1236_rx_data, RXBYTES);
|
||||
i2cReleaseBus(&I2CD2);
|
||||
#undef RXBYTES
|
||||
#undef TXBYTES
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
/* input buffer */
|
||||
static i2cblock_t tmp75_rx_data[TMP75_RX_DEPTH];
|
||||
static i2cblock_t tmp75_tx_data[TMP75_TX_DEPTH];
|
||||
/* temperature value */
|
||||
static int16_t temperature = 0;
|
||||
|
||||
|
@ -29,16 +28,15 @@ static void i2c_tmp75_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
|
|||
/* This callback raise up when transfer finished */
|
||||
static void i2c_tmp75_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
|
||||
(void)*i2cp;
|
||||
(void)*i2cscfg;
|
||||
/* store temperature value */
|
||||
temperature = (i2cscfg->rxbuf[0] << 8) + i2cscfg->rxbuf[1];
|
||||
temperature = (tmp75_rx_data[0] << 8) + tmp75_rx_data[1];
|
||||
}
|
||||
|
||||
/* Fill TMP75 config. */
|
||||
static const I2CSlaveConfig tmp75 = {
|
||||
i2c_tmp75_cb,
|
||||
i2c_tmp75_error_cb,
|
||||
tmp75_rx_data,
|
||||
tmp75_tx_data,
|
||||
};
|
||||
|
||||
#define tmp75_addr 0b1001000
|
||||
|
@ -49,7 +47,7 @@ void request_temperature(void){
|
|||
#define RXBYTES 2 /* we need to read 2 bytes */
|
||||
|
||||
i2cAcquireBus(&I2CD2);
|
||||
i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, RXBYTES);
|
||||
i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, tmp75_rx_data, RXBYTES);
|
||||
i2cReleaseBus(&I2CD2);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue