欣欣学习网,老工程师带你学习单片机技术,欢迎来坐坐。
首  页 | 学习NIOSII | 学习C51 | 学习CPLD | 51+CPLD实验板 | | | MY-RTOS

 系统简介
 系统启动
 创建任务
 等待与休眠
 使用互斥量
 使用信号量
 信号量组
 使用事件
 使用事件组
 消息队列
 动态内存管理
 只读内存管理
 临界段与内核锁
 任务复位与终止


玛雅实时操作系统(MY-RTOS)

临 界 段 与 内 核 锁


版权声明:玛雅实时操作系统(MY-RTOS)软件及其说明文档由 欣欣学习网 版主 Stoneway QI 创作,作者保留其版权。任何人可以免费在其产品设计或著作中使用或引用该软件及其说明文档,但要求保留原作品当中的版权声明,并注明引用段落的出处。

-- Stoneway QI 主页: http://www.xxworks.com 邮箱: Stonewayqi@hotmail.com

在应用程序设计过程中,有时我们希望程序的某些段落能够连续运行而不被其它任务或中断服务程序所打断。通常,有这样要求的程序段落被称为临界段。在玛雅系统中,临界段的设计是通过调用系统函数OSEnterCritical()和OSExitCritical()来实现的。函数OSEnterCritical()用来标定临界段的起始,而函数OSExitCritical()用来标定临界段的结束。

...
...
void main(void)
{
    ...
    BSP(); // 硬件初化
    OSInit(72000); //玛雅系统初始化
    ...
    while(1)
    {
        ...
        OSEnterCritical();                             //进入临界段
        ...
        ...                                            // 临
        ...                                            // 界
        ...                                            // 段
        ...
        OSExitCritical();                              //退出临界段
        ...
    }
}                       (1)

系统进入临界段运行时,会暂停对任务的调度及对中断请求的响应。因此,对临界段的设计要尽可能的简短,否则会削弱整个系统的实时响应能力。对于进入临界段与退出临界段的两个系统函数要尽可能的成对使用,以避免某些程序分枝跃出临界段而没有调用系统函数来结束临界段。玛雅系统允许临界段嵌套,最大嵌套层数为4294967295。

除了临界段之外,玛雅系统也支持应用程序使用准临界段。准临界段是只要求不被其它的任务打断,而允许被中断服务程序打断的程序段落。与临界段相比,使用准临界段不影响系统对中断请求的响应。因此,在满足需求的前提下,使用准临界段应该是优先予以考虑的。

实现准临界段是通过调用系统函数OSLockSwitch()与OSUnlockSwitch()对内核锁进行设置来完成的。函数OSLockSwitch()锁定内核锁之后,系统会暂停对任务的调度,而函数OSUnlockSwitch()解除内核锁之后,系统恢复对任务的调度。

...
...
void main(void)
{
    ...
    BSP(); // 硬件初化
    OSInit(72000); //玛雅系统初始化
    ...
    while(1)
    {
        ...
        OSLockSwitch();                                //锁定内核锁
        ...
        ...                                            // 
        ...                                            //准临界运行
        ...                                            //
        ...
        OSUnlockSwitch();                              //解除内核锁
        ...
    }
}                       (2)

同临界段一样,冗长的准临界段也会降低系统的整体实时响应能力。

在程序设计中,有时会遇到准临界段嵌套的问题。比如,在准临界段当中调用了一个函数,而该函数当中也有对准临界段的操作。此时,若该函数中使用系统函数OSUnlockSwitch()则会造成原来的准临界段部分失效。

...
...
void main(void)
{
    ...
    BSP(); // 硬件初化
    OSInit(72000); //玛雅系统初始化
    ...
    while(1)
    {
        ...
        OSLockSwitch();                                //锁定内核锁
        ...
        ...                                            // 
        SubRouting();                                  //子函数内解除了内核锁
        ...                                            //导致该子函数之后的段
        ...                                            //落失去了内核锁的保护
        OSUnlockSwitch();                              //解除内核锁
        ...
    }
}

void SubRouting(void)
{
    ...
    OSLockSwitch();                                    //锁定内核锁
    ...
    OSUnlockSwitch();                                  //解除内核锁
    ...
}                       (3)

为了避免内核锁被误解除,在子函数中不应该使用函数OSUnlockSwitch(),而要使用另外一个函数OSRestoreSwitch()。如以下代码所示:

...
...
void main(void)
{
    ...
    BSP(); // 硬件初化
    OSInit(72000); //玛雅系统初始化
    ...
    while(1)
    {
        ...
        OSLockSwitch();                                //锁定内核锁
        ...
        ...                                            // 
        SubRouting();                                  //子函数恢复内核锁
        ...                                            //原内核锁状态保留
        ...                                            //
        OSUnlockSwitch();                              //解除内核锁
        ...
    }
}

void SubRouting(void)
{
    U8 KernelSwitch;
    ...
    KernelSwitch = OSLockSwitch();                     //锁定内核锁并保存原状态
    ...
    OSRestoreSwitch(KernelSwitch);                     //恢复内核锁
    ...
}                       (4)


管理员信箱: stonewayqi@hotmail.com

欣 欣 学 习 网

粤ICP备2023138008号