Tmr Svc using 50% of CPU

Here’s an interesting problem. I have removed all software timers from my system, and yet Tmr Svc is still consuming more CPU than any other task – approaching 50%. Normally the system runs with a handful of timers, some running periodically, and others occasionally – none doing any heavy lifting. With or without actually instantiating timers, the CPU usage of the Tmr Svc task is approximately the same – 47-49%. Is this a known problem? Here are the particulars: FreeRTOS V8.1.2 MicroBlaze 8.50a (no MPU) on Xilinx Spartan 6 Xilinx SDK/EDK 14.5 The system clock is 100 MHz. The RTOS tick is 10 Hz. There is also a 1,000 Hz “high” resolution timer used for run-time stats. Here’s what’s reported by vTaskGetRunTimeStats():
HostIn         84  <1%
IDLE       247373  16%
HostXtra      787  <1%
Tmr Svc    724528  48% <-- WTF?
SdAuto          0  <1%
Sd1             0  <1%
Sd0            11  <1%
GPS             0  <1%
UartARx         1  <1%
UartATx         3  <1%
NetAuto         0  <1%
NetLAN          1  <1%
NetWiFi         2  <1%
HostOut        23  <1%
Logger         33  <1%
Uart0Tx        47  <1%
Uart0Rx        15  <1%
FIR          1985  <1%
IIR        143245   9%
Raw        362002  24%
Node            0  <1%
IPI           819  <1%
Any insight into this issue would be appreciated. Thanks! -Nick

Tmr Svc using 50% of CPU

No, definitely not a know problem, I have never seen anything like that before. I would not have thought it was specific to the Microblaze port (which will get updated sometime in the next quarter, by the way), as it is generic code. Do you have configASSERT() defined? Can you place a break point on the xTimerCreate() function in FreeRTOS/Source/Timers.c to ensure none are getting created, and if none are being created… Try stepping through the prvTimerTask() function in the same file. In particular, what is prvGetNextExpireTime() returning? Regards.

Tmr Svc using 50% of CPU

Thanks for the reply. Here’s what I found. 1. I did not have configASSERT defined, so I added it and repeated my tests. I got no asserts. 2. The breakpoint on xTimerCreate() was never taken. 3. prvGetNextExpireTime() returns 0. Here’s one more data point. There is one rather high-frequency interrupt in the system. Its ISR triggers the Raw task, which in the above example is consuming 24% of the CPU. If I disable that interrupt, Tmr Svc CPU usage drops below 1%. Of course this may simply be because the interrupt time gets charged to Tmr Svc because it’s usually running when the Raw interrupt occurs. I’m glad to hear that there will be an update to the Microblaze port coming out shortly. I’d be happy to share my (few) bug fixes on the off chance that they haven’t already been implemented. Thanks again for the quick response. -Nick

Tmr Svc using 50% of CPU

  1. prvGetNextExpireTime() returns 0.
I think that is expected, it is what is happening afterwards for you that is not expected. Try this:
  • Put a break point on prvGetNextExpireTime() before running the program. When the break point is hit, step into the function. You should find that, because there are no timers, xListWasEmpty is set to pdTRUE, and xNextExpireTime is set to 0.
  • Carry on stepping out of the function and into prvProcessTimerOrBlockTask(). Now you should find because xListWasEmpty is true the only path you can take is via vQueueWaitForMessageRestricted(). The block time is ( xNextExpireTime – xTimeNow ), which should evaluate to an extremely large time indeed as xNextExpireTime is 0 so you will get an underflow. Having a large block time will place the task into the blocked state and you will yield away from the task probably after stepping out of vQueueWaitForMessageRestricted().
When you step through the code, where do you see your scenario deviating from this description.
Here’s one more data point. There is one rather high-frequency interrupt in the system. Its ISR triggers the Raw task, which in the above example is consuming 24% of the CPU. If I disable that interrupt, Tmr Svc CPU usage drops below 1%.
That is indeed curious, but I would expect the idle task to be running – if the interrupt time were charged to any task it would be that one. (this is all assuming you don’t have any timers defined). Regards.

Tmr Svc using 50% of CPU

I’d be happy to share my (few) bug fixes
Yes, definitely please do that (you should do it as a matter of course anyway please). There is a bug tracker in SourceForge, and you can always use the business contact email on http://www.freertos.org/contact regards.

Tmr Svc using 50% of CPU

Thanks, I’ll be visiting the bug tracker shortly. After taking your suggestions, and following where they led, I have come to believe that the OS is functioning as designed. It appears that the reason the timer task is so busy is my use of xEventGroupSetBitsFromISR() from a couple of busy ISRs. This in turn calls xTimerPendFunctionCallFromISR(), which posts to the timer queue, which fires off the timer task. Clearly event flags are intended for relatively light duty. Fortunately, it should be easy to avoid heavy use. Thanks again for your assistance – I doubt I would have figured this one out without it. It makes me happy to have bought the book. 🙂 -Nick

Tmr Svc using 50% of CPU

Ah, right. I should have thought of that.