mikaelpatel / Arduino-Scheduler

Portable Cooperative Multi-tasking Scheduler for Arduino
https://mikaelpatel.github.io/Arduino-Scheduler/
164 stars 41 forks source link

Arduino Micro (and Leonardo?) software reset broken (and fix) #22

Closed dvsingletary closed 6 years ago

dvsingletary commented 7 years ago

As soon as the Scheduler is started, the Arduino Micro (and, I assume Leonardo since they are functionally equivalent) will no longer reset itself when the serial port is opened at 1200 baud and closed. The Arduino IDE/avrdude uses this method to auto-reset the Arduino and activate the bootloader for programming.

The immediate work-around to be able to reprogram either of these boards is to just hit the reset button on the Arduino immediately after instructing the Arduino IDE to upload the sketch. This manually resets the Ardunino and activates the bootloader.

An even better work-around is to fix the root of the problem by increasing the main stack size. Run this in setup() before any other Scheduler calls: Scheduler.begin(286);

The DEFAULT_MAIN_STACK_SIZE for ARDUINO_ARCH_AVR is 256. Experimentally I found that using 286 fixes the auto-reset issue on the Arduino Micro. My suspicion here is that the auto reset code means the top stack is larger on these boards, but I don't have direct evidence of that.

Additional investigation is warranted, but it's also worth considering using a larger DEFAULT_MAIN_STACK_SIZE constant in Scheduler.h when the Leonardo or Mirco boards are being used (I wasn't able to determine what preprocessor defines indicate that, though).

mikaelpatel commented 7 years ago

@dvsingletary Could you provide some additional information? Version of IDE/AVR tools? Test sketch? The USB ISR is much more advanced that the HardwareSerial ISR which results in a larger stack frame. This might be the cause of the main stack overwrite.

I will see if I can come up with a compile time DEFAULT_MAIN_STACK_SIZE setting for the Arduino Leonardo/Micro.

Thanks for your effort debugging and reporting this issue.

Cheers!

dvsingletary commented 7 years ago

After filing this issue it occurred to me that the a stack size of 286 might not work if the main loop() made calls to other functions. All I know for now is that with an empty loop() (only containing a call to yield()), the stack size of 256 isn't enough to handle the USB ISR.

I will get back to you with versions and a test sketch soon. Do you have a leonardo or micro to test with?

mikaelpatel commented 7 years ago

@dvsingletary Thanks for the info. That was basically what I needed to know, i.e. the test sketch was an empty loop with only yield(). I have both an Arduino Leonardo and a bunch of Micro's. Guess there is a dependency to the bootloader version as well or at least the Arduino USB firmware. A USB hardware register symbol (USBCON) might be the easiest to use to detect these boards. This is used in USBCore.cpp.

mikaelpatel commented 6 years ago

Please see commit https://github.com/mikaelpatel/Arduino-Scheduler/commit/db729298a963f1cabc2233149780302c8b55a774.