SAM4N 'tickless idle' losing ticks with Semaphore Take

helliwell_cj wrote on Monday, April 27, 2015:

I’m using v8.1.2 on an Atmel SAM4N, with ‘tickless idle’. I’ve used the implementation of the SAM4L low_power_tick_management.c from v8.0.1; modified - because it doesn’t have an AST - to the SAM4N’s similarly-slow-running RTT. The tick rate is 128Hz. configEXPECTED_IDLE_TIME_BEFORE_SLEEP is set to 5.

This seems to be working, but I’ve encountered an issue with one particular task (there’s only 3 in the app so far) which is waiting on a semaphore (xSemaphoreCreateBinary) given by an ISR: the tick count, comparing it with real time, is running 50% slow. In my current set-up the semaphore is never given (and I’ve disabled the interrupt).
The timeout on the xSemaphoreTake is 1sec; and the task loop then has a further 1sec vTaskDelay.
If I add a delay to the task before it enters its for loop, then the tick rate is fine until that delay ends.

Now there may be a problem with my low_power_tick_management.c, but I’ve discovered that if I change the xSemaphoreTake() to a plain vTaskDelay() then the problem goes away. Which makes me instead suspect something kernel-related - shouldn’t they then be amounting, in broad terms, to the same thing? i.e. delay the task for 1sec.

I haven’t spotted anything relevant in the change history, but is there a fix/update I’ve missed? I’m also unsure of the best way to dig to track the issue down further…?

helliwell_cj wrote on Monday, April 27, 2015:

Oh, and the other ‘interesting’ factor - if I enable FreeRTOS+Trace in the app, then the issue also disappears…

rtel wrote on Monday, April 27, 2015:

It is not quite clear to me how the issue is manifesting itself. Hopefully some questions and answers will make it clearer:

I’m using v8.1.2 on an Atmel SAM4N, with ‘tickless idle’. I’ve used
the implementation of the SAM4L low_power_tick_management.c from
v8.0.1; modified - because it doesn’t have an AST - to the SAM4N’s

Did you check the latest version of FreeRTOS to see if the tickless implementation had changed? I just did - and found in fact it had, with an additional line being added - being line 384 in this file:
http://sourceforge.net/p/freertos/code/HEAD/tree/trunk/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/SAM4L_low_power_tick_management.c

This seems to be working, but I’ve encountered an issue with one
particular task (there’s only 3 in the app so far) which is waiting
on a semaphore (xSemaphoreCreateBinary) given by an ISR:

I presume you are using xSemaphoreGiveFromISR(), rather than xSemaphoreGive().

If you were using the latest FreeRTOS version you would also be able to get a lot more run time checking of interrupt priorities (the most common cause of issues on Cortex-M) by having configASSERT() defined.

the tick
count, comparing it with real time, is running 50% slow.

…and is that also the case when configUSE_TICKLESS_IDLE is set to 0?

In my
current set-up the semaphore is never given (and I’ve disabled the
interrupt). The timeout on the xSemaphoreTake is 1sec; and the task
loop then has a further 1sec vTaskDelay. If I add a delay to the task
before it enters its for loop, then the tick rate is fine until that
delay ends.

Hmm. That does sound like an problem in your tickless idle implementation then, as that is when the tick frequency gets set back to its normal ‘ticking’ frequency. Could you also try this using the default tickless idle mode, which is build into the Cortex-M4 port layer (best to use the latest version). The power saving will not be as great, but it will be good for comparison as a test.

Now there may be a problem with my low_power_tick_management.c, but
I’ve discovered that if I change the xSemaphoreTake() to a plain
vTaskDelay() then the problem goes away.

Assuming the semaphore has been created, then timing out on a semaphore should indeed behave the same as calling vTaskDelay(). The underlying mechanisms in the code’s implementation are close to being the same.

Regards.

helliwell_cj wrote on Monday, April 27, 2015:

Thanks for the quick reply.

“Did you check the latest version of FreeRTOS to see if the tickless implementation had changed? I just did - and found in fact it had, with an additional line being added - being line 384 in this file:”
I did see this addition in an online post, but I’m unsure (I’ll re-check) whether its relevant to the different timer which I have. [And it’s accepted that you can’t comment a great deal on chip specifics].

“I presume you are using xSemaphoreGiveFromISR(), rather than xSemaphoreGive().”
Sorry, yes - I abbreviated it in my text. (And I’m not even enabling the interrupt anyway now).

“If you were using the latest FreeRTOS version you would also be able to get a lot more run time checking of interrupt priorities (the most common cause of issues on Cortex-M) by having configASSERT() defined.”
I’ll look at upgrading.

I haven’t checked without tickles idle (or with the default) - to be honest, because it’s critical to the app, I’ve been using tickless pretty much from the outset.

“That does sound like an problem in your tickless idle implementation then, as that is when the tick frequency gets set back to its normal ‘ticking’ frequency”
Is that the case? As I understood it [with this implementation], it’s always the slow tick which is being used, so the frequency is fixed.

rtel wrote on Monday, April 27, 2015:

“That does sound like an problem in your tickless idle implementation
then, as that is when the tick frequency gets set back to its normal
‘ticking’ frequency” Is that the case? As I understood it [with this
implementation], it’s always the slow tick which is being used, so
the frequency is fixed.

Right - that could well be the case for the SAM4L. It is the place
where the register that sets the time the next interrupt is written to
in any case, although granted the value written to the register is
probably only calculated once at initialisation or compile time, and
then just reused - so shouldn’t be wrong if it was correct the first
time it was used.

Worth trying with the default tickless implementation all the same
though, and it could narrow down the source of the issue.

Regards.

helliwell_cj wrote on Monday, April 27, 2015:

A follow-on re. upgrading FreeRTOS - I’m using Atmel Studio, which is always a PITA. Am I right in thinking that the versions of port.c and portmacro.h I should be pulling in for this processor are the ones in ‘ARM_CM3’? (I think that’s what I did last time I upgraded).

rtel wrote on Monday, April 27, 2015:

I can’t recall if the SAM4N has a floating point unit or not. If it
does then use the port layer files from
FreeRTOS/Source/portable/GCC/ARM_CM4F. On the other hand, if it does
not have a floating point unit then use the files from
FreeRTOS/Source/portable/GCC/ARM_CM3.

Regards.

helliwell_cj wrote on Monday, April 27, 2015:

Yep - no FPU. Thanks.

helliwell_cj wrote on Monday, April 27, 2015:

Ok, the default tickless implementation works ok [albeit my app is now stripped down a lot!]. Even with the latest kernel though, my low power tickless goes awry.
It’s odd that xSemaphoreTake() vs. vTaskDelay() makes a difference; similarly enabling FreeRTOS+Trace. Makes me wonder if it relates to execution time entering/exiting the tickless state, except both presumably involve extra instructions.
Any thoughts, from these RTOS perspectives, as to what area may being getting fouled up…?

rtel wrote on Monday, April 27, 2015:

Nothing comes to mind. It is very curious that the tick frequency
doubles (or halves, I forgot what you said now).

Can you view the registers in the peripheral used to generate the tick
at the time the tick frequency is executing at the wrong frequency to
see if any look incorrect (the compare match value, a divider, or
something).

Although, that assumes the tick is really at the wrong frequency, it
could alternatively be the code that stops the tick or re-starts the
tick that is somehow generating additional interrupts so in fact the
clock is correct, but the additional interrupts make it appear as if it
were to fast (or slow, or whatever).

Are you sure the interrupt that brings the system out of sleep is being
cleared correctly, and not executing twice?

Regards.

helliwell_cj wrote on Monday, April 27, 2015:

I do suspect it’s something to do with the reload/restart logic. I did previously see the ISR being entered twice at a time, which I thought I’d corrected. It may be that it is still happening on some occasions (as the rate error seems to be somewhat variable - especially depending what other code/tasks I have in there) - another close inspection needed!

helliwell_cj wrote on Tuesday, May 05, 2015:

Does look like a problem with the RTT - I can reproduce what looks like similar symptoms with just a simple [FreeRTOS-less] test app. Support ticket opened with Atmel!

I do have a question about the tickless SAM4L example in FreeRTOS though - is there someone here (i.e. authors) who might be able to clarify a part of the code?

rtel wrote on Tuesday, May 05, 2015:

“yes”. Which part?

helliwell_cj wrote on Tuesday, May 05, 2015:

The part of vPortSuppressTicksAndSleep() after the sleep has ended due to a tick interrupt: “if( ulTickFlag != pdFALSE ) { …”.
I’m just puzzled by resetting “the alarm value with whatever remains of this tick period” - the cpu has woken because of a tick, so hasn’t the ISR already set the alarm for the next tick? Why is it necessary to re-set it? Or in other words, isn’t the alarm value just going to be set to the value it already has?

rtel wrote on Tuesday, May 05, 2015:

I don’t have the code in front of me right now, but could it be because
the MCU will have been woken part way through a tick period, but the
interrupt itself didn’t take that into account so reset the wake time
for a complete tick period (rather than the remainder of the partial
tick period)?

Regards.

helliwell_cj wrote on Wednesday, May 06, 2015:

I think that case is the ‘else’ part.