-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Make delay() as overridable as yield() already is, and add overridable loop_end() #6306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Not sure of the use case, as changing the meaning of delay() in a RTOS/cooperative OS would make many sketches do odd things, but no real problem with the way it's broken up.
@earlephilhower First, thank you for the positive review. Now, I am honestly intrigued if you could give me some input regarding the unexpected consequences on ESP8266 sketches it can bring, if other co-op tasks/threads, besides the WLAN stack that's already there, are running. I was actually naïve enough to think that except the somewhat more slugging behavior of yield, and less precise returns from delay(), on the ESP8266 of all Arduino platforms, independent sketches should run quite fine without adaptations. As I think you've mentioned, once (Free)RTOS has to be implemented, it's getting even more interesting. Real Time OSs are really hard on their users compared to server/desktop OSes. Unfortunately I am having a hard time convincing the ESP32 maintainer of the utility of ESP8266 portability or cooperative multitasking in general. Honest, I don't think I want to HAVE TO know whether tasks at same priority are preempted among each other, or if higher priority tasks can only start once a lower priority one yields (there's a "preemptive" OS build setting than can be true or false!), just to serve a few sensors readings from the run-of-the-mill Arduino driver libraries to a webserver and control some outputs, too. And that's from a professional developer who finds this interesting, I don't think many of the 16-26 "maker" crowd feel keep on learning real time OS programming... |
I've seen lots of bit banging in sketches (not in the lib, except in SWSerial), and they normally do a {set gpios; delay(period); set gpios; delay(period);...} loop to do whatever. For example, a simple I2C interface over general IO pins. Or, say, WiFi connection timeouts where you give up to 1s to connect and if not, reboot. True, delay() could have some jitter today, but it is relatively small because only the OS task is doing anything. If delay() could take 100x because some other thread was calculating PI to 2000 digits, things would go pear shaped there quite fast. I haven't used FreeRTOS in anger, but I think the real difference between them and us, for the user, is cooperative (i.e. a yield() or WaitNextEvent under Win32 or (mumble mumble) under OSX) vs. preemptive (i.e. process/thread models under any full-fat OS today). Cooperative is harder to write since you need to break work into chunks, so even a FreeRTOS with every user process at the same priority level (assuming fair round-robin scheduling) would be liberating for them. Right now, everything we have is cooperative (between the ROM blob and the user app) anyway. So apps already have it, but the implicit contract is that delay(x) = a wall time delay of [x, x+epsilon], where epsilon is smallish... |
I almost completely agree - just I don't see much of a problem with it. EspSoftwareSerial works fine with CoopTask performing an "alive" blink in concurrent task/"sketch". The more delays, the better, because it keeps overall delay() deviation small. It's not a multiuser system, so one should expect the programmer to know what they are doing, at the of the day. |
@earlephilhower Oh great, thanks! I could use some help with getting PR #6307 approved, if there are any changes necessary, I am quite openminded, but for my scheduling needs, recursive scheduling from a function that's running off the scheduler itself is a must-have - my PR should fix that. |
@earlephilhower Come to think of it, we've both failed to mention the effects of the current series of merged patches for Straight from the documentation for that:
With only minor hints at the havoc this may/will cause to code that depends on timely returns from
Consequently, cooperative linear task code, that keeps these same constraints in mind, is not at all worse that what libs scheduling their recurrent work via |
The Arduino delay() (at least on AVR) cyclically calls yield(), whereas on Espressif SOCs the delay scheduling is quite different. In order to implement cooperative scheduling in a portable fashion, with global yield() and delay() in large sketches upholding the principle of least surprise, the delay() function must be supplanted. This patch allows that by the usual weak linkage approach.
Additionally, a weakly-linked loop_end() is added, that allows libraries to add special main-loop functionality, in case the Schedule recurrent et cetera functionality is not appropriate.
(EspSoftwareSerial is updated to 5.2.3, containing review results for circular_queue and minor internals)