meiden wrote on Tuesday, December 19, 2017:

Have a situation where xTimerCreate() with period 1 results in timer callback at twice the rate. Bump the period to 2 and I get the correct rate. I am wondering if setting the period to a single tick is legal?

configTICK_RATE_HZ is ((TickType_t)1000)

  const char * const taskName    = "SystemTimer";
  const TickType_t   periodTicks = 1/portTICK_RATE_MS;
  const UBaseType_t  autoReload  = pdTRUE;
  void * const       timerID     = ((void*)0);
  TickType_t         blockTime   = 0;

  timerHandle =
        (taskName, periodTicks, autoReload, timerID, SystemTickHandler);

rtel wrote on Tuesday, December 19, 2017:

Yes it is legal to have a period of 1, but keep in mind there is also a granularity of 1, so 1 means anywhere from 0.001 to 0.9999.

meiden wrote on Tuesday, December 19, 2017:

It very consistently gives me twice the number of timer callbacks as it should for this condition only? So that would indicate either a bug or that it is not really a valid use if you want an accurate count?

meiden wrote on Tuesday, December 19, 2017:

I measure this using xTaskGetTickCount() vs. the number of callbacks. I get double the callbacks vs. the tick count? Am I not using the tick count correctly then?

rtel wrote on Tuesday, December 19, 2017:

I will have to try and replicate this myself and get back to you.

meiden wrote on Tuesday, December 19, 2017:

I will try to pare down the code to something is OK to post in case you get a different result.

meiden wrote on Tuesday, December 19, 2017:

Hmmm, my “pared down version” seems to be working correctly with (1/portTICK_RATE_MS) for the period? Maybe you should wait on your trial. I thought I removed all unrelated code. Perhaps not… I will repost one way or another…

meiden wrote on Thursday, December 21, 2017:

OK, the problem turned out to be two instances of the timer causing double the number of callbacks. I had protected the timer creation with a mutex to prevent this, but apparently the timer callbacks run in the same task space as the task that creates the timer (If you can confirm this is the case would appreciate it). Since that task already owned the mutex it blew right by the protection. When the timer period was increased the callback was delayed and avoided the problem just by timing. I know this sounds convoluted, and I changed the implementation to avoid the issue altogether, but I am still interested in the task question above.

rtel wrote on Thursday, December 21, 2017:

Thanks for taking the time to report back - although note that timer
callback functions execute in the context of the timer service task, not
the context of the task that created the timer (unless of course the
timer was created by the timer service task).

meiden wrote on Friday, December 22, 2017:

If that is the case I am at a loss as to how this happened. I will outline the order of operations and give you a bit of background…

  • The class is singleton. The GetInstance() member function creates the instance and sets up the timer.
  • The timer callback was a function independent of the class that used GetInstance()->Update() to inform the singleton class when the timer fired.
  • The GetInstance() function incorporated a mutex to ensure that the timer setup would be called only once.
    So what was happening was that GetInstance() called TimerSetup(). TimerSetup() created the timer with TimerCallback(). TimerCallback() fired immediately and called GetInstance()->Update() before the call to TimerSetup() returned. This second call to GetInstance() was ALSO calling TimerSetup() resulting in a second timer instance calling the same TimerCallback() (this is why I was receiving double the number of updates).
    The mutex should have prevented that last call to GetInstance() from acquiring the mutex if as you say the callback is not running in the same context, thus avoiding a second call to TimerSetup()??? So the mutex must have failed in this scenario.
    My solution (and a better implementation) was to convert the Update member to static and pass it to timer creation as the callback function. This bypasses the need to call GetInstance() for the second time from an external TimerCallback() function.

rtel wrote on Friday, December 22, 2017:

Can you show the code of where the mutex is used.

meiden wrote on Tuesday, January 02, 2018:

I cannot post code as is proprietary, but I can mock something up if I get a chance this week. New year, alot of things piled up over the holidays :slight_smile:

meiden wrote on Tuesday, January 02, 2018:

This should produce the problem. “Lost” my hardware temporarily, so could not test. But the attached code produced the problem before I changed the design; I just removed all extraneous code. I did compile it… hopefully this will make sense along with the previous description…