购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.2 时间嘀嗒与延时函数

了解时间嘀嗒是理解调度的基础。实时操作系统延时函数暂停当前线程的执行,可执行其他线程,它不同于无操作系统下的机器周期空跑延时。

4.2.1 时间嘀嗒

时间嘀嗒是实时操作系统中时间的最小度量单位,是线程调度的基本时间单元。它主要用于系统计时、线程调度等。也就是说,要进行线程切换,至少需要等待一个时间嘀嗒。时间嘀嗒由硬件定时器产生,一般以毫秒(ms)为单位。在Mbed OS中,由于ARM Cortex-M内核中含有SysTick定时器,因此为了操作系统在芯片之间移植方便,时间嘀嗒由SysTick定时器产生。在本书中,SysTick定时器驻留于BIOS的Mbed OS内核中,时间嘀嗒设置为1ms。在第8章和第9章中,均有对此进行说明。

4.2.2 延时函数

1.实时操作系统下延时函数的基本内涵

在有操作系统的情况下,线程一般不采用原地空跑(空循环)的方式进行延时(该方式下线程仍然占用CPU的使用权),而往往会使用到延时函数(该方式线程会让出CPU使用权),通过使用延时列表管理延时线程,从而实现对线程的延时。在实时操作系统下使用延时函数,内核把暂时不需执行的线程,放入延时列表中,让出CPU的使用权,并对线程进行调度。

在Mbed OS中,提供了一个延时函数thread_delay。为了直观与通用,在Os_United_API.h头文件中将该函数宏定义为delay_ms。应用程序编程时就使用delay_ms,提高了应用程序的可移植性。delay_ms(30)代表延时30个时间嘀嗒。这个函数的基本原理是,执行该函数时,将当前线程按其延时参数指示的时间插入延时列表的相应位置,该列表中的线程按照延时时长从小到大排序,每一个线程控制块都记录了自身需要的等待唤醒时间(该时间=线程本身的延时时间-所有前驱节点的等待时间)。在延时期间,该线程已经放弃CPU的使用权,内核调度正常进行,可以执行其他就绪线程。当延时时间到达时,线程进入就绪列表,等待Mbed OS调度运行。

这里简要理解一下delay_ms函数的基本流程,第9章将对其进行详细剖析。进入delay_ms函数内部,其主要执行流程如下:①获取对内核数据区的访问;②获取当前线程描述符结构体指针;③根据延时的时间,将当前线程插入延时列表的相应位置;④放弃CPU使用权,由实时操作系统内核进行线程调度。

2.使用实时操作系统下延时函数的注意要点

在实时操作系统下使用delay_ms函数时,需要注意以下两点。

第一,delay_ms只能用在对时间精度要求不高或者时间间隔较长的场合。delay_ms函数的延时时长参数millisec以时间嘀嗒为单位,在Mbed OS中1个时间嘀嗒等于1ms,这样对延时时长参数就可以理解为是以ms为单位,此时实际延时时间与希望延时时间相等。但如果1个时间嘀嗒大于1ms时,而对希望延时的时间精度有较高要求时(如延时时间不是时间嘀嗒的整数倍),由于内核是在每个时间嘀嗒到来时(即产生SysTick中断)才会检查延时列表,因此此时的实际延时时间与希望延时时间可能会有误差,最坏的情况下的误差接近1个时间嘀嗒。所以,delay_ms只能用在对时间精度要求不高的场合,或者时间间隔较长的场合。

第二,延时小于1个时间嘀嗒,不使用delay_ms函数。若延时的时间小于1个时间嘀嗒,则不建议使用delay_ms函数,而是根据具体的延时时间,采用变量循环空跑、插入汇编指令(NOP指令)或探索其他更合理的方式来解决。 b2HHNOBmibPt6x3SnkZrkYWcuOiePLinAh7Cw9S326L7IXPj/qkFvp/ynPtvQvH6

点击中间区域
呼出菜单
上一章
目录
下一章
×