以下转载自安富莱电子: http://forum.armfly.com/forum.php

本章节为大家讲解 FreeRTOS 本身支持的低功耗模式 tickless 实现方法,tickless 低功耗机制是当前
小型 RTOS 所采用的通用低功耗方法,比如 embOS,RTX 和 uCOS-III(类似方法)都有这种机制。

tickless 低功耗模式介绍
tickless 低功耗机制是当前小型 RTOS 所采用的通用低功耗方法,比如 embOS,RTX 和 uCOS-III (类
似方法)都有这种机制。
FreeRTOS 的低功耗也是采用的这种方式,那么 tickless 又是怎样一种模式呢?仅从字母上看 tick 是
滴答时钟的意思,less 是 tick 的后缀,表示较少的,这里的含义可以表示为无滴答时钟。 整体看这个字母
就是表示滴答时钟节拍停止运行的情况。
反映在 FreeRTOS 上,tickless 又是怎样一种情况呢?我们都知道,当用户任务都被挂起或者阻塞时,
最低优先级的空闲任务会得到执行。 那么 STM32 支持的睡眠模式,停机模式就可以放在空闲任务里面实
现。 为了实现低功耗最优设计,我们还不能直接把睡眠或者停机模式直接放在空闲任务就可以了。 进入空
闲任务后,首先要计算可以执行低功耗的最大时间,也就是求出下一个要执行的高优先级任务还剩多少时
间。 然后就是把低功耗的唤醒时间设置为这个求出的时间,到时间后系统会从低功耗模式被唤醒,继续执
行多任务。这个就是所谓的 tickless 模式。 从上面的讲解中可以看出,实现 tickless 模式最麻烦是低功耗
可以执行的时间如何获取。 关于这个问题,FreeRTOS 已经为我们做好了。

FreeRTOS 的低功耗模式介绍
对于 Cortex-M3 和 M4 内核来说,FreeRTOS 已经提供了 tickless 低功耗代码的实现,通过调用指
令 WFI 实现睡眠模式,具体代码的实现就在 port.c 文件中,用户只需在 FreeRTOSConfig.h 文件中配置

宏定义 configUSE_TICKLESS_IDLE 为 1 即可。 如果配置此参数为 2,那么用户可以自定义 tickless 低功
耗模式的实现。 当用户将宏定义 configUSE_TICKLESS_IDLE 配置为 1 且系统运行满足以下两个条件时,
系统内核会自动的调用低功耗宏定义函数 portSUPPRESS_TICKS_AND_SLEEP():
-------------------------------
 当前空闲任务正在运行,所有其它的任务处在挂起状态或者阻塞状态。
 根据用户配置 configEXPECTED_IDLE_TIME_BEFORE_SLEEP 的大小,只有当系统可运行于低功耗模
式的时钟节拍数大于等于这个参数时,系统才可以进入到低功耗模式。 此参数默认已经在 FreeRTOS.h
文件进行定义了,下面是具体的定义内容,当然,用户也可以在 FreeRTOSConfig.h 文件中重新定义:

默认定义的大小是 2 个系统时钟节拍,且用户自定义的话,不可以小于 2 个系统时钟节拍。
---------------------------------
函数 portSUPPRESS_TICKS_AND_SLEEP 是 FreeRTOS 实现 tickles 模式的关键,此函数被空闲任务
调用,其定义是在 portmacro.h 文件中:

FreeRTOS 在线电子手册低功耗的说明 http://www.freertos.org/low-power-tickless-rtos.html
FreeRTOS 的低功耗模式配置
关于 FreeRTOS 低功耗方面的配置主要涉及到以下几个问题。

  1. 滴答定时器频率与系统主频的关系
    对于 Cortex-M3 和 M4 内核的微控制器来说,实时操作系统一般都是采用滴答定时器做系统时钟,
    FreeRTOS 也不例外。 SysTick 滴答定时器是一个 24bit 的递减计数器,有两种时钟源可选择,一个是系
    统主频,另一个是系统主频的八分频,默认的 port.c 移植文件中是用的系统主频。 这里我们就根据这两种
    时钟源来说一说配置上的不同。
    SysTick 滴答定时器时钟源选择系统主频

    如果滴答定时器选择系统主频的话,那么需要配置 configSYSTICK_CLOCK_HZ 等于
    configCPU_CLOCK_HZ,这种关系已经在 port.c 文件中进行默认配置了:

    其中系统主频 configCPU_CLOCK_HZ 是在 FreeRTOSConfig.h 文件中进行定义的。
    SysTick 滴答定时器时钟源选择系统主频的八分频
    这种情况的话,需要用户在 FreeRTOSConfig.h 文件中专门配置 configSYSTICK_CLOCK_HZ 为实际
    的频率,即系统主频的八分频大小。

  2. 系统时钟节拍不使用滴答定时器
    这种情况我们这里不做讨论,用户看 FreeRTOS 官网此处的说明即可:
    http://www.freertos.org/low-power-ARM-cortex-rtos.html
  3. 如何使用微控制器其它低功耗模式
    前面我们说了,对 Cortex-M3 和 M4 内核来说,FreeRTOS 自带的低功耗模式是通过指令 WFI 让系
    统进入睡眠模式,如果想让系统进入停机模式,又该怎么修改呢?FreeRTOS 为我们提供了两个函数:
    configPRE_SLEEP_PROCESSING( xExpectedIdleTime )
    configPOST_SLEEP_PROCESSING( xExpectedIdleTime )
    这两个函数的定义是在 FreeRTOS.h 文件中定义的,什么都没有执行:

    如果需要实际执行代码需要用户在 FreeRTOSConfig.h 文件中重新进行宏定义,将其映射到一个实际的函
    数中。 另外,这两个函数是在 port.C 文件中被函数 vPortSuppressTicksAndSleep 调用,具体位置如下:

    这两个函数位于指令 wfi 的前面和后面,用户想实现其它低功耗方式的关键就在这两个函数里面:
     configPRE_SLEEP_PROCESSING( xExpectedIdleTime )
    执行低功耗模式前,用户可以在这个函数里面关闭外设时钟来进一步降低系统功耗。 设置其它低功耗
    方式也是在这个函数里面,用户只需设置参数 xExpectedIdleTime=0 即可屏蔽掉默认的 wfi 指令执
    行方式,因为退出这个函数后会通过 if 语句检测此参数是否大于 0,即上面的代码所示。 因此,如果
    用 户 想 实 现 其 它 低 功 耗 模 式 还 是 比 较 方 便 的 , 配 置 好 其 它 低 功 耗 模 式 后 , 设 置 参 数
    xExpectedIdleTime = 0 即可,但切不可将此参数随意设置为 0 以外的其它数值。
     configPOST_SLEEP_PROCESSING ( xExpectedIdleTime )
    退出低功耗模式后,此函数会得到调用,之前在 configPRE_SLEEP_PROCESSING 里面关闭的外设时
    钟,可以在此函数里面重新打开,让系统恢复到正常运行状态。

  4. FreeRTOS 实现 tickless 模式的框架
    对 Cortex-M3 和 M4 内核的微控制器来说,FreeRTOS 已经提供了 tickless 低功耗模式的代码,对
    于没有支持的微控制器,用户可以在 FreeRTOSConfig.h 文件中配置 portSUPPRESS_TICKS_AND_SLEEP
    宏定义,来映射实际执行函数。
    如果用户不想使用 FreeRTOS 提供的的 tickless 也可以自定义,方法也是在 FreeRTOSConfig.h 文件
    中配置 portSUPPRESS_TICKS_AND_SLEEP 宏定义,来映射实际执行函数。
    下面是 FreeRTOS 实现低功耗 tickless 模式的代码框架,方便用户对 tickles 模式有一个认识,同时
    也方便 FreeRTOS 没有支持的微控制器,用户可以参考实现。 当然,不局限于这种方法,用户有更好的方
    法,也可以的。 其中函数 vTaskStepTick 和 eTaskConfirmSleepModeStatus 是 FreeRTOS 提供的,其
    余的函数是需要用户实现的。

  

         

    

    

显然用户自己配置要麻烦得多,好在FreeRTOS为M3,M4内核的做好了低功耗之睡眠模式,使得我们使用STM32 F1,F4系列的时候可以很简单,只需要在配置文件config.h中加上一个宏定义:#define configUSE_TICKLESS_IDLE     1

那我们要实现停机模式呢?那就只有自己动手了。

在介绍实现停机模式之前,有必要提醒一下:在低功耗的时候,要根据情况配置

回到正题,如何添加用户函数实现停机模式:

*    说    明 : 本实验主要学习FreeRTOS的低功耗(tickless之停机模式)
* 实验目的:
* . 学习FreeRTOS的低功耗(tickless之停机模式)
* . FreeRTOS自带的tickless 模式使用比较简单,只需用户使能宏配置:
* #define configUSE_TICKLESS_IDLE 1
* . 为了打印系统信息,前面的所有试验中始化一个定时器中断,精度高于滴答定时器中断,
* 每50us进一次,本例子关闭了任务执行情况打印功能,因为高频率的定时器中断影响低
* 功耗tickless模式效率。
* . 本实验在FreeRTOS自带的tickless睡眠模式的基础上实现停机模式,实现方法是重新
* 在文件FreeRTOSConfig.h定义如下函数两个函数
* #define configPRE_SLEEP_PROCESSING(x) OS_PreSleepProcessing(x)
* #define configPOST_SLEEP_PROCESSING(x) OS_PostSleepProcessing(x)
* 在文件port.c里面函数vPortSuppressTicksAndSleep调用了上面这两个函数:
* ---------------------------------------------------------------------
* configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
* if( xModifiableIdleTime > )
* {
* __dsb( portSY_FULL_READ_WRITE );
* __wfi();
* __isb( portSY_FULL_READ_WRITE );
* }
* configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
* -----------------------------------------------------------------------
* 函数OS_PreSleepProcessing和OS_PostSleepProcessing是需要用户提供的,用户可以在
* 这两个函数里面实现进入停机模式和从停机模式恢复到正常的运行状态。另外,通过在函数
* OS_PreSleepProcessing里设置其形参变量vParameters为0就可以屏蔽原有的休眠模式。
/*
*********************************************************************************************************
* 函 数 名: OS_PreSleepProcessing
* 功能说明: 下面的函数在文件FreeRTOSConfig.h文件里面进行了宏定义:
* #define configPRE_SLEEP_PROCESSING(x) OS_PreSleepProcessing(x)
* #define configPOST_SLEEP_PROCESSING(x) OS_PostSleepProcessing(x)
* 在文件port.c里面函数vPortSuppressTicksAndSleep调用了上面这两个函数:
* ---------------------------------------------------------------------
* configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
* if( xModifiableIdleTime > 0 )
* {
* __dsb( portSY_FULL_READ_WRITE );
* __wfi();
* __isb( portSY_FULL_READ_WRITE );
* }
* configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
* -----------------------------------------------------------------------
* 通过这两个函数可以实现在调用__WFI或者__WFE指令前后执行进一步的低功耗操作,主要有以下三种:
* 1. 降低系统主频。
* 2. 关闭外设时钟。
* 3. IO引脚要做处理,防止拉电流和灌电流增加功耗。
* 如果此IO口带上拉,请设置为高电平输出或者高阻态输入;
* 如果此IO口带下拉,请设置为低电平输出或者高阻态输入;
* 下面的函数未做关闭外设时钟的处理。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void OS_PreSleepProcessing(uint32_t vParameters)
{
(void)vParameters; /* 用户可以考虑在此处加入关闭外设时钟来进一步降低功耗 */
vParameters = ;
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
} void OS_PostSleepProcessing(uint32_t vParameters)
{
/* 如果前面关闭了外设时钟,需要在这里恢复 */
/*
1、当一个中断或唤醒事件导致退出停止模式时,HSI RC振荡器被选为系统时钟。
2、退出低功耗的停机模式后,需要重新配置使用HSE。
*/
RCC_HSEConfig(RCC_HSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET){} RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); while (RCC_GetSYSCLKSource() != 0x08){}
}

FreeRTOS 低功耗之 tickless 模式的更多相关文章

  1. FreeRTOS 低功耗之睡眠模式

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 低功耗是 MCU 的一项重要的指标,比如某些可穿戴的设备,其携带的电量有限,如果整个电路消耗的电量特别大的话 ...

  2. jlink RTT 打印 BUG , FreeRTOS 在开启 tickless 模式下 无法使用的问题

    一开始我以为是 jlink 的问题,后面发现是 tickless 模式搞鬼 tickless 模式下 ,内核 会 根据任务需求,会停止工作,这个时候 jlink rtt 打印就会失效!!! 不过 NR ...

  3. FreeRTOS 低功耗之停机模式

    以下转载自安富莱电子: http://forum.armfly.com/forum.php STM32F103 如何进入停机模式在 FreeRTOS 系统中,让 STM32 进入停机模式比较容易,调用 ...

  4. FreeRTOS 低功耗之待机模式

    STM32F103 如何进入待机模式在 FreeRTOS 系统中,让 STM32 进入待机模式比较容易,调用固件库函数PWR_EnterSTANDBYMode 即可. STM32F103 如何退出待机 ...

  5. FreeRTOS低功耗模式

    在系统或电源复位以后,微控制器处于运行状态.当CPU不需继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个外部事件时,用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳 ...

  6. STM32中用 stop 模式 配合低功耗模式下的自动唤醒(AWU) 能否实现FreeRTOS tickless 模式

    已经实现  ,2018年11月17日11:56:42,具体 如下: 第一步 : 修改 void vPortSetupTimerInterrupt( void ) 函数 ,修改原来的 systick 定 ...

  7. STM32——项目需求之低功耗的停机模式

    在说低功耗之前,先要明白一个东西,那就是stm32中的事件和中断. 事件是中断的触发源,开放了对应的中断屏蔽位,则事件可以触发相应的中断.在STM32中,中断与事件不是等价的,一个中断肯定对应一个事件 ...

  8. 第21章 RTX 低功耗之睡眠模式

    低功耗是 MCU 的一项非常重要的指标,比如某些可穿戴的设备,其携带的电量有限,如果整个电路消耗的电量特别大的话,就会经常出现电量不足的情况,影响用户体验. 本章节为大家讲解 M3/4的低功耗方式之睡 ...

  9. ESP8266的低功耗方案-睡眠模式

    在某些时候我们设计的产品可能不具备持久供电的环境,那通常会采用锂电池.干电池一类的轻便型的非持久性电源.当遇到这种情况时,产品的续航能力可能就会成用户评估产品的一个重要指标,加大电池容量当然是最为直接 ...

随机推荐

  1. with/as上下文管理器

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #Python学习手册 868 #with/as上下文管理器 #with语句的基本格式: with open( ...

  2. spyder python 相关

    1.python开发集成工具Spyder中,如何设置变量成员提示和代码补全呢? 答: pip install rope,安装好rope 就可以了 2.最常用的是:tap的制动补全 (IPython c ...

  3. JSON 接口如何实现 RSA 非对称加密与签名

    代码地址如下:http://www.demodashi.com/demo/14000.html 一.概述 1. 数字签名的作用:保证数据完整性,机密性和发送方角色的不可抵赖性,加密与签字结合时,两套公 ...

  4. 利用 AFN 上传相册或拍照图片

    概述 自定义上传图片请求,自定义调取相册及拍照,方便多处使用时调用. 详细 代码下载:http://www.demodashi.com/demo/10718.html 由于项目中多处需要上传图片,我们 ...

  5. shell随机读取一行

    使用shell随机读取文件的一行数据 shuf -n1 file_name

  6. docker登录没有配置https的harbor镜像仓库

    已经搭建harbor 仓库 ,域名  172.16.1.99 出现问题: 客户端尝试登录 仓库 [root@localhost docker]# docker login 172.16.1.99:80 ...

  7. Matlab调用返回游标的存储过程的分析和处理

    2.Matlab调用Oracl带游标参数输出的存储过程 笔者也是将工作之中遇到的问题进行了搜集与整理,才完成该文的编写,希望能帮助到有需要的朋友. 2.1.PLSQL中的存储过程 PROCEDURE ...

  8. C++知识整理(进制)

    ++输出二进制.十进制.八进制和十六进制总结 分类: C++ 2013-01-14 02:26 592人阅读 评论(0) 收藏 举报 在C++中,默认状态下,数据按十进制输入输出.如果要求按八进制或十 ...

  9. tomcat使用方法大全

    一.安装tomcat之后 tomcat压缩包解压之后,进入webapps目录,可以看到如下webapp: docs文档:这是一个静态页面集,不用启动tomcat也可以阅读 examples样例 hos ...

  10. automake安装出错

    automake命令出错 configure.ac:64: error: possibly undefined macro: AM_ICONV    If this token and others ...