coroutines: wip compiles but does not link

1.2-legacy
Kevin Hester 2020-10-09 14:16:51 +08:00
rodzic 10f64590a9
commit 2044427e97
23 zmienionych plików z 132 dodań i 299 usunięć

Wyświetl plik

@ -30,6 +30,7 @@ build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/n
-DHW_VERSION_${sysenv.COUNTRY}
-DAPP_VERSION=${sysenv.APP_VERSION}
-DHW_VERSION=${sysenv.HW_VERSION}
-DUSE_THREAD_NAMES
; leave this commented out to avoid breaking Windows
;upload_port = /dev/ttyUSB0

Wyświetl plik

@ -62,6 +62,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual bool isBatteryConnect() { return getBattVoltage() != -1; }
} analogLevel;
Power::Power() : OSThread("Power") {}
bool Power::analogInit()
{
#ifdef BATTERY_PIN
@ -86,10 +88,7 @@ bool Power::setup()
if (!found) {
found = analogInit();
}
if (found) {
concurrency::PeriodicTask::setup(); // We don't start our periodic task unless we actually found the device
setPeriod(1);
}
enabled = found;
return found;
}
@ -135,13 +134,46 @@ void Power::readPowerStatus()
}
}
void Power::doTask()
uint32_t Power::runOnce()
{
readPowerStatus();
#ifdef PMU_IRQ
if (pmu_irq) {
pmu_irq = false;
axp.readIRQ();
DEBUG_MSG("pmu irq!\n");
if (axp.isChargingIRQ()) {
DEBUG_MSG("Battery start charging\n");
}
if (axp.isChargingDoneIRQ()) {
DEBUG_MSG("Battery fully charged\n");
}
if (axp.isVbusRemoveIRQ()) {
DEBUG_MSG("USB unplugged\n");
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
}
if (axp.isVbusPlugInIRQ()) {
DEBUG_MSG("USB plugged In\n");
powerFSM.trigger(EVENT_POWER_CONNECTED);
}
if (axp.isBattPlugInIRQ()) {
DEBUG_MSG("Battery inserted\n");
}
if (axp.isBattRemoveIRQ()) {
DEBUG_MSG("Battery removed\n");
}
if (axp.isPEKShortPressIRQ()) {
DEBUG_MSG("PEK short button press\n");
}
axp.clearIRQ();
}
#endif
// Only read once every 20 seconds once the power status for the app has been initialized
if (statusHandler && statusHandler->isInitialized())
setPeriod(1000 * 20);
return (statusHandler && statusHandler->isInitialized()) ? (1000 * 20) : 0;
}
/**
@ -208,8 +240,7 @@ bool Power::axp192Init()
// no battery also it could cause inadvertent waking from light sleep just because the battery filled
// we don't look for AXP202_BATT_REMOVED_IRQ because it occurs repeatedly while no battery installed
// we don't look at AXP202_VBUS_REMOVED_IRQ because we don't have anything hooked to vbus
axp.enableIRQ(AXP202_BATT_CONNECT_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_PEK_SHORTPRESS_IRQ,
1);
axp.enableIRQ(AXP202_BATT_CONNECT_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1);
axp.clearIRQ();
#endif
@ -226,43 +257,3 @@ bool Power::axp192Init()
return false;
#endif
}
void Power::loop()
{
#ifdef PMU_IRQ
if (pmu_irq) {
pmu_irq = false;
axp.readIRQ();
DEBUG_MSG("pmu irq!\n");
if (axp.isChargingIRQ()) {
DEBUG_MSG("Battery start charging\n");
}
if (axp.isChargingDoneIRQ()) {
DEBUG_MSG("Battery fully charged\n");
}
if (axp.isVbusRemoveIRQ()) {
DEBUG_MSG("USB unplugged\n");
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
}
if (axp.isVbusPlugInIRQ()) {
DEBUG_MSG("USB plugged In\n");
powerFSM.trigger(EVENT_POWER_CONNECTED);
}
if (axp.isBattPlugInIRQ()) {
DEBUG_MSG("Battery inserted\n");
}
if (axp.isBattRemoveIRQ()) {
DEBUG_MSG("Battery removed\n");
}
if (axp.isPEKShortPressIRQ()) {
DEBUG_MSG("PEK short button press\n");
}
readPowerStatus();
axp.clearIRQ();
}
#endif
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -1,6 +1,5 @@
#pragma once
#include "../concurrency/PeriodicTask.h"
#include "GPS.h"
#include "Observer.h"
#include "TinyGPS++.h"

Wyświetl plik

@ -561,7 +561,7 @@ void _screen_header()
}
#endif
Screen::Screen(uint8_t address, int sda, int scl) : cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev) {}
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev) {}
void Screen::handleSetOn(bool on)
{
@ -573,9 +573,12 @@ void Screen::handleSetOn(bool on)
DEBUG_MSG("Turning on screen\n");
dispdev.displayOn();
dispdev.displayOn();
enabled = true;
setInterval(0); // Draw ASAP
} else {
DEBUG_MSG("Turning off screen\n");
dispdev.displayOff();
enabled = false;
}
screenOn = on;
}
@ -583,8 +586,6 @@ void Screen::handleSetOn(bool on)
void Screen::setup()
{
concurrency::PeriodicTask::setup();
// We don't set useDisplay until setup() is called, because some boards have a declaration of this object but the device
// is never found when probing i2c and therefore we don't call setup and never want to do (invalid) accesses to this device.
useDisplay = true;
@ -642,12 +643,12 @@ void Screen::setup()
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
}
void Screen::doTask()
uint32_t Screen::runOnce()
{
// If we don't have a screen, don't ever spend any CPU for us.
if (!useDisplay) {
setPeriod(0);
return;
enabled = false;
return 0;
}
// Process incoming commands.
@ -684,8 +685,8 @@ void Screen::doTask()
if (!screenOn) { // If we didn't just wake and the screen is still off, then
// stop updating until it is on again
setPeriod(0);
return;
enabled = false;
return 0;
}
// Switch to a low framerate (to save CPU) when we are not in transition
@ -711,7 +712,7 @@ void Screen::doTask()
// soon, otherwise just 1 fps (to save CPU) We also ask to be called twice
// as fast as we really need so that any rounding errors still result with
// the correct framerate
setPeriod(1000 / targetFramerate);
return (1000 / targetFramerate);
}
void Screen::drawDebugInfoTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
@ -801,7 +802,7 @@ void Screen::handleOnPress()
// If screen was off, just wake it, otherwise advance to next frame
// If we are in a transition, the press must have bounced, drop it.
if (ui.getUiState()->frameState == FIXED) {
setPeriod(1); // redraw ASAP
setInterval(0); // redraw ASAP
ui.nextFrame();
DEBUG_MSG("Setting fast framerate\n");
@ -1062,7 +1063,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
if (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
setFrames(); // Regen the list of screens
prevFrame = -1; // Force a GUI update
setPeriod(1); // Update the screen right away
setInterval(0); // Update the screen right away
}
nodeDB.updateGUI = false;
nodeDB.updateTextMessage = false;

Wyświetl plik

@ -15,7 +15,7 @@
#include "TypedQueue.h"
#include "commands.h"
#include "concurrency/LockGuard.h"
#include "concurrency/PeriodicTask.h"
#include "concurrency/OSThread.h"
#include "power.h"
#include <string>
@ -62,7 +62,7 @@ class DebugInfo
* multiple times simultaneously. All state-changing calls are queued and executed
* when the main loop calls us.
*/
class Screen : public concurrency::PeriodicTask
class Screen : public concurrency::OSThread
{
CallbackObserver<Screen, const meshtastic::Status *> powerStatusObserver =
CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate);
@ -184,7 +184,7 @@ class Screen : public concurrency::PeriodicTask
/// Updates the UI.
//
// Called periodically from the main loop.
void doTask() final;
uint32_t runOnce() final;
private:
struct ScreenCmd {
@ -202,7 +202,7 @@ class Screen : public concurrency::PeriodicTask
return true; // claim success if our display is not in use
else {
bool success = cmdQueue.enqueue(cmd, 0);
setPeriod(1); // handle ASAP
setInterval(0); // handle ASAP
return success;
}
}

Wyświetl plik

@ -1,25 +1,3 @@
/*
Main module
# Modified by Kyle T. Gabriel to fix issue with incorrect GPS data for TTNMapper
Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Air530GPS.h"
#include "MeshRadio.h"
@ -27,7 +5,6 @@
#include "NodeDB.h"
#include "PowerFSM.h"
#include "UBloxGPS.h"
#include "concurrency/Periodic.h"
#include "configuration.h"
#include "error.h"
#include "power.h"
@ -36,6 +13,7 @@
// #include "debug.h"
#include "RTC.h"
#include "SPILock.h"
#include "concurrency/Periodic.h"
#include "graphics/Screen.h"
#include "main.h"
#include "meshwifi/meshhttp.h"
@ -134,7 +112,7 @@ static uint32_t ledBlinker()
return powerStatus->getIsCharging() ? 1000 : (ledOn ? 2 : 1000);
}
concurrency::Periodic ledPeriodic(ledBlinker);
concurrency::Periodic ledPeriodic("Blink", ledBlinker);
// Prepare for button presses
#ifdef BUTTON_PIN
@ -203,8 +181,6 @@ void setup()
digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now
#endif
ledPeriodic.setup();
// Hello
DEBUG_MSG("Meshtastic swver=%s, hwver=%s\n", optstr(APP_VERSION), optstr(HW_VERSION));
@ -378,11 +354,8 @@ void loop()
if (gps)
gps->loop(); // FIXME, remove from main, instead block on read
router.loop();
powerFSM.run_machine();
service.loop();
concurrency::periodicScheduler.loop();
// axpDebugOutput.loop();
#ifdef DEBUG_PORT
@ -394,9 +367,6 @@ void loop()
#ifndef NO_ESP32
esp32Loop();
#endif
#ifdef TBEAM_V10
power->loop();
#endif
#ifdef BUTTON_PIN
userButton.tick();

Wyświetl plik

@ -1,7 +1,6 @@
#pragma once
#include "PacketHistory.h"
#include "../concurrency/PeriodicTask.h"
#include "Router.h"
/**

Wyświetl plik

@ -56,7 +56,7 @@ static uint32_t sendOwnerCb()
return getPref_send_owner_interval() * getPref_position_broadcast_secs() * 1000;
}
static concurrency::Periodic sendOwnerPeriod(sendOwnerCb);
static concurrency::Periodic sendOwnerPeriod("SendOwner", sendOwnerCb);
MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE)
{
@ -65,7 +65,6 @@ MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE)
void MeshService::init()
{
sendOwnerPeriod.setup();
nodeDB.init();
if (gps)
@ -227,7 +226,7 @@ void MeshService::handleToRadio(MeshPacket &p)
p.id = generatePacketId(); // If the phone didn't supply one, then pick one
p.rx_time = getValidTime(RTCQualityFromNet); // Record the time the packet arrived from the phone
// (so we update our nodedb for the local node)
// (so we update our nodedb for the local node)
// Send the packet into the mesh
@ -285,7 +284,8 @@ void MeshService::sendOurPosition(NodeNum dest, bool wantReplies)
p->decoded.which_payload = SubPacket_position_tag;
p->decoded.position = node->position;
p->decoded.want_response = wantReplies;
p->decoded.position.time = getValidTime(RTCQualityGPS); // This nodedb timestamp might be stale, so update it if our clock is valid.
p->decoded.position.time =
getValidTime(RTCQualityGPS); // This nodedb timestamp might be stale, so update it if our clock is valid.
sendToMesh(p);
}

Wyświetl plik

@ -91,7 +91,7 @@ void printPacket(const char *prefix, const MeshPacket *p)
DEBUG_MSG(")\n");
}
RadioInterface::RadioInterface()
RadioInterface::RadioInterface() : NotifiedWorkerThread("RadioIf")
{
assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected
@ -120,10 +120,7 @@ bool RadioInterface::init()
// we now expect interfaces to operate in promiscous mode
// radioIf.setThisAddress(nodeDB.getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at constructor
// time.
// we want this thread to run at very high priority, because it is effectively running as a user space ISR
start("radio", RADIO_STACK_SIZE, configMAX_PRIORITIES - 1); // Start our worker thread
return true;
}

Wyświetl plik

@ -117,8 +117,6 @@ class RadioInterface : protected concurrency::NotifiedWorkerThread
*/
size_t beginSending(MeshPacket *p);
virtual void loop() {} // Idle processing
/**
* Some regulatory regions limit xmit power.
* This function should be called by subclasses after setting their desired power. It might lower it

Wyświetl plik

@ -19,7 +19,7 @@ void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint
RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi, PhysicalLayer *_iface)
: concurrency::PeriodicTask(0), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
: module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
{
instance = this;
}
@ -41,7 +41,6 @@ void INTERRUPT_ATTR RadioLibInterface::isrLevel0Common(PendingISR cause)
{
instance->disableInterrupt();
instance->pending = cause;
BaseType_t xHigherPriorityTaskWoken;
instance->notifyFromISR(&xHigherPriorityTaskWoken, cause, eSetValueWithOverwrite);
@ -191,10 +190,8 @@ transmitters that we are potentially stomping on. Requires further thought.
FIXME, the MIN_TX_WAIT_MSEC and MAX_TX_WAIT_MSEC values should be tuned via logic analyzer later.
*/
void RadioLibInterface::loop()
void RadioLibInterface::onNotify(uint32_t notification)
{
pending = ISR_NONE;
switch (notification) {
case ISR_TX:
handleTransmitInterrupt();
@ -229,25 +226,15 @@ void RadioLibInterface::loop()
}
}
void RadioLibInterface::doTask()
{
disable(); // Don't call this callback again
// We use without overwrite, so that if there is already an interrupt pending to be handled, that gets handle properly (the
// ISR handler will restart our timer)
notify(TRANSMIT_DELAY_COMPLETED, eSetValueWithoutOverwrite);
}
void RadioLibInterface::startTransmitTimer(bool withDelay)
{
// If we have work to do and the timer wasn't already scheduled, schedule it now
if (getPeriod() == 0 && !txQueue.isEmpty()) {
if (!txQueue.isEmpty()) {
uint32_t delay =
!withDelay ? 1 : random(MIN_TX_WAIT_MSEC, MAX_TX_WAIT_MSEC); // See documentation for loop() wrt these values
// DEBUG_MSG("xmit timer %d\n", delay);
// DEBUG_MSG("delaying %u\n", delay);
setPeriod(delay);
DEBUG_MSG("delaying %u\n", delay);
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
}
}

Wyświetl plik

@ -1,6 +1,6 @@
#pragma once
#include "../concurrency/PeriodicTask.h"
#include "../concurrency/OSThread.h"
#include "RadioInterface.h"
#ifdef CubeCell_BoardPlus
@ -59,13 +59,11 @@ class LockingModule : public Module
virtual void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes);
};
class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTask
class RadioLibInterface : public RadioInterface
{
/// Used as our notification from the ISR
enum PendingISR { ISR_NONE = 0, ISR_RX, ISR_TX, TRANSMIT_DELAY_COMPLETED };
volatile PendingISR pending = ISR_NONE;
/**
* Raw ISR handler that just calls our polymorphic method
*/
@ -155,7 +153,7 @@ class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTa
static void timerCallback(void *p1, uint32_t p2);
virtual void doTask();
virtual void onNotify(uint32_t notification);
/** start an immediate transmit
* This method is virtual so subclasses can hook as needed, subclasses should not call directly
@ -195,7 +193,5 @@ class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTa
*/
virtual void addReceiveMetadata(MeshPacket *mp) = 0;
virtual void loop(); // Idle processing
virtual void setStandby() = 0;
};

Wyświetl plik

@ -1,7 +1,6 @@
#pragma once
#include "FloodingRouter.h"
#include "../concurrency/PeriodicTask.h"
#include <unordered_map>
/**
@ -80,10 +79,10 @@ class ReliableRouter : public FloodingRouter
virtual ErrorCode send(MeshPacket *p);
/** Do our retransmission handling */
virtual void loop()
virtual uint32_t runOnce()
{
doRetransmissions();
FloodingRouter::loop();
return FloodingRouter::runOnce();
}
protected:

Wyświetl plik

@ -34,7 +34,7 @@ Allocator<MeshPacket> &packetPool = staticPool;
*
* Currently we only allow one interface, that may change in the future
*/
Router::Router() : fromRadioQueue(MAX_RX_FROMRADIO)
Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRADIO)
{
// This is called pre main(), don't touch anything here, the following code is not safe
@ -47,12 +47,14 @@ Router::Router() : fromRadioQueue(MAX_RX_FROMRADIO)
* do idle processing
* Mostly looking in our incoming rxPacket queue and calling handleReceived.
*/
void Router::loop()
uint32_t Router::runOnce()
{
MeshPacket *mp;
while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL) {
perhapsHandleReceived(mp);
}
return 0;
}
/// Generate a unique packet id

Wyświetl plik

@ -5,12 +5,13 @@
#include "Observer.h"
#include "PointerQueue.h"
#include "RadioInterface.h"
#include "concurrency/OSThread.h"
#include "mesh.pb.h"
/**
* A mesh aware router that supports multiple interfaces.
*/
class Router
class Router : protected concurrency::OSThread
{
private:
RadioInterface *iface;
@ -44,7 +45,7 @@ class Router
* do idle processing
* Mostly looking in our incoming rxPacket queue and calling handleReceived.
*/
virtual void loop();
virtual uint32_t runOnce();
/**
* Works like send, but if we are sending to the local node, we directly put the message in the receive queue

Wyświetl plik

@ -1,6 +1,6 @@
#pragma once
#include "PowerStatus.h"
#include "concurrency/PeriodicTask.h"
#include "concurrency/OSThread.h"
/**
* Per @spattinson
@ -15,16 +15,17 @@
#define BAT_MILLIVOLTS_FULL 4100
#define BAT_MILLIVOLTS_EMPTY 3500
class Power : public concurrency::PeriodicTask
class Power : private concurrency::OSThread
{
public:
Observable<const meshtastic::PowerStatus *> newStatus;
Power();
void readPowerStatus();
void loop();
virtual bool setup();
virtual void doTask();
virtual uint32_t runOnce();
void setStatusHandler(meshtastic::PowerStatus *handler) { statusHandler = handler; }
protected: