Low Power RTOS For ARM Cortex-M MCUs
Saving power on ARM Cortex-M microcontrollers
[More Advanced]
[See also Tickless Demos on SAM4L, RX100, and STM32L MCUs ]
This page augments the main low power
tickless idle page with information that is specific to microcontrollers that
use a ARM Cortex-M3 or ARM Cortex-M4F FreeRTOS port.
On this page:
By default, the FreeRTOS ARM Cortex-M port uses the 24-bit SysTick timer to generate tick
interrupts.
When SysTick is clocked at the core speed...
Most ARM Cortex-M microcontrollers clock the SysTick timer at the same frequency
as the ARM Cortex-M core. When this is the case, the combination of high clock speed
and 24-bit resolution result in
a sever limitation in the maximum tickless period that can be achieved. To achieve
very high power saving gains it is necessary to override the built in tickless
idle implementation with an implementation that uses an alternative time source.
If the SysTick timer frequency equals the core frequency then configSYSTICK_CLOCK_HZ
must be defined to equal configCPU_CLOCK_HZ in FreeRTOSConfig.h. Alternatively,
a definition for configSYSTICK_CLOCK_HZ can just be omitted, in which case it will
default to equal configCPU_CLOCK_HZ.
When SysTick is clocked below the core speed...
The maximum tickless period that can be achieved increases dramatically when
the frequency of the SysTick timer is less than the frequency of the core.
If the SysTick timer frequency does not equal the core frequency then
configSYSTICK_CLOCK_HZ must be defined in FreeRTOSConfig.h to equal the SysTick
frequency (in Hz).
Versions of FreeRTOS prior to version 7.3.0 always generate the tick interrupt
from the SysTick timer. From FreeRTOS version 7.3.0 it is possible for the
application writer to optionally provide their own tick interrupt source. An
application writer might want to do this to extend the maximum tickless period
that can be achieved, or to generate the tick interrupt from a timer that remains
active when the microcontroller is in a deep sleep mode.
To define an alternative timer source:
-
Setup the timer interrupt
Define a function to configure a timer to generate a periodic interrupt.
The function must have the following name and prototype:
void vPortSetupTimerInterrupt( void );
The frequency of the interrupt must equal the value of configTICK_RATE_HZ
(which is defined in FreeRTOSConfig.h).
-
Install the interrupt service routine
The FreeRTOS tick interrupt handler is called xPortSysTickHandler().
xPortSysTickHandler() must be installed as the handler for the timer that
is configured by the application defined vPortSetupTimerInterrupt() function.
-
Ensure CMSIS names are not being used
Some FreeRTOS demo applications map the name of the FreeRTOS tick interrupt handler to
the default CMSIS SysTick handler name, which is SysTick_Handler(). This
is done by including the following line in FreeRTOSConfig.h:
#define xPortSysTickHandler SysTick_Handler
This must not be done if the tick interrupt is being generated by a timer
other than SysTick.
Some FreeRTOS packages distributed by third parties have gone further
by actually renaming xPortSysTickHandler() to SysTick_Handler() in the
FreeRTOS port.c source file. If this is the case then a #define in
FreeRTOSConfig.h can
be used to reverse the change, as follows:
#define SysTick_Handler xPortSysTickHandler
In any case, it is important to ensure the FreeRTOS tick interrupt
handler is not installed as the SysTick handler if the SysTick timer is
not the interrupt source.
The built in tickless idle implementation uses the
WFI (Wait For Interrupt) instruction to suspend execution after stopping the tick interrupt. The following
two hook macros are provided to allow application specific power saving code to
be inserted either side of the WFI instruction, and actually replace the WFI
with an application specific alternative instruction:
-
configPRE_SLEEP_PROCESSING( xExpectedIdleTime )
configPRE_SLEEP_PROCESSING() is executed immediately before the WFI
instruction. It can be used to turn peripheral clocks off, and activate
any microcontroller specific low power functionality.
The expected idle time in ticks is passed as the only parameter, and can
be modified by the macro's implementation. If the implementation sets
xExpectedIdleTime to 0 then WFI will not be called. This allows the
macro's implementation to override the default sleep mode. It is
dangerous to set xExpectedIdleTime to any value other than zero!
-
configPOST_SLEEP_PROCESSING( xExpectedIdleTime )
configPOST_SLEEP_PROCESSING() is executed as soon as the microcontroller
leaves its low power state. It can be used to reverse the actions of
configPRE_SLEEP_PROCESSING(), and in so doing, return the microcontroller
back to its fully operational state.
The expected idle time in ticks is passed as the only parameter, and can
be modified by the macro's implementation. Modifying the expected idle
time after the microcontroller has left its low power state should only
be attempted by expert users who fully understand the built in ARM Cortex-M
low power implementation (by viewing the source code comments).
configPRE_SLEEP_PROCESSING and configPOST_SLEEP_PROCESSING() can be defined in
FreeRTOSConfig.h.
Using the built in tickless idle implementation when SysTick frequency equals core frequency
-
Set configUSE_TICKLESS_IDLE to 1 in FreeRTOSConfig.h
Using the built in tickless idle implementation when SysTick frequency does not equal the core frequency
-
Set configUSE_TICKLESS_IDLE to 1 in FreeRTOSConfig.h
-
Set configSYSTICK_CLOCK_HZ to equal the SysTick clock frequency in Hz.
Using the built in tickless idle implementation when using a clock other than SysTick to generate the tick interrupt
This is not a valid configuration.
Using a clock other than SysTick to generate the tick interrupt
-
Set configUSE_TICKLESS_IDLE to 2 in FreeRTOSConfig.h.
-
Provide an implementation of vPortSetupTimerInterrupt() that generates
an interrupt at the frequency specified by the configTICK_RATE_HZ
FreeRTOSConfig.h constant.
-
Install xPortSysTickHandler() as the handler for the timer interrupt,
and ensure xPortSysTickHandler() is not mapped to SysTick_Handler() in
FreeRTOSConfig.h, or renamed as SysTick_Handler() in port.c.
-
Define portSUPPRESS_TICKS_AND_YIELD() as described on the main
tickless idle documentation
page.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|