论坛原始地址(已完结):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514
第23章 ThreadX低功耗之tickless模式
本章节为大家讲解ThreadX本身支持的低功耗模式tickless实现方法,tickless低功耗机制是当前RTOS所采用的通用低功耗方法,。
目录
23.1 tickless低功耗模式介绍
tickless低功耗机制是当前RTOS所采用的通用低功耗方法。
ThreadX的低功耗也是采用的这种方式,那么tickless又是怎样一种模式呢,仅从字母上看tick是滴答时钟的意思,less是tick的后缀,表示较少的,这里的含义可以表示为无滴答时钟。整体看这个字母就是表示滴答时钟节拍停止运行的情况。
反映在ThreadX上,tickless又是怎样一种情况呢?我们都知道,当用户任务都被挂起时,最低优先级的任务会得到执行,但ThreadX是没有空闲任务的,实际上是一种无任务执行的空闲状态。那么STM32支持的睡眠模式,停机模式就可以放在空闲状态里面实现。为了实现低功耗最优设计,我们还不能直接把睡眠或者停机模式直接放在空闲状态就可以了。进入空闲状态后,首先要计算可以执行低功耗的最大时间,也就是求出下一个要执行的高优先级任务还剩多少时间。然后就是把低功耗的唤醒时间设置为这个求出的时间,时间到后系统会从低功耗模式被唤醒,继续执行多任务。这个就是所谓的tickless模式。从上面的讲解中可以看出,实现tickless模式最麻烦是低功耗可以执行的时间如何获取。关于这个问题,ThreadX已经为我们做好了。
23.2 ThreadX实现tickless模式的框架
ThreadX实现低功耗tickless模式的代码框架如下:
/* 通过函数tx_low_power_enter获取系统可以处于低功耗模式的时钟节拍个数 */ #ifdef TX_LOW_POWER PUSH {r0-r3} BL tx_low_power_enter // Enter low power mode POP {r0-r3} #endif /* 调用低功耗指令进入低功耗模式 */ #ifdef TX_ENABLE_WFI DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed #endif /* 退出低功耗 */ #ifdef TX_LOW_POWER PUSH {r0-r3} BL tx_low_power_exit // Exit low power mode POP {r0-r3} #endif
23.3 tickless模式宏定义
tickless模式有如下几个宏定义需要了解:
- TX_LOW_POWER_TIMER_SETUP
用户可以重定向低功耗时钟建立,由函数tx_low_power_enter调用。
- TX_LOW_POWER_TICKLESS
使能tickless模式。
- TX_LOW_POWER_USER_ENTER
用户可以重定向进入低功耗模式,由函数tx_low_power_enter调用。
- TX_LOW_POWER_USER_EXIT
用户可以重定向退出低功耗模式,由函数tx_low_power_exit调用。
- TX_LOW_POWER_USER_TIMER_ADJUST
用户可以重定向退出低功耗后的时钟调整,可以获取处于低功耗模式的时间,由函数tx_low_power_exit调用。
23.4 tickless低功耗模式移植
23.4.1 第1步,添加低功耗文件
低功耗文件是从ThreadX内核版本V6.1.5开始提供的:
23.4.2 第2步,添加头文件路径
仅添加一个路径即可:
23.4.3 第3步,在tx_port.h文件添加宏定义
添加如下几个宏定义:
/* Define the LowPower macros and flags */ /* Define a macro that sets up a low power clock and keep track of time */ /*#define TX_LOW_POWER_TIMER_SETUP */ /* Define the TX_LOW_POWER_TICKLESS to disable the internal ticks */ #define TX_LOW_POWER_TICKLESS /* A user defined macro to make the system enter low power mode */ extern void App_ThreadX_LowPower_Enter(void); #define TX_LOW_POWER_USER_ENTER App_ThreadX_LowPower_Enter() /* A user defined macro to make the system exit low power mode */ extern void App_ThreadX_LowPower_Exit(void); #define TX_LOW_POWER_USER_EXIT App_ThreadX_LowPower_Exit() /* User's low-power macro to obtain the amount of time (in ticks) the system has been in low power mode */ /*#define TX_LOW_POWER_USER_TIMER_ADJUST */
其中函数App_ThreadX_LowPower_Enter和App_ThreadX_LowPower_Exit放在了main.c里面实现:
/* ********************************************************************************************************* * 函 数 名: App_ThreadX_LowPower_Enter * 功能说明: 进入低功耗模式 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void App_ThreadX_LowPower_Enter(void) { HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); } /* ********************************************************************************************************* * 函 数 名: App_ThreadX_LowPower_Exit * 功能说明: 退出低功耗模式 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void App_ThreadX_LowPower_Exit(void) { }
23.4.4 第4步,使能预定义宏TX_LOW_POWER
使能汇编文件的预定义宏TX_LOW_POWER:
23.4.5 第5步,注意事项
注意tx_thread_schedule.s文件中低功耗函数调用前后寄存器的入栈和出栈问题,早期几个版本此处没有做寄存器的入栈和出栈处理,最新的内核版本V6.1.8开始已经修正了这个问题。如果不做处理,移植后运行程序会进入硬件异常。
至此就完成了ThreadX低功耗移植。
23.5 实验例程
配套例子:
V7-3018_ThreadX Low Power
实验目的:
- 学习ThreadX低功耗设计。
实验内容:
1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况
========================================================
CPU利用率 = 0.89%
任务执行时间 = 0.586484645s
空闲执行时间 = 85.504470575s
中断执行时间 = 0.173225395s
系统总执行时间 = 86.264180615s
=======================================================
任务优先级 任务栈大小 当前使用栈 最大栈使用 任务名
Prio StackSize CurStack MaxStack Taskname
2 4092 303 459 App Task Start
5 4092 167 167 App Msp Pro
4 4092 167 167 App Task UserIF
5 4092 167 167 App Task COM
0 1020 191 191 System Timer Thread
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。
App Task Start任务 :启动任务,这里用作BSP驱动包处理。
App Task MspPro任务 :消息处理。
App Task UserIF任务 :按键消息处理。
App Task COM任务 :这里用作LED闪烁。
System Timer Thread任务:系统定时器任务
2、K2按键按下演示内存块的申请和释放,K3按键按下演示内存池的申请和释放。
3、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
(2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
4、默认上电是通过串口打印信息,如果使用RTT打印信息
(1) MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
#define Enable_RTTViewer 1
(2) Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。
串口打印信息方式(AC5,AC6和IAR):
波特率 115200,数据位 8,奇偶校验位无,停止位 1
RTT打印信息方式(AC5,AC6和IAR):
程序执行框图:
23.6 总结
本章节主要为大家讲解了ThreadX低功耗tickless模式的实现,采用的睡眠模式,大家感兴趣可以试试停机模式。