feat: 全量同步 254 个常用的 Arduino 扩展库文件

This commit is contained in:
yczpf2019
2026-01-24 16:05:38 +08:00
parent c665ba662b
commit 397b9a23a3
6878 changed files with 2732224 additions and 1 deletions

View File

@@ -0,0 +1,99 @@
#include <CoopTaskBase.h>
#include <CoopTask.h>
#include <CoopSemaphore.h>
#include <CoopMutex.h>
#include <BasicCoopTask.h>
#if defined(ARDUINO_attiny)
#define LED_BUILTIN 1
struct DummySerial {
void print(const __FlashStringHelper* s = nullptr) {}
void println(const __FlashStringHelper* s = nullptr) {}
void println(long unsigned int) {}
void flush() {}
};
DummySerial Serial;
#endif
CoopTask<void>* blinkTask = nullptr;
CoopTask<void>* switchTask = nullptr;
void blinkFunction()
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
for (;;)
{
yield(); // A
digitalWrite(LED_BUILTIN, LOW);
delay(5000); // B
digitalWrite(LED_BUILTIN, HIGH);
CoopTask<void>::sleep(); // D
}
}
void switchFunction()
{
for (;;)
{
yield(); // A
Serial.println(F("Switch on"));
delay(100); // B
Serial.println(F("Switch off"));
CoopTask<void>::sleep(); // C
}
}
bool delayCb(uint32_t ms)
{
Serial.print(F("delayDb, ms = "));
Serial.println(ms);
delay(ms);
return true;
}
bool sleepCb()
{
Serial.println(F("sleepCb"));
Serial.flush();
delay(10000);
if (blinkTask) blinkTask->wakeup();
if (switchTask) switchTask->wakeup();
return true;
}
void setup()
{
#if !defined(ARDUINO_attiny)
Serial.begin(74880);
while (!Serial);
delay(100);
Serial.println();
Serial.println(F("runTasks callback test"));
#endif
runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("no tasks yet, sleepCb()?"));
blinkTask = new CoopTask<void>(F("blink"), blinkFunction);
switchTask = new CoopTask<void>(F("switch"), switchFunction);
blinkTask->scheduleTask();
switchTask->scheduleTask();
}
// Add the main program code into the continuous loop() function
void loop()
{
runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("A - both tasks yielded, no Cb?"));
yield();
runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("B - both tasks delayed, delayCb(100)?"));
yield();
runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("C - blink task delayed, switch task sleeping, delayCb(4900)?"));
yield();
runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("D - both tasks sleeping, sleepCb()?"));
}

View File

@@ -0,0 +1,143 @@
/*
Multiple Blinks
Ported to CoopTask from the version that
demonstrates the use of the Scheduler library for the Arduino Due.
CoopTask works on Arduino AVR (including ATtiny), ESP8266, ESP32, ARM Linux and PC OSs.
created 8 Oct 2012
by Cristian Maglie
Modified by
Scott Fitzgerald 19 Oct 2012
Ported to CoopTask by
Dirk O. Kaar 22 Dec 2019
This example code is in the public domain
http://www.arduino.cc/en/Tutorial/MultipleBlinks
*/
// Include CoopTask since we want to manage multiple tasks.
#include <CoopTask.h>
#include <CoopSemaphore.h>
// ATtiny85 max. working memory utilization, AVR 1.8.2 toolchain:
// "Minimum Memory Usage: 357 bytes (70% of a 512 byte maximum)"
#if defined(ARDUINO_attiny)
#define LED_BUILTIN 1
#endif
#if defined(ARDUINO_AVR_MICRO)
#define STACKSIZE_8BIT 92
#else
#define STACKSIZE_8BIT 40
#endif
CoopSemaphore taskSema(1, 1);
int taskToken = 1;
// Task no.1: blink LED with 1 second delay.
void loop1() {
for (;;) // explicitly run forever without returning
{
taskSema.wait();
if (1 != taskToken)
{
taskSema.post();
yield();
continue;
}
for (int i = 0; i < 3; ++i)
{
digitalWrite(LED_BUILTIN, HIGH);
// IMPORTANT:
// When multiple tasks are running 'delay' passes control to
// other tasks while waiting and guarantees they get executed.
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
taskToken = 2;
taskSema.post();
}
}
// Task no.2: blink LED with 0.25 second delay.
void loop2() {
for (;;) // explicitly run forever without returning
{
taskSema.wait();
if (2 != taskToken)
{
taskSema.post();
yield();
continue;
}
for (int i = 0; i < 6; ++i)
{
digitalWrite(LED_BUILTIN, HIGH);
// IMPORTANT:
// When multiple tasks are running 'delay' passes control to
// other tasks while waiting and guarantees they get executed.
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(250);
}
taskToken = 3;
taskSema.post();
}
}
// Task no.3: blink LED with 0.05 second delay.
void loop3() {
for (;;) // explicitly run forever without returning
{
taskSema.wait();
if (3 != taskToken)
{
taskSema.post();
yield();
continue;
}
for (int i = 0; i < 6; ++i)
{
digitalWrite(LED_BUILTIN, HIGH);
// IMPORTANT:
// When multiple tasks are running 'delay' passes control to
// other tasks while waiting and guarantees they get executed.
delay(50);
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
taskToken = 1;
taskSema.post();
}
}
BasicCoopTask<CoopTaskStackAllocatorAsMember<sizeof(unsigned) >= 4 ? 800 : STACKSIZE_8BIT>> task1("l1", loop1);
BasicCoopTask<CoopTaskStackAllocatorAsMember<sizeof(unsigned) >= 4 ? 800 : STACKSIZE_8BIT>> task2("l2", loop2);
BasicCoopTask<CoopTaskStackAllocatorFromLoop<sizeof(unsigned) >= 4 ? 800 : STACKSIZE_8BIT>> task3("l3", loop3, sizeof(unsigned) >= 4 ? 800 : STACKSIZE_8BIT);
void setup() {
//Serial.begin(9600);
// Setup the 3 pins as OUTPUT
pinMode(LED_BUILTIN, OUTPUT);
// Add "loop1", "loop2" and "loop3" to CoopTask scheduling.
// "loop" is always started by default, and is not under the control of CoopTask.
task1.scheduleTask();
task2.scheduleTask();
task3.scheduleTask();
}
void loop() {
// loops forever by default
runCoopTasks();
}

View File

@@ -0,0 +1,451 @@
#include <CoopTask.h>
#include <CoopMutex.h>
#include <CoopSemaphore.h>
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
ESP8266WebServer server(80);
#elif defined(ESP32)
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
WebServer server(80);
#endif
#if !defined(ESP8266) && !defined(ESP32)
#define IRAM_ATTR
#endif
#if defined(ESP8266)
constexpr auto LEDON = LOW;
constexpr auto LEDOFF = HIGH;
#else
constexpr auto LEDON = HIGH;
constexpr auto LEDOFF = LOW;
#endif
#if defined(ESP32)
#define BUTTON1 17
//#define BUTTON1 GPIO_NUM_27
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
#define BUTTON1 D3
#else
#define BUTTON1 0
#endif
#define USE_BUILTIN_TASK_SCHEDULER
// enter your WiFi configuration below
static const char AP_SSID[] PROGMEM = "SSID"; // your router's SSID here
static const char AP_PASS[] PROGMEM = "PSK"; // your router's password here
CoopMutex serialMutex;
CoopSemaphore blinkSema(0);
#if defined(ESP8266) || defined(ESP32)
class Button {
protected:
CoopSemaphore& reportSema;
public:
Button(uint8_t reqPin, CoopSemaphore& _reportSema) : reportSema(_reportSema), pushSema(0), PIN(reqPin) {
pinMode(PIN, INPUT_PULLUP);
attachInterruptArg(PIN, Button::buttonIsr_static, this, FALLING);
};
~Button() {
detachInterrupt(PIN);
}
CoopSemaphore pushSema;
void IRAM_ATTR buttonIsr() {
numberKeyPresses += 1;
pressed = true;
pushSema.post();
reportSema.post();
}
static void IRAM_ATTR buttonIsr_static(void* const self) {
reinterpret_cast<Button*>(self)->buttonIsr();
}
unsigned testResetPressed() {
if (pressed) {
CoopMutexLock serialLock(serialMutex);
Serial.printf_P(PSTR("Button on pin %u has been pressed %u times\n"), PIN, numberKeyPresses);
pressed = false;
}
return numberKeyPresses;
}
private:
const uint8_t PIN;
volatile unsigned numberKeyPresses = 0;
volatile bool pressed = false;
};
#endif
void loopBlink() noexcept
{
for (;;)
{
digitalWrite(LED_BUILTIN, LEDOFF);
blinkSema.wait(1000);
digitalWrite(LED_BUILTIN, LEDON);
CoopTask<>::delay(4000);
}
}
#if defined(ESP8266) || defined(ESP32)
Button* button1;
void loopButton() noexcept
{
int count = 0;
for (;;)
{
if (!button1->pushSema.wait())
{
CoopMutexLock serialLock(serialMutex);
Serial.println(F("loopButton: wait failed"));
yield();
continue;
}
else
{
++count;
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(F("loopButton: count = "));
Serial.println(count);
}
if (nullptr != button1 && 8000 < button1->testResetPressed()) {
delete button1;
button1 = nullptr;
CoopTask<>::exit();
}
yield();
}
}
void handleRoot() {
server.send(200, F("text/plain"), F("hello from esp8266!"));
}
void handleNotFound() {
String message = F("File Not Found\n\n");
message += F("URI: ");
message += server.uri();
message += F("\nMethod: ");
message += (server.method() == HTTP_GET) ? F("GET") : F("POST");
message += F("\nArguments: ");
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += ' ' + server.argName(i) + F(": ") + server.arg(i) + '\n';
}
server.send(404, F("text/plain"), message);
}
#endif
#if defined(ESP8266) || defined(ESP32)
CoopTask<void>* taskButton;
#endif
CoopTask<void, CoopTaskStackAllocatorFromLoop<>>* taskBlink;
CoopTask<unsigned>* taskText;
CoopTask<void>* taskReport0;
CoopTask<void>* taskReport1;
CoopTask<void>* taskReport2;
#if defined(ESP8266) || defined(ESP32)
CoopTask<void>* taskReport3;
CoopTask<void>* taskReport4;
CoopTask<void>* taskWeb;
#endif
CoopSemaphore reportSema(0);
void printStackReport(CoopTaskBase* task)
{
if (!task) return;
Serial.print(task->name().c_str());
Serial.print(F(" free stack = "));
Serial.println(task->getFreeStack());
}
uint32_t iterations = 0;
uint32_t start;
// to demonstrate that yield and delay work in subroutines
void printReport()
{
//CoopTask<>::delayMicroseconds(4000000);
Serial.print(F("cycle period/us = "));
if (iterations)
{
Serial.println(1.0F * (micros() - start) / iterations);
}
else
{
Serial.println(F("N/A"));
}
#if defined(ESP8266) || defined(ESP32)
printStackReport(taskButton);
#endif
printStackReport(taskBlink);
printStackReport(taskText);
printStackReport(CoopTask<>::self());
#if defined(ESP8266) || defined(ESP32)
printStackReport(taskWeb);
#endif
iterations = 0;
};
class RAIITest
{
public:
~RAIITest()
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" stack unwound, RAIITest object destructed"));
}
};
void setup()
{
#ifdef ESP8266
Serial.begin(74880);
#else
Serial.begin(115200);
#endif
while (!Serial) {}
delay(500);
Serial.println(F("Scheduler test"));
#if defined(ESP8266) || defined(ESP32)
WiFi.mode(WIFI_STA);
WiFi.begin(FPSTR(AP_SSID), FPSTR(AP_PASS));
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print('.');
}
Serial.println();
Serial.print(F("IP address: "));
Serial.println(WiFi.localIP());
if (MDNS.begin(F("esp"))) {
Serial.println(F("MDNS responder started"));
}
server.on(F("/"), handleRoot);
server.on(F("/inline"), []() {
server.send(200, F("text/plain"), F("this works as well"));
});
server.onNotFound(handleNotFound);
server.begin();
Serial.println(F("HTTP server started"));
#endif
#if defined(ESP8266) && defined(USE_BUILTIN_TASK_SCHEDULER)
CoopTaskBase::useBuiltinScheduler();
#endif
pinMode(LED_BUILTIN, OUTPUT);
#if defined(ESP8266) || defined(ESP32)
button1 = new Button(BUTTON1, reportSema);
taskButton = new CoopTask<void>(F("Button"), loopButton,
#if defined(ESP8266)
0x700);
#elif defined(ESP32)
0x940);
#endif
if (!*taskButton) Serial.printf_P(PSTR("CoopTask %s out of stack\n"), taskButton->name().c_str());
#endif
taskBlink = new CoopTask<void, CoopTaskStackAllocatorFromLoop<>>(F("Blink"), loopBlink,
#if defined(ESP8266)
0x400);
#elif defined(ESP32)
0x540);
#else
0x40);
#endif
if (!*taskBlink) Serial.println(F("CoopTask Blink out of stack"));
taskText = new CoopTask<unsigned>(F("Text"), []() -> unsigned
{
RAIITest raii;
{
CoopMutexLock serialLock(serialMutex);
Serial.println(F("Task1 - A"));
}
yield();
{
CoopMutexLock serialLock(serialMutex);
Serial.println(F("Task1 - B"));
}
uint32_t start = millis();
CoopTask<>::delay(6000);
{
CoopMutexLock serialLock(serialMutex);
Serial.print(F("!!!Task1 - C - "));
Serial.println(millis() - start);
printStackReport(taskText);
}
#if !defined(ARDUINO)
throw static_cast<unsigned>(41);
#endif
CoopMutexLock serialLock(serialMutex);
Serial.print(F("exiting from task "));
Serial.println(CoopTaskBase::self()->name());
//CoopTask<unsigned>::exit(42);
return 43;
}
#if defined(ESP8266)
, 0x380);
#elif defined(ESP32)
, 0x4c0);
#else
, 0x70);
#endif
if (!*taskText) Serial.println(F("CoopTask Text out of stack"));
auto reportFunc = []() noexcept
{
uint32_t count = 0;
for (;;) {
if (!reportSema.wait(120000))
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name().c_str());
Serial.println(F(": wait failed"));
}
yield();
continue;
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTask<>::self()->name());
Serial.print(F(" ("));
Serial.print(++count);
Serial.println(F("x)"));
printReport();
}
yield();
reportSema.setval(0);
}
};
taskReport0 = new CoopTask<void>(F("Report0"), reportFunc
#if defined(ESP8266) || defined(ESP32)
, 0x600);
#else
, 0x70);
#endif
if (!*taskReport0) Serial.println(F("CoopTask Report out of stack"));
taskReport1 = new CoopTask<void>(F("Report1"), reportFunc
#if defined(ESP8266) || defined(ESP32)
, 0x600);
#else
, 0x70);
#endif
if (!*taskReport1) Serial.println(F("CoopTask Report out of stack"));
taskReport2 = new CoopTask<void>(F("Report2"), reportFunc
#if defined(ESP8266) || defined(ESP32)
, 0x600);
#else
, 0x70);
#endif
if (!*taskReport2) Serial.println(F("CoopTask Report out of stack"));
#if defined(ESP8266) || defined(ESP32)
taskReport3 = new CoopTask<void>(F("Report3"), reportFunc
, 0x600);
if (!*taskReport3) Serial.println(F("CoopTask Report out of stack"));
taskReport4 = new CoopTask<void>(F("Report4"), reportFunc
, 0x600);
if (!*taskReport4) Serial.println(F("CoopTask Report out of stack"));
taskWeb = new CoopTask<void>(F("Web"), []() noexcept
{
for (;;) {
server.handleClient();
#ifdef ESP8266
MDNS.update();
#endif
yield();
}
},
#if defined(ESP8266)
0x800);
#else
0xa00);
#endif
if (!*taskWeb) Serial.printf_P(PSTR("CoopTask %s out of stack\n"), taskWeb->name().c_str());
if (!taskButton->scheduleTask()) { Serial.printf_P(PSTR("Could not schedule task %s\n"), taskButton->name().c_str()); }
if (!taskReport3->scheduleTask()) { Serial.printf_P(PSTR("Could not schedule task %s\n"), taskReport3->name().c_str()); }
if (!taskReport4->scheduleTask()) { Serial.printf_P(PSTR("Could not schedule task %s\n"), taskReport4->name().c_str()); }
if (!taskWeb->scheduleTask()) { Serial.printf_P(PSTR("Could not schedule task %s\n"), taskWeb->name().c_str()); }
#endif
if (!taskBlink->scheduleTask()) { Serial.print(F("Could not schedule task ")); Serial.println(taskBlink->name().c_str()); }
if (!taskText->scheduleTask()) { Serial.print(F("Could not schedule task ")); Serial.println(taskText->name().c_str()); }
if (!taskReport0->scheduleTask()) { Serial.print(F("Could not schedule task ")); Serial.println(taskReport0->name().c_str()); }
if (!taskReport1->scheduleTask()) { Serial.print(F("Could not schedule task ")); Serial.println(taskReport1->name().c_str()); }
if (!taskReport2->scheduleTask()) { Serial.print(F("Could not schedule task ")); Serial.println(taskReport2->name().c_str()); }
#ifdef ESP32
Serial.print(F("Loop free stack = ")); Serial.println(uxTaskGetStackHighWaterMark(NULL));
#endif
}
void taskReaper(const CoopTaskBase* const task)
{
if (task == taskText)
{
delete task;
taskText = nullptr;
}
}
void loop()
{
#if defined(ESP8266) && defined(USE_BUILTIN_TASK_SCHEDULER)
if (taskText && !*taskText)
{
taskReaper(taskText);
}
#else
runCoopTasks(taskReaper);
#endif
// taskReport sleeps on first run(), and after each report.
// It resets iterations to 0 on each report.
if (!iterations) start = micros();
++iterations;
#ifdef ESP32_FREERTOS
if (iterations >= 50000)
#else
if (iterations >= 200000)
#endif
{
reportSema.post();
}
}

View File

@@ -0,0 +1,252 @@
/*
Name: mutex.ino
Created: 2019-08-04 22:40:11
Author: dok@dok-net.net
*/
#include <CoopTask.h>
#include <CoopSemaphore.h>
#include <CoopMutex.h>
#define USE_BUILTIN_TASK_SCHEDULER
CoopMutex serialMutex;
CoopMutex mutex;
CoopTaskBase* hasMutex(nullptr);
void haveMutex()
{
if (hasMutex)
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" called haveMutex, despite "));
Serial.print(hasMutex->name());
Serial.println(F(" is known to have mutex."));
return;
}
hasMutex = CoopTaskBase::self();
}
void yieldMutex()
{
if (hasMutex != CoopTaskBase::self())
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" called yieldMutex, but no task currently has the mutex."));
return;
}
hasMutex = nullptr;
}
CoopTask<int>* firstTask;
CoopTask<int>* secondTask;
CoopTask<int>* thirdTask;
void setup() {
#ifdef ESP8266
Serial.begin(74880);
#else
Serial.begin(115200);
#endif
while (!Serial) {}
delay(500);
Serial.println(F("Mutex test"));
#if defined(ESP8266) && defined(USE_BUILTIN_TASK_SCHEDULER)
CoopTaskBase::useBuiltinScheduler();
#endif
firstTask = createCoopTask(F("first"), []()
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" starts"));
}
for (int i = 0; i < 30; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" locks mutex"));
}
{
CoopMutexLock lock(mutex);
if (!lock) {
CoopMutexLock serialLock(serialMutex);
Serial.print(F("failed to lock mutex in "));
Serial.println(CoopTaskBase::self()->name());
}
haveMutex();
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" has mutex"));
}
yield();
yieldMutex();
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
CoopMutexLock serialLock(serialMutex);
Serial.print(F("exiting from task "));
Serial.println(CoopTaskBase::self()->name());
return 0;
}
#if defined(ESP8266) || defined(ESP32)
);
#else
, 0x120);
#endif
if (!firstTask) Serial.println(F("firstTask not created"));
secondTask = createCoopTask(F("second"), []()
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" starts"));
}
for (int i = 0; i < 30; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" locks mutex"));
}
{
CoopMutexLock lock(mutex);
if (!lock) {
CoopMutexLock serialLock(serialMutex);
Serial.print(F("failed to lock mutex in "));
Serial.println(CoopTaskBase::self()->name());
}
haveMutex();
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" has mutex"));
}
yield();
yieldMutex();
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
CoopMutexLock serialLock(serialMutex);
Serial.print(F("exiting from task "));
Serial.println(CoopTaskBase::self()->name());
return 0;
}
#if defined(ESP8266) || defined(ESP32)
);
#else
, 0x120);
#endif
if (!secondTask) Serial.println(F("secondTask not created"));
thirdTask = createCoopTask(F("third"), []()
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" starts"));
}
for (int i = 0; i < 10; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" locks mutex"));
}
{
CoopMutexLock lock(mutex);
if (!lock) {
CoopMutexLock serialLock(serialMutex);
Serial.print(F("failed to lock mutex in "));
Serial.println(CoopTaskBase::self()->name());
}
haveMutex();
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" has mutex"));
}
yield();
yieldMutex();
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
for (int i = 0; i < 10; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" still runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
CoopMutexLock serialLock(serialMutex);
Serial.print(F("exiting from task "));
Serial.println(CoopTaskBase::self()->name());
return 0;
}
#if defined(ESP8266) || defined(ESP32)
);
#else
, 0x120);
#endif
if (!thirdTask) Serial.println(F("thirdTask not created"));
#ifdef ESP32
Serial.print(F("Loop free stack = ")); Serial.println(uxTaskGetStackHighWaterMark(NULL));
#endif
}
void taskReaper(const CoopTaskBase* const task)
{
delete task;
}
// the loop function runs over and over again until power down or reset
void loop()
{
#if defined(ESP8266) && defined(USE_BUILTIN_TASK_SCHEDULER)
if (firstTask && !*firstTask)
{
taskReaper(firstTask); firstTask = nullptr;
}
if (secondTask && !*secondTask)
{
taskReaper(secondTask); secondTask = nullptr;
}
if (thirdTask && !*thirdTask)
{
taskReaper(thirdTask); thirdTask = nullptr;
}
#else
runCoopTasks(taskReaper);
#endif
}

View File

@@ -0,0 +1,96 @@
// portable.cpp
// This is a basic portable example, without a scheduler.
// All tasks are run round-robin inside a for loop.
// It shows CoopTask creation, synchronization, and termination.
#include <iostream>
#include "CoopTask.h"
#include "CoopSemaphore.h"
#include "CoopMutex.h"
template<typename StackAllocator> void printStackReport(BasicCoopTask<StackAllocator>& task)
{
if (!task) return;
std::cerr << task.name().c_str() << " free stack = " << task.getFreeStack() << std::endl;
}
CoopMutex blinkMutex;
int main()
{
CoopSemaphore terminatorSema(0);
CoopSemaphore helloSema(0);
auto& hello = *createCoopTask<void>(std::string("hello"), [&terminatorSema, &helloSema]() noexcept
{
std::cerr << "Hello" << std::endl;
yield();
for (int x = 0; x < 10; ++x)
{
{
CoopMutexLock lock(blinkMutex);
std::cerr << "Loop" << std::endl;
}
helloSema.wait(2000);
}
terminatorSema.post();
}, 0x2000);
if (!hello) std::cerr << hello.name() << " CoopTask not created" << std::endl;
bool keepBlinking = true;
auto& terminator = *createCoopTask<void>(std::string("terminator"), [&keepBlinking, &terminatorSema]() noexcept
{
if (!terminatorSema.wait()) std::cerr << "terminatorSema.wait() failed" << std::endl;
keepBlinking = false;
}, 0x2000);
if (!terminator) std::cerr << terminator.name() << " CoopTask not created" << std::endl;
auto& blink = *createCoopTask<std::string, CoopTaskStackAllocatorFromLoop<>>(std::string("blink"), [&keepBlinking]()
{
while (keepBlinking)
{
{
CoopMutexLock lock(blinkMutex);
std::cerr << "LED on" << std::endl;
delay(1000);
std::cerr << "LED off" << std::endl;
}
delay(1000);
}
throw std::string("sixtynine");
return "fortytwo";
}, 0x2000);
if (!blink) std::cerr << blink.name() << " CoopTask not created" << std::endl;
auto& report = *createCoopTask<void>(std::string("report"), [&hello, &blink]() noexcept
{
for (;;) {
delay(5000);
{
CoopMutexLock lock(blinkMutex);
printStackReport(hello);
printStackReport(blink);
}
}
}, 0x2000);
if (!report) std::cerr << report.name() << " CoopTask not created" << std::endl;
auto taskReaper = [&blink](const CoopTaskBase* const task)
{
// once: hello posts terminatorSema -> terminator sets keepBlinking = false -> blink exits -> break leaves for-loop -> program exits
if (task == &blink)
{
std::cerr << task->name() << " returns = " << blink.exitCode() << std::endl;
delete task;
exit(0);
}
};
for (;;)
{
runCoopTasks(taskReaper);
}
return 0;
}