Software Timers - sequential or simultaneous?

Hello,

I’m trying to use the new Software Timers to replace a bunch of code in my loop() that relies on millis() to handle timing. I’ve been looking at the FreeRTOS documentation for their software timers, but couldn’t specifically find the answer to this question:

When I have multiple timers, all set to a period of e.g. 500, and start them all at the same time, do all of the callbacks get fired simultaneously using some kind of threading, or do they happen sequentially, one after the other?

See below ASCII art for an idea of what I mean…

Given this definition:


void cb1() {
  /* something that takes about 300ms to complete */
}
void cb2() {
  /* something else that takes about 300ms to complete */
}

Timer t1(500, cb1);
Timer t2(500, cb2);

void setup(){
  t1.start();
  t2.start();
}

Simultaneous timers:

 cb1 -------------x         ---------------x
 cb2 -------------x         ---------------x

   |----|----|----|----|----|----|----|----|----|----|…
   0   100  200  300  400  500  600  700  800  900  1000

Sequential timers:

 cb1 -------------x              ---------------x (missed our mark!)
 cb2              ---------------x              ---------------x (same here!)

   |----|----|----|----|----|----|----|----|----|----|…
   0   100  200  300  400  500  600  700  800  900  1000

This makes a big difference in how I can handle routinely pushing data to a TCPClient, as (depending on WiFi signal, etc) this can vary wildly in actual time taken, and I don’t want it to block any other part of my program.

Hi @legoguy,

according to the docs, you should think at software timers as a single (i.e., sequential) subsystem, and bad programming practices can block it.

The timer callback is similar to an interrupt - it shouldn't block. However, it is less restrictive than an interrupt. If the code does block, the system will not crash - the only consequence is that other software timers that should have triggered will be delayed until the blocking timer callback function returns.

Okay, fair enough, I just thought I would clarify.

Another question, though: Should variables that are used in timer callbacks be considered “volatile”, a la ISRs?

@legoguy, I would say treat them like ISRs since they are called asynchronously of your loop(). Better be safe than sorry! :wink:

1 Like

Somewhat related: Do I need to call Timer.changePeriodFromISR() from inside a Timer callback? Or are the ‘FromISR’ versions to be used only from within ‘attachInterrupt()-ed’ ISR functions? (in which case I’d call Timer.changePeriod())

@johnshifflett, the FromISR versions are only necessary when call within a “true” ISR. Software Timers are run in a timer thread and called from there. :wink:

Do you have a spare hand free so you could add that to the timer docs? :smile:

@peekay123 - beautiful, thanks!

Here’s another one for you, @peekay123: I’ve been assuming that a call to noInterrupts() will suspend Timer callbacks. Trying to track down a bug and want to double-check that’s true? If yes, are Timer callbacks executed with interrupts disabled? If -that’s- not the case, will noInterrupts() inside a Timer callback suspend further Timer callbacks until the current one returns? And what about Timer callbacks within a bona fide ISR (and vise versa)?

Sorry for all these messy questions, but the docs are either blank or ambiguous on this stuff. Heck - I haven’t even seen confirmation that -ISR’s- are called with interrupts disabled!

@johnshifflett, the best documentation regarding Software Timers is the FreeRTOS source docs.

If you disable all interrupts, regardless if within a Timer call back or anywhere else, you will be stopping ALL interrupts, stopping the multi-tasking which includes software timers!. If you want to disable a software timer within a callback, use the stop() function.

As for timer callbacks within a bona fide ISR, well I’m not sure what that means. An ISR is an ISR and a callback is, well a callback. You can’t have a callback IN an ISR so you have to help me understand here!

Perhaps you can describe how the system behaves with the bug so I can better help. :wink:

I will read the RTOS docs, thanks for the link.

Your statement about “disabling interrupts stops EVERYTHING” addresses most of what I was (inarticulately) asking, thanks! I have 2 remaining questions:

  1. does RTOS disable ints before calling a Timer callback?
  2. does RTOS disable ints before calling an Interrupt “callback” (ISR)?

Thanks in advance for any light you can shed, and now I’ll fish around in the FreeRTOS info.

The answer is no to both questions - interrupts continue executing while in a timer callback - so your timer can be interrupted, and interrupts continue running when an interrupt is currently being handled in a ISR. If the new interrupt is a higher pirority, then it will interrupt a currently running interrupt. If it’s the same or lower priority, then the interrupt will be queued until the current ISR exits.

1 Like