第16章 低功耗TickLess
约 760 字大约 3 分钟
2026-01-19
16.1 核心知识点
概述:
FreeRTOS 的 Tickless 模式是一种特殊的运行模式,用于最小化系统的时钟中断频率,以降低功耗。
在 Tickless 模式下,系统只在有需要时才会启动时钟中断,而在无任务要运行时则完全进入休眠状态,从而降低功耗。
相关宏
configUSE_TICKLESS_IDLE 是否启动 Tickless 模式,默认0
configEXPECTED_IDLE_TIME_BEFORE_SLEEP 系统进入 Tickless 模式的最短时长,默认 2
configPRE_SLEEP_PROCESSING( x ) 在系统进入 Tickless 模式前执行的事务,比如关闭外设时钟
configPOST_SLEEP_PROCESSING( x ) 系统退出 Tickless 模式后执行的事务,比如开启之前关闭的外设时钟configPRE_SLEEP_PROCESSING() 和 configPRE_SLEEP_PROCESSING() 能够接收到 xModifiableIdleTime 作为参数,xModifiableIdleTime 表示系统进入低功耗后预计休眠的时钟节拍数,其最大值限制如下:
portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
#ffffff / (72000000/1000) ≈ 233HAL 库开启关闭GPIO外设时钟的函数:
__HAL_RCC_GPIOA_CLK_DISABLE()
__HAL_RCC_GPIOB_CLK_DISABLE()
__HAL_RCC_GPIOC_CLK_DISABLE()
__HAL_RCC_GPIOD_CLK_DISABLE()
__HAL_RCC_GPIOE_CLK_DISABLE()
__HAL_RCC_GPIOF_CLK_DISABLE()
__HAL_RCC_GPIOG_CLK_DISABLE()
__HAL_RCC_GPIOA_CLK_ENABLE()
__HAL_RCC_GPIOB_CLK_ENABLE()
__HAL_RCC_GPIOC_CLK_ENABLE()
__HAL_RCC_GPIOD_CLK_ENABLE()
__HAL_RCC_GPIOE_CLK_ENABLE()
__HAL_RCC_GPIOF_CLK_ENABLE()
__HAL_RCC_GPIOG_CLK_ENABLE()16.2 案例
① 需求
任务1: 每次循环都阻塞延时1000ms
需要注意的是,低功耗模式无法测试,只能通过调试源码的方式判断是否真正进入了低功耗模式。② 代码
FreeRTOSConfig.h
添加配置项:
// 函数原型:进入TickLess模式前的钩子函数
void enter_tickless_mode( uint32_t time );
// 函数原型:退出TickLess模式后的钩子函数
void exit_tickless_mode( uint32_t time );
// 开启TickLess功能
#define configUSE_TICKLESS_IDLE 1
// 设置只剩空闲任务时进入TickLess等待的滴答数
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
// 定义进入TickLess模式前的钩子函数
#define configPRE_SLEEP_PROCESSING( x ) enter_tickless_mode( x )
// 定义退出TickLess模式后的钩子函数
#define configPOST_SLEEP_PROCESSING( x ) exit_tickless_mode( x )App_Task.c
#include "App_Task.h"
// 任务1 ------------------------------------
// 任务1函数的原型
void task1_callback(void *pvParameters);
// 任务1名称
#define TASK1_NAME "task1"
// 任务1堆栈大小
#define TASK1_STACK_SIZE 128
// 任务1的优先级
#define TASK1_PRIORITY 1
// 任务1的句柄
TaskHandle_t task1_handle;
// 声明使用全局变量 htim6;
extern TIM_HandleTypeDef htim6;
/**
* @brief 启动 FreeRTOS 任务管理
*
*/
void App_Task_Start(void)
{
// 进入临界区
taskENTER_CRITICAL();
// 创建任务1
xTaskCreate(task1_callback, TASK1_NAME, TASK1_STACK_SIZE, NULL, TASK1_PRIORITY, &task1_handle) == pdPASS ? printf("任务1创建成功! \n") : printf("任务1穿件失败! \n");
taskEXIT_CRITICAL();
// 启动任务调度器 ( vTaskStartScheduler() 后面的代码不会被执行)
printf("任务调度器启动... \n");
vTaskStartScheduler();
}
// 任务1函数的实现
void task1_callback(void *pvParameters)
{
printf("任务1启动... \n");
while (1)
{
// 打印内容
printf("任务1: 正在运行... \n");
// 阻塞延时
// vTaskDelay(200);
vTaskDelay(1000);
}
}
// 定义进入TickLess前的钩子函数的
void enter_tickless_mode(uint32_t time)
{
// 关闭TIM6更新中断,防止TIM6中断唤醒TickLess(Sleep)
HAL_TIM_Base_Stop_IT(&htim6);
// 打印内容 time 的值最大是233
printf("进入TickLess低功耗模式, 期望睡眠时间是 %d \n", time);
}
// 定义退出TickLess后的钩子函数的
void exit_tickless_mode(uint32_t time)
{
// 开启TIM6更新中断
HAL_TIM_Base_Start_IT(&htim6);
// 打印内容
printf("退出TickLess低功耗模式, 实际睡眠时间是 %d \n", time);
}