These are chat archives for esp8266/Arduino

17th
Jul 2015
Me No Dev
@me-no-dev
Jul 17 2015 09:00
having issues across the board with the network using optimistic_yield
network should revert to "normal" yield I thnk
Ivan Grokhotkov
@igrr
Jul 17 2015 09:05
so is optimistic_yield not yielding often enough?
Me No Dev
@me-no-dev
Jul 17 2015 09:05
not for netowrk at least
many netowrk operations fail if additional yields are not added
in cases where the data is conatined in more than one packet
Ivan Grokhotkov
@igrr
Jul 17 2015 09:08
yeah... it will yield at most every 16ms... not good.
we can make optimistic_yield detect if it was called more than once since last task switch
replacing the time difference check
Me No Dev
@me-no-dev
Jul 17 2015 09:11
can't we have the netowrk stack do it's own normal yield
optimistic is good for many things
just not for network
me running 3 different services, is getting into trouble lots :)
Ivan Grokhotkov
@igrr
Jul 17 2015 09:13
ok, the point is, we should still detect if available() was called first time or not, otherwise every single call to it will get really expensive
Me No Dev
@me-no-dev
Jul 17 2015 09:18
if we are calling it and there is no data, doesn't that mean that we are expecting more data?
if so maybe yield and check available again before returning
but I don;'t think that will fix the problem
other connections migt not be handled at that yield
Ivan Grokhotkov
@igrr
Jul 17 2015 09:20
sometimes yes, sometimes no. i have something like this in one of my sketches:
while(true) {
if (client.available()) {
  consoleParser.parseInput(client);
}
run_sensors();
delay(1)
}
Me No Dev
@me-no-dev
Jul 17 2015 09:21
have a go at some of the more complex examples
maybe ota, http, mdns and whatnot at the same time
if one service is busy, the rest will kill the esp
Ivan Grokhotkov
@igrr
Jul 17 2015 09:22
sure
because they are synchronous :)
okay, mdns is not
OTA (the UDP listener part) doesn't have to be synchronous either
Me No Dev
@me-no-dev
Jul 17 2015 09:24
i had a case where i starged OTA and other service got a packet and... exception
Ivan Grokhotkov
@igrr
Jul 17 2015 09:24
i think you should stop other services when you start OTA
Me No Dev
@me-no-dev
Jul 17 2015 09:24
the exception was not on the busy service but on one of the other ones
well it's me again with the same answer to that
OTA is nothing different than HTTP Upload
large file being transfered
Ivan Grokhotkov
@igrr
Jul 17 2015 09:25
but with OTA, you can stop all other services, right?
because you're going for a reboot anyway
Me No Dev
@me-no-dev
Jul 17 2015 09:25
i do not want to
OTA might fail
for many reasons, then I have to either restart or start all service
Ivan Grokhotkov
@igrr
Jul 17 2015 09:26
i think restart is the way to go
Me No Dev
@me-no-dev
Jul 17 2015 09:26
OTA was working fine with lots of service concurently without optimistic yield
i did all my best to not have to stop anything
and it was 100% working fine
Ivan Grokhotkov
@igrr
Jul 17 2015 09:27
okay, so let's revert it, what do you think?
Me No Dev
@me-no-dev
Jul 17 2015 09:27
it's a good feature, bt maybe not everywhere
I brought it to get attention from you and @Links2004 and @Makuna to maybe rething it a bit
it's actually really necessary in Serial so Arduino sketches with while(!Serial.available()); work
Ivan Grokhotkov
@igrr
Jul 17 2015 09:32
i mean, revert the changes on the network side of things
Markus
@Links2004
Jul 17 2015 09:33
i think we shut add a function like "waitForData" with a while and a yield for the network .
Me No Dev
@me-no-dev
Jul 17 2015 09:33
we can give it a go an see how the ESP behaves then
"waitforData" would require users to now about it, so they use that instead? or can we hide that in the network classes?
Ivan Grokhotkov
@igrr
Jul 17 2015 09:35
waitForData — meh... makes API more complicated
Markus
@Links2004
Jul 17 2015 09:35
may we can also give the available an optional option to give the choice for advanced programmer and keep it enabled for beginers
Ivan Grokhotkov
@igrr
Jul 17 2015 09:36
there are several patterns of use, and it's not immediately obvious how to detect them from inside the network classes
one pattern is "loop while no data, then do something with data"
another one is "if there is data, do something, otherwise do something else"
first one requires calling yield every time
Markus
@Links2004
Jul 17 2015 09:37
normally i program more asynchronous then a while
This message was deleted
Ivan Grokhotkov
@igrr
Jul 17 2015 09:38
second one requires you to call yield every once in a while, but not too often
Markus
@Links2004
Jul 17 2015 09:39
or even none be course you do it automatically be returning the loop
Ivan Grokhotkov
@igrr
Jul 17 2015 09:39
the code we had earlier (before it got accidentally broken) would call yield every second time since the loop started
Markus
@Links2004
Jul 17 2015 09:43
the only possibility to see if we in a while is the call stack, not know if we can it be read in a good way?
Ivan Grokhotkov
@igrr
Jul 17 2015 09:43
no it's not possible
Markus
@Links2004
Jul 17 2015 09:43
dam
Ivan Grokhotkov
@igrr
Jul 17 2015 09:44
if we could find an easy way to check whether we are looping, that would mean we solved the Halting problem, which would be kinda strange :)
okay, was looking through the code again and found something i don't understand
Markus
@Links2004
Jul 17 2015 09:46
a basic check is easy to do if we had access to the call stack
Ivan Grokhotkov
@igrr
Jul 17 2015 09:46
how do you imagine that would work?
let's say we have access to call stack
@Makuna why is g_micros_at_last_task_yield set in two places in the new code: in esp_yield and in loop_task?
Markus
@Links2004
Jul 17 2015 09:48
at each call of available we store the call part if we have store something we compare if its the same we are in a loop.
before the call of void loop() we need to clear the storage we compare against
Ivan Grokhotkov
@igrr
Jul 17 2015 09:50
@Links2004 what if someone just calls .available() two times, not in a loop?
Markus
@Links2004
Jul 17 2015 09:50
we get a other address in the path so not the same
Ivan Grokhotkov
@igrr
Jul 17 2015 09:51
not necessarily, compiler may generate one piece of code for calling the available() function, and then jump to it setting some registers to determine the execution path after available() returns
it's quite common when you optimize for size.
it's like loop unrolling, but the other way around :)
Markus
@Links2004
Jul 17 2015 09:53
k, this is a problem.
Michael Miller
@Makuna
Jul 17 2015 13:41
did you just try to reset the yield time to a lower value? Like 2ms?
Ivan Grokhotkov
@igrr
Jul 17 2015 13:43
thinking about this again, for network it makes absolutely no sense spinning in a while() loop waiting for data — better to give control to the SDK
UART is event-driven, so while loop makes sense — data will get received
Michael Miller
@Makuna
Jul 17 2015 13:44
@igrr the time is captured in both loop and the last yield so that if someone used yield in their code but still kept a long loop it would space out the yields some.
Ivan Grokhotkov
@igrr
Jul 17 2015 13:44
not so with network stack — we need to give control to the SDK to actually receive anything.
i see the time is captured when you call yield, and then it is captured again when code resumes from yield
Michael Miller
@Makuna
Jul 17 2015 13:46
again? Where?
Ivan Grokhotkov
@igrr
Jul 17 2015 13:46
static void loop_task(os_event_t *events) {
    g_micros_at_last_task_yield = system_get_time();
this will be called each time we return from yield
Michael Miller
@Makuna
Jul 17 2015 13:47
ahh, this wasn't obvious, this looked like the main loop service routine.
only
Ivan Grokhotkov
@igrr
Jul 17 2015 13:48
it is the main loop service routine
it calls cont_run(&g_cont, &loop_wrapper);
which either jumps into loop_wrapper if there is no saved context, or jumps to the saved state
Michael Miller
@Makuna
Jul 17 2015 13:50
Ok, but what about other tasks, do they use this same routine?
Ivan Grokhotkov
@igrr
Jul 17 2015 13:50
other tasks? like network task?
Michael Miller
@Makuna
Jul 17 2015 13:51
if so, then you are correct, it's not needed in yield.
I thought you can create tasks still
Ivan Grokhotkov
@igrr
Jul 17 2015 13:52
you can create tasks, those will be cooperatively scheduled by OS, just like our loop task
Michael Miller
@Makuna
Jul 17 2015 13:53
(Sorry not at computer) then how would those tasks handle updating this last save time, only by use of the yield?
Ivan Grokhotkov
@igrr
Jul 17 2015 13:53
only the loop task can use yield
there's no protection currently against user calling yield() from other tasks
Michael Miller
@Makuna
Jul 17 2015 13:54
And it's not obvious that I couldn't call it either.
was there a reason for this limitation?
BTW, did you try setting the time value to a smaller value and see how the network functions?
Ivan Grokhotkov
@igrr
Jul 17 2015 13:58
well since we only manage the stack for the loop task, we can only implement yield() there
Michael Miller
@Makuna
Jul 17 2015 13:59
I didn't see problems but I may not be pushing it as hard as others.
Ivan Grokhotkov
@igrr
Jul 17 2015 13:59
if the user creates his own task, it will use system stack, and there is no way for us to switch the context
i think this context switching may be wrapped into an object or library which will let users add context switching to other tasks
Michael Miller
@Makuna
Jul 17 2015 14:01
wrap it and expose?
Ivan Grokhotkov
@igrr
Jul 17 2015 14:01
yes.
but i don't see the average arduino user going as far as creating SDK tasks... so it's not a really important addition as far as i can tell.
documenting this limitation (i.e. you can only use network and serial write/read/available functions from setup/loop functions) is necessary though
i'll add that note
Michael Miller
@Makuna
Jul 17 2015 14:03
Agreed, just dangerous if they call yield?
Ivan Grokhotkov
@igrr
Jul 17 2015 14:04
it would lead to undefined behaviour... which could be either "all works okay" or "exception" depending on the exact circumstances
Michael Miller
@Makuna
Jul 17 2015 14:05
ticker doesn't use this?
Ivan Grokhotkov
@igrr
Jul 17 2015 14:06
right now ticker calls user functions from system timer, which makes it behave like an interrupt (i.e. no print and other blocking functions)
i have prototype code which makes Ticker run user functions in the same context as the main loop
but the downside is that timing gets rather unpredictable
i.e. ticker callback will not run until loop function returns
so no network/serial IO from Ticker as well (this is documented)
Michael Miller
@Makuna
Jul 17 2015 14:14
Yeah, I have a Task library that replaces all code in the loop, but requires the programmer to rethink how they code as it is non preemptive and requires the code to return to yield.
Mine works for AvR also.
did you try lowering the time value for optimistic yield? The value is rather arbitrary.
probonopd
@probonopd
Jul 17 2015 15:08
hi all, has anyone ever tried to get the ESP mp3 player code running in Arduino?