第四章 μC/OS-Ⅱ的中断和时钟
4.1 μC/OS-Ⅱ的中断
中断:应内部或外部异步事件的请求中止当前任务,而去处理异步事件
中断服务程序:应中断请求而运行的程序
4.1.1 μC/OS-Ⅱ的中断过程
注:对于可剥夺型的μC/OS-Ⅱ内核来说,中断服务程序运行结束后,系统将会根据情况进行一次任务调度去运行优先级最高的就绪任务,而不一定接续运行被中断的任务
μC/OS-Ⅱ系统允许中断嵌套,即高优先级别的中断源的中断请求可以中断低优先级别的中断服务程序的运行。
两个重要函数:OSIntEnter()和OSIntExit()
OSIntEnter():把全局变量OSIntNexting加1,记录中断嵌套的层数。常常发生在中断服务程序保护了被中断任务的断点数据之后,运行用户中断服务代码之前,称为进入中断服务函数。
OSIntExit():中断嵌套层数计数器为0、调度器未被锁定且从任务就绪表中查找到的最高级就绪任务又不是被中断的任务时进行任务切换,否则返回被中断的服务子程序。
OSIntExit()的流程图:
中断服务子程序流程图:
4.1.2 中断级任务的切换函数
完成任务切换(中断级任务调度器):OSIntCtxSw()函数à中断级任务切换函数
4.1.3 应用程序中的临界段
所有CPU都有开中断和关中断指令,在μC/OS-Ⅱ中不希望被中断的代码段为临界段。从代码上来看,处在关中断和开中断之间的代码段为临界段。
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()这两个宏封装了系统硬件相关的关中断和开中断指令。
提示:在临界段中,不要调用μC/OS-Ⅱ提供的功能函数,以免系统崩溃。
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()的实现方法:
-----------------------------------------------------------------------------------------------------------------
#define OS_ENTER_CRITICAL() \
asm(“DI”)//关中断
#define OS_EXIT_CRITICAL() \
asm(“EI”)//开中断
OS_CRITICAL_METHOD = 1
-----------------------------------------------------------------------------------------------------------------
#define OS_ENTER_CRITICAL() \
asm(“PUSH PSW”) \ //通过保存程序状态字来保存中断允许标志
asm(“DI”)//关中断
#define OS_EXIT_CRITICAL() \
asm(“POP PSW”)//恢复中断允许标志
OS_CRITICAL_METHOD = 2
-----------------------------------------------------------------------------------------------------------------
#define OS_ENTER_CRITICAL() \
cpu_sr = get_processor_psw(); \//获取程序状态字并保存在全局变量sr中
disable_interrupts();//关中断
#define OS_EXIT_CRITICAL() \
set_processor_psw();//用sr恢复中断允许标志
OS_CRITICAL_METHOD = 3,用户使用的C编译器具有扩展功能
------------------------------------------------------------------------------------------------------------------
4.2 μC/OS-Ⅱ的时钟à周期性信号
用硬件定时器产生一个周期为毫秒级的周期性中断来实现系统时钟。产生的中断的中断服务程序为OSTickISR()(汇编语言),通过调用时钟节拍服务函数OSTimeTick()来完成系统在每个时钟节拍需要的工作。
最小的时钟单位是两次中断之间相间隔的时间,称之为时钟节拍。
调用时钟节拍服务函数OSTimeTick()做了两件事:给计数器OSTime加1;遍历任务控制块链表中的所有任务控制块,把各个控制块中用来存放任务延时时限的OSTCBDly变量减1,并使该项为0,不使被挂起的任务进入就绪状态。(即在每个时钟节拍了解每个任务的延时状态,使已经到了延时时限的非挂起任务进入就绪状态)
4.3 时间管理
4.3.1 任务的延时
μC/OS-Ⅱ是一个抢占式内核。
规定:除了空闲任务之外的所有任务必须在任务中合适的位置调用系统提供的函数OSTimeDly(),使当前任务的运行延时一段时间并进行一次任务调用,以让出CPU使用权。
OSTimeDly()函数参数是以时钟节拍数为单位的延时时间。
延时函数OSTimeDlyHMSM(INT8U hours, INT8Uminutes, INT8U seconds, INY16U milli);
调用了函数OSTimeDly()和OSTimeDlyHMSM()的任务,当规定的延时时间期满,或有其他任务通过调用函数OSTimeDlyResume()取消了延时时,它立即会进入就绪状态。
4.3.2 取消任务的延时
OSTimeDlyResume()函数取消延时而进入就绪状态
OSTimeDlyResume(INT8Uprio);
4.3.3 获取和设置系统时间
OSTime记录系统发生的时钟节拍数。
在应用程序调用OSStart()时被初始化为0,每发生1各时钟节拍OSTime就加1.
INT32U OSTimeGet(void);获取OSTime的值
void OSTimeSet(INT32U ticks);设置OSTime的值