[PATCH 0/2] Arc tickless idle issue


Desfarges, Simon <simon.desfarges@...>
 

From: Simon Desfarges <simon.desfarges(a)intel.com>

Hello,

I am trying to enable the tickless idle of ARC in our project. Here is my
problem.

OS: Zephyr 1.0.0
Processor: Quark_se

The ARC TICK timer contains 2 registers: limit register and count register.
Count register is automatically incremented and when is equal to limit
register, an ISR is fired and count wraps to 0.

Trying to enable the tickless idle on Arc, I found that in some corner case
the limit register ends up to be smaller than the count register. So then, the
count register will wrap to 0 at UINT32_MAX value (~133 seconds), leading to a
very long TICK.

I managed to fix this problem (patch 1) and added plenty of assertions (patch 2,
used to debug, validate and understand the code).

TL;DR:

I still have a remaining issue: the TICK is no more regular. I have a small
jitter when the tickless idle is interrupted by an external event. To check I
set a timer expiring every 1000 ms, and I compute the time between 2 ISR using
the AON counter and using the OS Timer.

Here are my results:
Working case:
4574464|ARC| MAIN| INFO| timer 32767k, 1000ms, os: 1000
4575464|ARC| MAIN| INFO| timer 32767k, 1000ms, os: 1000
4576464|ARC| MAIN| INFO| timer 32767k, 1000ms, os: 1000
4577464|ARC| MAIN| INFO| timer 32767k, 1000ms, os: 1000
4578464|ARC| MAIN| INFO| timer 32767k, 1000ms, os: 1000
4579464|ARC| MAIN| INFO| timer 32767k, 1000ms, os: 1000

Here, the time between 2 Interrupts is always 1000ms (32767 ticks of the AON
counter, counting at 32768Hz). The 'os' value actually counts the elapsed
TICKs.

Tickless idle case:
4745475|ARC| MAIN| INFO| timer 32786k, 1001ms, os: 1000
4746476|ARC| MAIN| INFO| timer 32780k, 1000ms, os: 1000
4747476|ARC| MAIN| INFO| timer 32786k, 1001ms, os: 1000
4748476|ARC| MAIN| INFO| timer 32780k, 1000ms, os: 1000
4749477|ARC| MAIN| INFO| timer 32786k, 1001ms, os: 1000

Here, the time between 2 ISR may vary up to 1ms for 1000 ticks.

The issue appears only when there are external ISR (I shake the board, accel
sensor does the rest). So in the exact path I just changed :(

I do not understand from where does the issue comes from (yes, from my patch I
guess), so if a tickless guru can give me some hints, I may have missed an
obvious stuff...

Thank you very much !
Simon.

Simon Desfarges (2):
arc_timer: fix tickless idle
arc_timer: assert that counter always lower than limit

drivers/timer/arcv2_timer0.c | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)

--
1.9.1


Rodriguez, Sergio SF <sergio.sf.rodriguez@...>
 

Hi Simon,

The macro _sys_clock_tick_announce() call _nano_sys_clock_tick_announce(_sys_idle_elapsed_ticks), so _sys_idle_elapsed_ticks might off, can you check the value of _sys_idle_elapsed_ticks before every _sys_clock_tick_announce on the timer driver?, I think this line might be suspect on

drivers/timer/arcv2_timer0.c on the function _timer_idle_exit, look for the lines

uint32_t remaining_cycles = programmed_limit - current_count;

_sys_idle_elapsed_ticks = current_count / cycles_per_tick;
if (_sys_idle_elapsed_ticks > 0) {
update_accumulated_count();
_sys_clock_tick_announce();
}

The problem here is maybe _sys_idle_elapsed_ticks is going off,

also take a look at _timer_idle_exit when is coming off a timer interrupt,

if (control & _ARC_V2_TMR_CTRL_IP) {
/*
* The timer has expired. The handler _timer_int_handler() is
* guaranteed to execute. Track the number of elapsed ticks. The
* handler _timer_int_handler() will account for the final tick.
*/

_sys_idle_elapsed_ticks = programmed_ticks - 1;
update_accumulated_count();
_sys_clock_tick_announce();

return;
}

Is announcing the ticks minus one to all the timers (if any), so if no other interrupt happens (just the timer) the count will be fullfilled at the next tick, but if other interrupt happens and add more that one tick to _sys_idle_elapsed_ticks, that might set the timers with wrong count, so we have to revisit the non timer interrupt tick anounce