summaryrefslogtreecommitdiff
path: root/digital/ucoolib/ucoolib
diff options
context:
space:
mode:
Diffstat (limited to 'digital/ucoolib/ucoolib')
-rw-r--r--digital/ucoolib/ucoolib/hal/i2c/i2c_hard.stm32.cc6
-rw-r--r--digital/ucoolib/ucoolib/hal/i2c/test/test_i2c.cc59
-rw-r--r--digital/ucoolib/ucoolib/intf/i2c.hh3
3 files changed, 68 insertions, 0 deletions
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) { }