From 377d2f7d7f04e067d022419363236960bc8a22f1 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Mon, 7 Apr 2014 15:17:58 +0400 Subject: [PATCH] STM32: iface activity indication --- .../stm32/driver/include/uavcan_stm32/can.hpp | 23 +++++++++++++++++++ .../stm32/driver/src/uc_stm32_can.cpp | 21 +++++++++++++++++ .../stm32/test_stm32f107/src/main.cpp | 9 ++++---- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp index 1117cf8f1d..37bbb03b97 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp @@ -114,6 +114,7 @@ class CanIface : public uavcan::ICanIface, uavcan::Noncopyable TxItem pending_tx_[NumTxMailboxes]; uavcan::uint8_t last_hw_error_code_; const uavcan::uint8_t self_index_; + bool had_activity_; int computeTimings(uavcan::uint32_t target_bitrate, Timings& out_timings); @@ -141,11 +142,13 @@ public: , update_event_(update_event) , last_hw_error_code_(0) , self_index_(self_index) + , had_activity_(false) { assert(self_index_ < UAVCAN_STM32_NUM_IFACES); } /** + * Initializes the hardware CAN controller. * Assumes: * - Iface clock is enabled * - Iface has been resetted via RCC @@ -163,8 +166,22 @@ public: bool isTxBufferFull() const; bool isRxBufferEmpty() const; + /** + * Total number of hardware failures. + * May increase continuously if the interface is not connected to the bus. + */ virtual uavcan::uint64_t getErrorCount() const; + + /** + * Returns last hardware error code (LEC field in the register ESR) + */ uavcan::uint8_t yieldLastHardwareErrorCode(); + + /** + * Whether this iface had at least one successful IO since previous call of this method. + * This is designed for use with iface activity LEDs. + */ + bool hadActivity(); }; /** @@ -199,6 +216,12 @@ public: virtual CanIface* getIface(uavcan::uint8_t iface_index); virtual uavcan::uint8_t getNumIfaces() const { return UAVCAN_STM32_NUM_IFACES; } + + /** + * Whether at least one iface had at least one successful IO since previous call of this method. + * This is designed for use with iface activity LEDs. + */ + bool hadActivity(); }; /** diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index 35f8c0e4e4..2b8351dacf 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -381,6 +381,9 @@ leave: void CanIface::handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok, const uavcan::uint64_t utc_usec) { assert(mailbox_index < NumTxMailboxes); + + had_activity_ = had_activity_ || txok; + TxItem& txi = pending_tx_[mailbox_index]; if (txi.loopback && txok && txi.pending) { @@ -471,6 +474,7 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut */ rx_queue_.push(frame, utc_usec, 0); update_event_.signalFromInterrupt(); + had_activity_ = true; } void CanIface::handleStatusInterrupt() @@ -522,6 +526,14 @@ uavcan::uint8_t CanIface::yieldLastHardwareErrorCode() return val; } +bool CanIface::hadActivity() +{ + CriticalSectionLocker lock; + const bool ret = had_activity_; + had_activity_ = false; + return ret; +} + /* * CanDriver */ @@ -640,6 +652,15 @@ CanIface* CanDriver::getIface(uavcan::uint8_t iface_index) return NULL; } +bool CanDriver::hadActivity() +{ + bool ret = if0_.hadActivity(); +#if UAVCAN_STM32_NUM_IFACES > 1 + ret |= if1_.hadActivity(); +#endif + return ret; +} + } // namespace uavcan_stm32 /* diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp index 45def312f6..ae20071141 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp @@ -140,10 +140,11 @@ int main() while (true) { - app::ledSet(false); - sleep(1); - app::ledSet(true); - sleep(1); + for (int i = 0; i < 200; i++) + { + app::ledSet(app::can.driver.hadActivity()); + ::usleep(25000); + } const uavcan::UtcTime utc = uavcan_stm32::clock::getUtc(); lowsyslog("UTC %lu sec, %li corr, %lu jumps\n",