From 7635cfe4ad139e6de90acf4bbf924ec89624cccc Mon Sep 17 00:00:00 2001 From: "@CarlWachter" Date: Mon, 1 Jan 2024 16:03:21 +0100 Subject: [PATCH] Rebase onto main --- .gitignore | 3 + README.md | 1 + include/sta/tacos/can_bus.hpp | 118 ++++++++++++++++++++++++++++++++++ src/can_bus.cpp | 115 +++++++++++++++++++++++++++++++++ 4 files changed, 237 insertions(+) create mode 100644 include/sta/tacos/can_bus.hpp create mode 100644 src/can_bus.cpp diff --git a/.gitignore b/.gitignore index b9309ce..64dcbf5 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ Release/ docs/html docs/latex +# Config +include/sta/config.hpp + diff --git a/README.md b/README.md index 51cdb5b..a2d3146 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ In order to use TACOS, you need to provide a configuration file in the path `sta #define STA_RTOS_SYSTEM_EVENTS_ENABLE // #define STA_RTOS_SYSTEM_WATCHDOG_ENABLE // #define STA_RTOS_WATCHDOG_ENABLE +// #define STA_RTOS_CAN_BUS_ENABLE // Uses the default configuration for TACOS. #include diff --git a/include/sta/tacos/can_bus.hpp b/include/sta/tacos/can_bus.hpp new file mode 100644 index 0000000..ca3e4d4 --- /dev/null +++ b/include/sta/tacos/can_bus.hpp @@ -0,0 +1,118 @@ +#ifndef INCLUDE_TACOS_CAN_BUS_HPP_ +#define INCLUDE_TACOS_CAN_BUS_HPP_ + +#include + +//TODO UNCOMMENT THIS +//#ifdef STA_RTOS_CAN_BUS_ENABLE + +#include +#include +#include +#include + + +/** + * @defgroup tacos_can_bus Can Bus Task + * @ingroup tacos + * @brief Can Bus task for TACOS. + */ + +namespace sta +{ + namespace tacos + { + /** + * @brief Can Bus implementation for Tacos. + * + * @ingroup tacos_can_bus + */ + class CanBus : public TacosThread + { + public: + /** + * @brief Getter function for the singleton instance. + */ + static CanBus* instance(CAN_HandleTypeDef * handle) + { + static CGuard g; + + if (!_instance) + { + // Create the can bus singleton instance. + CanBus::_instance = new CanBus(handle); + } + + return _instance; + } + + /** + * @brief Place data message in CAN driver TX queue. + * + * @param msg Message to transmit + * @param timeout Timeout for placing message (0 = no wait, osWaitForever = blocking) + * @return True if message was queued successfully + */ + bool queueCanBusMsg(const CanDataMsg & msg, uint32_t timeout); + /** + * @brief Place system message in CAN driver TX queue. + * + * @param msg Message to transmit + * @param timeout Timeout for placing message (0 = no wait, osWaitForever = blocking) + * @return True if message was queued successfully + */ + bool queueCanBusMsg(const CanSysMsg & msg, uint32_t timeout); + + /** + * @brief Retrieve data message from CAN driver TX queue. + * + * @param[out] msg Output address for retrieved message + * @param timeout Timeout for retrieving message (0 = no wait, osWaitForever = blocking) + * @return True if message was retrieved successfully + */ + bool getCanBusMsg(CanDataMsg * msg, uint32_t timeout); + /** + * @brief Retrieve system message from CAN driver TX queue. + * + * @param[out] msg Destination for retrieved message + * @param timeout Timeout for retrieving message (0 = no wait, osWaitForever = blocking) + * @return True if message was retrieved successfully + */ + bool getCanBusMsg(CanSysMsg * msg, uint32_t timeout); + + + private: + static CanBus * _instance; + + class CGuard + { + public: + ~CGuard() + { + if( NULL != CanBus::_instance ) + { + delete CanBus::_instance; + CanBus::_instance = NULL; + } + } + }; + + + RtosQueue canBusDataQueue_; + RtosQueue canBusSysQueue_; + + CanDataMsg canBusDataQueueBuffer[queueLength]; + CanSysMsg canBusSysQueueBuffer[queueLength]; + uint32_t canBusStack[256]; + + sta::STM32CanController * canBusController_; + const size_t queueLength_; + AlpakaCanBus canBus_; + } + + } /* namespace tacos */ + +} /* namespace sta */ + +#endif /* STA_RTOS_CAN_BUS_ENABLE */ +#endif /* INCLUDE_TACOS_CAN_BUS_HPP_ */ \ No newline at end of file diff --git a/src/can_bus.cpp b/src/can_bus.cpp new file mode 100644 index 0000000..c6bd795 --- /dev/null +++ b/src/can_bus.cpp @@ -0,0 +1,115 @@ +#include +#include +#include + +namespace sta +{ + namespace tacos + { + CanBus::CanBus(CAN_HandleTypeDef * handle) + : TacosThread{"Can Bus", STA_TACOS_CAN_BUS_PRIORITY}, + canBusController_{handle}, + canBusDataQueueBuffer{nullptr}, + canBusSysQueueBuffer{nullptr}, + canSysDataQueue_{STA_RTOS_CAN_BUS_QUEUE_LENGTH}, + canBusDataQueue_{STA_RTOS_CAN_BUS_QUEUE_LENGTH}, + canBus_{&canBusController_, HAL_GetTick, dummy::handleSysMessage, dummy::handleDataMessage} + { + } + + void CanBus::init() + { + canBusController_.start(); + } + + void CanBus::func() + { + uint32_t flags = osThreadFlagsWait(STA_RTOS_THREAD_FLAGS_VALID_BITS, osFlagsWaitAny, 50); + + if (flags != static_cast(osErrorTimeout)) + { + STA_ASSERT_MSG((flags & osStatusReserved) == flags, "Unexpected error occurred in wait"); + + if (flags & STA_RTOS_CAN_FLAG_SYS_QUEUED) + { + // Take messages from queue until empty + CanSysMsg msg; + while (rtos::getCanBusMsg(&msg, 0)) + { + canBus_.send(msg); + } + } + + if (flags & STA_RTOS_CAN_FLAG_DATA_QUEUED) + { + // Take messages from queue until empty + CanDataMsg msg; + while (rtos::getCanBusMsg(&msg, 0)) + { + canBus_.send(msg); + } + } + + if (flags & STA_RTOS_CAN_FLAG_MSG_AVAIL) + { + STA_DEBUG_PRINTLN("[event] CAN INT"); + + canBus_.processRx(); + } + + if (flags & STA_RTOS_CAN_FLAG_SHOW_STATS) + { + canBus_.showStatistics(); + } + } + + // Process ISOTP transmissions + canBus.processTx(); + } + + bool queueCanBusMsg(const CanDataMsg & msg, uint32_t timeout) + { + STA_ASSERT((msg.header.sid & STA_CAN_SID_SYS_BITS) == 0); + STA_ASSERT(msg.header.payloadLength <= sizeof(msg.payload)); + + if (canBusDataQueue_.put(&msg, timeout)) + { + // Signal thread + notify(STA_RTOS_CAN_FLAG_DATA_QUEUED); + return true; + } + else + { + return false; + } + } + + bool queueCanBusMsg(const CanSysMsg & msg, uint32_t timeout) + { + STA_ASSERT((msg.header.sid & ~STA_CAN_SID_SYS_BITS) == 0); + + if (canBusSysQueue_.put(&msg, timeout)) + { + // Signal thread + notify(STA_RTOS_CAN_FLAG_SYS_QUEUED); + return true; + } + else + { + return false; + } + } + + + bool getCanBusMsg(CanDataMsg * msg, uint32_t timeout) + { + return (osOK == osMessageQueueGet(canBusDataQueueHandle, msg, 0, timeout)); + } + + bool getCanBusMsg(CanSysMsg * msg, uint32_t timeout) + { + return (osOK == osMessageQueueGet(canBusSysQueueHandle, msg, 0, timeout)); + } + + } /* namespace tacos */ +} /* namespace sta */ \ No newline at end of file