mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-22 10:42:49 +00:00
coroutines: wip compiles but does not link
This commit is contained in:
@@ -1,37 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "WorkerThread.h"
|
||||
#include "OSThread.h"
|
||||
|
||||
namespace concurrency {
|
||||
namespace concurrency
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A worker thread that waits on a freertos notification
|
||||
*/
|
||||
class NotifiedWorkerThread : public WorkerThread
|
||||
class NotifiedWorkerThread : public OSThread
|
||||
{
|
||||
public:
|
||||
NotifiedWorkerThread(const char *name) : OSThread(name) {}
|
||||
|
||||
/**
|
||||
* Notify this thread so it can run
|
||||
*/
|
||||
virtual void notify(uint32_t v = 0, eNotifyAction action = eNoAction) = 0;
|
||||
void notify(uint32_t v, bool overwrite);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
void notifyFromISR(BaseType_t *highPriWoken, uint32_t v, bool overwrite) { notify(v, overwrite); }
|
||||
|
||||
/**
|
||||
* A method that should block execution - either waiting ona queue/mutex or a "task notification"
|
||||
* Schedule a notification to fire in delay msecs
|
||||
*/
|
||||
virtual void block() = 0;
|
||||
void notifyLater(uint32_t delay, uint32_t v, bool overwrite);
|
||||
|
||||
protected:
|
||||
virtual void onNotify(uint32_t notification) = 0;
|
||||
|
||||
virtual uint32_t runOnce();
|
||||
|
||||
private:
|
||||
/**
|
||||
* The notification that was most recently used to wake the thread. Read from runOnce()
|
||||
*/
|
||||
uint32_t notification = 0;
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Thread.h"
|
||||
#include "freertosinc.h"
|
||||
#include "ThreadController.h"
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
|
||||
extern ThreadController mainController, timerController;
|
||||
|
||||
/**
|
||||
* @brief Base threading
|
||||
*
|
||||
@@ -17,23 +19,32 @@ namespace concurrency
|
||||
* sleeping the correct amount of time in main
|
||||
* NotifiedWorkerThread set/clears enabled
|
||||
*
|
||||
* notifyLater should start now - not relative to last start time
|
||||
* clear notification before calling handler
|
||||
*
|
||||
* stopping sleep instantly as soon as an event occurs.
|
||||
* use global functions delayTillWakeEvent(time), doWakeEvent(isInISR) - use freertos mutex or somesuch
|
||||
*
|
||||
* have router thread block on its message queue in runOnce
|
||||
*
|
||||
* remove lock/lockguard
|
||||
*/
|
||||
class OSThread
|
||||
class OSThread : public Thread
|
||||
{
|
||||
public:
|
||||
virtual ~OSThread() {}
|
||||
ThreadController *controller;
|
||||
|
||||
// uint32_t getStackHighwaterMark() { return uxTaskGetStackHighWaterMark(taskHandle); }
|
||||
public:
|
||||
OSThread(const char *name, uint32_t period = 0, ThreadController *controller = &mainController);
|
||||
|
||||
virtual ~OSThread();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The method that will be called each time our thread gets a chance to run
|
||||
*
|
||||
* Returns desired period for next invocation (or 0 for no change)
|
||||
*/
|
||||
virtual void runOnce() = 0;
|
||||
virtual uint32_t runOnce() = 0;
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "PeriodicTask.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
|
||||
namespace concurrency {
|
||||
namespace concurrency
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Periodically invoke a callback. This just provides C-style callback conventions
|
||||
* @brief Periodically invoke a callback. This just provides C-style callback conventions
|
||||
* rather than a virtual function - FIXME, remove?
|
||||
*/
|
||||
class Periodic : public PeriodicTask
|
||||
class Periodic : public OSThread
|
||||
{
|
||||
uint32_t (*callback)();
|
||||
|
||||
public:
|
||||
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
|
||||
Periodic(uint32_t (*_callback)()) : callback(_callback) {}
|
||||
Periodic(const char *name, uint32_t (*_callback)()) : OSThread(name), callback(_callback) {}
|
||||
|
||||
protected:
|
||||
void doTask() {
|
||||
uint32_t p = callback();
|
||||
setPeriod(p);
|
||||
}
|
||||
uint32_t runOnce() { return callback(); }
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#include "PeriodicTask.h"
|
||||
#include "Periodic.h"
|
||||
#include "LockGuard.h"
|
||||
|
||||
namespace concurrency {
|
||||
|
||||
PeriodicScheduler periodicScheduler;
|
||||
|
||||
PeriodicTask::PeriodicTask(uint32_t initialPeriod) : period(initialPeriod) {}
|
||||
|
||||
void PeriodicTask::setup()
|
||||
{
|
||||
periodicScheduler.schedule(this);
|
||||
}
|
||||
|
||||
} // namespace concurrency
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "PeriodicScheduler.h"
|
||||
|
||||
namespace concurrency {
|
||||
|
||||
/**
|
||||
* @brief A base class for tasks that want their doTask() method invoked periodically
|
||||
*
|
||||
* @todo currently just syntatic sugar for polling in loop (you must call .loop), but eventually
|
||||
* generalize with the freertos scheduler so we can save lots of power by having everything either in
|
||||
* something like this or triggered off of an irq.
|
||||
*/
|
||||
class PeriodicTask
|
||||
{
|
||||
uint32_t lastMsec = 0;
|
||||
uint32_t period = 1; // call soon after creation
|
||||
|
||||
public:
|
||||
virtual ~PeriodicTask() { periodicScheduler.unschedule(this); }
|
||||
|
||||
/**
|
||||
* Constructor (will schedule with the global PeriodicScheduler)
|
||||
*/
|
||||
PeriodicTask(uint32_t initialPeriod = 1);
|
||||
|
||||
/**
|
||||
* MUST be be called once at startup (but after threading is running - i.e. not from a constructor)
|
||||
*/
|
||||
void setup();
|
||||
|
||||
/**
|
||||
* Set a new period in msecs (can be called from doTask or elsewhere and the scheduler will cope)
|
||||
* While zero this task is disabled and will not run
|
||||
*/
|
||||
void setPeriod(uint32_t p)
|
||||
{
|
||||
lastMsec = millis(); // reset starting from now
|
||||
period = p;
|
||||
}
|
||||
|
||||
uint32_t getPeriod() const { return period; }
|
||||
|
||||
/**
|
||||
* Syntatic sugar for suspending tasks
|
||||
*/
|
||||
void disable();
|
||||
|
||||
protected:
|
||||
virtual void doTask() = 0;
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "WorkerThread.h"
|
||||
|
||||
namespace concurrency {
|
||||
|
||||
void WorkerThread::doRun()
|
||||
{
|
||||
startWatchdog();
|
||||
|
||||
while (!wantExit) {
|
||||
stopWatchdog();
|
||||
block();
|
||||
startWatchdog();
|
||||
|
||||
// no need - startWatchdog is guaranteed to give us one full watchdog interval
|
||||
// serviceWatchdog(); // Let our loop worker have one full watchdog interval (at least) to run
|
||||
|
||||
#ifdef DEBUG_STACK
|
||||
static uint32_t lastPrint = 0;
|
||||
if (millis() - lastPrint > 10 * 1000L) {
|
||||
lastPrint = millis();
|
||||
meshtastic::printThreadInfo("net");
|
||||
}
|
||||
#endif
|
||||
|
||||
loop();
|
||||
}
|
||||
|
||||
stopWatchdog();
|
||||
}
|
||||
|
||||
} // namespace concurrency
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "OSThread.h"
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
class WorkerThread : public OSThread
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Return true if this thread is ready to run - either waiting ona queue/mutex or a "task notification"
|
||||
*/
|
||||
virtual bool shouldRun() = 0;
|
||||
|
||||
virtual void loop() = 0;
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
Reference in New Issue
Block a user