2.临界段代码学习

来源:互联网 发布:网络小说作家 知乎 编辑:程序博客网 时间:2024/06/04 19:31

临界段代码的定义

临界段代码,也称作临界域,是一段不可分割的代码。uC/OS-III中包含了很多临界段代码。如果临界段可能被中断,那么就需要关中断以保护临界段。如果临界段可能被任务级代码打断,那么需要锁调度器保护临界段。uC/OS-III 中的临界段的保护方法决定于ISR 中对消息的处理方式。详见 “ 中断管理” 。如果OS_CFG_ISR_POST_DEFERRED_EN 被设为0(见OS_CFG.H),在进入临界段之前uC/OS-III 会关中断,在离开临界段之后开中断。如果OS_CFG_ISR_POST_DEFERRED_EN 被设为1,在进入大多数临界段之前会关调度器。

uC/OS-III 定义了一个进入临界段的宏和两个出临界段的宏。

OS_CRITICAL_ENTER(),

OS_CRITICAL_EXIT(),

OS_CRITICAL_EXIT_NO_SCHED()

这些是uC/OS-III 的内部宏,不能被用户代码调用。然而,如果你需要进入你自己定义的临界段。请查阅"资源管理"。

一:关中断

1.在上面我们说过的,当OS_CFG_ISR_POST_DEFERRED_EN 被设为0,在进入临界段之前uC/OS-III 会关中断,在离开临界段之后开中断。OS_CRITICAL_ENTER() 调用uC/CPU 的宏CPU_CRITICAL_ENTER() , 然后调用CPU_SR_Save() 。CPU_SR_Save()是用汇编写的用于保存当前CPU 寄存器并关中断。寄存器值以类型为“cpu_sr”的变量存于调用者堆栈。

OS_CRITICAL_EXIT() 和OS_CRITICAL_EXIT_NO_SCHED() 都会调用uC/CPU 的宏CPU_CRITICAL_EXIT() 。CPU_CRITICAL_EXIT()调用CPU_SR_Restore()。CPU_SR_Restore()恢复所保存寄存器值到CPU 寄存器,也就是OS_CRITICAL_ENTER()调用前的状态。如下:

#define  OS_CRITICAL_ENTER()                    CPU_CRITICAL_ENTER()
#define  OS_CRITICAL_ENTER_CPU_EXIT()
#define  OS_CRITICAL_EXIT()                     CPU_CRITICAL_EXIT()
#define  OS_CRITICAL_EXIT_NO_SCHED()            CPU_CRITICAL_EXIT()

2.测量关中断的时间

uC/CPU 提供了测量关中断时间的功能。通过设置CPU_CFG.H 中的CPU_CFG_TIME_MEAS_INT_DIS_EN (CPU_configure_time_measure_intrrupt_distance_enable其实是很好记的)为1 启用该功能。每次关中断前开始测量,开中断后结束测量。每个任务的关中断时间在上文保存的时候被保存于OS_TCB(详见OS_CPU.C 中的OSTaskSwHook()和第八章"上下文切换")

二:锁住调度器

1.当设置OS_CFG_ISR_POST_DEFERRED_EN 为1 时,在进入临界段前uC/OS-III 会锁住调度器,退出临界段后开启调度器。OS_CRITICAL_ENTER()递增OSSchedLockNestingCtr,给调度器加锁。这是一个决定调度器是否被开启的变量。如果它不为0 则调度器被锁。{称它为调度器锁嵌套值,表示调度器被加了几把锁}

OS_CRITICAL_EXIT()将OSSchedLockNestingCtr 递减,给调度器解锁。{调度器锁嵌套值被减为0 时,就会调用调度器}
OS_CRITICAL_EXIT_NO_SCHED() 也递减OSSchedLockNestingCtr 的值,不同的是当其值减为0 时,不调用调度器。

2.测量锁调度器时间uC/OS-III 提供了测量锁调度器时间的功能,通过设置OS_CFG.H中的OS_CFG_SCHED_LOCK_TIME_MEAS_EN 为1 开启。加锁调度器前测量开始,解锁调度器后测量结束。测得的两种值为:总的锁调度器时间,每个任务的锁调度器时间。因此,用户可以知道每个任务的锁调度器时间,并根据此优化代码。

三.uC/OS-III与长临界段

了解

四.总结
uC/OS-III 中会用到临界段, 用关中断(OS_CFG.H 中设置OS_CFG_ISR_POST_DEFERRED_EN 为0) 或者锁调度器( 设置OS_CFG_ISR_POST_DEFERRED_EN 为1)实现保护临界段的功能。用户程序不能使用这些代码:
OS_CRITICAL_ENTER()
OS_CRITICAL_EXIT()
OS_CRITICAL_EXIT_NO_SCHED()
如果设置了CPU_CFG.H 中的CPU_CFG_TIME_MEAS_INT_DIS_EN 为1 时。uC/CPU 将会任务总的关中断时间和每个任务的关中断时间。

如果设置了OS_CFG.H 中的OS_CFG_SCHED_LOCK_TIME_MEAS_EN 为1 时。uC/OS-III 会测量任务总的锁调度器时间和每个任务锁调度器时间。



原创粉丝点击