6-临界代码保护

UCOSIII 临界代码保护

 

在实际使用过程中,可能有些代码是需要连续运行,不能被打断的,这些代码局需要临界保护起来。常见的就是新建任务的时候一般都把代码保护起来,还有有些对时间要求很严格的协议传输的时候也不能被打断,比如说单总线时序、iic时序等,这些代码也是需要连续运行的。

UCOS临界代码保护有两种方式,关中断和关调度器。

至于是使用关调度器还是关中断的方式来保护临界代码,有宏OS_CFG_ISR_POST_DEFERRED_EN来确定,当宏OS_CFG_ISR_POST_DEFERRED_EN == 0时采用关中断的方式,当宏OS_CFG_ISR_POST_DEFERRED_EN > 0时采用关调度器的方式。

方式一;关中断。关闭的这个中断是总中断,把总中断关了,也就没有任何事件能够打断临界代码了,这个很好理解。但是关总中断对系统的影响是非常大的,如果把总中断关闭了,那么UCOS系统也就挂了,因为连滴答中断都屏蔽了,系统的心跳停止了,所有依赖心跳时钟的对象都暂停了,比如系统的延时函数,软件定时器等,这样会导致延时和软件定时器不准确,对系统的伤害是非常大的,所以一般都不推荐使用关中断的方式来保护临界代码。

方式二;关调度器。顾名思义就是把调度器关闭了,在临界代码运行期间,就算本任务的时间片用完了,也不会发生任务调度,还是运行原来的任务,等到执行完临界代码后才会发生任务调度。在执行完临界代码后任务该怎么调度还是怎么调度,所以这种方式对系统的影响只是推迟了任务调度而已。关闭调度器对系统没太大影响,滴答时钟还是正常运行,既然系统的心跳还在,那么与系统心跳相关系统延时函数、软件定时器等也不受影响。所以推荐使用这种方式俩保护临界代码。

 

一个程序只能使用一种方式,不能中途切换方式。比如任务1的临界代码想用关中断的方式保护,而任务2的临界代码用关调度器的方式,这是做不到的。因为OS_CFG_ISR_POST_DEFERRED_EN并不是一个变量,而是一个宏,这个宏决定了编译的是关中断的代码还是关闭调度器的代码,这应该就是根本原因吧。

原子的代码在创建任务的时候用了两个非用户API的函数来保护临界代码,OS_CRITICAL_ENTER()和OS_CRITICAL_EXIT()。虽然这是UCOS作者不建议的(虽然UCOS作者不建议用户使用这两个函数,但是系统的空闲任务临界段代码保护用的却是这两个函数,所以以后自己用这两个函数应该也是没问题的),但是感觉还是挺合理的,因为在创建任务的时候系统还没启动,也就不存在任务调度,但是还会有中断啊,所以这部分代码用关闭中断的方式保护,而其他的临界代码则用关调度器的方式来保护。

我并没有找到直接关闭和开启调度器锁来保护临界代码的栗子,那就自己写一个吧,当然,我也不敢保证这样写代码是正确的。在进入临界代码前调用函数OSSchedLock()来给调度器上锁,等执行完临界代码后调用函数OSSchedUnlock()给调度器解锁,让任务可以正常切换。这个调度器上锁和解锁具有累加效应,比如上锁5次,那么也要解锁5次才能把锁解除。这两个函数原型和入口参数如下;

  1. OSSchedLock()

调度器上锁函数

函数原型

void  OSSchedLock (OS_ERR  *p_err)

使能开关

永远有效

入口参数

OS_ERR  *p_err

返回的错误码

注意事项

调用本函数给调度器上锁后,在解锁前不能调用能让任务进入阻塞状态或者被挂起的函数,比如各种系统延时函数,等待各种内核对象等。因为当前任务被挂起来了,而调度器也上锁了,那么系统就挂掉了。

 

 

 

 

  1. OSSchedUnlock()

调度器解锁函数

函数原型

void  OSSchedLock (OS_ERR  *p_err)

使能开关

永远有效

入口参数

OS_ERR  *p_err

返回的错误码

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值