diff --git a/stm32basic.hpp b/stm32basic.hpp index 014df34..06323b0 100644 --- a/stm32basic.hpp +++ b/stm32basic.hpp @@ -5,4 +5,5 @@ #include "zspi.hpp" #include "zgpio.hpp" #include "ticket.hpp" -#include "zqueue.hpp" \ No newline at end of file +#include "zqueue.hpp" +#include "zthread.hpp" \ No newline at end of file diff --git a/zthread.cpp b/zthread.cpp new file mode 100644 index 0000000..f83748e --- /dev/null +++ b/zthread.cpp @@ -0,0 +1,94 @@ +#include "zthread.hpp" + +#include "mutex.hpp" + +extern "C" { +#include "basic\zlog.h" +} + +using namespace iflytop; +using namespace std; + +static ZThread g_default_thread; + +static void zosthread_default_task(void const *argument) { + ZThread *thread = (ZThread *)argument; + ZASSERT(thread); + thread->threadcb(); +}; + +void ZThread::threadcb() { + m_status = kidle; + + while (true) { + if (m_threadisworkingFlagCallSide) { + m_status = kworking; + if (m_taskfunction) m_taskfunction(); + if (m_taskfunction_exitcb) m_taskfunction_exitcb(); + m_status = kdead; + + while (m_threadisworkingFlagCallSide) { + vTaskDelay(10); + } + m_status = kidle; + } + vTaskDelay(10); + } +} + +void ZThread::init(const char *threadname, int stack_size, osPriority priority) { + // int r_task_create = 0; + ZASSERT(threadname); + + m_lock = xSemaphoreCreateMutex(); + ZASSERT(m_lock); + + m_stacksize = stack_size; + m_uxPriority = osPriorityNormal; + m_taskfunction = nullptr; + m_zthreadstartworkevent = xEventGroupCreate(); + m_name = threadname; + + osThreadDef(zosthread_default_task, zosthread_default_task, m_uxPriority, 0, m_stacksize); + m_defaultTaskHandle = osThreadCreate(osThread(zosthread_default_task), this); + ZASSERT(m_defaultTaskHandle != NULL); +} +void ZThread::start(zosthread_cb_t cb) { start(cb, nullptr); } + +void ZThread::start(zosthread_cb_t cb, zosthread_cb_t exitcb) { + stop(); + + m_taskfunction = cb; + m_taskfunction_exitcb = exitcb; + + ZASSERT(m_taskfunction); + xSemaphoreTake(m_lock, portMAX_DELAY); + m_threadisworkingFlagCallSide = true; + // xEventGroupSetBits(m_zthreadstartworkevent, 0x01); + while (m_status == kidle) { + xTaskNotifyGive(m_defaultTaskHandle); + vTaskDelay(1); + } + xSemaphoreGive(m_lock); +} + +void ZThread::stop() { + xSemaphoreTake(m_lock, portMAX_DELAY); + m_threadisworkingFlagCallSide = false; + // xEventGroupSetBits(m_zthreadstartworkevent, 0x01); + while (m_status != kidle) { + xTaskNotifyGive(m_defaultTaskHandle); + vTaskDelay(1); + } + xSemaphoreGive(m_lock); +} + +void ZThread::sleep(uint32_t ms) { ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(ms)); } +void ZThread::wake() { + BaseType_t state; + if (xPortIsInsideInterrupt()) { + vTaskNotifyGiveFromISR(m_defaultTaskHandle, &state); + } else { + xTaskNotifyGive(m_defaultTaskHandle); + } +} diff --git a/zthread.hpp b/zthread.hpp new file mode 100644 index 0000000..8eb8c29 --- /dev/null +++ b/zthread.hpp @@ -0,0 +1,54 @@ +#pragma once +#include +extern "C" { +#include "cmsis_os.h" +} +namespace iflytop { +using namespace std; + +typedef function zosthread_cb_t; + +class ZThread { + public: + typedef enum { + kidle, + kworking, + kdead, + } status_t; + + const char* m_name; + uint32_t m_stacksize; + osPriority m_uxPriority; + + status_t m_status = kidle; + + bool m_threadisworkingFlagCallSide = false; + + zosthread_cb_t m_taskfunction; + zosthread_cb_t m_taskfunction_exitcb; + EventGroupHandle_t m_zthreadstartworkevent; + + osThreadId m_defaultTaskHandle; + + SemaphoreHandle_t m_lock; + + public: + + void init(const char* threadname, int stack_size = 512, osPriority priority = osPriorityNormal); + void start(zosthread_cb_t cb); + void start(zosthread_cb_t cb, zosthread_cb_t exitcb); + void stop(); + + bool getExitFlag() { return !m_threadisworkingFlagCallSide; } + bool isworking() { return m_status == kworking; } + + void wake(); + + static void sleep(uint32_t ms); + + public: + void threadcb(); +}; + + +} // namespace iflytop