Thread rework to support watchdog restarting

This commit is contained in:
dario 2024-01-24 21:17:42 +01:00
parent ce2bb459cf
commit 3feedc948f
3 changed files with 90 additions and 68 deletions

View File

@ -60,7 +60,7 @@ namespace sta
/** /**
* @brief Access handle value. * @brief Access handle value.
* *
* If the deferred ctor was used the handle value is * If the deferred constructor was used the handle value is
* evaluated on the first call to this method. * evaluated on the first call to this method.
* *
* @return Handle value * @return Handle value

View File

@ -2,7 +2,6 @@
#define STA_RTOS_THREAD_HPP #define STA_RTOS_THREAD_HPP
#include <sta/rtos/defs.hpp> #include <sta/rtos/defs.hpp>
#include <sta/rtos/handle.hpp>
#include <cmsis_os2.h> #include <cmsis_os2.h>
@ -73,15 +72,30 @@ namespace sta
class RtosThread class RtosThread
{ {
public: public:
using Handle = RtosHandle<osThreadId_t>; /**< Thread handle type */ /**
* @brief Create an RtosThread.
public: *
RtosThread(); * @param name The thread's name. Will be used for debugging.
* @param prio The thread's priority.
*/
RtosThread(const char* name, osPriority_t prio);
/** /**
* @param handle Thread handle * @brief Get the currently running instance.
*
* @return The currently running instance id.
*/ */
RtosThread(const Handle & handle); osThreadId_t getInstance();
/**
* @brief Get the name of this thread.
*/
const char* getName() const;
/**
* @brief Start the execution of this thread.
*/
void start();
/** /**
* @brief Sets the thread to BLOCKED for a given number of ticks. * @brief Sets the thread to BLOCKED for a given number of ticks.
@ -117,23 +131,6 @@ namespace sta
*/ */
uint32_t clear(uint32_t flags); uint32_t clear(uint32_t flags);
/**
* @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();
/** /**
* @brief Forcibly terminate thread. * @brief Forcibly terminate thread.
*/ */
@ -145,22 +142,22 @@ namespace sta
* @param flags System flags * @param flags System flags
*/ */
void sysNotify(uint32_t flags); void sysNotify(uint32_t flags);
protected:
/**
* @brief A function that wraps this task's functionality.
*/
virtual void loop() = 0;
private: private:
Handle handle_; /**
bool terminate_; * @brief Static function to pass to RTOS to run as a thread. Calls the loop function implemented here.
*/
static void entry_point(void* arg);
private:
osThreadId_t instance_;
osThreadAttr_t attribs_;
}; };
} // namespace sta } // 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 #endif // STA_RTOS_THREAD_HPP

View File

@ -1,5 +1,5 @@
#include <sta/rtos/thread.hpp> #include <sta/rtos/thread.hpp>
#include <sta/debug/assert.hpp>
#define IS_THREAD_SYS_FLAGS(flags) ( ( flags & STA_RTOS_THREAD_FLAGS_VALID_SYS_BITS ) == flags ) #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 ) #define IS_THREAD_USER_FLAGS(flags) ( ( flags & STA_RTOS_THREAD_FLAGS_VALID_USER_BITS ) == flags )
@ -7,35 +7,64 @@
namespace sta namespace sta
{ {
RtosThread::RtosThread() RtosThread::RtosThread(const char* name, osPriority_t prio)
: handle_(nullptr), : instance_{NULL},
terminate_{false} attribs_{ .name = name, .priority = prio }
{} {}
RtosThread::RtosThread(const Handle & handle) osThreadId_t RtosThread::getInstance()
: handle_{handle}, {
terminate_{false} return instance_;
{} }
const char* RtosThread::getName() const
{
return attribs_.name;
}
void RtosThread::start()
{
// Check if there is no instance that is currently running.
STA_ASSERT(instance_ != NULL);
instance_ = osThreadNew(entry_point, this, &attribs_);
STA_ASSERT(instance_ != NULL);
// Send a thread start signal.
sysNotify(STA_RTOS_THREAD_FLAG_START);
}
void RtosThread::entry_point(void* arg)
{
STA_ASSERT(arg != nullptr);
RtosThread* instance = reinterpret_cast<RtosThread*>(arg) ;
instance->loop();
}
void RtosThread::sleep(uint32_t ticks) void RtosThread::sleep(uint32_t ticks)
{ {
// Make sure that the calling thread is this thread. If not, the
// developer very likely has made a mistake.
STA_ASSERT(osThreadGetId() == instance_);
osDelay(ticks); osDelay(ticks);
} }
void RtosThread::notify(uint32_t flags) void RtosThread::notify(uint32_t flags)
{ {
STA_ASSERT(handle_.get() != nullptr); STA_ASSERT(instance_ != NULL);
STA_ASSERT_MSG(IS_THREAD_USER_FLAGS(flags), "Only user flags allowed"); STA_ASSERT_MSG(IS_THREAD_USER_FLAGS(flags), "Only user flags allowed");
osThreadFlagsSet(handle_.get(), flags); osThreadFlagsSet(instance_, flags);
} }
void RtosThread::sysNotify(uint32_t flags) void RtosThread::sysNotify(uint32_t flags)
{ {
STA_ASSERT(handle_.get() != nullptr); STA_ASSERT(instance_ != NULL);
STA_ASSERT_MSG(IS_THREAD_SYS_FLAGS(flags), "Only system flags allowed"); STA_ASSERT_MSG(IS_THREAD_SYS_FLAGS(flags), "Only system flags allowed");
uint32_t rslt = osThreadFlagsSet(handle_.get(), flags); uint32_t rslt = osThreadFlagsSet(instance_, flags);
STA_ASSERT_MSG(rslt != osFlagsErrorUnknown, "Unknown thread flag error."); STA_ASSERT_MSG(rslt != osFlagsErrorUnknown, "Unknown thread flag error.");
STA_ASSERT_MSG(rslt != osFlagsErrorParameter, "Parameter thread_id is not a valid thread or flags has highest bit set."); STA_ASSERT_MSG(rslt != osFlagsErrorParameter, "Parameter thread_id is not a valid thread or flags has highest bit set.");
@ -44,11 +73,19 @@ namespace sta
uint32_t RtosThread::wait(uint32_t flags) uint32_t RtosThread::wait(uint32_t flags)
{ {
// Make sure that the calling thread is this thread. If not, the
// developer very likely has made a mistake.
STA_ASSERT(osThreadGetId() == instance_);
return osThreadFlagsWait(flags, osFlagsWaitAny, osWaitForever); return osThreadFlagsWait(flags, osFlagsWaitAny, osWaitForever);
} }
uint32_t RtosThread::clear(uint32_t flags) uint32_t RtosThread::clear(uint32_t flags)
{ {
// Make sure that the calling thread is this thread. If not, the
// developer very likely has made a mistake.
STA_ASSERT(osThreadGetId() == instance_);
uint32_t setFlags = osThreadFlagsClear(flags); uint32_t setFlags = osThreadFlagsClear(flags);
STA_ASSERT(setFlags != (uint32_t)osError); STA_ASSERT(setFlags != (uint32_t)osError);
@ -58,29 +95,17 @@ namespace sta
uint32_t RtosThread::getFlags() uint32_t RtosThread::getFlags()
{ {
STA_ASSERT(handle_.get() != nullptr); // Make sure that the calling thread is this thread. If not, the
// developer very likely has made a mistake.
STA_ASSERT(osThreadGetId() == instance_);
return osThreadFlagsGet(); return osThreadFlagsGet();
} }
void RtosThread::requestTermination()
{
terminate_ = true;
}
void RtosThread::deleteTerminationRequest()
{
terminate_ = false;
}
bool RtosThread::isTerminationRequested()
{
return terminate_;
}
void RtosThread::kill() void RtosThread::kill()
{ {
STA_ASSERT(handle_.get() != nullptr); STA_ASSERT(instance_ != NULL);
osThreadTerminate(handle_.get()); osThreadTerminate(instance_);
instance_ = NULL;
} }
} // namespace sta } // namespace sta