From cab54c77e772be0cce1d77439bdcbd63910c62be Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Wed, 20 Feb 2013 17:14:05 +0100 Subject: digital/ucoolib/ucoolib/hal/i2c: wait for BTF at end of transmission In master mode, wait for end of transmission before STOP bit is set. --- digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc | 28 +++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'digital/ucoolib/ucoolib') diff --git a/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc b/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc index 11baba60..75299535 100644 --- a/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc +++ b/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc @@ -252,20 +252,15 @@ I2cHard::ev_isr (int n) } i2c_trace ("<%d> master sr2=%04x", n, sr2); } - else if (sr1 & I2C_SR1_TxE) + else if (sr1 & I2C_SR1_TxE + && i2c.buf_index_ < i2c.buf_count_) { i2c_trace ("<%d> master tx index=%d", n, i2c.buf_index_); - // Send next byte or stop. - if (i2c.buf_index_ < i2c.buf_count_) - I2C_DR (base) = i2c.master_buf_[i2c.buf_index_++]; - else - { - I2C_CR1 (base) = I2C_CR1_ACK | I2C_CR1_STOP | I2C_CR1_PE; + // Send next byte. + I2C_DR (base) = i2c.master_buf_[i2c.buf_index_++]; + // Wait for BTF if last one. + if (i2c.buf_index_ == i2c.buf_count_) I2C_CR2 (base) &= ~I2C_CR2_ITBUFEN; - I2C_DR (base) = 0xff; - i2c.master_ = false; - i2c.master_status_ = i2c.buf_index_; - } } else if (sr1 & I2C_SR1_RxNE && i2c.buf_count_ - i2c.buf_index_ > 3) @@ -279,14 +274,23 @@ I2cHard::ev_isr (int n) else if (sr1 & I2C_SR1_BTF) { i2c_trace ("<%d> master btf index=%d", n, i2c.buf_index_); - if (i2c.buf_count_ - i2c.buf_index_ == 3) + if (!(i2c.master_slave_addr_ & 1)) + { + // End of transmission. + I2C_CR1 (base) = I2C_CR1_ACK | I2C_CR1_STOP | I2C_CR1_PE; + i2c.master_ = false; + i2c.master_status_ = i2c.buf_index_; + } + else if (i2c.buf_count_ - i2c.buf_index_ == 3) { + // Near end of reception. I2C_CR1 (base) = I2C_CR1_PE; i2c.master_buf_[i2c.buf_index_++] = I2C_DR (base); // Wait for BTF. } else { + // End of reception. I2C_CR1 (base) = I2C_CR1_ACK | I2C_CR1_STOP | I2C_CR1_PE; if (i2c.buf_count_ - i2c.buf_index_ == 2) i2c.master_buf_[i2c.buf_index_++] = I2C_DR (base); -- cgit v1.2.3