Use RTC rather than SysTick as the tick source?

fearless-fool wrote on Tuesday, July 23, 2019:

[Note: This is a cross-post from https://stackoverflow.com/questions/57156855/use-rtc-rather-than-systick-as-the-tick-source-for-freertos – I’m not sure which is the better venue for this question.]

I’m familiar with FreeRTOS ports for the Cortex-M0 that use SysTick for normal operations and switch to the RTC during tickless mode.

But why not use the RTC all the time as the tick source? Are there examples of doing that?

As far as I understand, using the RTC full-time would simplify the logic getting into and out of tick-less sleep states since the RTC is always running.

Am I missing something?

xz8987f wrote on Tuesday, July 23, 2019:

It depends on the resolution of the RTC tick. And not sure to which port you are referring. But here is what I use and do on Cortex-M:
a) Systick is used by default
b) Approach a) can be combined with tickless-idle mode
c) for low power, it depends what can wake me up from low power (depending on the mode). If Systick wakes me up (basically any interrupt), systick can be used
d) if Systick is not an exit from low power mode, I’m using a low power timer (which usually has a 1 ms resolution which is good enough)
e) if I need to go deeper in low power, I could use the RTC. That usually means that the RTC alarm interrupt is the only thing which can wake me up, so the low power timer does not help. But typically the RTC has a resolution of 1 sec which is not appropriate for most cases. In that case I’m using the low power timer (or systick) in tickless mode, and for extended sleep periods I set an RTC alarm to wake me up and continue to use the Systick or low power timer for ‘normal’ operation.

So I don’t switch the time-base (systick or low power timer): what I do is to use the RTC alarm to wake me up after some time.

I’m sure there are other ways doing this, but this has worked very well for me.

I hope this helps,
Erich

fearless-fool wrote on Tuesday, July 23, 2019:

Hi Erich!

Before switching to FreeRTOS, I have typically used the RTC running at
32KHz and used its COMP interrupt to wake the processor from sleep
mode(s).

Perhaps its because what I’m already familiar with, but is seems as if
FreeRTOS would benefit by using the RTC all the time: for “wake” modes the
COMP interrupt would be set for 1mSec, for “sleep” (aka tickless) modes,
the COMP interrupt would be set for N seconds in the future.

The advantage of this approach is simplicity and accuracy: you don’t have
to convert between two time bases, and since the RTC runs continually, you
never lose any accuracy. (I’ve read the code for tickless.c and I can see
where and why it would lose some accuracy.)

  • rdp

On Tue, Jul 23, 2019 at 7:33 AM Erich Styger xz8987f@users.sourceforge.net
wrote:

It depends on the resolution of the RTC tick. And not sure to which port
you are referring. But here is what I use and do on Cortex-M:
a) Systick is used by default
b) Approach a) can be combined with tickless-idle mode
c) for low power, it depends what can wake me up from low power (depending
on the mode). If Systick wakes me up (basically any interrupt), systick can
be used
d) if Systick is not an exit from low power mode, I’m using a low power
timer (which usually has a 1 ms resolution which is good enough)
e) if I need to go deeper in low power, I could use the RTC. That usually
means that the RTC alarm interrupt is the only thing which can wake me up,
so the low power timer does not help. But typically the RTC has a
resolution of 1 sec which is not appropriate for most cases. In that case
I’m using the low power timer (or systick) in tickless mode, and for
extended sleep periods I set an RTC alarm to wake me up and continue to use
the Systick or low power timer for ‘normal’ operation.

So I don’t switch the time-base (systick or low power timer): what I do is
to use the RTC alarm to wake me up after some time.

I’m sure there are other ways doing this, but this has worked very well
for me.

I hope this helps,
Erich

Use RTC rather than SysTick as the tick source?
https://sourceforge.net/p/freertos/discussion/382005/thread/44e1dff619/?limit=25#71c9

Sent from sourceforge.net because you indicated interest in
SourceForge.net: Log In to SourceForge.net

To unsubscribe from further messages, please visit
SourceForge.net: Log In to SourceForge.net

rtel wrote on Tuesday, July 23, 2019:

When I tried running the code found the sequence to be as follows:

After a short time the lines in DetectLimitReach() executed.

if(heures>=2)
{
  ComptFin = xEventGroupSetBits(
    ComptFin_Group,
    ( 1 << 2 ));
}
vTaskDelay(400 / portTICK_RATE_MS);

}
vTaskDelete(NULL);

This set bit 1<<2 in the event group, which unblocked RaZheure_IPC() -
but RaZheure_IPC() didn’t run immediately as it has the same priority as
DetectLimitReach(). When DetectLimitReach() then executed vTaskDelay(),
which put it into the blocked state, RaZheure_IPC() executed…which I
think was your intended behaviour.

There is a subtle bug in your code however as the event group is created
in DetectLimitReach(), which is a task that has equal priority to other
tasks that are attempting to use the event group - if any other task
should happen to run first (which would be the case if you changed the
order in which the tasks were created) then the code would crash because
an attempt was made to access an event group before it was created.
Creating the event group in main() before the scheduler is started would
prevent that.

richard_damon wrote on Tuesday, July 23, 2019:

I think one key reason FreeRTOS by default uses the SysTick is that it is universally available as a core resource for the full processor family, and thus there can be a single port that doesn’t depend on the particular processor. An RTC is not so universal.

A second issue is that for the Systick, the tick rate is typically able to be set to EXACTLY 1000 Hz (or 100 Hz or what ever round number is desired) while a low power timer based on a 32768 Hz crystal will give you something like 1024 Hz. While in most cases this difference isn’t important, for some people it is (or they think it is).

FreeRTOS does readily allow you to replace the Systick interrupt with something else for its time base, and I think a low power timer based on a 32768 Hz base works well (I will typically prescale by 32 and then divide by 10 to give me a 102.4 Hz tick rate, close enough to a 100 Hz/10ms tick.) This allowes a tickless idle period of about a minute, and if you need longer than the RTC could be used instead for that timeout (and let the tick count get off).

fearless-fool wrote on Tuesday, July 23, 2019:

Richard:

On Tue, Jul 23, 2019 at 9:00 AM Richard Damon <
richard_damon@users.sourceforge.net> wrote:

I think one key reason FreeRTOS by default uses the SysTick is that it is
universally available as a core resource for the full processor family, and
thus there can be a single port that doesn’t depend on the particular
processor. An RTC is not so universal.

Point well taken…

A second issue is that for the Systick, the tick rate is typically able to
be set to EXACTLY 1000 Hz … While in most cases this difference isn’t
important, for some people it is (or they think it is).

Exactly: there’s nothing magic about a tick rate of exactly 1mSec. Or if
it IS important, then you’d also care about losing accuracy across tickless
(sleeping) intervals. Using a continually-running RTC avoids that drift.

FreeRTOS does readily allow you to replace the Systick interrupt with
something else for its time base, and I think a low power timer based on a
32768 Hz base works well (I will typically prescale by 32 and then divide
by 10…

This implies you’ve done this? Is there a code example I could stare at?
It would accelerate my learning…

This allowes a tickless idle period of about a minute, and if you need
longer than the RTC could be used instead for that timeout (and let the
tick count get off).

The RTC’s I’ve been working with are 32 bits, so if you use the COMP
interrupt to wake the processor, you can get delays of up to (almost)
131072 seconds (1.5 days) – adequate for many applications.

Many thanks!

  • rdp

Use RTC rather than SysTick as the tick source?
https://sourceforge.net/p/freertos/discussion/382005/thread/44e1dff619/?limit=25#bd41

Sent from sourceforge.net because you indicated interest in
SourceForge.net: Log In to SourceForge.net

To unsubscribe from further messages, please visit
SourceForge.net: Log In to SourceForge.net

rtel wrote on Tuesday, July 23, 2019:

FreeRTOS does readily allow you to replace the Systick interrupt with
something else for its time base, and I think a low power timer
based on a
32768 Hz base works well (I will typically prescale by 32 and then
divide
by 10...

This implies you’ve done this? Is there a code example I could stare at?
It would accelerate my learning…

What is it you are looking for an example of? Replacing the systick
with something else, or using a 32KHz clock to generate the tick?

Replacing the systick as the clock is a matter of providing your own
implementation of vPortSetupTimerInterrupt() as the default
implementation is maked as a weak symbol:
https://sourceforge.net/p/freertos/code/HEAD/tree/tags/V10.2.1/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c#l550

You then have to install the interrupt handler for whichever interrupt
the timer you chose generates. The interrupt handler would be
functionally identical to this one, although you may need additional
code that is specific to managing the chosen timer:
https://sourceforge.net/p/freertos/code/HEAD/tree/tags/V10.2.1/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c#l529

fearless-fool wrote on Tuesday, July 23, 2019:

Richard:

On Tue, Jul 23, 2019 at 9:32 AM Richard Barry rtel@users.sourceforge.net
wrote:

What is it you are looking for an example of? Replacing the systick with

something else, or using a 32KHz clock to generate the tick?

Is that not the same thing? :slight_smile:

Replacing the systick as the clock is a matter of providing your own

implementation of vPortSetupTimerInterrupt() as the default implementation
is marked as a weak symbol:

FreeRTOS Real Time Kernel (RTOS) / Code / [r2837] /tags/V10.2.1/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c

You then have to install the interrupt handler for whichever interrupt the
timer you chose generates. The interrupt handler would be functionally
identical to this one, although you may need additional code that is
specific to managing the chosen timer:

FreeRTOS Real Time Kernel (RTOS) / Code / [r2837] /tags/V10.2.1/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c

Perfect – those are the pointers I was seeking. Many thanks.

  • rdp

richarddamon wrote on Wednesday, July 24, 2019:

Yes, I have done it, but the code is part of a product that I really can’t share. Richard Barry has shared the links to the documentation that I used to derive it, and that part is fairly simple.

My example is also for an M4, so not directly applicatable (but very similar), and most of the code is operating the timer, which would be different than your needs.

In my case, I am using a 16 bit low power timer in the chip, which can run and wake up the processor even when largely put to sleep (the main processor clock is stopped and most perpherals, other than a few ‘low power’ ones frozen). Yes, a 32 bit timer would give you much more time.

fearless-fool wrote on Wednesday, July 24, 2019:

Richard D:

Thank you for the confirmation.

I am using a 16 bit low power timer in the chip, which can run and wake up the processor even when largely put to sleep…

That’s my use case as well: the RTC is the only thing left running while the processor and other peripherals sleep. A match on the RTC’s COMP register can bring the processor out of sleep.

As I alluded to above, my motivation for using the RTC as FreeRTOS’s sole tick source is that you never lose any counts across sleeps, since the RTC runs continually without getting reset.

I’ll follow Mr. Barry’s pointers and see what I can cobble together. Thanks!

Yes, a 32 bit timer would give you much more time.

(Sure, but even a 16 bit timer running at 32KHz with a 32:1 prescaler will give you 1 millisecond resolution with 67M seconds before rolling over…)