mikaelpatel / Arduino-Scheduler

Portable Cooperative Multi-tasking Scheduler for Arduino

Home Page:https://mikaelpatel.github.io/Arduino-Scheduler/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Enhance: Support Teensy 3.5 and 3.6

dephillipsmi opened this issue · comments

I have modified your scheduler to support the Teensy 3.6 processor.
Scheduler.h - changed line
#if defined(TEENSYDUINO) && defined(MK20DX256)
to
#if defined(TEENSYDUINO) && (defined(MK20DX256) || defined(MK66FX1M0))

Scheduler.c - added
#elif defined(TEENSYDUINO) && defined(MK66FX1M0)
#undef ARDUINO_ARCH_AVR
#define TEENSY_ARCH_ARM
#define RAMEND 0x20030000

before

#elif defined(ARDUINO_ARCH_AVR)

@dephillipsmi Nice! Did you run the benchmarks and example sketches? I would like to update the statistics and library properties.

@dephillipsmi Added your changes. Thanks! Please feel free to check the update as I currently lack a Teensy 3.6 board. Please see 1424500.

Here are the results from the scheduler benchmark.
SchedulerBenchmark: started

  1. Initiate scheduler and main task: 1 us
  2. Yield main task: 0.43 us
  3. Start a task: 2 us
  4. Yield between two tasks: 0.98 us
  5. Delay 10 ms and check increments: 10001:8603, 1.16 us
  6. Start 25 tasks: 17:25, 0.68 us
  7. Yield and check increments: 13:26, 0.50 us
  8. Delay 10 ms and check increments: 10014:17602, 0.57 us

SchedulerBlinkMax would not run on either a Teensy 3.6 or a Due processor. First message was output then the serial monitor closed.

ScheduleTaskMax started 94 tasks. Loop ran 9 times then the serial monitor closed.

SchedulerChannel generated an unused variable warning on line "int res = m_size;"

All other examples ran without any errors or problems.

@dephillipsmi Thanks! Much appreciated. The ScheduleBlinkMax/TaskMax need a larger stack to work on 32-bit architectures. I will update that.

@dephillipsmi The "int res = m_size" was correct but the return value from Channel.recv() was not. Thanks for help finding that error. I have update the "TaskMax" examples and improved the stack() member function.

For Teensy 3.5, this might work?

#elif defined(TEENSYDUINO) && defined(__MK64FX512__)
#undef ARDUINO_ARCH_AVR
#define TEENSY_ARCH_ARM
#define RAMEND 0x20020000

@PaulStoffregen Perfect! Small update in the header file should do it. Please see commit 32bfba1.

For Teensy 3.6 I have verified that the changes to the stack size for the ScheduleBlinkMax/TaskMax resolved the issue with these two examples not running. Now they both run successfully.

I'm curious if Teensy's different yield() function matters?

Arduino has just an empty function. Arduino also doesn't actually call yield from anywhere other than delay().

On Teensy, I put the serialEvent stuff inside yield(). I'm considering doing much more in yield() at some point, for a more generalized event servicing mechanism. Unlike Arduino, Teensy's libraries do call yield from many places that block waiting for things to happen. The 6 hardware serial objects, all the USB communication stuff, and the Ethernet library call yield() while waiting to transmit. Other libraries like Wire and SD do not call yield() yet when blocking, but I'm considering patching them.

Maybe this is getting a little off-topic, but perhaps we could think a bit about how yield and event callbacks and scheduler libraries ought to work together? Ideally, I'd like to figure out a way for schedulers to use yield, but also for them to share yield with the core library to implement more responsive event callbacks.

@dephillipsmi Thanks for testing the stack size updates. I have changed the Scheduler.stack() member function to scan the stack and return the amount of "untouched" stack. The SchedulerDemo sketch is updated with print of the stack() value.

Should also mention that Scheduler.start/startLoop() will take longer time as the stack is filled with a "magic" pattern.

@PaulStoffregen I observed that the Teensy core had a different, non-empty, yield() when implementing the Teensy 3.1 support last year. The footprint benchmark came out negative (i.e. smaller size). This is why the README does not contain a footprint value.

Many of the libraries will have to evolve to support multi-tasking. In general mixing callbacks and tasking is not a good idea if the callback is not within the "correct" task context. Allowing callbacks in "any" task context becomes quickly "a can of worms". The new "untouched" Scheduler.stack() member function and the SchedulerDemo sketch shows how ISRs take some time before they hit the deepest call and consumes most stack.

One issue that will come up with libraries based on Wire, SPI, etc, is the lack of semaphores. I have changed a lot in Cosa to support RTOS style of acquire()-release() on resources such as buses, hardware modules, etc. And there is still much to do.

Should I open an issue on this so that we can discuss possible design patterns further?

Cheers! Mikael