diff --git a/platformio.ini b/platformio.ini index cf255f380..0b7ec863e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -68,6 +68,7 @@ lib_deps = https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 Wire ; explicitly needed here because the AXP202 library forgets to add it SPI + https://github.com/geeksville/ArduinoThread.git ; Common settings for conventional (non Portduino) Ardino targets [arduino_base] diff --git a/src/concurrency/BaseNotifiedWorkerThread.h b/src/concurrency/BaseNotifiedWorkerThread.h deleted file mode 100644 index 03b82c4b0..000000000 --- a/src/concurrency/BaseNotifiedWorkerThread.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "WorkerThread.h" - -namespace concurrency { - -/** - * @brief A worker thread that waits on a freertos notification - */ -class BaseNotifiedWorkerThread : public WorkerThread -{ - public: - /** - * Notify this thread so it can run - */ - virtual void notify(uint32_t v = 0, eNotifyAction action = eNoAction) = 0; - - /** - * Notify from an ISR - * - * This must be inline or IRAM_ATTR on ESP32 - */ - virtual void notifyFromISR(BaseType_t *highPriWoken, uint32_t v = 0, eNotifyAction action = eNoAction) { notify(v, action); } - - protected: - /** - * The notification that was most recently used to wake the thread. Read from loop() - */ - uint32_t notification = 0; - - /** - * What notification bits should be cleared just after we read and return them in notification? - * - * Defaults to clear all of them. - */ - uint32_t clearOnRead = UINT32_MAX; - - /** - * A method that should block execution - either waiting ona queue/mutex or a "task notification" - */ - virtual void block() = 0; -}; - -} // namespace concurrency diff --git a/src/concurrency/BaseThread.cpp b/src/concurrency/BaseThread.cpp deleted file mode 100644 index 5f304b5fe..000000000 --- a/src/concurrency/BaseThread.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "BaseThread.h" -#include - -namespace concurrency -{ - -void BaseThread::callRun(void *_this) -{ - ((BaseThread *)_this)->doRun(); -} - -} // namespace concurrency diff --git a/src/concurrency/BaseThread.h b/src/concurrency/BaseThread.h deleted file mode 100644 index b1947cf45..000000000 --- a/src/concurrency/BaseThread.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include - -#include "freertosinc.h" - -namespace concurrency -{ - -/** - * @brief Base threading - */ -class BaseThread -{ - protected: - /** - * set this to true to ask thread to cleanly exit asap - */ - volatile bool wantExit = false; - - public: - virtual void start(const char *name, size_t stackSize = 1024, uint32_t priority = tskIDLE_PRIORITY) = 0; - - virtual ~BaseThread() {} - - // uint32_t getStackHighwaterMark() { return uxTaskGetStackHighWaterMark(taskHandle); } - - protected: - /** - * The method that will be called when start is called. - */ - virtual void doRun() = 0; - - /** - * All thread run methods must periodically call serviceWatchdog, or the system will declare them hung and panic. - * - * this only applies after startWatchdog() has been called. If you need to sleep for a long time call stopWatchdog() - */ - virtual void serviceWatchdog() {} - virtual void startWatchdog() {} - virtual void stopWatchdog() {} - - static void callRun(void *_this); -}; - -} // namespace concurrency diff --git a/src/concurrency/FreeRtosNotifiedWorkerThread.cpp b/src/concurrency/FreeRtosNotifiedWorkerThread.cpp deleted file mode 100644 index 8fec432dc..000000000 --- a/src/concurrency/FreeRtosNotifiedWorkerThread.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "NotifiedWorkerThread.h" - -#ifdef HAS_FREE_RTOS - -namespace concurrency { - -/** - * Notify this thread so it can run - */ -void FreeRtosNotifiedWorkerThread::notify(uint32_t v, eNotifyAction action) -{ - xTaskNotify(taskHandle, v, action); -} - -void FreeRtosNotifiedWorkerThread::block() -{ - xTaskNotifyWait(0, // don't clear notification on entry - clearOnRead, ¬ification, portMAX_DELAY); // Wait forever -} - -} // namespace concurrency - -#endif \ No newline at end of file diff --git a/src/concurrency/FreeRtosNotifiedWorkerThread.h b/src/concurrency/FreeRtosNotifiedWorkerThread.h deleted file mode 100644 index c18009e43..000000000 --- a/src/concurrency/FreeRtosNotifiedWorkerThread.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "BaseNotifiedWorkerThread.h" - -#ifdef HAS_FREE_RTOS - -namespace concurrency { - -/** - * @brief A worker thread that waits on a freertos notification - */ -class FreeRtosNotifiedWorkerThread : public BaseNotifiedWorkerThread -{ - public: - /** - * Notify this thread so it can run - */ - void notify(uint32_t v = 0, eNotifyAction action = eNoAction); - - /** - * Notify from an ISR - * - * This must be inline or IRAM_ATTR on ESP32 - */ - inline void notifyFromISR(BaseType_t *highPriWoken, uint32_t v = 0, eNotifyAction action = eNoAction) - { - xTaskNotifyFromISR(taskHandle, v, action, highPriWoken); - } - - protected: - - /** - * A method that should block execution - either waiting ona queue/mutex or a "task notification" - */ - virtual void block(); -}; - -} // namespace concurrency - -#endif \ No newline at end of file diff --git a/src/concurrency/FreeRtosThread.cpp b/src/concurrency/FreeRtosThread.cpp deleted file mode 100644 index 1fe7108e3..000000000 --- a/src/concurrency/FreeRtosThread.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "FreeRtosThread.h" - -#ifdef HAS_FREE_RTOS - -#include - -#ifdef ARDUINO_ARCH_ESP32 -#include "esp_task_wdt.h" -#endif - -namespace concurrency -{ - -void FreeRtosThread::start(const char *name, size_t stackSize, uint32_t priority) -{ - auto r = xTaskCreate(callRun, name, stackSize, this, priority, &taskHandle); - assert(r == pdPASS); -} - -void FreeRtosThread::serviceWatchdog() -{ -#ifdef ARDUINO_ARCH_ESP32 - esp_task_wdt_reset(); -#endif -} - -void FreeRtosThread::startWatchdog() -{ -#ifdef ARDUINO_ARCH_ESP32 - auto r = esp_task_wdt_add(taskHandle); - assert(r == ESP_OK); -#endif -} - -void FreeRtosThread::stopWatchdog() -{ -#ifdef ARDUINO_ARCH_ESP32 - auto r = esp_task_wdt_delete(taskHandle); - assert(r == ESP_OK); -#endif -} - -} // namespace concurrency - -#endif \ No newline at end of file diff --git a/src/concurrency/FreeRtosThread.h b/src/concurrency/FreeRtosThread.h deleted file mode 100644 index 6f52119db..000000000 --- a/src/concurrency/FreeRtosThread.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "BaseThread.h" -#include "freertosinc.h" - -#ifdef HAS_FREE_RTOS - -namespace concurrency -{ - -/** - * @brief Base threading - */ -class FreeRtosThread : public BaseThread -{ - protected: - TaskHandle_t taskHandle = NULL; - - public: - void start(const char *name, size_t stackSize = 1024, uint32_t priority = tskIDLE_PRIORITY); - - virtual ~FreeRtosThread() { vTaskDelete(taskHandle); } - - // uint32_t getStackHighwaterMark() { return uxTaskGetStackHighWaterMark(taskHandle); } - - protected: - /** - * The method that will be called when start is called. - */ - virtual void doRun() = 0; - - /** - * All thread run methods must periodically call serviceWatchdog, or the system will declare them hung and panic. - * - * this only applies after startWatchdog() has been called. If you need to sleep for a long time call stopWatchdog() - */ - void serviceWatchdog(); - void startWatchdog(); - void stopWatchdog(); -}; - -} // namespace concurrency - -#endif \ No newline at end of file diff --git a/src/concurrency/NotifiedWorkerThread.h b/src/concurrency/NotifiedWorkerThread.h index dee92eb8a..2ec1ea78c 100644 --- a/src/concurrency/NotifiedWorkerThread.h +++ b/src/concurrency/NotifiedWorkerThread.h @@ -1,17 +1,37 @@ #pragma once -#include "FreeRtosNotifiedWorkerThread.h" -#include "PosixNotifiedWorkerThread.h" +#include "WorkerThread.h" -namespace concurrency +namespace concurrency { + +/** + * @brief A worker thread that waits on a freertos notification + */ +class NotifiedWorkerThread : public WorkerThread { + public: + /** + * Notify this thread so it can run + */ + virtual void notify(uint32_t v = 0, eNotifyAction action = eNoAction) = 0; -#ifdef HAS_FREE_RTOS -typedef FreeRtosNotifiedWorkerThread NotifiedWorkerThread; -#endif + /** + * Notify from an ISR + * + * This must be inline or IRAM_ATTR on ESP32 + */ + virtual void notifyFromISR(BaseType_t *highPriWoken, uint32_t v = 0, eNotifyAction action = eNoAction) { notify(v, action); } + + protected: + /** + * The notification that was most recently used to wake the thread. Read from loop() + */ + uint32_t notification = 0; -#ifdef __unix__ -typedef PosixNotifiedWorkerThread NotifiedWorkerThread; -#endif + /** + * A method that should block execution - either waiting ona queue/mutex or a "task notification" + */ + virtual void block() = 0; +}; } // namespace concurrency diff --git a/src/concurrency/OSThread.cpp b/src/concurrency/OSThread.cpp new file mode 100644 index 000000000..0569567c5 --- /dev/null +++ b/src/concurrency/OSThread.cpp @@ -0,0 +1,7 @@ +#include "OSThread.h" +#include + +namespace concurrency +{ + +} // namespace concurrency diff --git a/src/concurrency/OSThread.h b/src/concurrency/OSThread.h index 52ecdf525..3045ba543 100644 --- a/src/concurrency/OSThread.h +++ b/src/concurrency/OSThread.h @@ -1,17 +1,39 @@ #pragma once -#include "FreeRtosThread.h" -#include "PosixThread.h" +#include +#include + +#include "Thread.h" +#include "freertosinc.h" namespace concurrency { -#ifdef HAS_FREE_RTOS -typedef FreeRtosThread OSThread; -#endif +/** + * @brief Base threading + * + * TODO FIXME @geeksville + * basic functionality + * sleeping the correct amount of time in main + * NotifiedWorkerThread set/clears enabled + * + * stopping sleep instantly as soon as an event occurs. + * use global functions delayTillWakeEvent(time), doWakeEvent(isInISR) - use freertos mutex or somesuch + * + * remove lock/lockguard + */ +class OSThread +{ + public: + virtual ~OSThread() {} -#ifdef __unix__ -typedef PosixThread OSThread; -#endif + // uint32_t getStackHighwaterMark() { return uxTaskGetStackHighWaterMark(taskHandle); } + + protected: + /** + * The method that will be called each time our thread gets a chance to run + */ + virtual void runOnce() = 0; +}; } // namespace concurrency diff --git a/src/concurrency/PeriodicScheduler.cpp b/src/concurrency/PeriodicScheduler.cpp deleted file mode 100644 index 5902ddd7a..000000000 --- a/src/concurrency/PeriodicScheduler.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "PeriodicScheduler.h" -#include "PeriodicTask.h" -#include "LockGuard.h" - -namespace concurrency { - -/// call this from loop -void PeriodicScheduler::loop() -{ - LockGuard lg(&lock); - - uint32_t now = millis(); - for (auto t : tasks) { - if (t->period && (now - t->lastMsec) >= t->period) { - - t->doTask(); - t->lastMsec = now; - } - } -} - -void PeriodicScheduler::schedule(PeriodicTask *t) -{ - LockGuard lg(&lock); - tasks.insert(t); -} - -void PeriodicScheduler::unschedule(PeriodicTask *t) -{ - LockGuard lg(&lock); - tasks.erase(t); -} - -} // namespace concurrency diff --git a/src/concurrency/PeriodicScheduler.h b/src/concurrency/PeriodicScheduler.h deleted file mode 100644 index 943da17cb..000000000 --- a/src/concurrency/PeriodicScheduler.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "Lock.h" -#include -#include - -namespace concurrency { - -class PeriodicTask; - -/** - * @brief Runs all PeriodicTasks in the system. Currently called from main loop() - * but eventually should be its own thread blocked on a freertos timer. - */ -class PeriodicScheduler -{ - friend class PeriodicTask; - - /** - * This really should be some form of heap, and when the period gets changed on a task it should get - * rescheduled in that heap. Currently it is just a dumb array and everytime we run loop() we check - * _every_ tasks. If it was a heap we'd only have to check the first task. - */ - std::unordered_set tasks; - - // Protects the above variables. - Lock lock; - - public: - /// Run any next tasks which are due for execution - void loop(); - - private: - void schedule(PeriodicTask *t); - void unschedule(PeriodicTask *t); -}; - -extern PeriodicScheduler periodicScheduler; - -} // namespace concurrency diff --git a/src/concurrency/PeriodicTask.h b/src/concurrency/PeriodicTask.h index 74d4c8a34..4dd127f5b 100644 --- a/src/concurrency/PeriodicTask.h +++ b/src/concurrency/PeriodicTask.h @@ -14,8 +14,6 @@ namespace concurrency { */ class PeriodicTask { - friend class PeriodicScheduler; - uint32_t lastMsec = 0; uint32_t period = 1; // call soon after creation @@ -47,7 +45,7 @@ class PeriodicTask /** * Syntatic sugar for suspending tasks */ - void disable() { setPeriod(0); } + void disable(); protected: virtual void doTask() = 0; diff --git a/src/concurrency/PosixNotifiedWorkerThread.cpp b/src/concurrency/PosixNotifiedWorkerThread.cpp deleted file mode 100644 index e759a871e..000000000 --- a/src/concurrency/PosixNotifiedWorkerThread.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "PosixNotifiedWorkerThread.h" - -#ifdef __unix__ - -#include - -using namespace concurrency; - -/** - * Notify this thread so it can run - */ -void PosixNotifiedWorkerThread::notify(uint32_t v, eNotifyAction action) NOT_IMPLEMENTED("notify"); - -/** - * A method that should block execution - either waiting ona queue/mutex or a "task notification" - */ -void PosixNotifiedWorkerThread::block() NOT_IMPLEMENTED("block"); - -#endif \ No newline at end of file diff --git a/src/concurrency/PosixNotifiedWorkerThread.h b/src/concurrency/PosixNotifiedWorkerThread.h deleted file mode 100644 index d75b74dd8..000000000 --- a/src/concurrency/PosixNotifiedWorkerThread.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "BaseNotifiedWorkerThread.h" - -namespace concurrency { - -/** - * @brief A worker thread that waits on a freertos notification - */ -class PosixNotifiedWorkerThread : public BaseNotifiedWorkerThread -{ - public: - /** - * Notify this thread so it can run - */ - void notify(uint32_t v = 0, eNotifyAction action = eNoAction); - - protected: - - /** - * A method that should block execution - either waiting ona queue/mutex or a "task notification" - */ - virtual void block(); -}; - -} // namespace concurrency diff --git a/src/concurrency/PosixThread.h b/src/concurrency/PosixThread.h deleted file mode 100644 index 3f46ebc08..000000000 --- a/src/concurrency/PosixThread.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "BaseThread.h" - -#ifdef __unix__ - -namespace concurrency -{ - -/** - * @brief Base threading - */ -class PosixThread : public BaseThread -{ - protected: - public: - void start(const char *name, size_t stackSize = 1024, uint32_t priority = tskIDLE_PRIORITY) {} - - virtual ~PosixThread() {} - - // uint32_t getStackHighwaterMark() { return uxTaskGetStackHighWaterMark(taskHandle); } - - protected: - /** - * The method that will be called when start is called. - */ - virtual void doRun() = 0; - -}; - -} // namespace concurrency - -#endif \ No newline at end of file diff --git a/src/concurrency/WorkerThread.h b/src/concurrency/WorkerThread.h index c9b2c6b35..841c41458 100644 --- a/src/concurrency/WorkerThread.h +++ b/src/concurrency/WorkerThread.h @@ -2,10 +2,11 @@ #include "OSThread.h" -namespace concurrency { +namespace concurrency +{ /** - * @brief This wraps threading (FreeRTOS for now) with a blocking API intended for efficiently converting + * @brief This wraps threading (FreeRTOS for now) with a blocking API intended for efficiently converting * old-school arduino loop() code. Use as a mixin base class for the classes you want to convert. * * @link https://www.freertos.org/RTOS_Task_Notification_As_Mailbox.html @@ -14,16 +15,11 @@ class WorkerThread : public OSThread { protected: /** - * A method that should block execution - either waiting ona queue/mutex or a "task notification" + * Return true if this thread is ready to run - either waiting ona queue/mutex or a "task notification" */ - virtual void block() = 0; + virtual bool shouldRun() = 0; virtual void loop() = 0; - - /** - * The method that will be called when start is called. - */ - virtual void doRun(); }; } // namespace concurrency