knight_lxf 发表于 2013-9-12 22:51:35

uC/OS-II的OS_TaskIdle()怎么引起调度?

uC/OS-II(Version 2.86) 中空闲任务(OS_TaskIdle())的代码如下voidOS_TaskIdle (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register         */
    OS_CPU_SRcpu_sr = 0;
#endif



    (void)p_arg;                                 /* Prevent compiler warning for not using 'p_arg'   */
    for (;;) {
      OS_ENTER_CRITICAL();
      OSIdleCtr++;
      OS_EXIT_CRITICAL();
      OSTaskIdleHook();                        /* Call user definable HOOK                           */
    }
}在某一时刻该任务获得CPU使用权之后,在该任务中也没有调用调度器,那么当别的高优先级任务就绪时,如何实现调度呢?

Eric_Xue 发表于 2013-9-13 08:46:48

定时中断里面OSTimeTick()对所有TCB中非零OSTimedly减一,减后为零,则使该TCB对应的任务就绪(就续表相应位置1)。在OSIntExit()中查找最高优先级,调度。

Eric2013 发表于 2013-9-13 09:00:06

高优先级的任务释放CPU运行权利,低优先级的任务可以得到执行。
低优先级任务运行的过程中,高优先级的任务是通过抢占获得CPU的运行权利。举个例子
比如一个高优先级任务是通过延迟函数挂起的,那么会在这里让高优先级的任务重新加入到就绪列表
voidOSTimeTick (void)
{
   if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {/* Is task suspended?       */
                        OSRdyGrp               |= ptcb->OSTCBBitY;               /* No,Make ready          */
                        OSRdyTbl |= ptcb->OSTCBBitX;
      }

    退出的时候再让高优先级的任务得到执行,如果这个任务是当前需要执行的最高优先级的任务的话。
    OSIntExit();
}

knight_lxf 发表于 2013-9-13 21:21:26

Eric_Xue 发表于 2013-9-13 08:46 static/image/common/back.gif
定时中断里面OSTimeTick()对所有TCB中非零OSTimedly减一,减后为零,则使该TCB对应的任务就绪(就续表相 ...

你看我这样理解行不行:uC/OS任务调度有两种途径:一、在任务中,当任务的某个行为(例如释放互斥信号)会导致ReadyList发生改变时,在该任务中启动调度器,去判断释放需要进行任务切换(通过与当前任务的优先级的大小关系判断);二、在滴答中断中,该ISR完成的功能为:每次中断发生,都会去对每个TCB中的TimeDly域进行减一,并且判断是否为0。如果为0,则改变ReadyList进而启动任务调度,最终完成任务切换的工作。
而我的问题的答案正是第二种。

理解出错之处,敬请指教!

knight_lxf 发表于 2013-9-13 21:23:39

Eric2013 发表于 2013-9-13 09:00 static/image/common/back.gif
高优先级的任务释放CPU运行权利,低优先级的任务可以得到执行。
低优先级任务运行的过程中,高优先级的任务 ...

呵呵谢谢,看了兄台跟一楼的回答。貌似有点懂了,就是不知理解对不对。还烦请移步4楼,看下我的理解是否正确。出错之处、敬请指教!

Eric_Xue 发表于 2013-9-13 22:03:37

knight_lxf 发表于 2013-9-13 21:21 static/image/common/back.gif
你看我这样理解行不行:uC/OS任务调度有两种途径:一、在任务中,当任务的某个行为(例如释放互斥信号) ...

对的,前一种任务自身调用系统函数,执行任务级调度,
后一种是在中断中事件有效或延迟完成,进行中断级任务调度。
空闲程序不能调用系统函数,只能被中断打断执行其他就绪任务。

i55x 发表于 2013-9-13 22:53:31

knight_lxf 发表于 2013-9-13 21:21 static/image/common/back.gif
你看我这样理解行不行:uC/OS任务调度有两种途径:一、在任务中,当任务的某个行为(例如释放互斥信号) ...

有一个前提你没有注意到,一个任务的死循环里面必须有ostimedly和/或pend函数释放对处理器的控制权,否则优先级比这个任务低的任务永远无法执行。
在这个条件下,ucosii任务调度有两个途径,第一就是在systick中断处理函数里面要对ostimedly一系的挂起任务进行就绪检查,一旦发现有任务就绪就按照优先级高低进行执行。第二个就是中断处理函数里面post消息,在OSIntExit函数里面进行任务调度,发现pend在这个消息的任务,就会执行这个任务。
你说的途径一的错误在于,释放互斥信号如果是ostimedly时间到,那么本质上属于我说的途径一,如果释放互斥信号是来源于中断事件,那么就是我说的途径二。没有第三种途径来源。

knight_lxf 发表于 2013-9-14 00:02:26

Eric_Xue 发表于 2013-9-13 22:03 static/image/common/back.gif
对的,前一种任务自身调用系统函数,执行任务级调度,
后一种是在中断中事件有效或延迟完成,进行中断级 ...

嗯 谢谢 看过你的回复 有RTFS一遍 明白了 呵呵。谢谢!

Eric2013 发表于 2013-9-14 00:04:03

楼主你学的不慢啊,论坛的i55x前辈都给你回复了。{:lol:}

knight_lxf 发表于 2013-9-14 00:11:46

Eric2013 发表于 2013-9-14 00:04 static/image/common/back.gif
楼主你学的不慢啊,论坛的i55x前辈都给你回复了。

呵呵谢谢! 也就是瞎看呗! 之前是跳过任务管理看事件管理对里面的全局变量像OSTCBCur、OSTCBPrioHighRdy等等虽然从字面大概知道什么意思但不是彻底清除。 又反过来看任务管理呵呵 走弯路咯!!!

Eric2013 发表于 2013-9-14 00:13:03

knight_lxf 发表于 2013-9-14 00:11 static/image/common/back.gif
呵呵谢谢! 也就是瞎看呗! 之前是跳过任务管理看事件管理对里面的全局变量像OSTCBCur、OSTCBPrioHig ...

你已经学的非常快了,比我学习那会强很多了。我那时候简直就是蜗牛爬。

knight_lxf 发表于 2013-9-14 00:20:37

i55x 发表于 2013-9-13 22:53 static/image/common/back.gif
有一个前提你没有注意到,一个任务的死循环里面必须有ostimedly和/或pend函数释放对处理器的控制权,否则 ...

前辈好!
      小弟不才,对回复中“释放互斥信号如果是ostimedly时间到”这句话实在不解。举例如下:void TaskA(void *pdata)//prio = 4
{
   INT8U err;
         .
         .
    OSMutexPend(DispMutex,0,&err);
         .
         .
}

void TaskB(void *pdata) //prio = 5
{
   INT8U err;
         .
         .
   err = OSMutexPost(DispMutex)
         .
         .
}释放互斥信号跟OSTimeDly有什么关系呢?

还烦请前辈不要嫌弃这问题低端,谢谢!

knight_lxf 发表于 2013-9-14 00:22:20

Eric2013 发表于 2013-9-14 00:13 static/image/common/back.gif
你已经学的非常快了,比我学习那会强很多了。我那时候简直就是蜗牛爬。 ...

哎,提起来都是泪啊!毕业两年有余才开始看嵌入式操作系统!实在惭愧!

i55x 发表于 2013-9-14 00:25:40

knight_lxf 发表于 2013-9-14 00:20 static/image/common/back.gif
前辈好!
      小弟不才,对回复中“释放互斥信号如果是ostimedly时间到”这句话实在不解。举例如下:释 ...

你taskb里面没有ostimedly的话比他优先级低的任务永远无法执行

knight_lxf 发表于 2013-9-14 00:57:31

i55x 发表于 2013-9-14 00:25 static/image/common/back.gif
你taskb里面没有ostimedly的话比他优先级低的任务永远无法执行

刚试了试确实是死在一个任务中 没办法调度。那是因为互斥的PIP设置为3 比那两个都高。目前对我来说互斥的水还太深。换个。换成Sem,初值为0。基本相同的代码同样没有OSTimeDly这时候任务都能正常运行static void Task1(void *pdata)   //prio = 4
{
        INT8U err;

        pdata = pdata;

        while(1)
        {
#if OS_CRITICAL_METHOD==3

                OS_CPU_SR cpu_sr;

#endif

                //OSMutexPend(DispMutex,0,&err);
                OSSemPend(DispMutex,0,&err);
                if(err==OS_NO_ERR)
                {
                        OS_ENTER_CRITICAL();
                        UsartPrintf("任务2已经发生,任务1已经同步\n");
                        OS_EXIT_CRITICAL();
                }               
        }
}

static void Task2(void *pdata)   //prio = 5
{
        INT8U err;

        pdata = pdata;

        while(1)
        {
#if OS_CRITICAL_METHOD==3

                OS_CPU_SR cpu_sr;

#endif

                //err = OSMutexPost(DispMutex);
                err = OSSemPost(DispMutex);
                if(OS_NO_ERR==err)
                {
                        OS_ENTER_CRITICAL();
                        UsartPrintf("任务2正在发生\n");
                        OS_EXIT_CRITICAL()
                }
        }
}这时候也没有TimeDly 任务却能交替执行

i55x 发表于 2013-9-14 01:09:05

knight_lxf 发表于 2013-9-14 00:57 static/image/common/back.gif
刚试了试确实是死在一个任务中 没办法调度。那是因为互斥的PIP设置为3 比那两个都高。目前对我来说互斥 ...

你的代码能正确执行不等于你的代码有现实意义。task2优先级最低,task1当然能执行。但是你的代码里面task2耗尽了所有的cpu执行时间的宝贵资源,idle任务永远无法执行,cpu负载率100%,在一个真实可用的系统里面你的代码是严重错误的。
页: [1]
查看完整版本: uC/OS-II的OS_TaskIdle()怎么引起调度?