diff options
author | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-12-30 20:45:56 +0000 |
---|---|---|
committer | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-12-30 20:45:56 +0000 |
commit | 2234fd3e31d4ce6e2b3990340b52719951e65731 (patch) | |
tree | 3d8dadab8ab98a46ab2f98ed0b94d648e86ce837 | |
parent | 08feb80580ca82cfebd77a43d14d1197ec7c4f99 (diff) | |
download | ChibiOS-2234fd3e31d4ce6e2b3990340b52719951e65731.tar.gz ChibiOS-2234fd3e31d4ce6e2b3990340b52719951e65731.tar.bz2 ChibiOS-2234fd3e31d4ce6e2b3990340b52719951e65731.zip |
I2C. API changes mostly done.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3692 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r-- | os/hal/include/i2c.h | 4 | ||||
-rw-r--r-- | os/hal/platforms/STM32/i2c_lld.c | 94 | ||||
-rw-r--r-- | os/hal/platforms/STM32/i2c_lld.h | 105 | ||||
-rw-r--r-- | os/hal/src/i2c.c | 14 | ||||
-rw-r--r-- | testhal/STM32F1xx/I2C/Makefile | 5 | ||||
-rw-r--r-- | testhal/STM32F1xx/I2C/fake.c | 9 | ||||
-rw-r--r-- | testhal/STM32F1xx/I2C/i2c_pns.c | 2 | ||||
-rw-r--r-- | testhal/STM32F1xx/I2C/main.c | 39 | ||||
-rw-r--r-- | testhal/STM32F1xx/I2C/tmp75.c | 8 |
9 files changed, 225 insertions, 55 deletions
diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 80668f28c..8118bd73f 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -110,10 +110,10 @@ extern "C" { void i2cObjectInit(I2CDriver *i2cp);
void i2cStart(I2CDriver *i2cp, const I2CConfig *config);
void i2cStop(I2CDriver *i2cp);
- i2cflags_t i2cGetErrors(I2CDriver *i2cp);
+ inline i2cflags_t i2cGetErrors(I2CDriver *i2cp);
msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
i2caddr_t addr,
- const uint8_t *txbuf, size_t txbytes,
+ uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout);
msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index d172abebb..bfbaa410f 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -131,7 +131,8 @@ static volatile uint16_t dbgCR2 = 0; /** * @brief Return the last event value from I2C status registers. - * @details Important but implicit function is clearing interrupts flags. + * @details Important but implicit destination of this function is + * clearing interrupts flags. * @note Internal use only. * * @param[in] i2cp pointer to the @p I2CDriver object @@ -156,6 +157,8 @@ static uint32_t i2c_get_event(I2CDriver *i2cp){ * @brief I2C interrupts handler. * * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { I2C_TypeDef *dp = i2cp->id_i2c; @@ -179,13 +182,12 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* catch BTF event after the end of transmission */ if (i2cp->rxbytes > 1){ /* start "read after write" operation */ - i2c_lld_master_receive(i2cp, (i2cp->slave_addr >> 1), - i2cp->rxbuf, i2cp->rxbytes); + i2c_lld_master_transceive(i2cp); return; } else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - _i2c_isr_code(i2cp, i2cp->id_slave_config); + i2c_lld_isr_code(i2cp); break; default: @@ -203,7 +205,7 @@ static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp){ dmaStreamDisable(i2cp->dmarx); i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - _i2c_isr_code(i2cp, i2cp->id_slave_config); + i2c_lld_isr_code(i2cp); } @@ -268,7 +270,7 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { if(errors != I2CD_NO_ERROR) { /* send communication end signal */ i2cp->errors |= errors; - _i2c_isr_err_code(i2cp, i2cp->id_slave_config); + i2c_lld_isr_err_code(i2cp); } #undef reg } @@ -359,6 +361,7 @@ void i2c_lld_init(void) { #endif /* STM32_I2C_USE_I2C3 */ } + /** * @brief Configures and activates the I2C peripheral. * @@ -495,11 +498,22 @@ void i2c_lld_reset(I2CDriver *i2cp){ * @param[in] slave_addr slave device address * @param[in] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received + * + * @return The operation status. + * @retval RDY_OK if the function succeeded. + * @retval RDY_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval RDY_TIMEOUT if a timeout occurred before operation end. */ -void i2c_lld_master_receive(I2CDriver *i2cp, uint8_t slave_addr, - uint8_t *rxbuf, size_t rxbytes){ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, + uint8_t slave_addr, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout){ - uint32_t mode = 0; + msg_t rdymsg; + + chSysUnlock(); /* release lock from high level call */ chDbgCheck((rxbytes > 1), "i2c_lld_master_receive"); @@ -509,11 +523,12 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint8_t slave_addr, i2cp->rxbuf = rxbuf; i2cp->errors = 0; - mode = STM32_DMA_CR_DIR_P2M; /* TODO: DMA error handling */ dmaStreamSetMemory0(i2cp->dmarx, rxbuf); dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); - dmaStreamSetMode(i2cp->dmarx, ((i2cp->dmamode) | mode)); + dmaStreamSetMode(i2cp->dmarx, ((i2cp->dmamode) | STM32_DMA_CR_DIR_P2M)); + + i2c_lld_wait_bus_free(i2cp); /* wait stop bit from previous transaction*/ while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) @@ -521,6 +536,10 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint8_t slave_addr, i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN; i2cp->id_i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + + i2c_lld_wait_s(i2cp, timeout, rdymsg); + + return rdymsg; } @@ -536,12 +555,21 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint8_t slave_addr, * @param[in] txbytes number of bytes to be transmitted * @param[in] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received + * + * @return The operation status. + * @retval RDY_OK if the function succeeded. + * @retval RDY_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval RDY_TIMEOUT if a timeout occurred before operation end. */ -void i2c_lld_master_transmit(I2CDriver *i2cp, uint8_t slave_addr, - uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes){ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, uint8_t slave_addr, + uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout){ + + msg_t rdymsg; - uint32_t mode = 0; + chSysUnlock(); /* release lock from high level call */ chDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))), "i2cMasterTransmit"); @@ -554,20 +582,50 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint8_t slave_addr, i2cp->rxbuf = rxbuf; i2cp->errors = 0; - mode = STM32_DMA_CR_DIR_M2P; /* TODO: DMA error handling */ dmaStreamSetMemory0(i2cp->dmatx, txbuf); dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); - dmaStreamSetMode(i2cp->dmatx, ((i2cp->dmamode) | mode)); + dmaStreamSetMode(i2cp->dmatx, ((i2cp->dmamode) | STM32_DMA_CR_DIR_M2P)); - /* wait stop bit from previouse transaction*/ + i2c_lld_wait_bus_free(i2cp); + + /* wait stop bit from previous transaction*/ while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) ; i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN; i2cp->id_i2c->CR1 |= I2C_CR1_START; + + i2c_lld_wait_s(i2cp, timeout, rdymsg); + + return rdymsg; +} + + +/** + * @brief Receive data via the I2C bus after writing. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +inline void i2c_lld_master_transceive(I2CDriver *i2cp){ + /* There are no checks in this function because: + - all values checked earlier + - this function calls from ISR */ + + /* init driver fields */ + i2cp->slave_addr |= 0x01; /* LSB = 1 -> receive */ + + /* TODO: DMA error handling */ + dmaStreamSetMemory0(i2cp->dmarx, i2cp->rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, i2cp->rxbytes); + dmaStreamSetMode(i2cp->dmarx, ((i2cp->dmamode) | STM32_DMA_CR_DIR_P2M)); + + i2cp->id_i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; } + /** * @brief Set clock speed. * diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 378b3a335..db0704066 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -239,6 +239,11 @@ /*===========================================================================*/ /** + * @brief Type representing I2C address. + */ +typedef uint16_t i2caddr_t; + +/** * @brief I2C Driver condition flags type. */ typedef uint32_t i2cflags_t; @@ -307,7 +312,7 @@ struct I2CDriver{ __IO i2cflags_t errors; /*!< @brief Error flags.*/ - uint8_t slave_addr; /*!< @brief Current slave address without R/W bit. */ + i2caddr_t slave_addr; /*!< @brief Current slave address without R/W bit. */ /*********** End of the mandatory fields. **********************************/ @@ -330,6 +335,90 @@ struct I2CDriver{ while(i2cp->id_i2c->SR2 & I2C_SR2_BUSY) \ ; \ } +/** + * @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] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_wait_s(i2cp, timeout, rdymsg) { \ + chDbgAssert((i2cp)->id_thread == NULL, \ + "_i2c_wait(), #1", "already waiting"); \ + chSysLock(); /* this lock will be disarmed in high level part */ \ + (i2cp)->id_thread = chThdSelf(); \ + rdymsg = chSchGoSleepTimeoutS(THD_STATE_SUSPENDED, timeout); \ +} + +/** + * @brief Wakes up the waiting thread. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_wakeup_isr(i2cp) { \ + if ((i2cp)->id_thread != NULL) { \ + Thread *tp = (i2cp)->id_thread; \ + (i2cp)->id_thread = NULL; \ + chSysLockFromIsr(); \ + chSchReadyI(tp); \ + chSysUnlockFromIsr(); \ + } \ +} + +/** + * @brief Wakes up the waiting thread in case of errors. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_error_wakeup_isr(i2cp) { \ + if ((i2cp)->id_thread != NULL) { \ + Thread *tp = (i2cp)->id_thread; \ + (i2cp)->id_thread = NULL; \ + chSysLockFromIsr(); \ + chSchReadyI(tp); \ + chSysUnlockFromIsr(); \ + } \ +} + +/** + * @brief Common ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_isr_code(i2cp) { \ + i2c_lld_wakeup_isr(i2cp); \ +} + +/** + * @brief Error ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_isr_err_code(i2cp) { \ + i2c_lld_error_wakeup_isr(i2cp); \ +} + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) /*===========================================================================*/ /* External declarations. */ @@ -358,10 +447,16 @@ void i2c_lld_set_clock(I2CDriver *i2cp); void i2c_lld_set_opmode(I2CDriver *i2cp); void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_stop(I2CDriver *i2cp); -void i2c_lld_master_transmit(I2CDriver *i2cp, uint8_t slave_addr, - uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes); -void i2c_lld_master_receive(I2CDriver *i2cp, uint8_t slave_addr, - uint8_t *rxbuf, size_t rxbytes); +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, uint8_t slave_addr, + uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, + uint8_t slave_addr, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout); +void i2c_lld_master_transceive(I2CDriver *i2cp); #ifdef __cplusplus } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 598719d24..f48ca9e7e 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -179,7 +179,7 @@ i2cflags_t i2cGetErrors(I2CDriver *i2cp) { */
msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
i2caddr_t addr,
- const uint8_t *txbuf,
+ uint8_t *txbuf,
size_t txbytes,
uint8_t *rxbuf,
size_t rxbytes,
@@ -202,7 +202,10 @@ msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, rxbuf, rxbytes, timeout);
i2cp->id_state = I2C_READY;
chSysUnlock();
- return rdymsg;
+ if (i2cGetErrors(i2cp) != I2CD_NO_ERROR)
+ return RDY_RESET;
+ else
+ return rdymsg;
}
/**
@@ -228,7 +231,7 @@ msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, * @api
*/
msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
- i2caddr_t slave_addr,
+ i2caddr_t addr,
uint8_t *rxbuf,
size_t rxbytes,
systime_t timeout){
@@ -249,7 +252,10 @@ msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout);
i2cp->id_state = I2C_READY;
chSysUnlock();
- return rdymsg;
+ if (i2cGetErrors(i2cp) != I2CD_NO_ERROR)
+ return RDY_RESET;
+ else
+ return rdymsg;
}
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
diff --git a/testhal/STM32F1xx/I2C/Makefile b/testhal/STM32F1xx/I2C/Makefile index 08494928a..12eea9360 100644 --- a/testhal/STM32F1xx/I2C/Makefile +++ b/testhal/STM32F1xx/I2C/Makefile @@ -82,9 +82,10 @@ CSRC = $(PORTSRC) \ $(CHIBIOS)/os/various/syscalls.c \
main.c \
i2c_pns.c \
- lis3.c \
tmp75.c \
- fake.c
+ fake.c \
+ #lis3.c
+
diff --git a/testhal/STM32F1xx/I2C/fake.c b/testhal/STM32F1xx/I2C/fake.c index b06ffbdfd..9d46f448d 100644 --- a/testhal/STM32F1xx/I2C/fake.c +++ b/testhal/STM32F1xx/I2C/fake.c @@ -42,14 +42,17 @@ static i2cflags_t errors = 0; /* This is main function. */
void request_fake(void){
+ msg_t status = RDY_OK;
+ systime_t tmo = MS2ST(4);
i2cAcquireBus(&I2CD1);
- i2cMasterReceive(&I2CD1, addr, rx_data, 2, &errors, TIME_INFINITE);
+ status = i2cMasterReceiveTimeout(&I2CD1, addr, rx_data, 2, tmo);
i2cReleaseBus(&I2CD1);
- if (errors == I2CD_ACK_FAILURE){
- __NOP();
+ if (status != RDY_OK){
+ errors = i2cGetErrors(&I2CD1);
}
+
else{
temperature = (rx_data[0] << 8) + rx_data[1];
}
diff --git a/testhal/STM32F1xx/I2C/i2c_pns.c b/testhal/STM32F1xx/I2C/i2c_pns.c index 1c73482e3..b773846ba 100644 --- a/testhal/STM32F1xx/I2C/i2c_pns.c +++ b/testhal/STM32F1xx/I2C/i2c_pns.c @@ -45,7 +45,7 @@ void I2CInit_pns(void){ /* startups. Pauses added just to be safe */
chThdSleepMilliseconds(100);
- init_lis3();
+// init_lis3();
}
diff --git a/testhal/STM32F1xx/I2C/main.c b/testhal/STM32F1xx/I2C/main.c index 60cb1f3ae..760cee229 100644 --- a/testhal/STM32F1xx/I2C/main.c +++ b/testhal/STM32F1xx/I2C/main.c @@ -32,8 +32,9 @@ /*
* Red LEDs blinker thread, times are in milliseconds.
*/
-static WORKING_AREA(BlinkWA, 128);
+static WORKING_AREA(BlinkWA, 64);
static msg_t Blink(void *arg) {
+ chRegSetThreadName("Blink");
(void)arg;
while (TRUE) {
palClearPad(IOPORT3, GPIOC_LED);
@@ -47,21 +48,21 @@ static msg_t Blink(void *arg) { /*
* Accelerometer thread
*/
-static WORKING_AREA(PollAccelThreadWA, 128);
-static msg_t PollAccelThread(void *arg) {
- chRegSetThreadName("PollAccel");
- (void)arg;
- while (TRUE) {
-// chThdSleepMilliseconds(rand() & 31);
- chThdSleepMilliseconds(32);
- request_acceleration_data();
- }
- return 0;
-}
+//static WORKING_AREA(PollAccelThreadWA, 256);
+//static msg_t PollAccelThread(void *arg) {
+// chRegSetThreadName("PollAccel");
+// (void)arg;
+// while (TRUE) {
+//// chThdSleepMilliseconds(rand() & 31);
+// chThdSleepMilliseconds(32);
+// request_acceleration_data();
+// }
+// return 0;
+//}
/* Temperature polling thread */
-static WORKING_AREA(PollTmp75ThreadWA, 128);
+static WORKING_AREA(PollTmp75ThreadWA, 256);
static msg_t PollTmp75Thread(void *arg) {
chRegSetThreadName("PollTmp75");
(void)arg;
@@ -76,7 +77,7 @@ static msg_t PollTmp75Thread(void *arg) { /* Temperature polling thread */
-static WORKING_AREA(PollFakeThreadWA, 128);
+static WORKING_AREA(PollFakeThreadWA, 256);
static msg_t PollFakeThread(void *arg) {
chRegSetThreadName("PollFake");
(void)arg;
@@ -102,11 +103,11 @@ int main(void) { I2CInit_pns();
/* Create accelerometer thread */
- chThdCreateStatic(PollAccelThreadWA,
- sizeof(PollAccelThreadWA),
- NORMALPRIO,
- PollAccelThread,
- NULL);
+// chThdCreateStatic(PollAccelThreadWA,
+// sizeof(PollAccelThreadWA),
+// NORMALPRIO,
+// PollAccelThread,
+// NULL);
/* Create temperature thread */
chThdCreateStatic(PollTmp75ThreadWA,
diff --git a/testhal/STM32F1xx/I2C/tmp75.c b/testhal/STM32F1xx/I2C/tmp75.c index 23410843f..9d41e0a0f 100644 --- a/testhal/STM32F1xx/I2C/tmp75.c +++ b/testhal/STM32F1xx/I2C/tmp75.c @@ -45,11 +45,17 @@ static i2cflags_t errors = 0; /* This is main function. */
void request_temperature(void){
int16_t t_int = 0, t_frac = 0;
+ msg_t status = RDY_OK;
+ systime_t tmo = MS2ST(4);
i2cAcquireBus(&I2CD1);
- i2cMasterReceive(&I2CD1, tmp75_addr, tmp75_rx_data, 2, &errors, TIME_INFINITE);
+ status = i2cMasterReceiveTimeout(&I2CD1, tmp75_addr, tmp75_rx_data, 2, tmo);
i2cReleaseBus(&I2CD1);
+ if (status != RDY_OK){
+ errors = i2cGetErrors(&I2CD1);
+ }
+
t_int = tmp75_rx_data[0] * 100;
t_frac = (tmp75_rx_data[1] * 100) >> 8;
temperature = t_int + t_frac;
|