打印

ucosii操作系统下中断函数不允许任务切换问题!

[复制链接]
6395|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
电子乌托邦|  楼主 | 2010-3-26 08:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
xinzha| | 2010-3-26 10:06 | 只看该作者
这是为了中断嵌套准备的,每嵌套一次中断计数加1,直到最后一个中断处理完成才允许任务调度。
中断中不能进行任务调度的理由很多啊,想到一条是,你要是调度了的话,此时如果你已经清了中断标志,那么剩下的中断将无法再调度回来,得不到执行,因为中断不是任务,切换出去了如果没有特殊复杂的手段就回不来。如果你此时没有清中断,那就更乱了,再回中断的话整个处理什么的都要再执行一遍,都是错的。
另外中断的执行是要有时间要求,在操作系统的设计理念中中断的优先级就是高于所有任务的,中断切到任务的话,如果任务是个长时间执行的任务,那么万一再有相同中断进来,那么必然有一次中断就被淹没了。

使用特权

评论回复
板凳
ShakaLeo| | 2010-3-26 19:09 | 只看该作者
楼上正解。中断事件一般来说对实时性要求比较高,所以在中断期间不允许任务切换比较合理。有的处理器在硬件上还具有这种保护措施,如果在一个中断还未退出的时候就试图切入线程模式(任务模式),会导致硬件fault。

使用特权

评论回复
地板
电子乌托邦|  楼主 | 2010-3-26 20:09 | 只看该作者
谢谢楼上两位!
引用2楼的话:“要是调度了的话,此时如果你已经清了中断标志,那么剩下的中断将无法再调度回来......”
我认为,中断也是函数。中断中任务切换时,也会保存当前寄存器值到任务堆栈中,等这个任务再次就绪时,就会找到这个入口处继续执行。
所以不存在“剩下的中断将无法再调度回来”
不知道说的对不对!

使用特权

评论回复
5
xinzha| | 2010-3-26 20:54 | 只看该作者
回不来,因为你说的是调度,而不是调用,中断不是你起的一个task,不在任务列表里面,中断的生命周期只有从激起cpu响应到处理结束,而task的生命周期是从你主动建立到你主动销毁,这段时间内不管你喜欢它还是讨厌它,它始终会存在于系统中。
如果中断被调度程序打断切换出去,那么打断它的任务在几种情况下交出cpu,一是高优先级抢占,二是自己主动释放cpu(这种情况下cpu交给低优先级任务或者idle task),三是被中断打断,任何一种情况都回不到你以前的中断处理中去,四是自己的时间片到期交给同优先级的下一个就绪任务(这个叫做round robin调度,这种情况ucos不用考虑,因为ucos不支持多任务同优先级)。另外你从这段描述中会发现一个问题,如果你没有清中断标志位,那么即使调度出去了,那个task也要马上交还cpu,因为有中断在。
中断里面的pc指针入栈之类的操作是isr自己完成的而不是操作系统完成的。操作系统在进行任务调度的时候会记录tcb(task control block)的大量数据,而这种机制没有应用到中断处理被切换出去的情景。

使用特权

评论回复
6
电子乌托邦|  楼主 | 2010-3-27 08:56 | 只看该作者
再次感谢ls的朋友,我举个例子:
task_a()                       task_b()                             interrupt()
{                              {                                    {
    int i;                         int j;                              ...
    while(OS_TRUE)                 while(OS_TRUE)                      切换到任务b
    {                              {                                   ...
      i = 1;                           j = 5;                       }
      i = 2;                           j = 6;
      (运行后此处产生中断)             j = 7;
      i = 3;                           j = 8;
      i = 4;                           os_timedly(再切换回任务a);
    }                              }
}                              }

开始运行:
1.task_a() 运行到i = 2产生中断;
2.CPU自动保存当前状态为状态1到task_a的堆栈;
3.执行interrupt(),任务切换,保存当前状态为状态2
4.运行task_b,运行结束,假设该回归任务a,操作系统找出任务a堆栈的状态2,回归到中断函数跳转处继续执行;
5.中断执行到最后,执行中断返回指令,取出a堆栈的状态1,回归到任务a的中断运行处继续执行。
我得出的结论:没有丢失中断剩余部分的程序!可以在中断中进行任务的切换!
请大家看看我分析的哪里错了!

使用特权

评论回复
7
ShakaLeo| | 2010-3-27 09:18 | 只看该作者
楼主如果非得这么做,其实技术上也不一定就不能实现,只是在进入中断的时候不能调用OSIntEnter();或者说OSIntNesting这个变量不能加1了,因为任务调度的函数会检查这个变量,不是0就不进行调度。只是这样一来,中断似乎就失去了中断的意义,中断居然能被任务所打断并且停止一段不确定的时间,所以这种做法是不合理的。
而且ucos2的不少移植版本都是在刚进入中断的时候保存任务环境,在中断退出的时候做任务切换的时候不再保存,直接恢复当前优先级最高的任务环境,如果是这种移植版本,楼主的做法还是不能实现。

使用特权

评论回复
8
电子乌托邦|  楼主 | 2010-3-27 09:48 | 只看该作者
我举个例子:
task_a()                       task_b()                             interrupt()
{                              {                                    {
    int i;                         int j;                              ...
    while(OS_TRUE)                 while(OS_TRUE)                      切换到任务b
    {                              {                                   ...
      i = 1;                           j = 5;                       }
      i = 2;                           j = 6;
      (运行后此处产生中断)             j = 7;
      i = 3;                           j = 8;
      i = 4;                           os_timedly(再切换回任务a);
    }                              }
}                              }

开始运行:
1.task_a() 运行到i = 2产生中断;
2.CPU自动保存当前状态为状态1到task_a的堆栈;
3.执行interrupt(),任务切换,保存当前状态为状态2,
4.运行task_b,运行结束,假设该回归任务a,操作系统找出任务a堆栈的状态2,回归到中断函数跳转处继续执行;
5.中断执行到最后,执行中断返回指令,取出a堆栈的状态1,回归到任务a的中断运行处继续执行。
我得出的结论:没有丢失中断剩余部分的程序!可以在中断中进行任务的切换!
请大家看看我分析的哪里错了!

使用特权

评论回复
9
xinzha| | 2010-3-27 10:14 | 只看该作者
如果你想讨论的是将来能不能做成,那么肯定是能做的,只是系统失去了实时性,变得不可靠。
如果你想讨论的是现在能不能做,那肯定是不行的,因为系统没有提供从中断中调度给其他任务并保留现场的机制。
中断使用的是中断栈,任务使用的是任务栈和系统栈,要想实现这些的无缝切换就得整个推翻现在的设计理念。
楼主把中断处理当成了任务的一部分,而实际中断独立于任务,如果从优先级角度来讲,最低优先级中断也高于最高优先级中断,这种设计思想,决定了必须是一切中断得到充分执行之后,外面的task才能获得cpu时间。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

140

主题

633

帖子

2

粉丝