zjw2012 发表于 2012-5-14 08:57:54

新手关于ucos任务切换的问题

举个例子:王小二的任务现在正在被cpu执行,到某一处王小二的任务调用任务调度函数OSSched()准备任务切换,假设正好有一个更高优先级的任务李小三已经准备就绪,那么调度函数要切换到李小三运行,此时在调度函数里模拟软中断保存cpu所有寄存器的值以及当前PC值(注意这里),并恢复李小三堆栈空间里的值到PC,开始运行李小三任务。
那么我的问题是:切换是在调度函数里实现的,那么切换时当时PC的值也是调度函数里,当王小二重新被执行时,恢复CPU值,此时恢复的PC值是在调度函数里,如何再回到王小二任务里?
不知道大家能不能看明白我的意思,如果有理解这个问题的 希望帮我解说一下,看到这里一直被困扰,谢谢了。

zjw2012 发表于 2012-5-14 09:41:42

哪位大侠能帮帮我啊,在线坐等~~~~~~

niaojingxin 发表于 2012-5-14 10:07:25

系统这个时候不是返回去做王小二,而是切换,是一个新的切换过程,你只要把这个时候的王小二不当做以前的王小二去思考,就会明白了。本人也是新手,个人愚见,仅供参考。

zjw2012 发表于 2012-5-14 10:22:42

niaojingxin 发表于 2012-5-14 10:07 static/image/common/back.gif
系统这个时候不是返回去做王小二,而是切换,是一个新的切换过程,你只要把这个时候的王小二不当做以前的王 ...

谢谢你的回复
我假定是王小二又得到执行权,再次执行的时候,根据之前入栈保存的断点处的CP是调度函数里的某一点,那么在CP恢复的时候岂不是恢复到调度函数里边了,而没有恢复到王小二任务里。
主要是恢复王小二这个任务的具体过程。

niaojingxin 发表于 2012-5-14 11:08:38

PC值不是在调度函数里的某点,是任务挂起的那个点。你所说的在调度函数里面的某点位于临界段,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()两个函数将这段临界段代码封起来了,保存cpu寄存器的值以及当前PC值操作在OS_ENTER_CRITICAL()函数里。回复时间有限制,郁闷啊。

deny 发表于 2012-5-14 11:49:36

执行OSSched()时并不会立刻压栈吧,要执行到最后的OS_EXIT_CRITICAL()开中断以后才开始压栈吧,那回到王小二任务的时候,断点应该是OS_EXIT_CRITICAL()函数里开中断之后的一点吧,这是我个人见解,之前我也被这个问题困扰了一段时间,这样理解不知道正不正确,多多指教!

zjw2012 发表于 2012-5-14 12:23:08

niaojingxin 发表于 2012-5-14 11:08 static/image/common/back.gif
PC值不是在调度函数里的某点,是任务挂起的那个点。你所说的在调度函数里面的某点位于临界段,OS_ENTER_CRI ...

niaojingxin大侠您好 ,您可能没有明白我的意思,给你看图吧

zjw2012 发表于 2012-5-14 12:33:32

deny 发表于 2012-5-14 11:49 static/image/common/back.gif
执行OSSched()时并不会立刻压栈吧,要执行到最后的OS_EXIT_CRITICAL()开中断以后才开始压栈吧,那回到王 ...

voidOS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3                            //中断函数被设定为模式3   
    OS_CPU_SRcpu_sr;
#endif      
    INT8U      y;                                    //定义一个8位整数y   


    OS_ENTER_CRITICAL();                               //关闭中断   
   if ((OSIntNesting == 0) && (OSLockNesting == 0)) {   
         y             = OSUnMapTbl;          /* Get pointer to HPT ready to run            */
      OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl]);
         if (OSPrioHighRdy != OSPrioCur) {            /* No Ctx Sw if current task is highest rdy   */
            OSTCBHighRdy = OSTCBPrioTbl;
                  OSCtxSwCtr++;                              //统计计数器OSCtxSwCtr加1,以跟踪任务切换次数   
            OS_TASK_SW();                              //最后宏调用OS_TASK_SW()来完成实际上的任务切换   
      }
    }
    OS_EXIT_CRITICAL();                              //打开中断   
}


如源码,你的意思是,在OS_TASK_SW();执行后并没有压栈操作?是在OS_EXIT_CRITICAL()之后?
是不是OS_TASK_SW()只是软中断置位,当OS_EXIT_CRITICAL()之后才去响应中断然后保护断点的吗?

niaojingxin 发表于 2012-5-14 13:24:17

叫大侠是抬举我了,本人也是刚开始搞这个不久,水平不高,只能说和您讨论讨论。在OS_TASK_SW();执行有压栈操作的,详见《嵌入式实时操作系统uCOS-II》(第二版)3.05节图F3.7下面的第一句话,你图上所标注的点B的PC值其实和点A处的PC值是一样的,因为OS_ENTER_CRITICAL(); 执行这个函数后,系统总中断关闭了,节拍是通过中断服务子程序调用OSTIMETICK实现的,所以,关闭总中断之后,程序计数器得不到系统的节拍服务,PC值不计数了,所以B点处的PC值其实就是A点处的值。这个是我的理解。

zjw2012 发表于 2012-5-14 13:59:37

niaojingxin 发表于 2012-5-14 13:24 static/image/common/back.gif
叫大侠是抬举我了,本人也是刚开始搞这个不久,水平不高,只能说和您讨论讨论。在OS_TASK_SW();执行有压栈 ...

好兄弟,我更迷惑了PC值跟中断也有关系的吗?

zjw2012 发表于 2012-5-14 14:07:06

zjw2012 发表于 2012-5-14 13:59 static/image/common/back.gif
好兄弟,我更迷惑了PC值跟中断也有关系的吗?

PC不是记录当前程序运行的地址吗?怎么在ucos里中断还可以把它关掉?

deny 发表于 2012-5-14 14:28:39

zjw2012 发表于 2012-5-14 12:33 static/image/common/back.gif
voidOS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3                            //中断函数被设 ...

是啊,我就是这样理解,执行OS_TASK_SW()的时候应该会压栈,但这只是调用函数那种压栈,执行完以后堆栈恢复了,在执行OS_TASK_SW()函数时只是允许软中断,但是并不是立刻响应啊,要执行到进入OS_EXIT_CRITICAL()函数里开中断以后才开始切换(假设此刻王小二任务是就绪表优先级最高的)到王小二任务吧,不知道我这样理解对不对,恳请指正

niaojingxin 发表于 2012-5-14 15:53:08

本帖最后由 niaojingxin 于 2012-5-14 15:55 编辑

仔细去看了下我移植的工程的汇编代码,应该如deny网友所说,存贮操作是在OS_EXIT_CRITICAL()函数里开中断以后,以前应该是我理解有误。惭愧,呵呵。学习了。要感谢楼主和deny网友。

zjw2012 发表于 2012-5-14 16:55:10

niaojingxin 发表于 2012-5-14 15:53 static/image/common/back.gif
仔细去看了下我移植的工程的汇编代码,应该如deny网友所说,存贮操作是在OS_EXIT_CRITICAL()函数里开中断以 ...

嗯,太谢谢你们两位了,现在我对这个问题有了新的认识,等下班回去再好好看看源代码,谢谢你们。{:handshake:}
页: [1]
查看完整版本: 新手关于ucos任务切换的问题