diff --git a/include/sta/rtos/thread.hpp b/include/sta/rtos/thread.hpp new file mode 100644 index 0000000..8378c87 --- /dev/null +++ b/include/sta/rtos/thread.hpp @@ -0,0 +1,116 @@ +#ifndef STA_RTOS_THREAD_HPP +#define STA_RTOS_THREAD_HPP + +#include +#include + +#include + +/** + * @ingroup STA_RTOS_API + * @{ + */ + +/** + * @brief Number of bits in task notification flags used internally. + */ +#define STA_RTOS_MAX_BITS_THREAD_SYS_NOTIFY 1U +/** + * @brief Number of user usable bits in task notification flags. + */ +#define STA_RTOS_MAX_BITS_THREAD_USER_NOTIFY ( STA_RTOS_MAX_BITS_THREAD_NOTIFY - STA_RTOS_MAX_BITS_THREAD_SYS_NOTIFY ) +/** + * @brief Mask for valid system task notification flag bits. + */ +#define STA_RTOS_THREAD_FLAGS_VALID_SYS_BITS ( ( ( 1UL << STA_RTOS_MAX_BITS_THREAD_SYS_NOTIFY ) - 1U ) << STA_RTOS_MAX_BITS_THREAD_USER_NOTIFY ) +/** + * @brief Mask for valid user task notification flag bits. + */ +#define STA_RTOS_THREAD_FLAGS_VALID_USER_BITS ( ( 1UL << STA_RTOS_MAX_BITS_THREAD_USER_NOTIFY ) - 1U ) + + +/** + * @brief Indicate error code instead of flag values. + */ +#define STA_RTOS_THREAD_FLAG_ERROR_CODE ( 1UL << 31 ) + +/** + * @brief Request thread termination. + */ +#define STA_RTOS_THREAD_FLAG_TERMINATE ( 1UL << 30 ) + + +#define STA_RTOS_THREAD_FLAGS_ERROR_CODE_BITS UINT32_C( 0x0000000F ) +#define STA_RTOS_THREAD_FLAGS_ERROR_CODE_EXT_BITS UINT32_C( 0x7FFFFFF0 ) + + +#define STA_RTOS_THREAD_FLAGS_GET_EXT_ERROR_CODE(flags) (~flags & STA_RTOS_THREAD_FLAGS_ERROR_CODE_EXT_BITS) + + + +#define STA_RTOS_THREAD_FLAGS_WAIT_ANY(timeout) osThreadFlagsWait(STA_RTOS_THREAD_FLAGS_VALID_BITS, osFlagsWaitAny, timeout) + + +/** @} */ + + +namespace sta +{ + /** + * @brief Wrapper for RTOS thread control. + * + * @ingroup STA_RTOS_API + */ + class RtosThread + { + public: + using Handle = RtosHandle; /**< Thread handle type */ + + public: + RtosThread(); + + /** + * @param handle Thread handle + */ + RtosThread(const Handle & handle); + + /** + * @brief Send user notification flags to thread. + * + * @param flags User flags + */ + void notify(uint32_t flags); + + /** + * @brief Send termination request to thread. + */ + void requestTermination(); + /** + * @brief Forcibly terminate thread. + */ + void terminate(); + + /** + * @brief Send system notification flags to thread. + * + * @param flags System flags + */ + void sysNotify(uint32_t flags); + + private: + Handle handle_; + }; +} // namespace sta + + +/** + * @brief Create RtosThread wrapper object for thread handle. + * + * @param name Thread name + */ +#define STA_RTOS_THREAD_WRAPPER(name) \ + extern osThreadId_t name ## Handle; \ + sta::RtosThread name ## Thread = sta::RtosThread(sta::RtosThread::Handle::Deferred(&name ## Handle)); + + +#endif // STA_RTOS_THREAD_HPP diff --git a/src/thread.cpp b/src/thread.cpp new file mode 100644 index 0000000..781f0d1 --- /dev/null +++ b/src/thread.cpp @@ -0,0 +1,46 @@ +#include + + +#define IS_THREAD_SYS_FLAGS(flags) ( ( flags & STA_RTOS_THREAD_FLAGS_VALID_SYS_BITS ) == flags ) +#define IS_THREAD_USER_FLAGS(flags) ( ( flags & STA_RTOS_THREAD_FLAGS_VALID_USER_BITS ) == flags ) + + +namespace sta +{ + RtosThread::RtosThread() + : handle_(nullptr) + {} + + RtosThread::RtosThread(const Handle & handle) + : handle_{handle} + {} + + + void RtosThread::notify(uint32_t flags) + { + STA_ASSERT(handle_.get() != nullptr); + STA_ASSERT_MSG(IS_THREAD_USER_FLAGS(flags), "Only user flags allowed"); + + osThreadFlagsSet(handle_.get(), flags); + } + + void RtosThread::sysNotify(uint32_t flags) + { + STA_ASSERT(handle_.get() != nullptr); + STA_ASSERT_MSG(IS_THREAD_SYS_FLAGS(flags), "Only system flags allowed"); + + osThreadFlagsSet(handle_.get(), flags); + } + + + void RtosThread::requestTermination() + { + sysNotify(STA_RTOS_THREAD_FLAG_TERMINATE); + } + + void RtosThread::terminate() + { + STA_ASSERT(handle_.get() != nullptr); + osThreadTerminate(handle_.get()); + } +} // namespace sta