Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pluggable Scheduler: Make entry points into sequential cont/user scheduler weak functions #6182

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 10 additions & 20 deletions cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
//This may be used to change user task stack size:
//#define CONT_STACKSIZE 4096
#include <Arduino.h>
#include "Schedule.h"
extern "C" {
#include "ets_sys.h"
#include "os_type.h"
Expand All @@ -40,7 +39,6 @@ extern "C" {
#define OPTIMISTIC_YIELD_TIME_US 16000

extern "C" void call_user_start();
extern void loop();
extern void setup();
extern void (*__init_array_start)(void);
extern void (*__init_array_end)(void);
Expand Down Expand Up @@ -90,19 +88,15 @@ void preloop_update_frequency() {
#endif
}


static inline void esp_yield_within_cont() __attribute__((always_inline));
static void esp_yield_within_cont() {
cont_yield(g_pcont);
run_scheduled_recurrent_functions();
}

extern "C" void esp_yield() {
extern "C" void __esp_yield() __attribute__((weak));
extern "C" void __esp_yield() {
if (cont_can_yield(g_pcont)) {
esp_yield_within_cont();
cont_yield(g_pcont);
}
}

extern "C" void esp_yield(void) __attribute__ ((weak, alias("__esp_yield")));

extern "C" void esp_schedule() {
// always on CONT stack here
ets_post(LOOP_TASK_PRIORITY, 0, 0);
Expand All @@ -111,7 +105,7 @@ extern "C" void esp_schedule() {
extern "C" void __yield() {
if (cont_can_yield(g_pcont)) {
esp_schedule();
esp_yield_within_cont();
esp_yield();
}
else {
panic();
Expand Down Expand Up @@ -157,23 +151,19 @@ extern "C" bool IRAM_ATTR ets_post(uint8 prio, ETSSignal sig, ETSParam par) {
return rc;
}

extern "C" void __loop_end (void)
{
run_scheduled_functions();
run_scheduled_recurrent_functions();
extern "C" void esp_loop(void) __attribute__((weak));
extern "C" void esp_loop(void) {
loop();
}

extern "C" void loop_end (void) __attribute__ ((weak, alias("__loop_end")));

static void loop_wrapper() {
static bool setup_done = false;
preloop_update_frequency();
if(!setup_done) {
setup();
setup_done = true;
}
loop();
loop_end();
esp_loop();
esp_schedule();
}

Expand Down
19 changes: 15 additions & 4 deletions cores/esp8266/core_esp8266_wiring_digital.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,21 @@ typedef struct {
bool functional;
} interrupt_handler_t;

//duplicate from functionalInterrupt.h keep in sync
//duplicates from functionalInterrupt.h keep in sync
typedef struct InterruptInfo {
uint8_t pin;
uint8_t value;
uint32_t micro;
} InterruptInfo;

typedef struct {
typedef struct FunctionInfo {
std::function<void(void)> reqFunction;
std::function<void(InterruptInfo)> reqScheduledFunction;
} FunctionInfo;

typedef struct ArgStructure {
InterruptInfo* interruptInfo;
void* functionInfo;
FunctionInfo* functionInfo;
} ArgStructure;

static interrupt_handler_t interrupt_handlers[16] = { {0, 0, 0, 0}, };
Expand Down Expand Up @@ -172,7 +177,13 @@ void ICACHE_RAM_ATTR interrupt_handler(void*)
ETS_GPIO_INTR_ENABLE();
}

extern void cleanupFunctional(void* arg);
static void cleanupFunctional(void* arg)
{
ArgStructure* localArg = (ArgStructure*)arg;
delete localArg->interruptInfo;
delete localArg->functionInfo;
delete localArg;
}

static void set_interrupt_handlers(uint8_t pin, voidFuncPtr userFunc, void* arg, uint8_t mode, bool functional)
{
Expand Down
10 changes: 10 additions & 0 deletions libraries/Schedule/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name=Schedule
version=1.0
author=Ivan Grokhotkov ([email protected])
maintainer=Ivan Grokhotkov ([email protected])
sentence=
paragraph=
category=Other
url=https://github.com/esp8266/Arduino
architectures=esp8266
dot_a_linkage=true
26 changes: 22 additions & 4 deletions cores/esp8266/Schedule.cpp → libraries/Schedule/src/Schedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,27 @@
#include <assert.h>

#include "Schedule.h"
#include "PolledTimeout.h"
#include "interrupts.h"
#include "coredecls.h"
#include <PolledTimeout.h>
#include <interrupts.h>
#include <coredecls.h>

extern "C"
{
void esp_loop()
{
loop();
run_scheduled_functions();
run_scheduled_recurrent_functions();
}

void __esp_yield();

extern "C" void esp_yield()
{
__esp_yield();
run_scheduled_recurrent_functions();
}
}

typedef std::function<void(void)> mSchedFuncT;
struct scheduled_fn_t
Expand Down Expand Up @@ -120,7 +138,7 @@ void run_scheduled_functions ()

if (yieldNow)
{
// because scheduled function are allowed to last:
// because scheduled functions are allowed to last:
// this is yield() in cont stack:
esp_schedule();
cont_yield(g_pcont);
Expand Down
File renamed without changes.
69 changes: 69 additions & 0 deletions libraries/ScheduledInterrupts/examples/Functional/Functional.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <ScheduledInterrupts.h>

#ifndef IRAM_ATTR
#define IRAM_ATTR ICACHE_RAM_ATTR
#endif

#if defined(ESP32)
#define BUTTON1 16
#define BUTTON2 17
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
#define BUTTON1 D4
#define BUTTON2 D3
#else
#define BUTTON1 2
#define BUTTON2 0
#endif

class Button {
public:
Button(const uint8_t reqPin) : _PIN(reqPin) {
pinMode(_PIN, INPUT_PULLUP);
attachInterrupt(_PIN, std::bind(&Button::buttonIsr, this), FALLING);
};
~Button() {
detachInterrupt(_PIN);
}

void IRAM_ATTR buttonIsr() {
_numberKeyPresses += 1;
_pressed = true;
}

uint32_t testResetPressed() {
if (_pressed) {
Serial.printf("Button on pin %u has been pressed %u times\n", _PIN, _numberKeyPresses);
_pressed = false;
}
return _numberKeyPresses;
}

private:
const uint8_t _PIN;
volatile uint32_t _numberKeyPresses = 0;
volatile bool _pressed = false;
};

// Pointers and "new" in setup() are used in this example to simply test
// and demonstrate how an ISR object can be constructed and destructed at runtime,
// including the detach of the ISR from the GPIO.
Button* button1 = nullptr;
Button* button2 = nullptr;

void setup() {
Serial.begin(115200);
Serial.println("ScheduledInterrupts test/example");

button1 = new Button(BUTTON1);
button2 = new Button(BUTTON2);

Serial.println("setup() complete");
}

void loop() {
button1->testResetPressed();
if (nullptr != button2 && 10 < button2->testResetPressed()) {
delete button2;
button2 = nullptr;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <ScheduledInterrupts.h>

#ifndef IRAM_ATTR
#define IRAM_ATTR ICACHE_RAM_ATTR
#endif

#if defined(ESP32)
#define BUTTON1 16
#define BUTTON2 17
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
#define BUTTON1 D4
#define BUTTON2 D3
#else
#define BUTTON1 2
#define BUTTON2 0
#endif

class Button {
public:
Button(const uint8_t reqPin) : _PIN(reqPin) {
pinMode(_PIN, INPUT_PULLUP);
attachScheduledInterrupt(_PIN, [this](const InterruptInfo & ii) {
Serial.print("Pin ");
Serial.println(ii.pin);
buttonIsr();
}, FALLING); // works on ESP8266
};
~Button() {
detachInterrupt(_PIN);
}

void IRAM_ATTR buttonIsr() {
_numberKeyPresses += 1;
_pressed = true;
}

uint32_t testResetPressed() {
if (_pressed) {
Serial.printf("Button on pin %u has been pressed %u times\n", _PIN, _numberKeyPresses);
_pressed = false;
}
return _numberKeyPresses;
}

private:
const uint8_t _PIN;
volatile uint32_t _numberKeyPresses = 0;
volatile bool _pressed = false;
};

// Pointers and "new" in setup() are used in this example to simply test
// and demonstrate how an ISR object can be constructed and destructed at runtime,
// including the detach of the ISR from the GPIO.
Button* button1;
Button* button2;


void setup() {
Serial.begin(115200);
Serial.println("ScheduledInterrupts test/example");

button1 = new Button(BUTTON1);
button2 = new Button(BUTTON2);

Serial.println("setup() complete");
}

void loop() {
button1->testResetPressed();
if (nullptr != button2 && 10 < button2->testResetPressed()) {
delete button2;
button2 = nullptr;
}
}
13 changes: 13 additions & 0 deletions libraries/ScheduledInterrupts/keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#######################################
# Datatypes (KEYWORD1)
#######################################

InterruptInfo KEYWORD1
ArgStructure KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

attachInterrupt KEYWORD2
attachScheduledInterrupt KEYWORD2
10 changes: 10 additions & 0 deletions libraries/ScheduledInterrupts/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name=ScheduledInterrupts
version=1.0
author=hreintke <[email protected]>
maintainer=hreintke <[email protected]>
sentence=C++ functional, scheduled interrupt handling
paragraph=
category=Other
url=https://github.com/esp8266/Arduino
architectures=esp8266
dot_a_linkage=true
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <FunctionalInterrupt.h>
#include "ScheduledInterrupts.h"
#include <Schedule.h>
#include "Arduino.h"
#include <Arduino.h>

// Duplicate typedefs from core_esp8266_wiring_digital_c
typedef void (*voidFuncPtr)(void);
Expand All @@ -23,17 +23,6 @@ void ICACHE_RAM_ATTR interruptFunctional(void* arg)
}
}

extern "C"
{
void cleanupFunctional(void* arg)
{
ArgStructure* localArg = (ArgStructure*)arg;
delete (FunctionInfo*)localArg->functionInfo;
delete (InterruptInfo*)localArg->interruptInfo;
delete localArg;
}
}

void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
{
// use the local interrupt routine which takes the ArgStructure as argument
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef FUNCTIONALINTERRUPT_H
#define FUNCTIONALINTERRUPT_H
#ifndef SCHEDULEDINTERRUPTS_H
#define SCHEDULEDINTERRUPTS_H

#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -31,5 +31,4 @@ struct ArgStructure {
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode);


#endif //INTERRUPTS_H
#endif // SCHEDULEDINTERRUPTS_H
Loading