diff options
author | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-02-06 13:36:29 +0000 |
---|---|---|
committer | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-02-06 13:36:29 +0000 |
commit | 00800dd8ed98bfc23cfb9d4c50fa84ef0e2e0898 (patch) | |
tree | b7817133ee014788e66b6266ed4f33a0300d5287 /os/hal/platforms/STM32/i2c_lld.c | |
parent | da3a453945c635a030c7ec266036be72eb482937 (diff) | |
download | ChibiOS-00800dd8ed98bfc23cfb9d4c50fa84ef0e2e0898.tar.gz ChibiOS-00800dd8ed98bfc23cfb9d4c50fa84ef0e2e0898.tar.bz2 ChibiOS-00800dd8ed98bfc23cfb9d4c50fa84ef0e2e0898.zip |
I2C. Async transfer complete. Needs testing.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2716 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/platforms/STM32/i2c_lld.c')
-rw-r--r-- | os/hal/platforms/STM32/i2c_lld.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 71873be05..7a7a071ec 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -122,6 +122,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { // if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ chSysLockFromIsr(); + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); i = i2cp->id_i2c->SR1; @@ -283,16 +284,23 @@ void i2c_lld_stop(I2CDriver *i2cp) { * return TRUE if last byte written */ bool_t i2c_lld_txbyte(I2CDriver *i2cp) { - void *txbufhead = i2cp->id_slave_config->txbufhead; - void *txbytes = i2cp->id_slave_config->txbytes; - - if (i2cp->id_slave_config->txbufhead < i2cp->id_slave_config->txbytes){ - i2cp->id_i2c->DR = i2cp->id_slave_config->txbuf[i2cp->id_slave_config->txbufhead]; - (i2cp->id_slave_config->txbufhead)++; +#define _txbufhead (i2cp->id_slave_config->txbufhead) +#define _txbytes (i2cp->id_slave_config->txbytes) +#define _txbuf (i2cp->id_slave_config->txbuf) + + if (_txbufhead < _txbytes){ + /* disable interrupt to avoid jumping to ISR */ + if ( _txbytes - _txbufhead == 1) + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + i2cp->id_i2c->DR = _txbuf[_txbufhead]; + (_txbufhead)++; return(FALSE); } - i2cp->id_slave_config->txbufhead = 0; + _txbufhead = 0; return(TRUE); // last byte written +#undef _txbufhead +#undef _txbytes +#undef _txbuf } @@ -302,44 +310,49 @@ bool_t i2c_lld_txbyte(I2CDriver *i2cp) { */ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { // temporal variables - #define rxbuf i2cp->id_slave_config->rxbuf - #define rxbufhead i2cp->id_slave_config->rxbufhead - #define rxdepth i2cp->id_slave_config->rxdepth - #define rxbytes i2cp->id_slave_config->rxbytes +#define _rxbuf (i2cp->id_slave_config->rxbuf) +#define _rxbufhead (i2cp->id_slave_config->rxbufhead) +#define _rxdepth (i2cp->id_slave_config->rxdepth) +#define _rxbytes (i2cp->id_slave_config->rxbytes) /* In order to generate the non-acknowledge pulse after the last received * data byte, the ACK bit must be cleared just after reading the second * last data byte (after second last RxNE event). */ - if (rxbufhead < rxbytes){ - rxbuf[rxbufhead] = i2cp->id_i2c->DR; - if ((rxbytes - rxbufhead) <= 2){ + if (_rxbufhead < _rxbytes){ + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; + if ((_rxbytes - _rxbufhead) <= 2){ i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK } - rxbufhead++; + (_rxbufhead)++; return(FALSE); } - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); // disable interrupt - rxbuf[rxbufhead] = i2cp->id_i2c->DR; // read last byte - rxbufhead = 0; - #undef rxbuf - #undef rxbufhead - #undef rxdepth - #undef rxbytes + /* disable interrupt to avoid jumping to ISR */ + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; // read last byte + _rxbufhead = 0; return(TRUE); // last byte read + +#undef _rxbuf +#undef _rxbufhead +#undef _rxdepth +#undef _rxbytes } void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; + while (i2cp->id_i2c->CR1 & I2C_CR1_START); + + // enable interrupts + i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN; + i2cp->id_i2c->CR2 |= I2C_CR2_ITBUFEN; } void i2c_lld_master_stop(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - chSysLock(); while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); - chSysUnlock(); } |