适用于 ARM Cortex-M 的低功耗 RTOS
为 ARM Cortex-M 微控制器节省功耗
[
另请参阅 SAM4L、RX100 和 STM32L MCU 上的 Tickless 演示]
本页对主要的
低功耗
tickless 空闲页面进行扩充,补充了
使用 ARM Cortex-M FreeRTOS 移植的微控制器的相关信息。
本页面包含:
当 SysTick 频率不等于核心频率时,定义 SysTick 频率
默认情况下,FreeRTOS ARM Cortex-M 移植使用 24 位 SysTick 定时器生成 tick
中断。
当 SysTick 以核心速度计时时……
大多数 ARM Cortex-M 微控制器以与 ARM Cortex-M 核心相同的频率
对 SysTick 定时器进行计时。在这种情况下,高时钟速度
和 24 位分辨率的结合会导致
可实现的最大 tickless 周期严重受限。要实现
非常高的省电收益,有必要用一个使用替代时间源的实现
来覆盖内置的 tickless 空闲实现。
如果 SysTick 定时器的频率等于核心频率,那么必须将 configSYSTICK_CLOCK_HZ
定义为等于 FreeRTOSConfig.h 中的 configCPU_CLOCK_HZ。或者,
可以干脆省略 configSYSTICK_CLOCK_HZ 的定义,在这种情况下,
它将默认为等于 configCPU_CLOCK_HZ。
当 SysTick 以低于核心速度的速度计时时……
当 SysTick 定时器的频率低于核心的频率时,
可以实现的最大 tickless 周期会大幅增加。
如果 SysTick 定时器频率不等于核心频率,则
configSYSTICK_CLOCK_HZ 必须在 FreeRTOSConfig.h 中定义为等于 SysTick
频率(以赫兹为单位)。
从 SysTick 以外的时钟生成 tick 中断
7.3.0 之前的 FreeRTOS 版本总是从
SysTick 定时器生成 tick 中断。从 FreeRTOS 7.3.0 版开始,
应用程序编写者可以选择提供自己的 tick 中断源。应用程序编写者
可能想这样做,以延长可实现的最大 tickless 周期,
或者从一个在微控制器处于深度睡眠模式时保持活动的定时器中
生成 tick 中断。
要定义备用定时器源,请执行以下操作:
-
设置定时器中断
定义一个函数来配置定时器以生成周期性中断。
该函数必须具有以下名称和原型:
void vPortSetupTimerInterrupt( void );
中断的频率必须等于 configTICK_RATE_HZ 的值
(在 FreeRTOSConfig.h 中定义)。
-
安装中断服务程序
FreeRTOS tick 中断处理程序被称为 xPortSysTickHandler()。
必须将 xPortSysTickHandler() 安装为
定时器的处理程序,该定时器由应用程序定义的 vPortSetupTimerInterrupt() 函数配置。
-
确保不使用 CMSIS 名称
一些 FreeRTOS 演示应用程序会将 FreeRTOS tick 中断处理程序的名称映射到
默认的 CMSIS SysTick 处理程序名称,即 SysTick_Handler()。这是
通过在 FreeRTOSConfig.h 中包括以下行来实现的:
#define xPortSysTickHandler SysTick_Handler
如果 tick 中断是由 SysTick 以外的定时器生成的,
则不能这样做。
一些由第三方发布的 FreeRTOS 软件包更进一步,
在
FreeRTOS port.c 源文件中将 xPortSysTickHandler() 实际重命名为 SysTick_Handler()。在这种情况下,
那么 FreeRTOSConfig.h 中的 #define 就可以用来扭转这种变化,
如下所示:
#define SysTick_Handler xPortSysTickHandler
在任何情况下,如果 SysTick 定时器不是中断源,都必须确保不要将 FreeRTOS 的 tick 中断
处理程序安装为 SysTick 处理程序
。
使用微控制器特定的低功耗功能
内置的 tickless 空闲实现使用
WFI(等待中断)指令,在停止 tick 中断后暂停执行。以下
两个钩子宏允许在 WFI 指令的任何一侧插入应用程序特定的节能代码,
实际上是用应用程序特定的替代指令替换
WFI:
-
configPRE_SLEEP_PROCESSING( xExpectedIdleTime )
configPRE_SLEEP_PROCESSING() 在即将执行 WFI
指令之前执行。它可以用于关闭外设时钟,并激活
任何微控制器特定的低功耗功能。传递预计的空闲时间(以 tick 为单位)作为唯一参数,
可通过宏的实现进行修改。如果实现将
xExpectedIdleTime 设置为 0,则不会调用 WFI。这使得
宏的实现可以覆盖默认的睡眠模式。将
xExpectedIdleTime 设置为 0 以外的任何值都是危险的!
-
configPOST_SLEEP_PROCESSING( xExpectedIdleTime )
configPOST_SLEEP_PROCESSING() 在微控制器离开低功率状态后
立即执行。它可以用来逆转
configPRE_SLEEP_PROCESSING() 的动作,这样做
可以使微控制器恢复到全面运转状态。传递预计的空闲时间(以 tick 为单位)作为唯一参数,
可通过宏的实现进行修改。应只能由完全了解内置 ARM Cortex-M 低功率实现
(通过查看源代码注释)的专家用户,
来尝试修改微控制器离开低功率状态后
的预计空闲时间。
configPRE_SLEEP_PROCESSING 和 configPOST_SLEEP_PROCESSING() 可在
FreeRTOSConfig.h 中定义。
示例配置
当 SysTick 频率等于核心频率时,使用内置的 tickless 空闲实现
- 在 FreeRTOSConfig.h 中将 configUSE_TICKLESS_IDLE 设置为 1
当 SysTick 频率不等于核心频率时,使用内置的 tickless 空闲实现
- 在 FreeRTOSConfig.h 中将 configUSE_TICKLESS_IDLE 设置为 1
- 将 configSYSTICK_CLOCK_HZ 设置为等于 SysTick 时钟频率(以赫兹为单位)。
当使用 SysTick 以外的时钟来生成 tick 中断时,使用内置的 tickless 空闲实现
这不是一个有效的配置。
使用 SysTick 以外的时钟生成 tick 中断
- 在 FreeRTOSConfig.h 中将 configUSE_TICKLESS_IDLE 设置为 2。
- 提供 vPortSetupTimerInterrupt() 的实现,
以 configTICK_RATE_HZ
FreeRTOSConfig.h 常量指定的频率生成一个中断。
- 安装 xPortSysTickHandler() 作为定时器中断的处理程序,
并确保 xPortSysTickHandler() 没有被映射到
FreeRTOSConfig.h 中的 SysTick_Handler(),或在 port.c 中被重命名为 SysTick_Handler()。
- 按照
tickless 空闲文档
页面所述定义 portSUPPRESS_TICKS_AND_SLEEP()。
或者,这也可以通过覆盖弱定义的 vPortSetupTimerInterrupt() 和 vPortSuppressTicksAndSleep() 来实现。在这种情况下,configUSE_TICKLESS_IDLE 设置为 1。用户需要提供 vPortSetupTimerInterrupt() 和 vPortSuppressTicksAndSleep() 的匹配实现。并且函数定义不应有弱属性。用户还需要安装 xPortSysTickHandler(),如上所述。
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.