I have a pair of nested millis timers that is producing a stack crash when it executes. I have a workaround that works, but I am curious why nested millis timers should crash like this. My sketch is approaching over 1,000 lines of code, so is this a warning that my stack is running out of space??
Here's the code segment that crashes:
// Loop here for i*1000 ms, checking offHook every 500 ms.
// If the user hung up the handset, exit.
long j;
while (millis() < ringbackStartTime + (i * 1000)) { // Waiting for timeout
j = millis();
if (millis() > j + 500) {
if (!offHook()) return; // Abort if the user hung up the handset.
}
}
}
And, here is my workaround that doesn't crash. Blocking code is OK here:
// Loop here for i*1000 ms, checking offHook every 500 ms.
// If the user hung up the handset, exit.
while (millis() < ringStartTime + (i * 1000)) { // Waiting for timeout
if (!offHook()) return; // Abort if the user hung up the handset.
delay(500);
}
Think about this for just a second. If j is set equal to millis, then what are the chances that one instruction later it is suddenly 500ms later? That if will NEVER be true.
Delta_G:
timing should always be handled with subtraction to find intervals, not addition to predict future times. The former is safe. The latter is bugged.
Thanks. That's good to know. am I understanding correctly that millis() may take an awful long time to be less than startTime + interval if the addition would go over the long rollover?
I have an awful lot of millis timers in my sketch to fix because I am trying real hard to avoid blocking code. But since this program won't be running more than a day, this is unlikely to trip me.
Think about this for just a second. If j is set equal to millis, then what are the chances that one instruction later it is suddenly 500ms later? That if will NEVER be true.
You're right- that inner loop should be a do-while instead of an if-then.
long j;
while (millis() - ringbackStartTime < (i * 1000)) {
j = millis();
do {
if (!offHook()){
return;
}
while (millis() -j < 500)
}
Where are you getting that crash report from? It has Soft WDT Reset right at the top of it, that doesn't sound like a stack overflow crash to me. Are you enabling the watchdog timer anywhere in your sketch? If so the problem isn't your stack crashing, but you're getting stuck in an infinite loop and not resetting the watchdog timer.
It doesn't even need to be an infinite loop, it only needs to be some code that blocks loop longer than the watchdog timer timeout duration. If that's the case, you can work around it by calling yield(), which resets the watchdog timer. But it's best to avoid blocking code if possible.