/* * task.hpp * * Created on: Sep 14, 2023 * Author: Dario */ #ifndef INCLUDE_TACOS_TASK_HPP_ #define INCLUDE_TACOS_TASK_HPP_ #include #include #include #include #include /** * @defgroup tacos_thread TACOS Thread * @ingroup tacos * @brief TACOS Thread class. */ namespace sta { namespace tacos { #ifdef STA_TACOS_WATCHDOG_ENABLED /** * @brief A status flags for the watchdog. * * @ingroup tacos_thread */ enum class ThreadStatus { /** * @brief This thread wants to be ignored by the watchdog. * */ IGNORED, /** * @brief The thread terminated regularly. The watchdog will not try to restart this thread. * */ STOPPED, /** * @brief The thread's status is unknown. If the watchdog encounters this status, it will try to * restart the affected thread. * */ UNKNOWN, /** * @brief The thread is running as intended. The watchdog will set this flag back to UNKNOWN. * */ RUNNING, /** * @brief The thread is waiting and might not send a heartbeat signal in a while. The watchdog will * not do anything in this case. * */ WAITING }; #endif // STA_TACOS_WATCHDOG_ENABLED /** * @brief Abstract class for thread implementations in Tacos. * * @ingroup tacos_thread */ class TacosThread : public RtosThread { public: /** * @brief Create a new thread with the given name and priority. * * @param name The thread's name. This is used for debugging. * @param prio The thread's priority. Generally, this should be lower than the manager and statemachine priority. * @param stack_size The stack size for the task. The default is 0, i.e. the stack size specified in the FreeRTOS settings. * @param cb_size The control block size for the task. The default is 0, i.e. the size specified in the FreeRTOS settings. */ TacosThread(const char* name, osPriority_t prio, uint32_t stack_size = 0, uint32_t cb_size = 0); virtual ~TacosThread(); /** * @brief Checks if this thread is currently running. */ bool isRunning(); bool operator==(const TacosThread& other) const; /** * @brief Compare two threads by their names. */ bool operator<(const TacosThread& other) const; void loop() override; void start() override; /** * @brief This function is executed first when this thread is started. */ virtual void init(); /** * @brief The body of the thread's loop. Has to be implemented by the user. * This function is called repeatedly until termination is requested. */ virtual void func() = 0; /** * @brief This function is executed when the thread is terminated. Has to be implemented by the user. * This function should free all ressources used by this thread. */ virtual void cleanup(); /** * @brief Sleep for a given number of ticks. Sets itself to WAITING if the watchdog is enabled, preventing * the watchdog from restarting this thread. * * @param ticks */ void sleep(uint32_t ticks); /** * @brief Sleep until next period. Sets itself to WAITING if the watchdog is enabled, preventing * the watchdog from restarting this thread. * * @param frequency */ void periodicDelay(uint32_t frequency); #ifdef STA_CAN_BUS_ENABLE /** * @brief Set the ID of the CAN bus this thread is associated with. * * @param canID */ void setCanID(uint32_t canID); /** * @brief Get the ID of the CAN bus this thread is associated with. * * @return can ID */ uint32_t getCanID(); sta::RtosQueue CAN_queue_; #endif // STA_CAN_BUS_ENABLE #ifdef STA_TACOS_WATCHDOG_ENABLED /** * @brief This macro wraps a given statement into waiting() and heartbeat() to make the code more readable. * */ #define blocking(...) \ waiting(); \ __VA_ARGS__ \ heartbeat(); \ protected: /** * @brief Sends a heartbeat signal by setting the thread status to RUNNING * */ void heartbeat(); /** * @brief Set the thread's status to waiting. This can called before executing code which is very likely * to exceed a watchdog cycle. This stops the watchdog from restarting the thread. * */ void waiting(); public: /** * @brief Get the current status of the thread. * * @return ThreadStatus The current status of the thread. */ ThreadStatus getStatus(); /** * @brief Reset the thread's status to UNKNOWN. Should only be called by the Watchdog. * */ void resetStatus(); /** * @brief This thread status tells the watchdog to ignore this thread. */ void watchdogIgnore(); #endif // STA_TACOS_WATCHDOG_ENABLED /** * @brief Send termination request to thread. */ void requestTermination(); /** * @brief Clear the termination request flag for this thread. */ void deleteTerminationRequest(); /** * @brief Resets the terminate bool to false. * * @return Returns the previous value of this variable. */ bool isTerminationRequested(); private: osThreadId_t instance_; osThreadAttr_t attribs_; bool running_; #ifdef STA_TACOS_WATCHDOG_ENABLED ThreadStatus status_; #endif // STA_TACOS_WATCHDOG_ENABLED #ifdef STA_CAN_BUS_ENABLE uint32_t canID_; #endif // STA_TACOS_WATCHDOG_ENABLED bool terminate_; uint32_t previous_tick_; }; } } #endif /* INCLUDE_TACOS_TASK_HPP_ */