From ce8581af2514e8d60c0ce14f4a2c39944b6ab988 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Wed, 20 Feb 2013 17:15:53 +0100 Subject: digital/ucoolib/ucoolib/hal/i2c: add finished handler call --- digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc | 6 +++ digital/ucoolib/ucoolib/hal/i2c/test/test_i2c.cc | 59 +++++++++++++++++++++++ digital/ucoolib/ucoolib/intf/i2c.hh | 3 ++ 3 files changed, 68 insertions(+) diff --git a/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc b/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc index 75299535..f11006ba 100644 --- a/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc +++ b/digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc @@ -280,6 +280,8 @@ I2cHard::ev_isr (int n) I2C_CR1 (base) = I2C_CR1_ACK | I2C_CR1_STOP | I2C_CR1_PE; i2c.master_ = false; i2c.master_status_ = i2c.buf_index_; + if (i2c.finished_handler_) + i2c.finished_handler_->finished (i2c.master_status_); } else if (i2c.buf_count_ - i2c.buf_index_ == 3) { @@ -297,6 +299,8 @@ I2cHard::ev_isr (int n) i2c.master_buf_[i2c.buf_index_++] = I2C_DR (base); i2c.master_ = false; i2c.master_status_ = i2c.buf_index_; + if (i2c.finished_handler_) + i2c.finished_handler_->finished (i2c.master_status_); } } else @@ -381,6 +385,8 @@ I2cHard::er_isr (int n) I2C_CR1 (base) = I2C_CR1_ACK | I2C_CR1_STOP | I2C_CR1_PE; i2c.master_ = false; i2c.master_status_ = i2c.buf_index_; + if (i2c.finished_handler_) + i2c.finished_handler_->finished (i2c.master_status_); } } I2C_CR2 (base) &= ~I2C_CR2_ITBUFEN; diff --git a/digital/ucoolib/ucoolib/hal/i2c/test/test_i2c.cc b/digital/ucoolib/ucoolib/hal/i2c/test/test_i2c.cc index b870665b..8196b663 100644 --- a/digital/ucoolib/ucoolib/hal/i2c/test/test_i2c.cc +++ b/digital/ucoolib/ucoolib/hal/i2c/test/test_i2c.cc @@ -89,6 +89,65 @@ test_basic (ucoo::TestSuite &tsuite, ucoo::I2cMaster &m, test_fail_break_unless (test, std::count (buf, buf + r, c) == r); } } + do { + ucoo::Test test (tsuite, "callback"); + // Callback object will start a reception, then a transmission of what + // was received. + class TestCallback : public ucoo::I2cMaster::FinishedHandler + { + ucoo::I2cMaster &m_; + uint8_t addr_; + int step_; + char buf_[buffer_size]; + public: + bool failed; + public: + TestCallback (ucoo::I2cMaster &m, uint8_t addr) + : m_ (m), addr_ (addr), step_ (0), failed (false) { } + void finished (int status) + { + if (status != buffer_size) + failed = true; + else + { + switch (step_) + { + case 0: + m_.recv (addr_, buf_, buffer_size); + step_++; + break; + case 1: + m_.send (addr_, buf_, buffer_size); + step_++; + break; + case 2: + // Nothing, stop. + break; + } + } + } + }; + TestCallback callback (m, addr); + m.register_finished (callback); + // Set slave data. + char buf[buffer_size]; + std::fill (buf, buf + sizeof (buf), 42); + d.update (buf, sizeof (buf)); + // Start transfers. + std::fill (buf, buf + sizeof (buf), 21); + m.send (addr, buf, sizeof (buf)); + // Will only return after the last transfer. + m.wait (); + m.unregister_finished (); + test_fail_break_unless (test, !callback.failed); + // Let some time for slave to finish reception. + ucoo::delay_ms (1); + // Check what is received by slave (master should have read 42 from + // slave and send it back). + int r = d.poll (buf, sizeof (buf)); + test_fail_break_unless (test, r == buffer_size); + test_fail_break_unless (test, std::count (buf, buf + r, 42) == r); + } while (0); } int diff --git a/digital/ucoolib/ucoolib/intf/i2c.hh b/digital/ucoolib/ucoolib/intf/i2c.hh index 622510a1..20acf008 100644 --- a/digital/ucoolib/ucoolib/intf/i2c.hh +++ b/digital/ucoolib/ucoolib/intf/i2c.hh @@ -70,6 +70,9 @@ class I2cMaster /// Register a handler called when transfer is finished. void register_finished (FinishedHandler &finished_handler) { finished_handler_ = &finished_handler; } + /// Remove registered handler. + void unregister_finished (void) + { finished_handler_ = 0; } protected: /// Default constructor. I2cMaster () : finished_handler_ (0) { } -- cgit v1.2.3