├── README.md ├── Scheduler.cpp ├── Scheduler.h ├── Scheduler ├── Channel.h ├── Queue.h └── Semaphore.h ├── core_esp8266_2.6.3.patch ├── core_esp8266_2.7.0.patch ├── examples ├── SchedulerAlarmClock │ ├── Alarm.h │ ├── Clock.h │ └── SchedulerAlarmClock.ino ├── SchedulerBenchmark │ └── SchedulerBenchmark.ino ├── SchedulerBenchmarkChannel │ └── SchedulerBenchmarkChannel.ino ├── SchedulerBenchmarkQueue │ └── SchedulerBenchmarkQueue.ino ├── SchedulerBenchmarkSemaphore │ └── SchedulerBenchmarkSemaphore.ino ├── SchedulerBenchmarkSize │ └── SchedulerBenchmarkSize.ino ├── SchedulerBlink │ └── SchedulerBlink.ino ├── SchedulerBlinkController │ └── SchedulerBlinkController.ino ├── SchedulerBlinkMax │ └── SchedulerBlinkMax.ino ├── SchedulerBlinkTemplateClass │ ├── Blink.h │ └── SchedulerBlinkTemplateClass.ino ├── SchedulerBlinkTemplateFunctions │ └── SchedulerBlinkTemplateFunctions.ino ├── SchedulerChannel │ └── SchedulerChannel.ino ├── SchedulerDebounce │ └── SchedulerDebounce.ino ├── SchedulerDebounceTemplate │ ├── Debounce.h │ └── SchedulerDebounceTemplate.ino ├── SchedulerDemo │ └── SchedulerDemo.ino ├── SchedulerDemoNamespaces │ ├── BlinkTask.h │ ├── SchedulerDemoNamespaces.ino │ ├── ShellTask.h │ └── Trace.h ├── SchedulerEvent │ └── SchedulerEvent.ino ├── SchedulerEventQueue │ └── SchedulerEventQueue.ino ├── SchedulerSemaphore │ └── SchedulerSemaphore.ino ├── SchedulerTaskMax │ └── SchedulerTaskMax.ino └── SchedulerWatchdogTemplate │ ├── SchedulerWatchdogTemplate.ino │ └── Watchdog.h └── library.properties /README.md: -------------------------------------------------------------------------------- 1 | # esp8266-scheduler 2 | 3 | ## Notes for patching ESP8266 core 4 | 5 | The current scheduler library supports esp8266 Arduino core '2.6.3'. 6 | 7 | Apply the path `core_esp8266_2.6.3.patch` for esp8266 Arduino core '2.6.3'. First, unpack git repository to the home directory and then apply the patch into the current availabe esp8266 core. Currently, the esp8266 core is available at `~/.arduino15`. Use the following commands to apply the path and adapt them accordingly if needed. 8 | ``` 9 | cd ~ 10 | git clone https://github.com/anmaped/esp8266-scheduler.git 11 | cd ~/.arduino15/packages/esp8266/hardware/esp8266/ 12 | patch -s -p0 < ~/esp8266-scheduler/libraries/scheduler/core_esp8266_2.6.3.patch 13 | ``` 14 | 15 | ### Old instructions for esp8266 core version 2.3.0: 16 | 17 | We have to chose the Arduino 1.6.8 with esp8266 core version 2.3.0. This patched runtime is available in `https://github.com/srmq/Arduino/tree/scheduler_branch`. The Arduino 1.6.8 for windows is availalbe in `https://www.arduino.cc/download_handler.php?f=/arduino-1.6.8-windows.zip` and for Linux 32 in `https://www.arduino.cc/download_handler.php?f=/arduino-1.6.8-linux32.tar.xz`. 18 | 19 | Instructions: Replace the esp8266 core inside the Arduino folder `~/.arduino15/packages/esp8266/hardware` with the patched version provided in the branch above. 20 | 21 | - Install esp8266 2.3.0 using the usual arduino esp8266 instructions (add http://arduino.esp8266.com/stable/package_esp8266com_index.json to preferences, and install it using the board manager). 22 | - Create the folder 'hardware/esp8266com/esp8266' and extract inside it the content available in the branch `https://github.com/srmq/Arduino/tree/scheduler_branch`. Simply download the zip file from GitHub and rename it locally. 23 | - Add the Scheduler library to Arduino. 24 | 25 | Note that the esp8266 core will replace the installed version 2.3.0. 26 | 27 | 28 | ## Introduction 29 | 30 | This library implements an extended sub-set of the Arduino Scheduler 31 | class. Multiple loop() functions, tasks, may be started and run in a 32 | collaborative multi-tasking style. The tasks are run until they call 33 | yield() or delay(). The Arduino yield() function is replaced by an 34 | implementation in the library that allows context switching. 35 | 36 | Tasks should be viewed as static and continuous. This implementation 37 | does not allocate tasks on the heap. They are allocated on the normal 38 | stack and linked into a cyclic run queue. One-shot tasks are not 39 | supported. Instead the task start function is extended with a setup 40 | function reference. Tasks are started with: 41 | 42 | ```` 43 | Scheduler.start(taskSetup, taskLoop [,taskStackSize]). 44 | ```` 45 | The tasks will start execution when the main task yields. The 46 | _taskSetup_ is called first and once by the task followed by repeated 47 | calls to _taskLoop_. This works just as the Arduino setup() and loop() 48 | functions. There is also an optional parameter, _taskStackSize_. The 49 | default value depends on the architecture (128 bytes for AVR and 512 50 | bytes for SAM/SAMD/Teensy 3.1). 51 | 52 | The Scheduler is a single-ton and the library creates the single 53 | instance. 54 | 55 | This library also includes support for task synchronization and 56 | communication; Semaphores, Queues and Channels. 57 | 58 | ## Install 59 | 60 | Download and unzip the esp8266-scheduler library into your sketchbook 61 | libraries directory. Rename from esp8266-scheduler-master to esp8266-scheduler. 62 | 63 | The Scheduler library and examples should be found in the Arduino IDE 64 | File>Examples menu. 65 | 66 | ## Performance 67 | 68 | There are several benchmark sketches in the examples directory. Below 69 | are some of the results. 70 | 71 | ### Context Switch 72 | 73 | Board | us | cycles 74 | ------|----|------- 75 | Arduino Mega 2560 (16 MHz) | 12.64 | 203 76 | Arduino Uno, Nano, Pro-Mini, etc (16 MHz) | 11.00 | 176 77 | Sparkfun SAMD21 (48 MHz) | 2.60 | 125 78 | Arduino Due (84 MHz) | 1.36 | 115 79 | Teensy 3.1 (72 MHz) | 1.10 | 80 80 | 81 | ### Max Tasks (default stack size) 82 | 83 | Board | Tasks | Stack (bytes) 84 | ------|-------|-------------- 85 | Arduino Uno, Nano, Pro-Mini, etc (16 MHz) | 9 | 128 86 | Sparkfun SAMD21 (48 MHz) | 26 | 512 87 | Teensy 3.1 (72 MHz) | 26 | 512 88 | Arduino Mega 2560 (16 MHz) | 48 | 128 89 | Arduino Due (84 MHz) | 52 | 512 90 | 91 | 92 | ### Memory Footprint 93 | 94 | Board | PROGMEM | SRAM (bytes) 95 | ------|---------|------------- 96 | Arduino Due (84 MHz) | 224 | NA 97 | Arduino Uno, Nano, Pro-Mini, etc (16 MHz) | 546 | 42 98 | Arduino Mega 2560 (16 MHz) | 548 | 44 99 | Sparkfun SAMD21 (48 MHz) | NA | NA 100 | Teensy 3.1 (72 MHz) | NA | NA 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /Scheduler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Scheduler.cpp 3 | * @version 1.2 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #include "Scheduler.h" 20 | #include 21 | 22 | // Configuration: SRAM and heap handling 23 | #if defined(TEENSYDUINO) && defined(__MK20DX256__) 24 | #undef ARDUINO_ARCH_AVR 25 | #define TEENSY_ARCH_ARM 26 | #define RAMEND 0x20008000 27 | 28 | #elif defined(ARDUINO_ARCH_AVR) 29 | extern int __heap_start, *__brkval; 30 | extern char* __malloc_heap_end; 31 | extern size_t __malloc_margin; 32 | 33 | #elif defined(ARDUINO_ARCH_SAM) 34 | #define RAMEND 0x20088000 35 | 36 | #elif defined(ARDUINO_ARCH_SAMD) 37 | #define RAMEND 0x20008000 38 | 39 | #elif defined(ARDUINO_ARCH_ESP8266) 40 | // https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map 41 | #define RAMSTART 0x3FFE8000 42 | #define RAMSIZE 0x14000 43 | #define RAMEND RAMSTART + RAMSIZE - 1 44 | //#define RAMEND 0x3fffffb0 45 | 46 | #endif 47 | 48 | 49 | // Single-ton 50 | //SchedulerClass Scheduler; 51 | SchedulerClass& sched(void) 52 | { 53 | static SchedulerClass ans = SchedulerClass(); 54 | return ans; 55 | } 56 | 57 | // Main task and run queue 58 | SchedulerClass::task_t SchedulerClass::s_main = { 59 | &SchedulerClass::s_main, 60 | &SchedulerClass::s_main, 61 | { 0 }, 62 | NULL 63 | }; 64 | 65 | // Reference running task 66 | SchedulerClass::task_t* SchedulerClass::s_running = &SchedulerClass::s_main; 67 | 68 | // Initial top stack for task allocation 69 | size_t SchedulerClass::s_top = SchedulerClass::DEFAULT_STACK_SIZE; 70 | 71 | // Initial number of tasks 72 | size_t SchedulerClass::s_count = 0; 73 | 74 | #if defined(ARDUINO_ARCH_ESP8266) 75 | extern "C" { 76 | #include "os_type.h" 77 | //#include "signal.h" 78 | #include "user_interface.h" 79 | } 80 | #include "Scheduler/Semaphore.h" 81 | 82 | #define LOOP_TASK_PRIORITY 1 83 | #define LOOP_QUEUE_SIZE 1 84 | 85 | //void handler (int signum) { printf("SIGNAL\n"); }; 86 | 87 | extern "C" uint32_t system_get_time(); 88 | extern "C" void preloop_update_frequency(); 89 | 90 | static uint32_t g_micros_at_task_start = 0; 91 | 92 | extern "C" void esp_yield(void){ yield(); } 93 | 94 | extern "C" void optimistic_yield(uint32_t interval_us){ yield(); } 95 | 96 | extern "C" void delay(unsigned long interval_ms) 97 | { 98 | uint32_t g_micros_at_task_start = system_get_time(); 99 | 100 | while((system_get_time() - g_micros_at_task_start) < interval_ms*1000) 101 | { 102 | system_soft_wdt_feed(); 103 | yield(); 104 | } 105 | } 106 | 107 | extern "C" void delay_until(uint32_t clock) 108 | { 109 | uint32_t current_clock; 110 | 111 | while((current_clock = system_get_time()) < clock) 112 | { 113 | system_soft_wdt_feed(); 114 | yield(); 115 | } 116 | 117 | if((current_clock - clock) > 100) 118 | { 119 | #ifdef DEBUG_SCHEDULER 120 | printf_P(PSTR("deadline miss\n")); 121 | #endif 122 | } 123 | } 124 | 125 | extern "C" unsigned int get_clock() 126 | { 127 | return system_get_time(); 128 | } 129 | 130 | extern "C" void loop_task(os_event_t *events) 131 | { 132 | static bool one = true; 133 | 134 | g_micros_at_task_start = system_get_time(); 135 | 136 | //signal (SIGSEGV, handler); 137 | 138 | if(one) 139 | { 140 | one = false; 141 | 142 | preloop_update_frequency(); 143 | Scheduler.begin(0x0); 144 | setup(); 145 | 146 | if(!Scheduler.start(NULL, loop, 1024)) 147 | { 148 | panic(); 149 | } 150 | } 151 | 152 | yield(); 153 | 154 | ets_post(LOOP_TASK_PRIORITY, 0, 0); 155 | } 156 | 157 | static Semaphore spiffs(1); 158 | 159 | extern "C" void esp_spiffs_lock(uint32_t* fs) 160 | { 161 | spiffs.wait(1); 162 | } 163 | 164 | extern "C" void esp_spiffs_unlock(uint32_t* fs) 165 | { 166 | spiffs.signal(1); 167 | } 168 | 169 | #endif 170 | 171 | 172 | bool SchedulerClass::begin(size_t stackSize) 173 | { 174 | static bool initiated = true; 175 | 176 | if(initiated) 177 | { 178 | initiated = false; 179 | // Set main task stack size 180 | s_top = stackSize; 181 | } 182 | 183 | #if defined(ARDUINO_ARCH_ESP8266) 184 | // fill the remaining stack with a pattern 185 | uint8_t * fr = (uint8_t*)RAMEND-STACK_MAX; 186 | memset(fr, 0x08, STACK_MAX-stackSize); 187 | #endif 188 | 189 | return true; 190 | } 191 | 192 | bool SchedulerClass::start(func_t taskSetup, func_t taskLoop, size_t stackSize) 193 | { 194 | // Check called from main task and valid task loop function 195 | if ((s_running != &s_main) || (taskLoop == NULL)) return (false); 196 | 197 | // Adjust stack size with size of task context 198 | stackSize += sizeof(task_t); 199 | 200 | // Allocate stack(s) and check if main stack top should be set 201 | size_t frame = RAMEND - (size_t) &frame; 202 | 203 | #ifdef DEBUG_SCHEDULER 204 | printf_P(PSTR("%p\n"), (size_t) &frame); 205 | printf_P(PSTR("s_top - frame=%u\n"), s_top - frame); 206 | #endif 207 | 208 | uint8_t stack[s_top - frame]; 209 | if (s_main.stack == NULL) s_main.stack = stack; 210 | 211 | #if defined(ARDUINO_ARCH_AVR) 212 | // Check that the task can be allocated 213 | int HEAPEND = (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 214 | int STACKSTART = ((int) stack) - stackSize; 215 | HEAPEND += __malloc_margin; 216 | if (STACKSTART < HEAPEND) return (false); 217 | 218 | // Adjust heap limit 219 | __malloc_heap_end = (char*) STACKSTART; 220 | #endif 221 | 222 | #if defined(ARDUINO_ARCH_SAM) || \ 223 | defined(ARDUINO_ARCH_SAMD) || \ 224 | defined(TEENSY_ARCH_ARM) || \ 225 | defined(ARDUINO_ARCH_ESP8266) 226 | // Check that the task can be allocated 227 | if (s_top + stackSize > STACK_MAX) return (false); 228 | #endif 229 | 230 | // Adjust stack top for next task allocation 231 | s_top += stackSize; 232 | s_count++; 233 | 234 | // Initiate task with given functions and stack top 235 | init(taskSetup, taskLoop, stack - stackSize); 236 | return (true); 237 | } 238 | 239 | void SchedulerClass::yield() 240 | { 241 | // Caller will continue here on yield 242 | if (setjmp(s_running->context)) return; 243 | 244 | // Next task in run queue will continue 245 | s_running = s_running->next; 246 | longjmp(s_running->context, true); 247 | } 248 | 249 | size_t SchedulerClass::stack() 250 | { 251 | unsigned char marker; 252 | return (&marker - s_running->stack); 253 | } 254 | 255 | void SchedulerClass::init(func_t setup, func_t loop, const uint8_t* stack) 256 | { 257 | // Add task last in run queue (main task) 258 | task_t task; 259 | task.next = &s_main; 260 | task.prev = s_main.prev; 261 | s_main.prev->next = &task; 262 | s_main.prev = &task; 263 | task.stack = stack; 264 | 265 | // Create context for new task, caller will return 266 | if (setjmp(task.context)) { 267 | if (setup != NULL) setup(); 268 | while (1) loop(); 269 | } 270 | } 271 | 272 | extern "C" void yield(void) 273 | { 274 | Scheduler.yield(); 275 | } 276 | -------------------------------------------------------------------------------- /Scheduler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Scheduler.h 3 | * @version 1.2 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SCHEDULER_H 20 | #define SCHEDULER_H 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | //#define DEBUG_SCHEDULER 1 27 | 28 | #if defined(ARDUINO_ARCH_ESP8266) 29 | extern "C" unsigned int get_clock(); 30 | extern "C" void delay_until(uint32_t clock_ms); 31 | #endif 32 | 33 | class SchedulerClass { 34 | public: 35 | /** 36 | * Function prototype (task setup and loop functions). 37 | */ 38 | typedef void (*func_t)(); 39 | 40 | /** 41 | * Initiate scheduler and main task with given stack size. Should 42 | * be called before start of any tasks if the main task requires a 43 | * stack size other than the default size. Returns true if 44 | * successful otherwise false. 45 | * @param[in] stackSize in bytes. 46 | * @return bool. 47 | */ 48 | static bool begin(size_t stackSize); 49 | 50 | /** 51 | * Start a task with given functions and stack size. Should be 52 | * called from main task (in setup). The functions are executed by 53 | * the task. The taskSetup function (if provided) is run once. 54 | * The taskLoop function is repeatedly called. The taskSetup may be 55 | * omitted (NULL). Returns true if successful otherwise false. 56 | * @param[in] taskSetup function (may be NULL). 57 | * @param[in] taskLoop function (may not be NULL). 58 | * @param[in] stackSize in bytes. 59 | * @return bool. 60 | */ 61 | static bool start(func_t taskSetup, 62 | func_t taskLoop, 63 | size_t stackSize = DEFAULT_STACK_SIZE); 64 | 65 | /** 66 | * Context switch to next task in run queue. 67 | */ 68 | static void yield(); 69 | 70 | /** 71 | * Return stack length of the current task. 72 | * @return bytes 73 | */ 74 | static size_t stack(); 75 | 76 | /** 77 | * Return stack size 78 | * @return size_t 79 | */ 80 | static size_t * stackSize() { return (size_t *) s_top; }; 81 | 82 | /** 83 | * Return number of tasks 84 | * @return size_t 85 | */ 86 | static size_t numberOfTasks() { return s_count; }; 87 | 88 | protected: 89 | /** 90 | * Initiate a task with the given functions and stack. When control 91 | * is yield to the task the setup function is first called and then 92 | * the loop function is repeatedly called. 93 | * @param[in] setup task function (may be NULL). 94 | * @param[in] loop task function (may not be NULL). 95 | * @param[in] stack top reference. 96 | */ 97 | static void init(func_t setup, func_t loop, const uint8_t* stack); 98 | 99 | /** 100 | * Task run-time structure. 101 | */ 102 | struct task_t { 103 | task_t* next; //!< Next task. 104 | task_t* prev; //!< Previous task. 105 | jmp_buf context; //!< Task context. 106 | const uint8_t* stack; //!< Task stack. 107 | }; 108 | 109 | #if defined(TEENSYDUINO) && defined(__MK20DX256__) 110 | /** Default stack size and stack max. */ 111 | static const size_t DEFAULT_STACK_SIZE = 512; 112 | static const size_t STACK_MAX = 16384; 113 | 114 | #elif defined(ARDUINO_ARCH_AVR) 115 | /** Default stack size. */ 116 | static const size_t DEFAULT_STACK_SIZE = 128; 117 | 118 | #elif defined(ARDUINO_ARCH_SAM) 119 | /** Default stack size and stack max. */ 120 | static const size_t DEFAULT_STACK_SIZE = 512; 121 | static const size_t STACK_MAX = 32768; 122 | 123 | #elif defined(ARDUINO_ARCH_SAMD) 124 | /** Default stack size and stack max. */ 125 | static const size_t DEFAULT_STACK_SIZE = 512; 126 | static const size_t STACK_MAX = 16384; 127 | 128 | #elif defined(ARDUINO_ARCH_ESP8266) 129 | 130 | /** Default stack size and stack max. */ 131 | static const size_t DEFAULT_STACK_SIZE = 512; 132 | static const size_t STACK_MAX = 0x2000 + 0x4000 + 0x2000; // esp8266 Arduino reserves 4096bytes for the stack (heap starts 0x3FFF after the stack begin address) 133 | 134 | #else 135 | #error "Scheduler.h: board not supported" 136 | #endif 137 | 138 | /** Main task. */ 139 | static task_t s_main; 140 | 141 | /** Running task. */ 142 | static task_t* s_running; 143 | 144 | /** Task stack allocation top. */ 145 | static size_t s_top; 146 | 147 | /** Number of registered tasks. */ 148 | static size_t s_count; 149 | }; 150 | 151 | /** Scheduler single-ton. */ 152 | //extern SchedulerClass Scheduler; 153 | #define Scheduler sched() 154 | extern SchedulerClass& sched(void); 155 | 156 | /** 157 | * Syntactic sugar for scheduler based busy-wait for condition; 158 | * yield until condition is valid. May require volatile condition 159 | * variable(s). 160 | * @param[in] cond condition to await. 161 | */ 162 | #define await(cond) while (!(cond)) yield() 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /Scheduler/Channel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Scheduler/Channel.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SCHEDULER_CHANNEL_H 20 | #define SCHEDULER_CHANNEL_H 21 | 22 | #include 23 | 24 | class Channel { 25 | public: 26 | /** 27 | * Initiate channel for message passing between tasks. 28 | */ 29 | Channel() : 30 | m_buf(NULL), 31 | m_max(0), 32 | m_size(0), 33 | m_ticket(0), 34 | m_serving(0) 35 | {} 36 | 37 | /** 38 | * Send given message, buffer and size, to receiving task. Wait 39 | * until receiver task is ready before copying message to receiver 40 | * buffer. Multiple senders will queue in order. Returns message 41 | * size if successful otherwise negative error code. 42 | * @param[in] buf message buffer. 43 | * @param[in] size message size. 44 | * @return message size or negative error code. 45 | */ 46 | int send(const void* buf, size_t size) 47 | { 48 | // Take a ticket and wait for service 49 | uint8_t ticket = m_ticket++; 50 | await(ticket == m_serving && m_buf != NULL); 51 | 52 | // Check that the receiver buffer can hold the message 53 | if (size > m_max) { 54 | m_serving += 1; 55 | return (-1); 56 | } 57 | 58 | // Copy message to receiver buffer 59 | memcpy(m_buf, buf, size); 60 | m_size = size; 61 | return (size); 62 | } 63 | 64 | /** 65 | * Receive message from channel. Wait for sender task to copy 66 | * message into given receive buffer. Returns received message size. 67 | * @param[in] buf message buffer. 68 | * @param[in] size message size. 69 | * @return received message size. 70 | */ 71 | int recv(void* buf, size_t size) 72 | { 73 | // Wait for the channel to be free for receive 74 | await(m_buf == NULL); 75 | m_buf = buf; 76 | m_max = size; 77 | m_size = 0; 78 | 79 | // Wait for message from sender 80 | await(m_size != 0); 81 | int res = m_size; 82 | m_buf = NULL; 83 | m_max = 0; 84 | m_size = 0; 85 | m_serving += 1; 86 | 87 | // Return size of received message 88 | return (m_size); 89 | } 90 | 91 | protected: 92 | void* m_buf; //!< Message buffer 93 | volatile size_t m_max; //!< Max message size 94 | volatile size_t m_size; //!< Actual message size 95 | volatile uint8_t m_ticket; //!< Sender ticket 96 | volatile uint8_t m_serving; //!< Next sender ticket 97 | }; 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /Scheduler/Queue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Scheduler/Queue.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SCHEDULER_QUEUE_H 20 | #define SCHEDULER_QUEUE_H 21 | 22 | /** 23 | * Template class for ring-buffer of queueing data elements. 24 | * @param[in] T element class. 25 | * @param[in] nmemb number of elements in queue. 26 | */ 27 | template 28 | class Queue { 29 | static_assert(NMEMB && !(NMEMB & (NMEMB - 1)), "Queue::NMEMB should be power of 2"); 30 | public: 31 | /** 32 | * Construct a ring-buffer queue with given number of members and 33 | * member type. 34 | */ 35 | Queue() : 36 | m_put(0), 37 | m_get(0) 38 | {} 39 | 40 | /** 41 | * Return number of elements in queue. 42 | * @return available elements. 43 | */ 44 | unsigned int available() const 45 | __attribute__((always_inline)) 46 | { 47 | return ((NMEMB + m_put - m_get) & MASK); 48 | } 49 | 50 | /** 51 | * Number of elements room in queue. 52 | * @return room for elements. 53 | */ 54 | unsigned int room() const 55 | __attribute__((always_inline)) 56 | { 57 | return ((NMEMB - m_put + m_get - 1) & MASK); 58 | } 59 | 60 | /** 61 | * Push given data into queue. Will yield until room is available. 62 | * @param[in] data pointer to data buffer. 63 | */ 64 | void push(const T* data) 65 | { 66 | await(room()); 67 | unsigned int next = (m_put + 1) & MASK; 68 | m_buffer[next] = *data; 69 | m_put = next; 70 | } 71 | 72 | /** 73 | * Push given data in program memory into queue. Will yield until 74 | * room is available. 75 | * @param[in] data pointer to data buffer in program memory. 76 | */ 77 | void push_P(const T* data) 78 | { 79 | await(room()); 80 | unsigned int next = (m_put + 1) & MASK; 81 | memcpy_P(&m_buffer[next], data, sizeof(T)); 82 | m_put = next; 83 | } 84 | 85 | /** 86 | * Pull data from queue to given buffer. Will yield until data is 87 | * available. 88 | * @param[in,out] data pointer to data buffer. 89 | */ 90 | void pull(T* data) 91 | { 92 | await(available()); 93 | unsigned int next = (m_get + 1) & MASK; 94 | m_get = next; 95 | *data = m_buffer[next]; 96 | } 97 | 98 | private: 99 | static const unsigned int MASK = (NMEMB - 1); 100 | volatile unsigned int m_put; 101 | volatile unsigned int m_get; 102 | T m_buffer[NMEMB]; 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /Scheduler/Semaphore.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Scheduler/Semaphore.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SCHEDULER_SEMAPHORE_H 20 | #define SCHEDULER_SEMAPHORE_H 21 | 22 | #include 23 | 24 | class Semaphore { 25 | public: 26 | /** 27 | * Initiate semaphore with given count. 28 | * @param[in] count (default mutex). 29 | */ 30 | Semaphore(unsigned int count = 1) : m_count(count) {} 31 | 32 | /** 33 | * Wait for semaphore count. 34 | * @param[in] count (default mutex). 35 | */ 36 | void wait(unsigned int count = 1) 37 | { 38 | await(m_count >= count); 39 | m_count -= count; 40 | } 41 | 42 | /** 43 | * Signal semaphore count. 44 | * @param[in] count (default mutex). 45 | */ 46 | void signal(unsigned int count = 1) 47 | { 48 | m_count += count; 49 | yield(); 50 | } 51 | 52 | protected: 53 | volatile unsigned int m_count; 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /core_esp8266_2.6.3.patch: -------------------------------------------------------------------------------- 1 | diff -ruN 2.6.3/cores/esp8266/core_esp8266_main.cpp 2.6.3_mod/cores/esp8266/core_esp8266_main.cpp 2 | --- 2.6.3/cores/esp8266/core_esp8266_main.cpp 2020-04-25 09:58:37.657733964 -0700 3 | +++ 2.6.3_mod/cores/esp8266/core_esp8266_main.cpp 2020-04-06 11:00:58.955024000 -0700 4 | @@ -82,8 +82,8 @@ 5 | void initVariant() { 6 | } 7 | 8 | -void preloop_update_frequency() __attribute__((weak)); 9 | -void preloop_update_frequency() { 10 | +extern "C" void preloop_update_frequency() __attribute__((weak)); 11 | +extern "C" void preloop_update_frequency() { 12 | #if defined(F_CPU) && (F_CPU == 160000000L) 13 | REG_SET_BIT(0x3ff00014, BIT(0)); 14 | ets_update_cpu_frequency(160); 15 | @@ -108,10 +108,13 @@ 16 | 17 | extern "C" void esp_yield() __attribute__ ((weak, alias("__esp_yield"))); 18 | 19 | -extern "C" IRAM_ATTR void esp_schedule() { 20 | +extern "C" void __esp_schedule() { 21 | +//extern "C" IRAM_ATTR void esp_schedule() { 22 | ets_post(LOOP_TASK_PRIORITY, 0, 0); 23 | } 24 | 25 | +extern "C" void esp_schedule(void) __attribute__ ((weak, alias("__esp_schedule"))); 26 | + 27 | extern "C" void __yield() { 28 | if (can_yield()) { 29 | esp_schedule(); 30 | @@ -124,7 +127,7 @@ 31 | 32 | extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); 33 | 34 | -extern "C" void optimistic_yield(uint32_t interval_us) { 35 | +extern "C" void __optimistic_yield(uint32_t interval_us) { 36 | if (can_yield() && 37 | (system_get_time() - s_micros_at_task_start) > interval_us) 38 | { 39 | @@ -132,6 +135,8 @@ 40 | } 41 | } 42 | 43 | +extern "C" void optimistic_yield(uint32_t interval_us) __attribute__ ((weak, alias("__optimistic_yield"))); 44 | + 45 | 46 | // Replace ets_intr_(un)lock with nestable versions 47 | extern "C" void IRAM_ATTR ets_intr_lock() { 48 | @@ -181,7 +186,7 @@ 49 | esp_schedule(); 50 | } 51 | 52 | -static void loop_task(os_event_t *events) { 53 | +extern "C" void __loop_task(os_event_t *events) { 54 | (void) events; 55 | s_micros_at_task_start = system_get_time(); 56 | cont_run(g_pcont, &loop_wrapper); 57 | @@ -189,6 +194,10 @@ 58 | panic(); 59 | } 60 | } 61 | + 62 | +extern "C" void loop_task(os_event_t *events) __attribute__ ((weak, alias("__loop_task"))); 63 | + 64 | + 65 | extern "C" { 66 | 67 | struct object { long placeholder[ 10 ]; }; 68 | diff -ruN 2.6.3/cores/esp8266/spiffs/spiffs_config.h 2.6.3_mod/cores/esp8266/spiffs/spiffs_config.h 69 | --- 2.6.3/cores/esp8266/spiffs/spiffs_config.h 2020-04-25 09:58:37.657733964 -0700 70 | +++ 2.6.3_mod/cores/esp8266/spiffs/spiffs_config.h 2020-04-07 09:39:35.720492000 -0700 71 | @@ -162,7 +162,7 @@ 72 | 73 | // Object name maximum length. 74 | #ifndef SPIFFS_OBJ_NAME_LEN 75 | -#define SPIFFS_OBJ_NAME_LEN (32) 76 | +#define SPIFFS_OBJ_NAME_LEN (64) 77 | #endif 78 | 79 | // Maximum length of the metadata associated with an object. 80 | @@ -210,11 +210,13 @@ 81 | 82 | // define this to enter a mutex if you're running on a multithreaded system 83 | #ifndef SPIFFS_LOCK 84 | -#define SPIFFS_LOCK(fs) 85 | +extern void esp_spiffs_lock(uint32_t*); 86 | +#define SPIFFS_LOCK(fs) esp_spiffs_lock((uint32_t *)fs) 87 | #endif 88 | // define this to exit a mutex if you're running on a multithreaded system 89 | #ifndef SPIFFS_UNLOCK 90 | -#define SPIFFS_UNLOCK(fs) 91 | +extern void esp_spiffs_unlock(uint32_t*); 92 | +#define SPIFFS_UNLOCK(fs) esp_spiffs_unlock((uint32_t *)fs) 93 | #endif 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /core_esp8266_2.7.0.patch: -------------------------------------------------------------------------------- 1 | diff -ruN 2.7.0/cores/esp8266/core_esp8266_main.cpp 2.7.0_mod/cores/esp8266/core_esp8266_main.cpp 2 | --- 2.7.0/cores/esp8266/core_esp8266_main.cpp 2020-04-25 09:58:37.657733964 -0700 3 | +++ 2.7.0_mod/cores/esp8266/core_esp8266_main.cpp 2020-04-06 11:00:58.955024000 -0700 4 | @@ -120,10 +120,12 @@ 5 | 6 | extern "C" void esp_yield() __attribute__ ((weak, alias("__esp_yield"))); 7 | 8 | -extern "C" IRAM_ATTR void esp_schedule() { 9 | +extern "C" IRAM_ATTR void __esp_schedule() { 10 | ets_post(LOOP_TASK_PRIORITY, 0, 0); 11 | } 12 | 13 | +extern "C" void esp_schedule(void) __attribute__ ((weak, alias("__esp_schedule"))); 14 | + 15 | extern "C" void __yield() { 16 | if (can_yield()) { 17 | esp_schedule(); 18 | @@ -136,7 +138,7 @@ 19 | 20 | extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); 21 | 22 | -extern "C" void optimistic_yield(uint32_t interval_us) { 23 | +extern "C" void __optimistic_yield(uint32_t interval_us) { 24 | const uint32_t intvl_cycles = interval_us * 25 | #if defined(F_CPU) 26 | clockCyclesPerMicrosecond(); 27 | @@ -150,6 +152,8 @@ 28 | } 29 | } 30 | 31 | +extern "C" void optimistic_yield(uint32_t interval_us) __attribute__ ((weak, alias("__optimistic_yield"))); 32 | + 33 | // Replace ets_intr_(un)lock with nestable versions 34 | extern "C" void IRAM_ATTR ets_intr_lock() { 35 | if (ets_intr_lock_stack_ptr < ETS_INTR_LOCK_NEST_MAX) 36 | @@ -198,7 +202,7 @@ 37 | esp_schedule(); 38 | } 39 | 40 | -static void loop_task(os_event_t *events) { 41 | +extern "C" void __loop_task(os_event_t *events) { 42 | (void) events; 43 | s_cycles_at_yield_start = ESP.getCycleCount(); 44 | cont_run(g_pcont, &loop_wrapper); 45 | @@ -206,6 +210,9 @@ 46 | panic(); 47 | } 48 | } 49 | + 50 | +extern "C" void loop_task(os_event_t *events) __attribute__ ((weak, alias("__loop_task"))); 51 | + 52 | extern "C" { 53 | 54 | struct object { long placeholder[ 10 ]; }; 55 | diff -ruN 2.7.0/cores/esp8266/spiffs/spiffs_config.h 2.7.0_mod/cores/esp8266/spiffs/spiffs_config.h 56 | --- 2.7.0/cores/esp8266/spiffs/spiffs_config.h 2020-04-25 09:58:37.657733964 -0700 57 | +++ 2.7.0_mod/cores/esp8266/spiffs/spiffs_config.h 2020-04-07 09:39:35.720492000 -0700 58 | @@ -162,7 +162,7 @@ 59 | 60 | // Object name maximum length. 61 | #ifndef SPIFFS_OBJ_NAME_LEN 62 | -#define SPIFFS_OBJ_NAME_LEN (32) 63 | +#define SPIFFS_OBJ_NAME_LEN (64) 64 | #endif 65 | 66 | // Maximum length of the metadata associated with an object. 67 | @@ -210,11 +210,13 @@ 68 | 69 | // define this to enter a mutex if you're running on a multithreaded system 70 | #ifndef SPIFFS_LOCK 71 | -#define SPIFFS_LOCK(fs) 72 | +extern void esp_spiffs_lock(uint32_t*); 73 | +#define SPIFFS_LOCK(fs) esp_spiffs_lock((uint32_t *)fs) 74 | #endif 75 | // define this to exit a mutex if you're running on a multithreaded system 76 | #ifndef SPIFFS_UNLOCK 77 | -#define SPIFFS_UNLOCK(fs) 78 | +extern void esp_spiffs_unlock(uint32_t*); 79 | +#define SPIFFS_UNLOCK(fs) esp_spiffs_unlock((uint32_t *)fs) 80 | #endif 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /examples/SchedulerAlarmClock/Alarm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Alarm.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Alarm task. 20 | */ 21 | 22 | #ifndef ALARM_H 23 | #define ALARM_H 24 | 25 | #include "Clock.h" 26 | 27 | namespace Alarm { 28 | 29 | unsigned long time = 0; 30 | 31 | void setup() 32 | { 33 | } 34 | 35 | void loop() 36 | { 37 | unsigned long seconds = Clock::seconds; 38 | if ((time != 0) && (seconds == time)) { 39 | Serial.println(F("alarm")); 40 | time += 20; 41 | } 42 | await(seconds != Clock::seconds); 43 | } 44 | }; 45 | #endif 46 | -------------------------------------------------------------------------------- /examples/SchedulerAlarmClock/Clock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Clock.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Clock as a task. 20 | */ 21 | 22 | #ifndef CLOCK_H 23 | #define CLOCK_H 24 | 25 | namespace Clock { 26 | 27 | volatile unsigned long seconds = 0; 28 | 29 | void setup() 30 | { 31 | } 32 | 33 | void loop() 34 | { 35 | unsigned long start = millis(); 36 | await(millis() - start >= 1000); 37 | seconds += 1; 38 | } 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /examples/SchedulerAlarmClock/SchedulerAlarmClock.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerAlarmClock.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library. 20 | */ 21 | 22 | #include 23 | 24 | #include "Clock.h" 25 | #include "Alarm.h" 26 | 27 | // Check for SparkFun SAMD21 Breakout 28 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 29 | #define Serial SerialUSB 30 | #endif 31 | 32 | void setup() 33 | { 34 | Serial.begin(57600); 35 | while (!Serial); 36 | Serial.println(F("SchedulerAlarmClock: started")); 37 | 38 | // Initiate tasks 39 | Scheduler.start(Clock::setup, Clock::loop); 40 | Scheduler.start(Alarm::setup, Alarm::loop); 41 | 42 | // Set alarm time 43 | Alarm::time = 15; 44 | } 45 | 46 | void loop() 47 | { 48 | unsigned long seconds = Clock::seconds; 49 | unsigned long minutes = seconds / 60; 50 | unsigned long hours = minutes / 60; 51 | Serial.print(millis()); 52 | Serial.print(':'); 53 | Serial.print(hours); 54 | Serial.print(':'); 55 | Serial.print(minutes % 60); 56 | Serial.print(':'); 57 | Serial.println(seconds % 60); 58 | await(seconds != Clock::seconds); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /examples/SchedulerBenchmark/SchedulerBenchmark.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBenchmark.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Benchmark Scheduler library. 20 | * 21 | * @section Results Arduino 1.6.7, Arduino Pro-Mini 22 | * SchedulerBenchmark: started 23 | * 1. Initiate scheduler and main task: 4 us 24 | * 2. Yield main task: 11.00 us 25 | * 3. Start a task: 20 us 26 | * 4. Yield between two tasks: 22.89 us 27 | * 5. Delay 10 ms and check increments: 10028:381, 26.32 us 28 | * 6. Start 8 tasks: 148:8, 18.50 us 29 | * 7. Yield and check increments: 120:9, 13.33 us 30 | * 8. Delay 10 ms and check increments: 10088:747, 13.50 us 31 | * 32 | * @section Results Arduino 1.6.7, Arduino Mega 2560 33 | * SchedulerBenchmark: started 34 | * 1. Initiate scheduler and main task: 4 us 35 | * 2. Yield main task: 12.64 us 36 | * 3. Start a task: 24 us 37 | * 4. Yield between two tasks: 26.16 us 38 | * 5. Delay 10 ms and check increments: 10028:338, 29.67 us 39 | * 6. Start 46 tasks: 860:46, 18.70 us 40 | * 7. Yield and check increments: 648:47, 13.79 us 41 | * 8. Delay 10 ms and check increments: 10436:752, 13.88 us 42 | * 43 | * @section Results Arduino 1.6.7, Arduino Due 44 | * SchedulerBenchmark: started 45 | * 1. Initiate scheduler and main task: 2 us 46 | * 2. Yield main task: 1.30 us 47 | * 3. Start a task: 3 us 48 | * 4. Yield between two tasks: 2.80 us 49 | * 5. Delay 10 ms and check increments: 9497:3186, 2.98 us 50 | * 6. Start 51 tasks: 112:51, 2.20 us 51 | * 7. Yield and check increments: 78:52, 1.50 us 52 | * 8. Delay 10 ms and check increments: 9874:6500, 1.52 us 53 | * 54 | * @section Results Arduino 1.6.7, Teensy 3.1 (72 MHz) 55 | * SchedulerBenchmark: started 56 | * 1. Initiate scheduler and main task: 1 us 57 | * 2. Yield main task: 1.10 us 58 | * 3. Start a task: 2 us 59 | * 4. Yield between two tasks: 2.51 us 60 | * 5. Delay 10 ms and check increments: 10003:3105, 3.22 us 61 | * 6. Start 24 tasks: 38:24, 1.58 us 62 | * 7. Yield and check increments: 30:25, 1.20 us 63 | * 8. Delay 10 ms and check increments: 10015:6950, 1.44 us 64 | */ 65 | 66 | #include 67 | 68 | // Check for SparkFun SAMD21 Breakout 69 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 70 | #define Serial SerialUSB 71 | #endif 72 | 73 | int counter = 0; 74 | 75 | void setup() 76 | { 77 | unsigned long start, stop, us; 78 | int nr; 79 | 80 | Serial.begin(115200); 81 | while (!Serial); 82 | 83 | 84 | for(int i=0; i<10000; i++) 85 | Serial.print("."); 86 | 87 | Serial.println(F("SchedulerBenchmark: started")); 88 | Serial.flush(); 89 | 90 | // 1. Measure initiate scheduler 91 | start = micros(); 92 | //Scheduler.begin(1024); 93 | stop = micros(); 94 | us = stop - start; 95 | Serial.print(F("1. Initiate scheduler and main task: ")); 96 | Serial.print(us); 97 | Serial.println(F(" us")); 98 | Serial.flush(); 99 | 100 | // 2. Measure yield with single task 101 | start = micros(); 102 | for (int i = 0; i < 10000; i++) 103 | yield(); 104 | stop = micros(); 105 | us = stop - start; 106 | Serial.print(F("2. Yield main task: ")); 107 | Serial.print(us / 10000.0); 108 | Serial.println(F(" us")); 109 | Serial.flush(); 110 | 111 | // 3. Measure start of task 112 | start = micros(); 113 | Scheduler.start(NULL, incrementCounter); 114 | stop = micros(); 115 | us = stop - start; 116 | Serial.print(F("3. Start a task: ")); 117 | Serial.print(us); 118 | Serial.println(F(" us")); 119 | Serial.flush(); 120 | 121 | // 4. Measure yield between two tasks 122 | start = micros(); 123 | for (int i = 0; i < 10000; i++) 124 | yield(); 125 | stop = micros(); 126 | us = stop - start; 127 | if (counter != 10000) Serial.println(F("Error: counter")); 128 | Serial.print(F("4. Yield between two tasks: ")); 129 | Serial.print(us / 10000.0); 130 | Serial.println(F(" us")); 131 | Serial.flush(); 132 | 133 | // 5. Measure counter update during 10 ms delay 134 | counter = 0; 135 | start = micros(); 136 | delay(10); 137 | stop = micros(); 138 | us = stop - start; 139 | Serial.print(F("5. Delay 10 ms and check increments: ")); 140 | Serial.print(us); 141 | Serial.print(F(":")); 142 | Serial.print(counter); 143 | Serial.print(F(", ")); 144 | Serial.print(us / (float) counter); 145 | Serial.println(F(" us")); 146 | Serial.flush(); 147 | 148 | // 6. Measure max number of tasks 149 | start = micros(); 150 | nr = 0; 151 | //while (Scheduler.start(NULL, incrementCounter)) nr++; 152 | for(nr =0; nr < 5; nr++) 153 | Scheduler.start(NULL, incrementCounter); 154 | stop = micros(); 155 | us = stop - start; 156 | Serial.print(F("6. Start ")); 157 | Serial.print(nr); 158 | Serial.print(F(" tasks: ")); 159 | Serial.print(us); 160 | Serial.print(F(":")); 161 | Serial.print(nr); 162 | Serial.print(F(", ")); 163 | Serial.print(us / (float) nr); 164 | Serial.println(F(" us")); 165 | Serial.flush(); 166 | 167 | // 7. Measure one yield cycle with max tasks 168 | counter = 0; 169 | start = micros(); 170 | yield(); 171 | stop = micros(); 172 | us = stop - start; 173 | Serial.print(F("7. Yield and check increments: ")); 174 | Serial.print(us); 175 | Serial.print(F(":")); 176 | Serial.print(counter); 177 | Serial.print(F(", ")); 178 | Serial.print(us / (float) counter); 179 | Serial.println(F(" us")); 180 | Serial.flush(); 181 | 182 | // 8. Measure counter update during 10 ms delay with max tasks 183 | counter = 0; 184 | start = micros(); 185 | delay(10); 186 | stop = micros(); 187 | us = stop - start; 188 | Serial.print(F("8. Delay 10 ms and check increments: ")); 189 | Serial.print(us); 190 | Serial.print(F(":")); 191 | Serial.print(counter); 192 | Serial.print(F(", ")); 193 | Serial.print(us / (float) counter); 194 | Serial.println(F(" us")); 195 | Serial.flush(); 196 | } 197 | unsigned int x = 1000000; 198 | void loop() 199 | { 200 | if(x > 100000) 201 | panic(); 202 | 203 | x++; 204 | 205 | yield(); 206 | } 207 | 208 | void incrementCounter() 209 | { 210 | counter += 1; 211 | delay(1); 212 | Serial.println("I"); 213 | yield(); 214 | } 215 | 216 | -------------------------------------------------------------------------------- /examples/SchedulerBenchmarkChannel/SchedulerBenchmarkChannel.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBenchmarkChannel.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Benchmark Scheduler Channel. 20 | * 21 | * @section Results Arduino 1.6.7 22 | * Messages per second (send/recv). PAYLOAD 1, 8 23 | * Arduino Pro-Mini 23921 (41.80 us), 22002 (45.45 us) 24 | * Arduino Mega 2560 21379 (46.77 us), 19834 (50.41 us) 25 | * Arduino Due 165322 (6.05 us), 160893 (6.22 us) 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | // Check for SparkFun SAMD21 Breakout 32 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 33 | #define Serial SerialUSB 34 | #endif 35 | 36 | // const size_t PAYLOAD_MAX = 1; 37 | const size_t PAYLOAD_MAX = 8; 38 | struct msg_t { 39 | uint8_t payload[PAYLOAD_MAX]; 40 | }; 41 | 42 | Channel chan; 43 | unsigned long count = 0; 44 | 45 | void setup() 46 | { 47 | Serial.begin(57600); 48 | while (!Serial); 49 | Serial.println(F("SchedulerBenchmarkChannel: started")); 50 | Serial.flush(); 51 | 52 | Scheduler.start(NULL, producer); 53 | Scheduler.start(NULL, consumer); 54 | } 55 | 56 | void loop() 57 | { 58 | unsigned long start = millis(); 59 | await(millis() - start >= 1000); 60 | Serial.print(count); 61 | Serial.print(F(" (")); 62 | Serial.print(1000000.0 / count); 63 | Serial.println(F(" us)")); 64 | Serial.flush(); 65 | count = 0; 66 | } 67 | 68 | void producer() 69 | { 70 | msg_t msg; 71 | while (1) 72 | chan.send(&msg, sizeof(msg)); 73 | } 74 | 75 | void consumer() 76 | { 77 | msg_t msg; 78 | while (1) { 79 | chan.recv(&msg, sizeof(msg)); 80 | count += 1; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/SchedulerBenchmarkQueue/SchedulerBenchmarkQueue.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBenchmarkQueue.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Benchmark Scheduler Queue. 20 | * 21 | * @section Results Arduino 1.6.7 22 | * Events per second (push/pull). QUEUE_MAX 2, 8 23 | * Arduino Pro-Mini 24029 (41.62 us), 92638 (10.79 us) 24 | * Arduino Mega 2560 21466 (46.59 us), 86919 (11.50 us) 25 | * Arduino Due 183411 (5.45 us), 677502 (1.48 us) 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | // Check for SparkFun SAMD21 Breakout 32 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 33 | #define Serial SerialUSB 34 | #endif 35 | 36 | // const unsigned int QUEUE_MAX = 2; 37 | const unsigned int QUEUE_MAX = 8; 38 | typedef int event_t; 39 | Queue queue; 40 | unsigned long count = 0; 41 | 42 | void setup() 43 | { 44 | Serial.begin(57600); 45 | while (!Serial); 46 | Serial.println(F("SchedulerBenchmarkQueue: started")); 47 | Serial.flush(); 48 | 49 | Scheduler.start(NULL, producer); 50 | Scheduler.start(NULL, consumer); 51 | } 52 | 53 | void loop() 54 | { 55 | unsigned long start = millis(); 56 | await(millis() - start >= 1000); 57 | Serial.print(count); 58 | Serial.print(F(" (")); 59 | Serial.print(1000000.0 / count); 60 | Serial.println(F(" us)")); 61 | Serial.flush(); 62 | count = 0; 63 | } 64 | 65 | void producer() 66 | { 67 | event_t event = 0; 68 | while (1) queue.push(&event); 69 | } 70 | 71 | void consumer() 72 | { 73 | event_t event; 74 | while (1) { 75 | queue.pull(&event); 76 | count += 1; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /examples/SchedulerBenchmarkSemaphore/SchedulerBenchmarkSemaphore.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBenchmarkSemaphore.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Benchmark Scheduler Semaphore. 20 | * 21 | * @section Results Arduino 1.6.7 22 | * Semaphore wait/signal per seconds. 23 | * Arduino Pro-Mini 26337 (37.97 us) 24 | * Arduino Mega 2560 23289 (42.94 us) 25 | * Arduino Due 196770 (5.08 us) 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | // Check for SparkFun SAMD21 Breakout 32 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 33 | #define Serial SerialUSB 34 | #endif 35 | 36 | Semaphore semaphore(0); 37 | unsigned long count = 0; 38 | 39 | void setup() 40 | { 41 | Serial.begin(57600); 42 | while (!Serial); 43 | Serial.println(F("SchedulerBenchmarkSemaphore: started")); 44 | Serial.flush(); 45 | 46 | Scheduler.start(NULL, producer); 47 | Scheduler.start(NULL, consumer); 48 | } 49 | 50 | void loop() 51 | { 52 | unsigned long start = millis(); 53 | await(millis() - start >= 1000); 54 | Serial.print(count); 55 | Serial.print(F(" (")); 56 | Serial.print(1000000.0 / count); 57 | Serial.println(F(" us)")); 58 | Serial.flush(); 59 | count = 0; 60 | } 61 | 62 | void producer() 63 | { 64 | while (1) semaphore.signal(); 65 | } 66 | 67 | void consumer() 68 | { 69 | while (1) { 70 | semaphore.wait(); 71 | count += 1; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /examples/SchedulerBenchmarkSize/SchedulerBenchmarkSize.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBenchmarkSize.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Benchmark size of Scheduler library. 20 | * 21 | * @section Results Arduino 1.6.7 22 | * Board Baseline Total Size 23 | * Arduino Pro-Mini 1810/200 2356/242 546/42 24 | * Arduino Mega 2560 2098/200 2646/244 548/44 25 | * Arduino Due 10204/-- 10428/-- 224/-- 26 | * Teensy 3.1 (72 MHz) 16312/4644 10556/4304 ???/??? 27 | */ 28 | 29 | // Comment for baseline 30 | #define TASKS 31 | 32 | #ifdef TASKS 33 | #include 34 | 35 | // Check for SparkFun SAMD21 Breakout 36 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 37 | #define Serial SerialUSB 38 | #endif 39 | 40 | #endif 41 | 42 | void setup() 43 | { 44 | Serial.begin(57600); 45 | while (!Serial); 46 | Serial.println(F("SchedulerBenchmarkSize: started")); 47 | Serial.flush(); 48 | 49 | #ifdef TASKS 50 | Scheduler.start(NULL, loop); 51 | #endif 52 | } 53 | 54 | void loop() 55 | { 56 | yield(); 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /examples/SchedulerBlink/SchedulerBlink.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBlink.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library to blink four 20 | * LEDs with different speed. Each LED is controlled by a separate 21 | * task. 22 | */ 23 | 24 | #include 25 | 26 | const int led = 13; 27 | 28 | void setup() 29 | { 30 | pinMode(led, OUTPUT); 31 | 32 | Scheduler.start(setup1, loop1); 33 | Scheduler.start(setup2, loop2); 34 | Scheduler.start(setup3, loop3); 35 | } 36 | 37 | void loop() 38 | { 39 | blink(led, 1000); 40 | } 41 | 42 | const int led1 = 10; 43 | 44 | void setup1() 45 | { 46 | pinMode(led1, OUTPUT); 47 | } 48 | 49 | void loop1() 50 | { 51 | blink(led1, 250); 52 | } 53 | 54 | const int led2 = 11; 55 | 56 | void setup2() 57 | { 58 | pinMode(led2, OUTPUT); 59 | } 60 | 61 | void loop2() 62 | { 63 | blink(led2, 500); 64 | } 65 | 66 | const int led3 = 12; 67 | 68 | void setup3() 69 | { 70 | pinMode(led3, OUTPUT); 71 | } 72 | 73 | void loop3() 74 | { 75 | blink(led3, 750); 76 | } 77 | 78 | void blink(int pin, unsigned int ms) 79 | { 80 | digitalWrite(pin, HIGH); 81 | delay(ms); 82 | digitalWrite(pin, LOW); 83 | delay(ms); 84 | } 85 | -------------------------------------------------------------------------------- /examples/SchedulerBlinkController/SchedulerBlinkController.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBlinkController.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library to control and 20 | * blink built-in LED. Send '1' to turn LED on and '0' to turn off. 21 | */ 22 | 23 | #include 24 | 25 | // Check for SparkFun SAMD21 Breakout 26 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 27 | #define Serial SerialUSB 28 | #endif 29 | 30 | const int LED = 13; 31 | volatile unsigned int period = 0; 32 | 33 | void setup() 34 | { 35 | Serial.begin(57600); 36 | while (!Serial); 37 | Serial.println(F("SchedulerBlinkController: started")); 38 | 39 | pinMode(LED, OUTPUT); 40 | digitalWrite(LED, LOW); 41 | Serial.print(millis()); 42 | Serial.println(F(":LED off")); 43 | Serial.flush(); 44 | 45 | Scheduler.start(NULL, controllerLoop); 46 | Scheduler.start(NULL, buttonLoop); 47 | } 48 | 49 | void loop() 50 | { 51 | await(period != 0); 52 | digitalWrite(LED, HIGH); 53 | delay(period); 54 | digitalWrite(LED, LOW); 55 | if (period == 0) return; 56 | delay(period); 57 | } 58 | 59 | void controllerLoop() 60 | { 61 | unsigned int ms = 100; 62 | for (; ms < 1000; ms += 100) { 63 | delay(2000); 64 | if (period == 0) return; 65 | period = ms; 66 | Serial.print(millis()); 67 | Serial.print(F(":period = ")); 68 | Serial.println(ms); 69 | } 70 | for (; ms > 100; ms -= 100) { 71 | delay(2000); 72 | if (period == 0) return; 73 | period = ms; 74 | Serial.print(millis()); 75 | Serial.print(F(":period = ")); 76 | Serial.println(ms); 77 | } 78 | } 79 | 80 | void buttonLoop() 81 | { 82 | unsigned long start = millis(); 83 | await(Serial.available() != 0); 84 | unsigned long stop = millis(); 85 | unsigned long ms = stop - start; 86 | int c = Serial.read(); 87 | if (c == '0' && period != 0) { 88 | Serial.print(stop); 89 | Serial.print(':'); 90 | Serial.print(ms); 91 | Serial.println(F(":LED off")); 92 | period = 0; 93 | } 94 | else if (c == '1' && period == 0) { 95 | Serial.print(stop); 96 | Serial.print(':'); 97 | Serial.print(ms); 98 | Serial.println(F(":LED on")); 99 | period = 100; 100 | } 101 | } 102 | 103 | 104 | -------------------------------------------------------------------------------- /examples/SchedulerBlinkMax/SchedulerBlinkMax.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBlinkMax.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library. 20 | * Blink with max number of pins; 64 bytes per task. 21 | */ 22 | 23 | #include 24 | 25 | int next_pin = 2; 26 | int stack; 27 | 28 | void blink() 29 | { 30 | // Allocate a pin and set output mode 31 | int pin = next_pin++; 32 | pinMode(pin, OUTPUT); 33 | 34 | // Capture stack available 35 | stack = Scheduler.stack(); 36 | 37 | // Toggle the pin on and off 38 | while (1) { 39 | digitalWrite(pin, HIGH); 40 | delay(500); 41 | digitalWrite(pin, LOW); 42 | delay(500); 43 | } 44 | } 45 | 46 | void setup() 47 | { 48 | Serial.begin(57600); 49 | while (!Serial); 50 | Serial.println(F("SchedulerBlinkMax: started")); 51 | Serial.flush(); 52 | 53 | // Start a blink task for each pin (use 64 byte stack) 54 | int tasks = 0; 55 | const int TASKS_MAX = NUM_DIGITAL_PINS - 2; 56 | while (tasks < TASKS_MAX && Scheduler.start(NULL, blink, 64)) tasks++; 57 | Serial.print(millis()); 58 | Serial.print(F(":setup::task=")); 59 | Serial.println(tasks); 60 | 61 | // Run blink tasks startup and print stack available 62 | yield(); 63 | Serial.print(millis()); 64 | Serial.print(F(":setup::stack=")); 65 | Serial.println(stack); 66 | } 67 | 68 | void loop() 69 | { 70 | // Print the iteration count 71 | static unsigned int i = 0; 72 | Serial.print(millis()); 73 | Serial.print(F(":loop::i=")); 74 | Serial.println(i++); 75 | 76 | // Delay gracefully 77 | unsigned long start = millis(); 78 | await((millis() - start) >= 1000); 79 | } 80 | -------------------------------------------------------------------------------- /examples/SchedulerBlinkTemplateClass/Blink.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Blink.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library. 20 | * Blink as a template class. 21 | */ 22 | 23 | #ifndef BLINK_H 24 | #define BLINK_H 25 | 26 | template 27 | class Blink { 28 | public: 29 | static void setup() 30 | { 31 | pinMode(PIN, OUTPUT); 32 | } 33 | static void loop() 34 | { 35 | digitalWrite(PIN, HIGH); 36 | delay(MS); 37 | digitalWrite(PIN, LOW); 38 | delay(MS); 39 | } 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /examples/SchedulerBlinkTemplateClass/SchedulerBlinkTemplateClass.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBlinkTemplateClass.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library. Rewrite of 20 | * SchedulerBlink with template class. 21 | */ 22 | 23 | #include 24 | #include "Blink.h" 25 | 26 | // Blink task functions with pin and delay period 27 | Blink<10, 250> blink1; 28 | Blink<11, 500> blink2; 29 | Blink<12, 750> blink3; 30 | Blink<13, 1000> blink; 31 | 32 | void setup() 33 | { 34 | blink.setup(); 35 | Scheduler.start(blink1.setup, blink1.loop); 36 | Scheduler.start(blink2.setup, blink2.loop); 37 | Scheduler.start(blink3.setup, blink3.loop); 38 | } 39 | 40 | void loop() 41 | { 42 | blink.loop(); 43 | } 44 | -------------------------------------------------------------------------------- /examples/SchedulerBlinkTemplateFunctions/SchedulerBlinkTemplateFunctions.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerBlinkTemplateFunctions.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library. Rewrite of 20 | * SchedulerBlink with template functions for Blink setup and loop. 21 | */ 22 | 23 | #include 24 | 25 | template void setupBlink() 26 | { 27 | pinMode(pin, OUTPUT); 28 | } 29 | 30 | template void loopBlink() 31 | { 32 | digitalWrite(pin, HIGH); 33 | delay(ms); 34 | digitalWrite(pin, LOW); 35 | delay(ms); 36 | } 37 | 38 | void setup() 39 | { 40 | setupBlink<13>(); 41 | Scheduler.start(setupBlink<10>, loopBlink<10,250>); 42 | Scheduler.start(setupBlink<11>, loopBlink<11,500>); 43 | Scheduler.start(setupBlink<12>, loopBlink<12,750>); 44 | } 45 | 46 | void loop() 47 | { 48 | loopBlink<13,1000>(); 49 | } 50 | -------------------------------------------------------------------------------- /examples/SchedulerChannel/SchedulerChannel.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerChannel.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library; 20 | * Message channel between tasks; two senders and one receiver. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | // Check for SparkFun SAMD21 Breakout 27 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 28 | #define Serial SerialUSB 29 | #endif 30 | 31 | Channel chan; 32 | 33 | void setup() 34 | { 35 | Serial.begin(57600); 36 | while (!Serial); 37 | Serial.println(F("SchedulerChannel: started")); 38 | Serial.flush(); 39 | 40 | Scheduler.start(NULL, messageSender); 41 | Scheduler.start(NULL, messageSender); 42 | Scheduler.start(NULL, messageReceiver); 43 | Scheduler.start(NULL, messageReceiver); 44 | } 45 | 46 | void loop() 47 | { 48 | static unsigned int count = 0; 49 | Serial.print(millis()); 50 | Serial.print(F(":loop:count=")); 51 | Serial.println(count++); 52 | unsigned long start = millis(); 53 | await(millis() - start >= 1000); 54 | } 55 | 56 | struct msg_t { 57 | int ref; 58 | unsigned int nr; 59 | }; 60 | 61 | void messageSender() 62 | { 63 | msg_t msg = { (int) &msg, 0 }; 64 | while (1) { 65 | Serial.print(millis()); 66 | Serial.print(F(":messageSender#")); 67 | Serial.print(msg.ref); 68 | Serial.print(F("::send msg.nr=")); 69 | Serial.println(msg.nr); 70 | chan.send(&msg, sizeof(msg)); 71 | msg.nr += 1; 72 | delay(random(500)); 73 | } 74 | } 75 | 76 | void messageReceiver() 77 | { 78 | msg_t msg; 79 | chan.recv(&msg, sizeof(msg)); 80 | Serial.print(millis()); 81 | Serial.print(F(":messageReceiver#")); 82 | Serial.print((int) &msg); 83 | Serial.print(F("::receive msg.ref=")); 84 | Serial.print(msg.ref); 85 | Serial.print(F(", msg.nr=")); 86 | Serial.println(msg.nr); 87 | delay(random(1000)); 88 | } 89 | -------------------------------------------------------------------------------- /examples/SchedulerDebounce/SchedulerDebounce.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerDebounce.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library; 20 | * Software debounce a button. 21 | */ 22 | 23 | #include 24 | 25 | // Check for SparkFun SAMD21 Breakout 26 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 27 | #define Serial SerialUSB 28 | #endif 29 | 30 | unsigned int count = 0; 31 | 32 | void setup() 33 | { 34 | Serial.begin(57600); 35 | while (!Serial); 36 | Serial.println(F("SchedulerDebounce: started")); 37 | Scheduler.start(debounceSetup, debounceLoop); 38 | } 39 | 40 | void loop() 41 | { 42 | Serial.print(millis()); 43 | Serial.print(F(":loop::count=")); 44 | Serial.println(count); 45 | delay(1000); 46 | } 47 | 48 | const int BUTTON = 4; 49 | volatile int state; 50 | 51 | void debounceSetup() 52 | { 53 | pinMode(BUTTON, INPUT_PULLUP); 54 | } 55 | 56 | void debounceLoop() 57 | { 58 | const unsigned int DEBOUNCE = 50; 59 | state = digitalRead(BUTTON); 60 | while (1) { 61 | await(digitalRead(BUTTON) != state); 62 | state = !state; 63 | if (state) 64 | buttonUp(); 65 | else 66 | buttonDown(); 67 | delay(DEBOUNCE); 68 | } 69 | } 70 | 71 | void buttonDown() 72 | { 73 | Serial.print(millis()); 74 | Serial.println(F(":buttonDown")); 75 | count += 1; 76 | } 77 | 78 | void buttonUp() 79 | { 80 | Serial.print(millis()); 81 | Serial.println(F(":buttonUp")); 82 | } 83 | -------------------------------------------------------------------------------- /examples/SchedulerDebounceTemplate/Debounce.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Debounce.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Debounce task template class. 20 | */ 21 | 22 | #ifndef DEBOUNCE_H 23 | #define DEBOUNCE_H 24 | 25 | template 26 | class Debounce { 27 | public: 28 | static void setup() 29 | { 30 | pinMode(PIN, INPUT_PULLUP); 31 | } 32 | static void loop() 33 | { 34 | const unsigned int DEBOUNCE = 50; 35 | int state = digitalRead(PIN); 36 | while (1) { 37 | await(digitalRead(PIN) != state); 38 | unsigned int start = millis(); 39 | if (state) CALLBACK(); 40 | unsigned int ms = millis() - start; 41 | if (ms < DEBOUNCE) delay(DEBOUNCE - ms); 42 | state = !state; 43 | } 44 | } 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /examples/SchedulerDebounceTemplate/SchedulerDebounceTemplate.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerDebounceTemplate.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library; 20 | * Rewrite of SchedulerDebounce with Debounce task template class. 21 | */ 22 | 23 | #include 24 | #include "Debounce.h" 25 | 26 | // Check for SparkFun SAMD21 Breakout 27 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 28 | #define Serial SerialUSB 29 | #endif 30 | 31 | const int BUTTON = 4; 32 | unsigned int count = 0; 33 | 34 | void buttonDown() 35 | { 36 | Serial.print(millis()); 37 | Serial.println(F(":buttonDown")); 38 | count += 1; 39 | } 40 | 41 | Debounce button; 42 | 43 | void setup() 44 | { 45 | Serial.begin(57600); 46 | while (!Serial); 47 | Serial.println(F("SchedulerDebounceTemplate: started")); 48 | Scheduler.start(button.setup, button.loop); 49 | } 50 | 51 | void loop() 52 | { 53 | Serial.print(millis()); 54 | Serial.print(F(":loop::count=")); 55 | Serial.println(count); 56 | delay(1000); 57 | } 58 | -------------------------------------------------------------------------------- /examples/SchedulerDemo/SchedulerDemo.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerDemo.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library. 20 | * Two tasks are scheduled together with the main task. 21 | * 1. The main task prints an iteration number and delays. 22 | * 2. The second task blinks the built-in LED and prints the 23 | * current status. 24 | * 3. The third task reads a line from Serial input. The line is 25 | * printed with number of yields during the input wait. 26 | */ 27 | 28 | #include 29 | 30 | // Check for SparkFun SAMD21 Breakout 31 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 32 | #define Serial SerialUSB 33 | #endif 34 | 35 | void setup() 36 | { 37 | Serial.begin(57600); 38 | while (!Serial); 39 | Serial.println(F("SchedulerDemo: started")); 40 | 41 | Serial.print(millis()); 42 | Serial.println(F(":setup")); 43 | 44 | Scheduler.start(setup2, loop2); 45 | Scheduler.start(setup3, loop3); 46 | } 47 | 48 | void loop() 49 | { 50 | // Main loop iteraction count 51 | static int i = 0; 52 | 53 | // Print main loop iterations 54 | Serial.print(millis()); 55 | Serial.print(F(":loop::i=")); 56 | Serial.println(i++); 57 | delay(500); 58 | } 59 | 60 | const int LED = 13; 61 | 62 | void setup2() 63 | { 64 | Serial.print(millis()); 65 | Serial.println(F(":setup2")); 66 | pinMode(LED, OUTPUT); 67 | } 68 | 69 | void loop2() 70 | { 71 | // Turn LED off 72 | Serial.print(millis()); 73 | Serial.println(F(":loop2::led off")); 74 | digitalWrite(LED, LOW); 75 | delay(1000); 76 | 77 | // Turn LED on 78 | Serial.print(millis()); 79 | Serial.println(F(":loop2::led on")); 80 | digitalWrite(LED, HIGH); 81 | delay(1000); 82 | } 83 | 84 | void setup3() 85 | { 86 | Serial.print(millis()); 87 | Serial.println(F(":setup3")); 88 | } 89 | 90 | void loop3() 91 | { 92 | static char* buf = NULL; 93 | 94 | // Check for buffer allocation 95 | if (buf == NULL) { 96 | buf = (char*) malloc(64); 97 | Serial.print(millis()); 98 | Serial.print(F(":loop3:alloc:buf=0x")); 99 | Serial.println((int) buf, HEX); 100 | if (buf == NULL) { 101 | delay(1000); 102 | return; 103 | } 104 | } 105 | 106 | // Read line and yield while waiting for characters 107 | // Capture wait time and number of yields 108 | char* bp = buf; 109 | unsigned long yields = 0; 110 | unsigned long start = millis(); 111 | int c; 112 | while ((c = Serial.read()) != '\n') { 113 | if (c > 0) 114 | *bp++ = c; 115 | else { 116 | yields += 1; 117 | yield(); 118 | } 119 | } 120 | *bp = 0; 121 | 122 | // Print wait time, number of yields and line 123 | unsigned long stop = millis(); 124 | unsigned long ms = stop - start; 125 | Serial.print(millis()); 126 | Serial.print(F(":loop3:yields=")); 127 | Serial.print(yields); 128 | Serial.print(F(",ms=")); 129 | Serial.print(ms); 130 | Serial.print(F(",buf=")); 131 | Serial.println(buf); 132 | 133 | // Check for buffer free command 134 | if (!strcmp_P(buf, (const char*) F("free"))) { 135 | Serial.print(millis()); 136 | Serial.print(F(":loop3:free:buf=0x")); 137 | Serial.println((int) buf, HEX); 138 | free(buf); 139 | delay(500); 140 | buf = NULL; 141 | } 142 | } 143 | 144 | -------------------------------------------------------------------------------- /examples/SchedulerDemoNamespaces/BlinkTask.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file BlinkTask.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * BlinkTask demo as namespace. 20 | */ 21 | 22 | #ifndef BLINK_TASK_H 23 | #define BLINK_TASK_H 24 | 25 | #include 26 | #include "Trace.h" 27 | 28 | namespace BlinkTask { 29 | 30 | const unsigned int PERIOD = 1000; 31 | const int LED = 13; 32 | 33 | void setup() 34 | { 35 | TRACE("stack="); 36 | Serial.println(Scheduler.stack()); 37 | 38 | TRACELN("led output"); 39 | pinMode(LED, OUTPUT); 40 | } 41 | 42 | void loop() 43 | { 44 | TRACE("stack="); 45 | Serial.println(Scheduler.stack()); 46 | 47 | TRACELN("led off"); 48 | digitalWrite(LED, LOW); 49 | delay(PERIOD); 50 | 51 | TRACELN("led on"); 52 | digitalWrite(LED, HIGH); 53 | delay(PERIOD); 54 | } 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /examples/SchedulerDemoNamespaces/SchedulerDemoNamespaces.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerDemoNamespaces.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library. 20 | * Rewrite of the SchedulerDemo sketch using namespaces for 21 | * each task. 22 | */ 23 | 24 | #include 25 | 26 | // Check for SparkFun SAMD21 Breakout 27 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 28 | #define Serial SerialUSB 29 | #endif 30 | 31 | #include "Trace.h" 32 | #include "BlinkTask.h" 33 | #include "ShellTask.h" 34 | 35 | void setup() 36 | { 37 | Serial.begin(57600); 38 | while (!Serial); 39 | Serial.println(F("SchedulerDemoNamespaces: started")); 40 | 41 | // Initiate tasks 42 | Scheduler.start(BlinkTask::setup, BlinkTask::loop); 43 | Scheduler.start(ShellTask::setup, ShellTask::loop); 44 | 45 | // Print stack size 46 | TRACE("stack="); 47 | Serial.println(Scheduler.stack()); 48 | } 49 | 50 | void loop() 51 | { 52 | // Main loop iteration count 53 | static int i = 0; 54 | 55 | // Print main loop iterations 56 | TRACE("i="); 57 | Serial.println(i++); 58 | delay(500); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /examples/SchedulerDemoNamespaces/ShellTask.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ShellTask.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * ShellTask demo as namespace. 20 | */ 21 | 22 | #ifndef SHELL_TASK_H 23 | #define SHELL_TASK_H 24 | 25 | #include 26 | #include "Trace.h" 27 | 28 | namespace ShellTask { 29 | 30 | const size_t BUF_MAX = 64; 31 | static char* buf = NULL; 32 | 33 | void setup() 34 | { 35 | TRACE("stack="); 36 | Serial.println(Scheduler.stack()); 37 | } 38 | 39 | void loop() 40 | { 41 | // Check for buffer allocation 42 | if (buf == NULL) { 43 | buf = (char*) malloc(BUF_MAX); 44 | TRACE("malloc:buf=0x"); 45 | Serial.println((int) buf, HEX); 46 | if (buf == NULL) { 47 | delay(1000); 48 | return; 49 | } 50 | } 51 | 52 | // Read line and yield while waiting for characters 53 | // Capture wait time and number of yields 54 | char* bp = buf; 55 | unsigned long yields = 0; 56 | unsigned long start = millis(); 57 | int c; 58 | TRACE("stack="); 59 | Serial.println(Scheduler.stack()); 60 | while ((c = Serial.read()) != '\n') { 61 | if (c > 0) 62 | *bp++ = c; 63 | else { 64 | yields += 1; 65 | yield(); 66 | } 67 | } 68 | *bp = 0; 69 | 70 | // Print wait time, number of yields and line 71 | unsigned long stop = millis(); 72 | unsigned long ms = stop - start; 73 | TRACE("yields="); 74 | Serial.print(yields); 75 | Serial.print(F(",ms=")); 76 | Serial.print(ms); 77 | Serial.print(F(",buf=")); 78 | Serial.println(buf); 79 | 80 | // Check for buffer free command 81 | if (!strcmp_P(buf, (const char*) F("free"))) { 82 | TRACE("free:buf=0x"); 83 | Serial.println((int) buf, HEX); 84 | free(buf); 85 | delay(500); 86 | buf = NULL; 87 | } 88 | } 89 | }; 90 | #endif 91 | -------------------------------------------------------------------------------- /examples/SchedulerDemoNamespaces/Trace.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Trace.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Some serial trace support macros. 20 | */ 21 | 22 | #ifndef TRACE_H 23 | #define TRACE_H 24 | 25 | #define TRACE(msg) \ 26 | do { \ 27 | Serial.print(millis()); \ 28 | Serial.print(':'); \ 29 | Serial.print(__PRETTY_FUNCTION__); \ 30 | Serial.print(':'); \ 31 | Serial.print(F(msg)); \ 32 | } while (0) 33 | 34 | #define TRACELN(msg) \ 35 | do { \ 36 | TRACE(msg); \ 37 | Serial.println(); \ 38 | } while (0) 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /examples/SchedulerEvent/SchedulerEvent.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerEvent.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library; 20 | * Pass events between tasks. 21 | */ 22 | 23 | #include 24 | 25 | // Check for SparkFun SAMD21 Breakout 26 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 27 | #define Serial SerialUSB 28 | #endif 29 | 30 | class Event { 31 | public: 32 | /** 33 | * Initiate task event. 34 | */ 35 | Event() : m_event(0) {} 36 | 37 | /** 38 | * Wait for task event. Returns event code (non zero). 39 | * Typically called by event handler. 40 | * @return event. 41 | */ 42 | unsigned int wait() 43 | { 44 | await(m_event != 0); 45 | return (m_event); 46 | } 47 | 48 | /** 49 | * Signal task event. Wait for ongoing event handler, 50 | * assign new event code and yield. 51 | * @param[in] value event code (non zero). 52 | */ 53 | void signal(unsigned int value) 54 | { 55 | await(m_event == 0); 56 | m_event = value; 57 | yield(); 58 | } 59 | 60 | /** 61 | * Clear event code to mark that it was completed. 62 | */ 63 | void clear() 64 | { 65 | m_event = 0; 66 | } 67 | 68 | protected: 69 | volatile unsigned int m_event; 70 | }; 71 | 72 | Event event; 73 | 74 | void setup() 75 | { 76 | Serial.begin(57600); 77 | while (!Serial); 78 | Serial.println(F("SchedulerEvent: started")); 79 | Scheduler.start(NULL, eventHandler); 80 | } 81 | 82 | void loop() 83 | { 84 | static unsigned int i = 1; 85 | Serial.print(millis()); 86 | Serial.print(F(":loop::event=")); 87 | Serial.println(i); 88 | delay(1000); 89 | event.signal(i); 90 | i += 1; 91 | if (i == 0) i = 1; 92 | } 93 | 94 | void eventHandler() 95 | { 96 | unsigned int value = event.wait(); 97 | Serial.print(millis()); 98 | Serial.print(F(":eventHandler::event=")); 99 | Serial.println(value); 100 | delay(200); 101 | event.clear(); 102 | } 103 | -------------------------------------------------------------------------------- /examples/SchedulerEventQueue/SchedulerEventQueue.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerEventQueue.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library; 20 | * Queue events between tasks. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | // Check for SparkFun SAMD21 Breakout 27 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 28 | #define Serial SerialUSB 29 | #endif 30 | 31 | Queue eventq; 32 | 33 | void setup() 34 | { 35 | Serial.begin(57600); 36 | while (!Serial); 37 | Serial.println(F("SchedulerEventQueue: started")); 38 | Serial.flush(); 39 | 40 | // Start two event handlers 41 | Scheduler.start(NULL, eventHandler); 42 | Scheduler.start(NULL, eventHandler); 43 | } 44 | 45 | void loop() 46 | { 47 | // Push events 48 | static unsigned int event = 0; 49 | Serial.print(millis()); 50 | Serial.print(F(":loop::push event=")); 51 | Serial.println(event); 52 | eventq.push(&event); 53 | event += 1; 54 | 55 | // Random processing time 56 | delay(random(500)); 57 | } 58 | 59 | void eventHandler() 60 | { 61 | // Pull events 62 | unsigned int event; 63 | eventq.pull(&event); 64 | Serial.print(millis()); 65 | Serial.print(F(":eventHandler#")); 66 | Serial.print((int) &event); 67 | Serial.print(F("::pull event=")); 68 | Serial.println(event); 69 | 70 | // Random service time 71 | delay(random(1000)); 72 | } 73 | -------------------------------------------------------------------------------- /examples/SchedulerSemaphore/SchedulerSemaphore.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerSemaphore.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch shows how to use the Scheduler library; 20 | * Classical semafores used in this example to protect serial 21 | * output sequences. 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | // Check for SparkFun SAMD21 Breakout 28 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 29 | #define Serial SerialUSB 30 | #endif 31 | 32 | Semaphore mutex; 33 | 34 | void setup() 35 | { 36 | Serial.begin(57600); 37 | while (!Serial); 38 | Serial.println(F("SchedulerSemaphore: started")); 39 | Scheduler.start(NULL, loop1); 40 | } 41 | 42 | void loop() 43 | { 44 | static unsigned int i = 1; 45 | unsigned long start, stop, ms; 46 | 47 | start = millis(); 48 | mutex.wait(); 49 | { 50 | stop = millis(); 51 | ms = stop - start; 52 | Serial.print(stop); 53 | Serial.print(F(":loop::i=")); 54 | Serial.print(i); 55 | Serial.print(F(", wait=")); 56 | Serial.println(ms); 57 | Serial.flush(); 58 | delay(100); 59 | } 60 | mutex.signal(); 61 | delay(random(300)); 62 | i += 1; 63 | } 64 | 65 | void loop1() 66 | { 67 | mutex.wait(); 68 | { 69 | Serial.print(millis()); 70 | Serial.println(F(":loop1::step-1")); 71 | delay(random(100)); 72 | 73 | Serial.print(millis()); 74 | Serial.println(F(":loop1::step-2")); 75 | delay(random(100)); 76 | 77 | Serial.print(millis()); 78 | Serial.println(F(":loop1::step-3")); 79 | Serial.flush(); 80 | delay(random(100)); 81 | } 82 | mutex.signal(); 83 | } 84 | -------------------------------------------------------------------------------- /examples/SchedulerTaskMax/SchedulerTaskMax.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerTaskMax.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library. 20 | * Schedule max number of counter tasks. 21 | */ 22 | 23 | #include 24 | 25 | // Check for SparkFun SAMD21 Breakout 26 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 27 | #define Serial SerialUSB 28 | #endif 29 | 30 | unsigned long count = 0L; 31 | 32 | void setup() 33 | { 34 | Serial.begin(57600); 35 | while (!Serial); 36 | Serial.println(F("SchedulerTaskMax: started")); 37 | Serial.flush(); 38 | 39 | int tasks = 0; 40 | while (Scheduler.start(NULL, counter, 64)) tasks++; 41 | Serial.print(millis()); 42 | Serial.print(F(":setup::task=")); 43 | Serial.println(tasks); 44 | yield(); 45 | Serial.print(millis()); 46 | Serial.print(F(":setup::count=")); 47 | Serial.println(count); 48 | } 49 | 50 | void loop() 51 | { 52 | count = 0; 53 | unsigned long start = millis(); 54 | await((millis() - start) >= 1000); 55 | Serial.print(millis() - start); 56 | Serial.print(F(":loop::count=")); 57 | Serial.println(count); 58 | } 59 | 60 | void counter() 61 | { 62 | count += 1; 63 | yield(); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /examples/SchedulerWatchdogTemplate/SchedulerWatchdogTemplate.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SchedulerWatchdogTemplate.ino 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * This Arduino sketch uses the Scheduler library. A watchdog task 20 | * that monitors the time to scheduler all tasks. The alarm is called 21 | * if the cycle is long than 10 ms. 22 | */ 23 | 24 | #include 25 | #include "Watchdog.h" 26 | 27 | // Check for SparkFun SAMD21 Breakout 28 | #if defined(ARDUINO_ARCH_SAMD) && (USB_PID == 0x8D21) 29 | #define Serial SerialUSB 30 | #endif 31 | 32 | unsigned long count = 0; 33 | 34 | void alarm(unsigned long ms) 35 | { 36 | Serial.print(millis()); 37 | Serial.print(':'); 38 | Serial.print(count); 39 | Serial.print(F(":watchdog alarm:ms=")); 40 | Serial.println(ms); 41 | count = 0; 42 | } 43 | 44 | Watchdog<15, alarm> watchdog; 45 | 46 | void setup() 47 | { 48 | Serial.begin(57600); 49 | while (!Serial); 50 | Serial.println(F("SchedulerWatchdogTemplate: started")); 51 | Scheduler.start(watchdog.setup, watchdog.loop); 52 | } 53 | 54 | void loop() 55 | { 56 | delayMicroseconds(random(17000)); 57 | yield(); 58 | count += 1; 59 | } 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/SchedulerWatchdogTemplate/Watchdog.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Watchdog.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2015-2016, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section Description 19 | * Scheduler watchdog template class. 20 | */ 21 | 22 | #ifndef BLINK_H 23 | #define BLINK_H 24 | 25 | template 26 | class Watchdog { 27 | public: 28 | static void setup() 29 | { 30 | } 31 | static void loop() 32 | { 33 | unsigned long start = millis(); 34 | yield(); 35 | unsigned long ms = millis() - start; 36 | if (ms > DEADLINE) ALARM(ms); 37 | } 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Simple Scheduler 2 | version=1.2.1 3 | author=Mikael Patel 4 | maintainer=Mikael Patel 5 | sentence=Scheduler for simple multi-tasking. 6 | paragraph=This library is an implementation of an extended sub-set of Arduino Scheduler interface. The function yield() will context switch between multiple loop() functions. 7 | category=Other 8 | url=https://github.com/mikaelpatel/Arduino-Scheduler 9 | architectures=avr,sam,samd,esp8266 10 | --------------------------------------------------------------------------------