mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-07 16:23:38 +03:00
add regular scheduled functions, now also callable on yield()
(#6039)
* add regular scheduled functions, now also callable on `yield()` added bool schedule_function_us(std::function<bool(void)> fn, uint32_t repeat_us) lambda must return true to be not removed from the schedule function list if repeat_us is 0, then the function is called only once. Legacy schedule_function() is preserved This addition allows network drivers like ethernet chips on lwIP to be regularly called - even if some user code loops on receiving data without getting out from main loop (callable from yield()) - without the need to call the driver handling function (transparent) This may be also applicable with common libraries (mDNS, Webserver, )
This commit is contained in:
parent
6191fbbd92
commit
b55199227b
@ -213,7 +213,8 @@ uint32_t EspClass::getCycleCount()
|
|||||||
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
||||||
return ccount;
|
return ccount;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif // !defined(CORE_MOCK)
|
||||||
|
|
||||||
extern EspClass ESP;
|
extern EspClass ESP;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include <FunctionalInterrupt.h>
|
#include <FunctionalInterrupt.h>
|
||||||
#include <Schedule.h>
|
#include <Schedule.h>
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <ScheduledFunctions.h>
|
|
||||||
|
|
||||||
// Duplicate typedefs from core_esp8266_wiring_digital_c
|
// Duplicate typedefs from core_esp8266_wiring_digital_c
|
||||||
typedef void (*voidFuncPtr)(void);
|
typedef void (*voidFuncPtr)(void);
|
||||||
@ -17,7 +16,6 @@ void ICACHE_RAM_ATTR interruptFunctional(void* arg)
|
|||||||
if (localArg->functionInfo->reqScheduledFunction)
|
if (localArg->functionInfo->reqScheduledFunction)
|
||||||
{
|
{
|
||||||
schedule_function(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo))));
|
schedule_function(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo))));
|
||||||
// scheduledInterrupts->scheduleFunctionReg(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo))), false, true);
|
|
||||||
}
|
}
|
||||||
if (localArg->functionInfo->reqFunction)
|
if (localArg->functionInfo->reqFunction)
|
||||||
{
|
{
|
||||||
@ -54,10 +52,6 @@ void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode
|
|||||||
|
|
||||||
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
|
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
|
||||||
{
|
{
|
||||||
if (!scheduledInterrupts)
|
|
||||||
{
|
|
||||||
scheduledInterrupts = new ScheduledFunctions(32);
|
|
||||||
}
|
|
||||||
InterruptInfo* ii = new InterruptInfo;
|
InterruptInfo* ii = new InterruptInfo;
|
||||||
|
|
||||||
FunctionInfo* fi = new FunctionInfo;
|
FunctionInfo* fi = new FunctionInfo;
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <ScheduledFunctions.h>
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
@ -29,7 +28,6 @@ struct ArgStructure {
|
|||||||
FunctionInfo* functionInfo = nullptr;
|
FunctionInfo* functionInfo = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ScheduledFunctions* scheduledInterrupts;
|
|
||||||
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
|
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
|
||||||
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode);
|
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode);
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public:
|
|||||||
reset(userTimeout);
|
reset(userTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
ICACHE_RAM_ATTR
|
IRAM_ATTR // fast
|
||||||
bool expired()
|
bool expired()
|
||||||
{
|
{
|
||||||
YieldPolicyT::execute(); //in case of DoNothing: gets optimized away
|
YieldPolicyT::execute(); //in case of DoNothing: gets optimized away
|
||||||
@ -162,7 +162,7 @@ public:
|
|||||||
return expiredOneShot();
|
return expiredOneShot();
|
||||||
}
|
}
|
||||||
|
|
||||||
ICACHE_RAM_ATTR
|
IRAM_ATTR // fast
|
||||||
operator bool()
|
operator bool()
|
||||||
{
|
{
|
||||||
return expired();
|
return expired();
|
||||||
@ -178,6 +178,7 @@ public:
|
|||||||
return _timeout != alwaysExpired;
|
return _timeout != alwaysExpired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR // called from ISR
|
||||||
void reset(const timeType newUserTimeout)
|
void reset(const timeType newUserTimeout)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
@ -185,6 +186,7 @@ public:
|
|||||||
_neverExpires = (newUserTimeout < 0) || (newUserTimeout > timeMax());
|
_neverExpires = (newUserTimeout < 0) || (newUserTimeout > timeMax());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR // called from ISR
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
_start = TimePolicyT::time();
|
_start = TimePolicyT::time();
|
||||||
@ -208,7 +210,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ICACHE_RAM_ATTR
|
IRAM_ATTR // fast
|
||||||
bool checkExpired(const timeType internalUnit) const
|
bool checkExpired(const timeType internalUnit) const
|
||||||
{
|
{
|
||||||
// canWait() is not checked here
|
// canWait() is not checked here
|
||||||
@ -218,7 +220,7 @@ private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
ICACHE_RAM_ATTR
|
IRAM_ATTR // fast
|
||||||
bool expiredRetrigger()
|
bool expiredRetrigger()
|
||||||
{
|
{
|
||||||
if (!canWait())
|
if (!canWait())
|
||||||
@ -234,7 +236,7 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICACHE_RAM_ATTR
|
IRAM_ATTR // fast
|
||||||
bool expiredOneShot() const
|
bool expiredOneShot() const
|
||||||
{
|
{
|
||||||
// returns "always expired" or "has expired"
|
// returns "always expired" or "has expired"
|
||||||
|
@ -1,78 +1,131 @@
|
|||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "Schedule.h"
|
#include "Schedule.h"
|
||||||
|
#include "PolledTimeout.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
|
||||||
|
typedef std::function<bool(void)> mFuncT;
|
||||||
|
|
||||||
struct scheduled_fn_t
|
struct scheduled_fn_t
|
||||||
{
|
{
|
||||||
scheduled_fn_t* mNext;
|
scheduled_fn_t* mNext = nullptr;
|
||||||
std::function<void(void)> mFunc;
|
mFuncT mFunc;
|
||||||
|
esp8266::polledTimeout::periodicFastUs callNow;
|
||||||
|
|
||||||
|
scheduled_fn_t() : callNow(esp8266::polledTimeout::periodicFastUs::alwaysExpired) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
static scheduled_fn_t* sFirst = 0;
|
static scheduled_fn_t* sFirst = nullptr;
|
||||||
static scheduled_fn_t* sLast = 0;
|
static scheduled_fn_t* sLast = nullptr;
|
||||||
|
|
||||||
static scheduled_fn_t* sFirstUnused = 0;
|
static scheduled_fn_t* sUnused = nullptr;
|
||||||
static scheduled_fn_t* sLastUnused = 0;
|
|
||||||
|
|
||||||
static int sCount = 0;
|
static int sCount = 0;
|
||||||
|
|
||||||
static scheduled_fn_t* get_fn() {
|
IRAM_ATTR // called from ISR
|
||||||
scheduled_fn_t* result = NULL;
|
static scheduled_fn_t* get_fn_unsafe()
|
||||||
|
{
|
||||||
|
scheduled_fn_t* result = nullptr;
|
||||||
// try to get an item from unused items list
|
// try to get an item from unused items list
|
||||||
if (sFirstUnused) {
|
if (sUnused)
|
||||||
result = sFirstUnused;
|
{
|
||||||
sFirstUnused = result->mNext;
|
result = sUnused;
|
||||||
if (sFirstUnused == NULL) {
|
sUnused = sUnused->mNext;
|
||||||
sLastUnused = NULL;
|
result->mNext = nullptr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// if no unused items, and count not too high, allocate a new one
|
// if no unused items, and count not too high, allocate a new one
|
||||||
else if (sCount != SCHEDULED_FN_MAX_COUNT) {
|
else if (sCount < SCHEDULED_FN_MAX_COUNT)
|
||||||
|
{
|
||||||
result = new scheduled_fn_t;
|
result = new scheduled_fn_t;
|
||||||
result->mNext = NULL;
|
|
||||||
++sCount;
|
++sCount;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void recycle_fn(scheduled_fn_t* fn)
|
static void recycle_fn_unsafe(scheduled_fn_t* fn)
|
||||||
{
|
{
|
||||||
if (!sLastUnused) {
|
fn->mFunc = nullptr; // special overload in c++ std lib
|
||||||
sFirstUnused = fn;
|
fn->mNext = sUnused;
|
||||||
}
|
sUnused = fn;
|
||||||
else {
|
|
||||||
sLastUnused->mNext = fn;
|
|
||||||
}
|
|
||||||
fn->mNext = NULL;
|
|
||||||
sLastUnused = fn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool schedule_function(std::function<void(void)> fn)
|
IRAM_ATTR // (not only) called from ISR
|
||||||
|
bool schedule_function_us(std::function<bool(void)>&& fn, uint32_t repeat_us)
|
||||||
{
|
{
|
||||||
scheduled_fn_t* item = get_fn();
|
assert(repeat_us < decltype(scheduled_fn_t::callNow)::neverExpires); //~26800000us (26.8s)
|
||||||
if (!item) {
|
|
||||||
|
InterruptLock lockAllInterruptsInThisScope;
|
||||||
|
|
||||||
|
scheduled_fn_t* item = get_fn_unsafe();
|
||||||
|
if (!item)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
if (repeat_us)
|
||||||
|
item->callNow.reset(repeat_us);
|
||||||
|
|
||||||
item->mFunc = fn;
|
item->mFunc = fn;
|
||||||
item->mNext = NULL;
|
if (sFirst)
|
||||||
if (!sFirst) {
|
|
||||||
sFirst = item;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sLast->mNext = item;
|
sLast->mNext = item;
|
||||||
}
|
else
|
||||||
|
sFirst = item;
|
||||||
sLast = item;
|
sLast = item;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR // (not only) called from ISR
|
||||||
|
bool schedule_function_us(const std::function<bool(void)>& fn, uint32_t repeat_us)
|
||||||
|
{
|
||||||
|
return schedule_function_us(std::function<bool(void)>(fn), repeat_us);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR // called from ISR
|
||||||
|
bool schedule_function(std::function<void(void)>&& fn)
|
||||||
|
{
|
||||||
|
return schedule_function_us([fn]() { fn(); return false; }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR // called from ISR
|
||||||
|
bool schedule_function(const std::function<void(void)>& fn)
|
||||||
|
{
|
||||||
|
return schedule_function(std::function<void(void)>(fn));
|
||||||
|
}
|
||||||
|
|
||||||
void run_scheduled_functions()
|
void run_scheduled_functions()
|
||||||
{
|
{
|
||||||
scheduled_fn_t* rFirst = sFirst;
|
// Note to the reader:
|
||||||
sFirst = NULL;
|
// There is no exposed API to remove a scheduled function:
|
||||||
sLast = NULL;
|
// Scheduled functions are removed only from this function, and
|
||||||
while (rFirst) {
|
// its purpose is that it is never called from an interrupt
|
||||||
scheduled_fn_t* item = rFirst;
|
// (always on cont stack).
|
||||||
rFirst = item->mNext;
|
|
||||||
item->mFunc();
|
scheduled_fn_t* lastRecurring = nullptr;
|
||||||
item->mFunc = std::function<void(void)>();
|
scheduled_fn_t* toCall = sFirst;
|
||||||
recycle_fn(item);
|
while (toCall)
|
||||||
|
{
|
||||||
|
scheduled_fn_t* item = toCall;
|
||||||
|
toCall = toCall->mNext;
|
||||||
|
if (item->callNow)
|
||||||
|
{
|
||||||
|
if (item->mFunc())
|
||||||
|
{
|
||||||
|
lastRecurring = item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InterruptLock lockAllInterruptsInThisScope;
|
||||||
|
|
||||||
|
if (sFirst == item)
|
||||||
|
sFirst = sFirst->mNext;
|
||||||
|
else if (lastRecurring)
|
||||||
|
lastRecurring->mNext = item->mNext;
|
||||||
|
|
||||||
|
if (sLast == item)
|
||||||
|
sLast = lastRecurring;
|
||||||
|
|
||||||
|
recycle_fn_unsafe(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,20 +4,26 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#define SCHEDULED_FN_MAX_COUNT 32
|
#define SCHEDULED_FN_MAX_COUNT 32
|
||||||
#define SCHEDULED_FN_INITIAL_COUNT 4
|
|
||||||
|
|
||||||
// Warning
|
// This API was not considered stable but is now stabilizing.
|
||||||
// This API is not considered stable.
|
// Function signatures may change, queue must stay FIFO.
|
||||||
// Function signatures will change.
|
|
||||||
// You have been warned.
|
// You have been warned.
|
||||||
|
|
||||||
// Run given function next time `loop` function returns,
|
// Run given function ONCE next time `loop` function returns,
|
||||||
|
// or `yield` is called,
|
||||||
// or `run_scheduled_functions` is called.
|
// or `run_scheduled_functions` is called.
|
||||||
// Use std::bind to pass arguments to a function, or call a class member function.
|
// Use std::bind to pass arguments to a function, or call a class member function.
|
||||||
// Note: there is no mechanism for cancelling scheduled functions.
|
// Note: there is no mechanism for cancelling scheduled functions.
|
||||||
// Keep that in mind when binding functions to objects which may have short lifetime.
|
// Keep that in mind when binding functions to objects which may have short lifetime.
|
||||||
// Returns false if the number of scheduled functions exceeds SCHEDULED_FN_MAX_COUNT.
|
// Returns false if the number of scheduled functions exceeds SCHEDULED_FN_MAX_COUNT.
|
||||||
bool schedule_function(std::function<void(void)> fn);
|
//bool schedule_function(std::function<void(void)>&& fn);
|
||||||
|
bool schedule_function(const std::function<void(void)>& fn);
|
||||||
|
|
||||||
|
// Run given function periodically about every <repeat_us> microseconds until it returns false.
|
||||||
|
// Note that it may be more than <repeat_us> microseconds between calls if `yield` is not called
|
||||||
|
// frequently, and therefore should not be used for timing critical operations.
|
||||||
|
//bool schedule_function_us(std::function<bool(void)>&& fn, uint32_t repeat_us);
|
||||||
|
bool schedule_function_us(const std::function<bool(void)>& fn, uint32_t repeat_us);
|
||||||
|
|
||||||
// Run all scheduled functions.
|
// Run all scheduled functions.
|
||||||
// Use this function if your are not using `loop`, or `loop` does not return
|
// Use this function if your are not using `loop`, or `loop` does not return
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* ScheduledFunctions.cpp
|
|
||||||
*
|
|
||||||
* Created on: 27 apr. 2018
|
|
||||||
* Author: Herman
|
|
||||||
*/
|
|
||||||
#include "ScheduledFunctions.h"
|
|
||||||
|
|
||||||
std::list<ScheduledFunctions::ScheduledElement> ScheduledFunctions::scheduledFunctions;
|
|
||||||
|
|
||||||
ScheduledFunctions::ScheduledFunctions()
|
|
||||||
:ScheduledFunctions(UINT_MAX)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ScheduledFunctions::ScheduledFunctions(unsigned int reqMax)
|
|
||||||
{
|
|
||||||
maxElements = reqMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScheduledFunctions::~ScheduledFunctions() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ScheduledRegistration ScheduledFunctions::insertElement(ScheduledElement se, bool front)
|
|
||||||
{
|
|
||||||
if (countElements >= maxElements)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
countElements++;
|
|
||||||
if (front)
|
|
||||||
{
|
|
||||||
scheduledFunctions.push_front(se);
|
|
||||||
return scheduledFunctions.begin()->registration;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scheduledFunctions.push_back(se);
|
|
||||||
return scheduledFunctions.rbegin()->registration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<ScheduledFunctions::ScheduledElement>::iterator ScheduledFunctions::eraseElement(std::list<ScheduledFunctions::ScheduledElement>::iterator it)
|
|
||||||
{
|
|
||||||
countElements--;
|
|
||||||
return scheduledFunctions.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScheduledFunctions::scheduleFunction(ScheduledFunction sf, bool continuous, bool front)
|
|
||||||
{
|
|
||||||
return (insertElement({this,continuous,nullptr,sf}, front) == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScheduledFunctions::scheduleFunction(ScheduledFunction sf)
|
|
||||||
{
|
|
||||||
return scheduleFunction(sf, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScheduledRegistration ScheduledFunctions::scheduleFunctionReg (ScheduledFunction sf, bool continuous, bool front)
|
|
||||||
{
|
|
||||||
return insertElement({this,continuous,std::make_shared<int>(1),sf},front);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScheduledFunctions::runScheduledFunctions()
|
|
||||||
{
|
|
||||||
auto lastElement = scheduledFunctions.end(); // do not execute elements added during runScheduledFunctions
|
|
||||||
auto it = scheduledFunctions.begin();
|
|
||||||
while (it != lastElement)
|
|
||||||
{
|
|
||||||
bool erase = false;
|
|
||||||
if (it->registration == nullptr)
|
|
||||||
{
|
|
||||||
it->function();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (it->registration.use_count() > 1)
|
|
||||||
{
|
|
||||||
it->function();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
erase = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((!it->continuous) || (erase))
|
|
||||||
{
|
|
||||||
it = it->_this->eraseElement(it);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScheduledFunctions::removeFunction(ScheduledRegistration sr)
|
|
||||||
{
|
|
||||||
auto it = scheduledFunctions.begin();
|
|
||||||
bool removed = false;
|
|
||||||
while ((!removed) && (it != scheduledFunctions.end()))
|
|
||||||
{
|
|
||||||
if (it->registration == sr)
|
|
||||||
{
|
|
||||||
it = eraseElement(it);
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* ScheduledFunctions.h
|
|
||||||
*
|
|
||||||
* Created on: 27 apr. 2018
|
|
||||||
* Author: Herman
|
|
||||||
*/
|
|
||||||
#include "Arduino.h"
|
|
||||||
#include "Schedule.h"
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <list>
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#ifndef SCHEDULEDFUNCTIONS_H_
|
|
||||||
#define SCHEDULEDFUNCTIONS_H_
|
|
||||||
|
|
||||||
typedef std::function<void(void)> ScheduledFunction;
|
|
||||||
typedef std::shared_ptr<void> ScheduledRegistration;
|
|
||||||
|
|
||||||
class ScheduledFunctions {
|
|
||||||
|
|
||||||
public:
|
|
||||||
ScheduledFunctions();
|
|
||||||
ScheduledFunctions(unsigned int reqMax);
|
|
||||||
virtual ~ScheduledFunctions();
|
|
||||||
|
|
||||||
struct ScheduledElement
|
|
||||||
{
|
|
||||||
ScheduledFunctions* _this;
|
|
||||||
bool continuous;
|
|
||||||
ScheduledRegistration registration;
|
|
||||||
ScheduledFunction function;
|
|
||||||
};
|
|
||||||
|
|
||||||
ScheduledRegistration insertElement(ScheduledElement se, bool front);
|
|
||||||
std::list<ScheduledElement>::iterator eraseElement(std::list<ScheduledElement>::iterator);
|
|
||||||
bool scheduleFunction(ScheduledFunction sf, bool continuous, bool front);
|
|
||||||
bool scheduleFunction(ScheduledFunction sf);
|
|
||||||
ScheduledRegistration scheduleFunctionReg (ScheduledFunction sf, bool continuous, bool front);
|
|
||||||
static void runScheduledFunctions();
|
|
||||||
void removeFunction(ScheduledRegistration sr);
|
|
||||||
|
|
||||||
|
|
||||||
static std::list<ScheduledElement> scheduledFunctions;
|
|
||||||
unsigned int maxElements;
|
|
||||||
unsigned int countElements = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* SCHEDULEDFUNCTIONS_H_ */
|
|
@ -91,13 +91,15 @@ extern "C" void esp_yield() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void esp_schedule() {
|
extern "C" void esp_schedule() {
|
||||||
|
// always on CONT stack here
|
||||||
|
run_scheduled_functions();
|
||||||
ets_post(LOOP_TASK_PRIORITY, 0, 0);
|
ets_post(LOOP_TASK_PRIORITY, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void __yield() {
|
extern "C" void __yield() {
|
||||||
if (cont_can_yield(g_pcont)) {
|
if (cont_can_yield(g_pcont)) {
|
||||||
esp_schedule();
|
esp_schedule();
|
||||||
esp_yield();
|
cont_yield(g_pcont); //esp_yield();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
panic();
|
panic();
|
||||||
@ -122,7 +124,6 @@ static void loop_wrapper() {
|
|||||||
setup_done = true;
|
setup_done = true;
|
||||||
}
|
}
|
||||||
loop();
|
loop();
|
||||||
run_scheduled_functions();
|
|
||||||
esp_schedule();
|
esp_schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,26 +143,12 @@ extern "C" {
|
|||||||
#define __STRINGIFY(a) #a
|
#define __STRINGIFY(a) #a
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// these low level routines provide a replacement for SREG interrupt save that AVR uses
|
#define xt_rsil(level) (level)
|
||||||
// but are esp8266 specific. A normal use pattern is like
|
#define xt_wsr_ps(state) do { (void)(state); } while (0)
|
||||||
//
|
|
||||||
//{
|
|
||||||
// uint32_t savedPS = xt_rsil(1); // this routine will allow level 2 and above
|
|
||||||
// // do work here
|
|
||||||
// xt_wsr_ps(savedPS); // restore the state
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
// level (0-15), interrupts of the given level and above will be active
|
|
||||||
// level 15 will disable ALL interrupts,
|
|
||||||
// level 0 will enable ALL interrupts,
|
|
||||||
//
|
|
||||||
#define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;}))
|
|
||||||
#define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
|
|
||||||
|
|
||||||
#define interrupts() xt_rsil(0)
|
#define interrupts() xt_rsil(0)
|
||||||
#define noInterrupts() xt_rsil(15)
|
#define noInterrupts() xt_rsil(15)
|
||||||
|
|
||||||
|
|
||||||
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||||
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
||||||
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
||||||
|
@ -102,6 +102,9 @@ typedef enum {
|
|||||||
#define ICACHE_RODATA_ATTR
|
#define ICACHE_RODATA_ATTR
|
||||||
#endif /* ICACHE_FLASH */
|
#endif /* ICACHE_FLASH */
|
||||||
|
|
||||||
|
// counterpart https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp8266-compat.h
|
||||||
|
#define IRAM_ATTR ICACHE_RAM_ATTR
|
||||||
|
|
||||||
#define STORE_ATTR __attribute__((aligned(4)))
|
#define STORE_ATTR __attribute__((aligned(4)))
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
|
@ -131,8 +131,6 @@ void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize);
|
|||||||
class UdpContext;
|
class UdpContext;
|
||||||
void register_udp (int sock, UdpContext* udp = nullptr);
|
void register_udp (int sock, UdpContext* udp = nullptr);
|
||||||
|
|
||||||
class InterruptLock { };
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb = 8, size_t page_b = 512);
|
void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb = 8, size_t page_b = 512);
|
||||||
|
@ -93,6 +93,9 @@ typedef enum {
|
|||||||
#define ICACHE_RAM_ATTR
|
#define ICACHE_RAM_ATTR
|
||||||
#endif /* ICACHE_FLASH */
|
#endif /* ICACHE_FLASH */
|
||||||
|
|
||||||
|
// counterpart https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp8266-compat.h
|
||||||
|
#define IRAM_ATTR ICACHE_RAM_ATTR
|
||||||
|
|
||||||
#define STORE_ATTR __attribute__((aligned(4)))
|
#define STORE_ATTR __attribute__((aligned(4)))
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
|
Loading…
x
Reference in New Issue
Block a user