查看: 1979|回复: 0
打印 上一主题 下一主题

如何缩短μC/OS-II中缩短中断关闭时间

[复制链接]
跳转到指定楼层
沙发
发表于 2015-4-18 14:21:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 leixiaofeng 于 2015-4-18 14:52 编辑

 1 系统状态标志法概述

  μC/OS-II中在进入临界区之前为什么要关闭中断?通过相关资料[1]的介绍和对μC/OS-II源代码的理解,我们知道在μC/OS-II中一旦不关中断就进入临界区。当某一任务进入临界区时,若恰好发生中断,那么这时有可能引起两种对临界区操作的冲突:①在中断服务程序中要操作同一临界区;②因为中断的产生而引起任务的转换,在新的任务中要操作同一临界区。所以μC/OS-II中在进入临界区前要关闭中断。

  针对μC/OS-II关中断机制的分析,考虑用一种系统状态标志法来解决这样的临界冲突。在μC/OS-II增加一个全局布尔变量来表示系统的状态,称为“系统状态标志”。

  对于μC/OS-II中所有可以在中断中出现又要对临界区操作的函数,可以在进入临界区之前先查询系统状态标志。如果目前系统没有进入临界操作状态,则首先将该标志置位,表示系统进入临界操作状态,然后该函数就可以操作临界区;而如果发现系统已进入临界操作状态,则将该函数对临界区操作的部分单独形成一个函数,放到一个系统循环函数数组里,等待系统任务调度时执行。

  对于μC/OS-II中所有不可能在中断程序中出现而又要对临界区操作的函数,因为函数不在中断中出现,所以函数开始时系统状态标志肯定不会在临界操作状态,因此可在函数操作临界区时直接将系统状态标志置位,表示系统进入临界操作状态,然后即可进行临界区的操作。

  系统状态标志的复位在任务调度函数中执行。当然对系统状态标志的设置是要在关中断的条件下执行的,这应该算是系统新的一个临界区。

  2 该方法的具体实现

  下面以对μC/OS-II v2.61代码的改进为例,具体讲解该方法的具体实现。

  2.1 任务调度函数OS_Sched的修改

  修改后的任务调度函数OS_Sched的伪代码如下:

{

  if(函数实在中断中被调用){

  执行点1:

    关中断;

     if(系统循环函数组不为空){

         开中断;

         调用烯烃循环函数数组里的各函数;

          goto 执行点1;

}

系统状态标志位复位;

开中断;

返回;

}

执行点2:

     查找当前就绪队列的优先级最高任务;

      if(就绪队列的优先级最高的任务就是当前任务){

      关中断;

      if(系统循环函数数组为空){

      系统状态标志位复位;

      开中断;

      返回;

}

开中断;

调用系统循环函数数组里的各函数;

goto执行点2;

}

  if(任务调用被锁){

     关中断;

if(系统循环函数数组为空){

系统状态标志位复位;

      开中断;

      返回;

}

开中断;

调用系统循环函数数组里的各函数;

goto执行点2;

}

调用任务转换函数进行任务调度;

}


  因为在任务调度函数OS_Sched中要执行循环函数数组里的函数,同时还要对系统状态标志复位,退出系统临界操作状态,所以修改过的函数在遇到以下3种情况--该函数是在中断里调用时、在任务调度锁定时、当前任务就是最高优先级任务时,都将执行系统循环函数数组里的函数,并将系统状态标志复位,而原任务调度函数在遇到以上3种情况时是直接返回的。

  2.2 增加任务重调度函数OS_Resched

  任务重调度函数OS_Resched的伪代码如下:

{

执行点:

while(没有就绪任务)

执行系统询函函数数组里的各函数;

查找当前就绪队列中优先级最高任务;

关中断;

if(
系统循环函数数组为空){

开中断;

goto 执行点;

}

系统状态标志位复位;

}



  任务重调度函数在以下两处执行:

  (1) 当μC/OS-II将当前任务控制块压栈,而还没有将最高优先级任务的控制块弹出栈时执行,因为这时在系统循环函数数组里有可能还有未执行的函数,这些函数的执行有可能导致另外一个更高优先级任务的就绪。

  (2) 在中断服务函数的末尾执行。如果μC/OS-II中断返回函数返回的是一个真值,则表示需要执行重调度函数,这时就要执行重调度函数。

2.3 中断返回函数OSIntExit的修改

  中断返回函数OSIntExit的伪代码如下:


返回1;

}

返回0;

}



  原函数的返回是void,而改动后的函数返回一个布尔量,用来表示下一步是要正常中断返回(返回布尔假值时),还是要调用任务重调度函数(返回布尔真值时);同时,改动后还增加对系统状态标志的查询,如果发现系统在临界操作状态,则直接返回布尔假值。所以在中断服务程序的最后不是象原来那样简单的调用,而是调用后根据返回值作相应的处理。

  2.4 信号量发送函数OSSemPoST的修改

  这里将以信号量发送函数OSSemPost为例来描述对可在中断中调用而又会对临界区操作的函数的改进。对于μC/OS-II中的其他函数,改进的方法大致相同。

  信号量发送函数OSSemPost的伪代码如下:

返回os-no-err;

}

}


  在这里,改动后的函数将先判断系统状态标志,如果系统在临界区操作状态,则将临界操作作为另一个函数放入全局函数循环数组,等待在任务调度时执行,如果不在临界区操作状态,则关中断后将系统状态标志置位,然后开中断进行原函数的那些临界操作和任务调度。

  2.5 信号量等待函数OSSemPend的修改

  同理,这里以信号量等待函数OSSemPend为例来描述对不能在中断中调用而又会对临界区操作的函数的改进。

  信号量等待函数OSSemPend的伪代码如下:

os_TIMEOUT放到crr中;

返回;

}

  在这里,改动后的函数先将系统状态标志置位,然后进行原来函数的临界区操作。需要说明的是,对于函数因为等待信号量时间到、还未获取信号量而返回的情况的处理机制,改动后的函数与原函数不同,改动后的函数将OS_EventTO函数放到时间节拍函数OSTimeTick中执行,并将OS_EventTO函数的输入参数由原来的事件pevent指针,改为任务控制块指针ptcb,因为在函数OSTimeTick中是按照任务控制块指针操作的。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?加入因仑

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

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