开启辅助访问 切换到窄版

打印 上一主题 下一主题

UCOSIII中断处理与时间管理

[复制链接]
楼主
跳转到指定楼层
| 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本文给大家讲解一下UCOSIII的中断处理与时间管理,想必大家如果学过51或者stm32单片机,它们都有中断控制的部分,但在使用UCOSIII操作系统时候我们对中断服务程序处理要做一定修改,这点与不使用实时系统有所区别,对于某些任务做延时时会使用到UCOSIII特定的延时函数。
本文分为两部分:中断管理,时间管理


中断管理
UCOSIII中断处理过程:在stm32中支持中断,众所周知,中断是一个硬件机制,其作用是用来向CPU通知一个异步事件发生了,与此同时,CPU就会将当前CPU寄存器值入栈,然后转而执行中断服务函数(这个步骤和51差不多),在CPU执行中断服务函数的时候有可能有更高优先级的任务就绪,那么当退出中断服务函数时,CPU就直接执行这个高优先级的任务。(任务切换)
UCOSIII支持中断嵌套,既高优先级的中断可以打断低优先级的中断,在前面几篇文章中讲述过,UCOSIII使用OSIntNestingCtr来记录中断嵌套次数,最大支持250级中断嵌套。也就是说,每进入一次中断服务函数时OSIntNestingCtr加1,当然,退出中断服务时此参数减1.
用户在编写中断服务函数时候必须要使用临界段代码保护函数OSIntEnter()和OSIntExit(),后者是中断级任务调度器,OSIntEnter()函数如下:

上面的OSIntEnter()函数其实就是将OSIntNestingCtr进行加一操作,用来记录中断嵌套次数。
下面,是我们一般编写中断服务函数的基本代码格式:
void XXX_Handle(void) //XXX为不同中断源的中断函数名
{
OSIntEnter();  //进入临界段(进入中断),并记录中断嵌套次数


用户编写的中断服务程序;


OSIntExit(); //退出临界段 (触发任务切换)

}


直接发布和延迟发布
UCOSIII对从中断发布消息或者信号的处理有两种模式:直接发布和延迟发布两种。需要通过宏OS_CFG_ISR_POST_DEFERRED_EN来选择使用直接发布还是延迟发布。这个宏在os_cfg.h文件中定义,当定义为0时,使用直接发布模式,1时为延迟发布模式,当然,在两种情况下,应用程序不需要做修改。
直接发布

外设产生中断请求,中断服务程序开始运行,该中断服务程序中可能包含发送信号量,消息,事件标志组等事件,则等待这个事件的任务的优先级就得比当前被中断的任务高或低。如果中断对应的事件使得某个比被中断任务优先级低的任务进入就绪态,则中断退出后仍然恢复运行被中断的任务。如果中断对应的事件使得某个比被中断任务优先级高的任务进入就绪态,则UCOSIII将进行任务切换,中断服务程序推出后执行更高优先级任务。

使用直接发布模式的话,UCOSIII会对临界段代码采取关闭中断的操作来保护,这样会延长中断的响应时间。



延迟发布

当设置OS_CFG_ISR_POST_DEFERRED_EN为1时,UCOSIII不是通过关中断,而是通过给任务调度器上锁的办法保护临界段,所以在延迟发布模式下不存在关中断的情况


外设产生中断请求,中断服务程序开始运行,中断服务程序通过调用系统的发布服务函数向任务发布信息与信号,在延迟模式下,这个过程不是直接进行发布,而是将这个发布函数调用和相应参数写入专用队列(中断队列),然后使中断队列处理任务进入就绪态。

中断服务函数处理结束时,UCOSIII切换执行中断队列处理任务,该任务从中断队列中提取出发布函数调用信息,此时需要关闭中断来防止中断服务函数同时对中断队列进行访问,之后,重新开中断,锁定任务调度器。

中断队列处理任务将中断队列处理完,将自身挂起,重新启动任务调度来运行处于最高优先级的就绪任务。



在使用延迟发布模式额外增加的操作是为了避免使用关中断,这些额外增加的操作仅包括将发布调用及其参数复制到中断队列中,从中断队列提取发布调用和相关参数

比较:直接发布模式下,UCOSIII通过关中断来保护临界断代码,延迟发布模式下,UCOSIII通过锁定任务调度来保护临界段。在延迟发布下,UCOSIII在访问中断队列时,仍然需要关闭中断,但这个时间很短。



OSTimeTick()函数

就像人的心脏一样,UCOSIII 需要一个系统时钟节拍,作为系统心跳,这个时钟我们一般 都使用 MCU 的硬件定时器。Cortex-M 内核提供了一个定时器用于产生系统时钟节拍,这个定 时器就是 Systick。UCOSIII 通过时钟节拍来对任务进行整个节拍的延迟,并为等待事件的任务 提供超时判断。时钟节拍中断必须调用 OSTimeTick()函数,我们使用 Systick 来为系统提供时 钟,因此在 Systick 的中断服务程序中就必须调用 OSTimeTick(),函数代码如下:


时钟节拍中断服务程序中首先会调用钩子函数OSTimeTickHook(),这个函数用户可以自行编写。如果使用了延迟发布模式,则UCOSIII读取当前时间戳信息,并在中断队列中放入发布函数调用请求和相关参数。



时间管理

OSTimeDly()函数

当我们需要对一个任务进行延时操作时候可以使用这个函数,原型:


dly:指定延迟的时间长度,单位为时间节拍数。

opt:指定延迟使用选项:OS_OPT_TIME_DLY----相对模式

OS_OPT_TIME_TIMEOUT ---相对模式

OS_OPT_TIME_MATCH----绝对模式

OS_OPT_TIME_PERIODIC---周期模式

p_err:指向调用该函数返回的错误码。

相对模式在系统负荷较重时有可能会少一个节拍,甚至偶尔差好多,因此推荐使用周期模式来实现长时间运行的周期延迟。。。。



OSTimeDlyHMSM()函数

这个函数更加直观来进行延迟。



前面这四个参数用来设置需要延时的时间,使用的是:小时、分钟、秒和毫 秒这种格式,这个就比较直观了,这个延时最小单位和我们设置的时钟节拍频率 有关,比如我们设置时钟节拍频率 OS_CFG_TICK_RATE_HZ 为 200 的话,那么 最小延时单位就是 5ms。
opt选项相比 OSTimeDly()函数多了两个选项 OS_OPT_TIME_HMSM_STRICT OS_OPT_TIME_HMSM_NON_STRICT,其他四个选项都一样的。
使用 OS_OPT_TIME_HMSM_NON_STRICT 选项的话将会检查延时参数, hours 的范围应该是 0~99,minutes 的范围应该是 0~59,seconds 的范围为 0~59, milli 的范围为 0~999。
使用 OS_OPT_TIME_HMSM_NON_STRICT 选项的话,hours 的范围为 0~999, minutes 的范围为 0~9999,seconds 的范围为 0~65535,mili 的范围为 0~4294967259。
p_err:调用此函数后返回的错误码


后面几天要去考科目三了,加油吧哈哈哈哈,祝我好运







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表