空闲线程Idle Demon
CMSIS-RTOS提供的最后一个定时器服务函数并不是一个真正的定时器,但是这里是最合适讨论它的地方。如果在我们的RTOS程序里没有任何线程正在运行,或者准备运行(举个例子,所有的线程都处于等待延时函数中),那么RTOS就会利用空闲的运行时间调用一个“Idle Demon”的线程,这个函数同样位于RTX_Conf_CM.c文件里面,空闲线程拥有一个低优先级,只有在没有其他任何线程准备运行的情况下才会运行。
void os_idle_demon(void)
{
for(;;){
/*此处包含一些用户的的可选代码,在没有线程运行时执行*/
}
}
你可以在这个线程里加入任何代码,但是同样要遵守常规线程的基本准则,一个最简单的应用就是在此线程中添加控制器MCU的低功耗模式。
void os_idle_demon(void)
{
__wfe();
}
下一步什么情况取决于MCU的功耗模式选择,至少CPU会暂停,直到sysTick产生中断并继续执行调度器。如果有线程准备运行,CPU就会去执行这个线程,否则,就会重新进入空闲线程,系统也会重新进入睡眠状态。
练习:空闲线程
打开Pack Installer,并选择“Ex 7 Idle”,然后拷贝到你的自定义路径。
这个工程复制了虚拟定时器的工程。
打开RTX_Conf_CM.c文件,并点击文本编辑标签。
定位到os_idle_demon线程,把__wfe()注释掉。
void os_idle_demon(void){
int32_t i;
for(;;){
//__wfe();
}
}
编译工程,并启动debugger仿真环境。
全速运行代码,打开线程时间观察器。
从图中看到idle线程几乎是连续运行的,这是因为本工程中,CPU的大部分时间都在执行idle线程。在实际的工程应用中,idle线程的运行时间表明了CPU的空闲周期。
打开View->Analysis windows->Performance Analyzer
这个窗口显示了每个函数的累积运行时间,在本工程中,os_idle_demon几乎用到了所有CPU运行时间。
退出debugger仿真环境。
去掉__wfe()的注释,如下:
void os_idle_demon(void){
f(;;){
__wfe();
}
}
Rebuild工程,并启动debugger仿真环境。
现在当我们进入idle线程,__wfe()(等待中断)指令就会暂停CPU,直到一个外设或SysTick产生中断。
另外,在你调试真正的MCU硬件时同样可以使用代码功能和分析工具,但是前提有两个条件:一是你使用的MCU必须适配ETM(嵌入式跟踪宏);二是你需要使用keil ULINKpro调试适配器,这个适配器可以通过ETM支持跟踪指令。