当前位置: 首页 > article >正文

FreeRTOS低功耗总结

前言

Cortex-M核的MCU一般支持以下三种低功耗方式:

● 睡眠(Sleep)模式

● 停止(Stop)模式

● 待机(Standby)模式

睡眠模式

 进入睡眠模式有两种指令:WFI(等待中断)和WFE(等待事件),

WFI进入睡眠模式后,任意中断都可唤醒。

WFE进入睡眠模式后,任意唤醒事件都可唤醒

FreeRTOS 使用 WFI 指令进入实现低功耗控制。

停止模式

在特定的条件下执行WFI(等待中断)或者WFE(等待事件)指令,保留SRAM数据,调压器正常工作或者低功耗,大部分时钟关闭。

由外部中断唤醒

待机模式

相比于停止,待机模式的功耗更低。在停止模式基础上,SRAM数据丢失,调压器也关闭,大部分寄存器内容也丢失

由wakeup引进,复位引脚,看门狗或者RTC退出

由于停止/待机模式下软件的正常运行功能都将无法使用,并且其实现需要特定的硬件设计及系统方案,不在本次总结的讨论范围内。

本次总结仅对FreeRTOS系统功能正常运行情况下的低功耗总结,即睡眠模式。

任务运行状态

FreeRTOS作为多任务实时操作系统,开发过程中研发难免需要对软件任务的状态进行查看,FreeRTOS提供了相关的接口用来查询相关状态,

void vTaskList( char *pcWriteBuffer );获取当前所有任务状态
void vTaskGetRunTimeStats( char *pcWriteBuffer );获取当前所有任务占用率

size_t xPortGetFreeHeapSize( void )

获取当前堆剩余字节数

size_t xPortGetMinimumEverFreeHeapSize( void )

获取历史堆最小剩余字节数

任务状态

void vTaskList( char *pcWriteBuffer )

FreeRTOSConfig.h 中 必须定义才能使用vTaskList

#define configUSE_TRACE_FACILITY  1

#define configUSE_STATS_FORMATTING_FUNCTIONS 1

任务占用率

void vTaskGetRunTimeStats( char *pcWriteBuffer )

Abs time : 任务占用的tick数

% time : 占用率

FreeRTOSConfig.h 中 必须定义才能使用vTaskList

#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1

configGENERATE_RUN_TIME_STATS 定义为1 后 还需要定义以下宏

统计定时器配置函数  

portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
portGET_RUN_TIME_COUNTER_VALUE()/portALT_GET_RUN_TIME_COUNTER_VALUE(Time)

统计定时器值获取函数  

方式1:高精度定时器

用户实现自己实现高精度定时器

    #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() configureTimeStats()//初始化硬件定时器#define portGET_RUN_TIME_COUNTER_VALUE() getRunTime()//获取定时器的计数值

优点:占用率计算准确

缺点:多使用硬件资源,多了个更高频率的定时器,影响性能

方式2:直接使用系统ticks

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() xTaskGetTickCount() //初始化执行一次
#define portGET_RUN_TIME_COUNTER_VALUE()         xTaskGetTickCount()

优点:不占用额外任何资源,不影响性能

缺点:占用率计算精度不高

堆使用状态

size_t xPortGetFreeHeapSize( void )  //当前堆剩余字节数
size_t xPortGetMinimumEverFreeHeapSize( void ) //获取历史堆最小剩余字节数

关系到 FreeRTOSConfig.h 中的 configTOTAL_HEAP_SIZE     大小设置

#define configTOTAL_HEAP_SIZE    ((size_t)(64 * 1024))

空闲任务


        空闲任务是 FreeRTOS 必不可少的一个任务,因此,空闲任务的优先级肯定是最低的,FreeRTOS 在空闲任务中也会执行一些其他的处理。

         vTaskStartScheduler()启动任务调度器的时候FreeRTOS会自动创建空闲任务,如果某个任务要调用函数 vTaskDelete()删除自身,那么这个任务的资源需要在空闲任务中释放掉。因此,空闲任务也需要一定的时间片执行。

       对于系统而言,一般软件都不会CPU满额运行,大部分时间都处于空闲状态,若用户需要在空闲状态下做一些特殊处理,如低功耗模式、关闭某些外设、降低系统主频等。

FreeRTOS 提供了相关的功能,即钩子函数,可简单理解为回调函数

常见钩子函数如下

FreeRTOSConfig.h 宏定义钩子函数说明

configUSE_IDLE_HOOK

void vApplicationIdleHook(void)

空闲回调

configUSE_TICK_HOOK

void  vApplicationTickHook(void);

tick自加回调
configCHECK_FOR_STACK_OVERFLOW

void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName)

任务栈溢出回调

configUSE_MALLOC_FAILED_HOOK

void vApplicationMallocFailedHook(void)

内存申请失败回调
configUSE_DAEMON_TASK_STARTUP_HOOKvoid vApplicationDaemonTaskStartupHook( void );定时器任务启动回调

定义举例

void vApplicationIdleHook(void)
{/* Enter sleep-mode */Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
}void vApplicationStackOverflowHook(TaskHandle_t *pxTask, signed char *pcTaskName)
{/* Remove warning for unused parameters */(void)pxTask;(void)pcTaskName;/* Print the error message with task name if debug is enabled in uart_debug.h file */DebugPrintf("Error!   : RTOS - stack overflow in %s \r\n", pcTaskName);/* Halt the CPU */CY_ASSERT(0);
}void vApplicationMallocFailedHook(void)
{/* Print the error message if debug is enabled in uart_debug.h file */DebugPrintf("Error!   : RTOS - Memory allocation failed \r\n");/* Halt the CPU */CY_ASSERT(0);
}

Idle低功耗

最简单的低功耗方式即:在空闲任务钩子函数中将处理器设置为低功耗模式

void vApplicationIdleHook(void)
{/* Enter sleep-mode */Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
}

几乎所有支持 RTOS 系统的MCU都可以使用这种方法实现低功耗,该方式有以下特点:

大多数场景下,系统时钟是由滴答定时器中断来提供的,系统时钟频率越高,那么滴答定时器中断频率也就越高,但中断MCU从睡眠模式中唤醒, 使得MCU周期性的进入和退出睡眠模式。因此,如果滴答定时器中断频率太高的话会导致大量的能量和时间消耗在进出睡眠模式中,这样导致的结果就是低功耗模式的作用被大大的削弱。

Tickless 低功耗

针对通用低功耗的问题,FreeRTOS提供了另一种低功耗方式,该方式不同MCU的支持可能存在不同,即为 Tickless 模式

当处理器进入空闲任务周期以后就关闭系统节拍中断(滴答定时器中断),只有当其他中断发生或者其他任务需要处理的时候处理器才会被从低功耗模式中唤醒。

由此需要解决两个问题:

问题1:关闭系统节拍中断会导致系统节拍计数器停止,系统tick就会停止

FreeRTOS解决方法:

       FreeRTOS 可通过另一定时器记录下系统节拍中断的关闭时间,当恢复的时候补上这段时间,如果是专用的低功耗处理器,该定时器一般都是用专用的低功耗定时器。

问题2:如何保证下一个要运行的任务能被准确的唤醒。即使处理器进入了低功耗模式,但是中断和应用层任务也要保证及时的响应和处理。 中断不用说,本身就可以唤醒。但是应用层任务就不行了,它无法将处理器从低功耗模式唤醒,无法唤醒就无法运行。

FreeRTOS解决方法:

       计算在进入低功耗模式之前能够获取到还有多长时间切换到下一任务,借助新增的定时器,将其中断周期修改为低功耗运行时间,其中断到来后即可唤醒处理器。

以apollo为例,其官方支持Tickless模式并且提供相应文档说明,但cypress不支持


#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1 // Enable non-SysTick based Tick
#define configUSE_TICKLESS_IDLE                   2 // Ambiq specific implementation for Tickless#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
extern uint32_t am_freertos_sleep(uint32_t);
extern void am_freertos_wakeup(uint32_t);#define configPRE_SLEEP_PROCESSING( time ) \do { \(time) = am_freertos_sleep(time); \} while (0);#define configPOST_SLEEP_PROCESSING(time)    am_freertos_wakeup(time)
#endif
/*-----------------------------------------------------------*/
#ifndef AM_PART_APOLLO
#define AM_FREERTOS_USE_STIMER_FOR_TICK
#endif#ifdef AM_FREERTOS_USE_STIMER_FOR_TICK
#ifdef APOLLO4_FPGA
#define configSTIMER_CLOCK_HZ                     1500000
#define configSTIMER_CLOCK                        AM_HAL_STIMER_HFRC_6MHZ
#else
#define configSTIMER_CLOCK_HZ                     32768
#define configSTIMER_CLOCK                        AM_HAL_STIMER_XTAL_32KHZ
#endif
#else // Use CTimer
#define configCTIMER_NUM                          3
#define configCTIMER_CLOCK_HZ                     32768
#define configCTIMER_CLOCK                        AM_HAL_CTIMER_XT_32_768KHZ
#endif

两种模式对比分析

图中有三个任务,它们分别为一个空闲任务(Idle),两个用户任务(Task1 和 Task2), 其中空闲任务一共有运行了三次,分别为(1) 、(2) 、(3),其中 T1 到 T12 是 12 个时刻,下面我们分别从这两种低功耗的实现方法去分析一下整个过程。

1、Idle低功耗模式

       如果使用通用低功耗模式的话每个滴答定时器中断都会将处理器从低功耗模式中唤醒,以 (1)为例,再 T2 时刻处理器从低功耗模式中唤醒,但是接下来由于没有就绪的其他任务所以处理器又再一次进入低功耗模式。T2、T3 和 T4 这三个时刻都一样,反复的进入低功耗、退出低功耗,最理想的情况应该是从 T1 时刻就进入低功耗,然后在 T5 时刻退出。

      在(2)中空闲任务只工作了两个时钟节拍,但是也执行了低功耗模式的进入和退出,显然这个意义不大,因为进出低功耗也是需要时间的。

      (3)中空闲任务在 T12 时刻被某个外部中断唤醒,中断的具体处理过程在任务 2(使用信号量实现中断与任务之间的同步)。

2 、 Tickless 低功耗模式

     在(1)中的 T1 时刻处理器进入低功耗模式,在 T5 时刻退出低功耗模式。相比通用低功耗模式少了 3 次进出低功耗模式的操作。

   在(2)中由于空闲任务只运行了两个时钟节拍, 所以就没必要进入低功耗模式。说明在 Tickless  模式中只有空闲任务要运行时间的超过某个最小阈值的时候才会进入低功耗模式,此阈值通过 configEXPECTED_IDLE_TIME_BEFORE_SLEEP 来设置,上一章已经讲过了。

     (3)中的情况和通用低功耗模式一样。

总结

    1、可以看出相对与通用低功耗模式, Tickless 模式更加合理有效,所以如果有低功耗设计需求的话大家尽量使用 Tickless 模式。

    2、几乎所有支持FreeRTOS的MCU都支持Idle低功耗模式,但不一定支持Tickless 模式,Tickless 模式的支持需要依赖于MCU厂家对该功能的支持,具体实现方式一般在对应的FreeRTOS的port.c文件中。

参考资料:

FreeRTOS的低功耗Tickless模式与空闲函数_freertos 空闲任务进入低功耗模式-CSDN博客

FreeRTOS_Reference_Manual_V10.0.0.pdf

FreeRTOS™ - FreeRTOS™

相关文章:

FreeRTOS低功耗总结

前言 Cortex-M核的MCU一般支持以下三种低功耗方式: ● 睡眠(Sleep)模式 ● 停止(Stop)模式 ● 待机(Standby)模式 睡眠模式 进入睡眠模式有两种指令:WFI(等待中断)和WFE(等待事件), WFI进入睡眠模式后,任意中断都可唤醒。 WFE进…...

【IC】AI处理器核心--第二部分 用于处理 DNN 的硬件设计

第 II 部分 用于处理 DNN 的硬件设计 第 3 章 关键指标和设计目标 在过去的几年里,对 DNN 的高效处理进行了大量研究。因此,讨论在比较和评估不同设计和拟议技术的优缺点时应考虑的关键指标非常重要,这些指标应纳入设计考虑中。虽然效率通常…...

React历代主要更新

一、React 16之前更新 React Fiber是16版本之后的一种更新机制,使用链表取代了树,是一种fiber数据结构,其有三个指针,分别指向了父节点、子节点、兄弟节点,当中断的时候会记录下当前的节点,然后继续更新&a…...

常用查找算法整理(顺序查找、二分查找、哈希查找、二叉排序树查找、平衡二叉树查找、红黑树查找、B树和B+树查找、分块查找)

常用的查找算法: 顺序查找:最简单的查找算法,适用于无序或数据量小的情况,逐个元素比较查找目标值。二分查找:要求数据有序,通过不断比较中间元素与目标值,将查找范围缩小一半,效率…...

Linux性能分析工具Trace使用

Linux Trace是⼀种⽤于抓取和分析系统运⾏时信息的⼯具。允许开发⼈员跟踪和分析系统的各种活动,以便深⼊了解系统的性能、⾏为和故障。下⾯是关于Linux Trace数据抓取的说明: 1. 数据抓取范围:Linux Trace可以抓取各种级别的数据,包括系统级别、进程级别和内核级别的数据。…...

2024华为OD机试真题-简单的自动曝光(C++)-E卷B卷-100分

2024华为OD机试最新E卷题库-(C卷+D卷+E卷)-(JAVA、Python、C++) 目录 题目描述 输入 输出 备注 示例1 示例2 解题思路 考点 代码 c++ 题目描述 一个图像有n个像素点,存储在一个长度为n的数组img里,每个像素点的取值范围[0,255]的正整数。 请你给图像每个像素点值…...

【python】向Jira测试计划下,附件中增加html测试报告

【python】连接Jira获取token以及jira对象 # 往 jira 测试计划下面,上传测试结果html def put_jira_file(plain_id):# 配置连接jiraconn ConnJira()jira conn.jira_login()[2]path jira.issue(O45- plain_id)attachments_dir os.path.abspath(..) \\test_API…...

STM32自学记录(九)

STM32自学记录 文章目录 STM32自学记录前言一、DMA杂记二、实验1.学习视频2.复现代码 总结 前言 DMA 一、DMA杂记 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预&…...

【C++】C++-教师信息管理系统(含源码+数据文件)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 【C】C教师信息管理系统(含源码&#x…...

Java Swing-5.jar 使用 jpackage 打包成 windows 可安装应用(exe,msi,免安装版exe)

环境 jdk17 (jdk14 以后自带将jar 打安装包工具 jpackage,版本从1.8调整到17) Maven:3.2.5 效果 对比 exe4j :免费版在启动的时候总是先弹出一个弹框,告诉用户你在用他们的免费版Launch4j:无法把jre环境打到exe文件中,用户需要单独…...

ADC入门准备(十):信号与系统知识回顾

4.7系统函数零极点分布决定时域特性 4.7.1 H(s)极点分布与h(t)的对应图解 4.7.2 H(s)、E(s)极点分布与自由响应、强迫响应特征的对应 4.8 H(s)零极点分布决定频域特性 4.8.1 s平面几何分析法 4.8.2 高通滤波器的频率特性 4.8.3 低通滤波器的频率特性 4.9 二阶谐振系…...

wx060基于springboot+vue+uniapp的宿舍报修系统小程序

开发语言:Java框架:springbootuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包&#…...

Spring Boot 配置 Mybatis 读写分离

JPA 的读写分离配置不能应用在 Mybatis 上, 所以 Mybatis 要单独处理 为了不影响原有代码, 使用了增加拦截器的方式, 在拦截器里根据 SQL 的 CRUD 来路由到不同的数据源 需要单独增加Mybatis的配置 Configuration public class MyBatisConfig {Beanpublic SqlSessionFactory…...

CCF-GESP 等级考试 2024年9月认证C++二级真题解析

2024年9月真题 一、单选题(每题2分,共30分) 正确答案:A 考察知识点:计算机存储 解析:磁心存储元件是早期计算机中用于存储数据的部件,它和现代计算机中的内存功能类似,都是用于临时…...

第二天:工具的使用

每天上午9点左右更新一到两篇文章到专栏《Python爬虫训练营》中,对于爬虫有兴趣的伙伴可以订阅专栏一起学习,完全免费。 键盘为桨,代码作帆。这趟为期30天左右的Python爬虫特训即将启航,每日解锁新海域:从Requests库的…...

HarmonyOS:使用List实现分组列表(包含粘性标题)

一、支持分组列表 在列表中支持数据的分组展示,可以使列表显示结构清晰,查找方便,从而提高使用效率。分组列表在实际应用中十分常见,如下图所示联系人列表。 联系人分组列表 在List组件中使用ListItemGroup对项目进行分组&#…...

Django5的新特征

Django是一个用Python编写的高级Web框架,它的目标是让开发人员能够快速高效地构建复杂的Web应用程序。自从2008年首次发布以来,Django已经成为开源Web框架中的佼佼者,被广泛应用于各种规模的项目中。Django 提供了一套强大且全面的工具&#…...

web自动化笔记(二)

文章目录 一、参数化测试1.pytest命令2.实现参数化测试3.填写地址测试4.生成Allure测试报告5.关键字驱动 二、案例1.实现后台登录1.1登录1.2.处理验证码1.3.封装识别验证码函数 2.通过cookie保持登录2.1给页面添加cookie2.2获取页面的cookie2.3自动化获取cookie 三、excel进行数…...

青少年编程与数学 02-009 Django 5 Web 编程 12课题、表单处理

青少年编程与数学 02-009 Django 5 Web 编程 12课题、表单处理 一、表单1. 表单类的定义示例:普通表单示例:模型表单 2. 字段类型3. 验证4. 渲染5. 表单处理示例:视图中的表单处理6. 自定义表单 二、验证1. 字段级验证示例2. 表单级验证示例3…...

JVM类加载和垃圾回收(详细)

文章目录 JVM介绍JDK/JRE/JVM的关系 内存结构堆程序计数器虚拟机栈本地方法栈本地内存 类文件字节码文件结构 类加载类的生命周期加载类加载器双亲委派模型 链接初始化类卸载 垃圾回收堆空间的基本结构内存分配和回收原则死亡对象判断方法垃圾收集算法垃圾收集器 JVM 介绍 JD…...

秘密信息嵌入到RGB通道的方式:分段嵌or完整嵌入各通道

目录 1. 将秘密信息分为三部分的理由 (1)均匀分布负载 (2)提高鲁棒性 (3)容量分配 2. 不将秘密信息分为三部分的情况 (1)嵌入容量 (2)视觉质量 &#…...

基于Flask的影视剧热度数据可视化分析系统的设计与实现

【FLask】基于Flask的影视剧热度数据可视化分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 随着互联网技术的飞速发展,影视剧行业的数据量呈爆炸性增长&#x…...

Docker Desktop如何恢复出厂设置

在测试dify、ragfow等几个模型过程中,各种拉镜像建容器,导致错误提示“AssertionError(Can t access Redis. Please check the Redis status.)”,两个模型都无法使用,如何清空重建?请参照下面操作: 1、Win…...

Go语言协程Goroutine高级用法(一)

什么协程 在Go语言中,协程就是一种轻量的线程,是并发编程的单元,由Go来管理,所以在GO层面的协程会更加的轻量、高效、开销更小,并且更容易实现并发编程。 轻量级线程 Go语言中协程(线程)与传…...

Android Studio:键值对存储sharedPreferences

一、了解 SharedPreferences SharedPreferences是Android的一个轻量级存储工具,它采用的存储结构是Key-Value的键值对方式,类似于Java的Properties,二者都是把Key-Value的键值对保存在配置文件中。不同的是,Properties的文件内容形…...

网络安全-攻击路径

以下是互联网场景下常见的攻击路径分类及详细说明,以分层结构呈现: 一、网络层攻击路径 DDoS攻击 原理:通过僵尸网络发起海量请求淹没目标服务器示例:SYN Flood攻击、HTTP洪泛攻击影响:服务不可用,带宽资源…...

记录阿里云CDN配置

网站接入CDN全流程,共4步!-阿里云开发者社区 1、开通阿里云CDN服务 2、添加加速域名 3、验证域名归属权 4、域名添加CDN生成的CNAME解析 按照官网描述增加。细节点: 1. 域名和泛域名区别 2.开启https,要用nginx的证书,和项…...

国自然专项项目申请:AI赋能的急性心肌梗死预警研究|基金申请·25-02-14

小罗碎碎念 急性心肌梗死严重威胁生命健康,因其起病隐匿、发病机制复杂,早期预警困难。现在,转机来了!国自然“AI赋能的急性心肌梗死预警研究”专项项目2025年度指南重磅发布。 该项目致力于攻克难题,通过多学科交叉…...

【鸿蒙开发】第二十八章 应用状态的讲解、状态持久化、网络管理、应用数据持久化、文件上传下载

目录 1 应用状态 1.1 LocalStorage:页面级UI状态存储 1.1.1 两个页面共享一个对象 1.1.2 页面间共享 1.1.3 应用逻辑中使用 1.2 AppStorage:应用全局的UI状态存储 1.2.1 概述 1.2.2 基本用法 1.2.3 经常使用的方法 1.3 PersistentStorage&#x…...

学习threejs,使用HemisphereLight半球光

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.HemisphereLight 二、…...