7121|20

76

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

关于ucos的一个问题 [复制链接]

 本人初学嵌入式系统

对于ucos尚留几个关于任务调度的问题,急需解惑,

(1)当前运行的任务是不是还在就绪表中:
        1.假设是,那么调度到新任务不都是当前任务么,也就是说实际上不会有任务切换了?(假设不会有等待状态,于是当前运行的prio就是最大的)
        2.若不是,当当前任务a(prio最大)暂停切换到新任务b,那任务a是否在就绪表中?不是又在哪里?

(2) 关于任务的何时调度:
        uCOS因该是在用户程序显示切换或者在中断时OSIntExit中检查切换的,
        那么如果很长时间没有产生中断或不手动调用任务调度函数,那任务还会不会切换了?

希望知者能够尽快回答。。。

最新回复

嗯,实践出真知啊!!!!!  详情 回复 发表于 2009-11-23 10:23
点赞 关注
 

回复
举报

74

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
发错地方了,这里是CE论坛
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
记不太清了,自己理解:
(1)、不是
       最高优先级任务暂停切换到新任务b,绝对要用一个sleep()函数挂起任务,挂起后并不是就绪状态,需要等到sleep时间到,才是就绪状态。
(2)
       系统跟根据时钟TICK,检查一遍任务TCB链上的所有任务就绪状态,就绪且优先级最高的运行
可以看一下
OS_CORE.c
中的OSTimeTick函数
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

4
 
  1. void  OSTimeTick (void)
  2. {
  3.     OS_TCB    *ptcb;
  4. #if OS_TICK_STEP_EN > 0
  5.     BOOLEAN    step;
  6. #endif
  7. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register     */
  8.     OS_CPU_SR  cpu_sr = 0;
  9. #endif



  10. #if OS_TIME_TICK_HOOK_EN > 0
  11.     OSTimeTickHook();                                      /* Call user definable hook                     */
  12. #endif
  13. #if OS_TIME_GET_SET_EN > 0
  14.     OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter               */
  15.     OSTime++;
  16.     OS_EXIT_CRITICAL();
  17. #endif
  18.     if (OSRunning == OS_TRUE) {
  19. #if OS_TICK_STEP_EN > 0
  20.         switch (OSTickStepState) {                         /* Determine whether we need to process a tick  */
  21.             case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled                    */
  22.                  step = OS_TRUE;
  23.                  break;

  24.             case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...       */
  25.                  step = OS_FALSE;                          /*      .. OSTickStepState to OS_TICK_STEP_ONCE */
  26.                  break;

  27.             case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ... */
  28.                  step            = OS_TRUE;                /*      ... step command from uC/OS-View        */
  29.                  OSTickStepState = OS_TICK_STEP_WAIT;
  30.                  break;

  31.             default:                                       /* Invalid case, correct situation              */
  32.                  step            = OS_TRUE;
  33.                  OSTickStepState = OS_TICK_STEP_DIS;
  34.                  break;
  35.         }
  36.         if (step == OS_FALSE) {                            /* Return if waiting for step command           */
  37.             return;
  38.         }
  39. #endif
  40.         ptcb = OSTCBList;                                  /* Point at first TCB in TCB list               */
  41.         while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list              */
  42.             OS_ENTER_CRITICAL();
  43.             if (ptcb->OSTCBDly != 0) {                     /* No, Delayed or waiting for event with TO     */
  44.                 [color=#FF0000]if (--ptcb->OSTCBDly == 0)[/color] {               /* Decrement nbr of ticks to end of delay       */
  45.                                                            /* Check for timeout                            */
  46.                     if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
  47.                         ptcb->OSTCBStat  &= ~(INT8U)OS_STAT_PEND_ANY;          /* Yes, Clear status flag   */
  48.                         ptcb->OSTCBStatPend = OS_STAT_PEND_TO;                 /* Indicate PEND timeout    */
  49.                     } else {
  50.                         ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
  51.                     }

  52.                     if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?       */
  53.                         OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready          */
  54.                         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  55.                     }
  56.                 }
  57.             }
  58.             ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list                */
  59.             OS_EXIT_CRITICAL();
  60.         }
  61.     }
  62. }
复制代码

ptcb->OSTCBDly就是挂起函数睡眠时间技术,每一次TICK减1,减到0就由挂起到就绪了
系统的TICK是可以设定的 一般在10ms到50ms
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

5
 
系统函数的
OSTimeDly()
函数的参数 就是TICK值!!!
原型:

void  OSTimeDly (INT16U ticks)
在os_time.c里
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

6
 
引用 3 楼 jkl9543 的回复:
OSTimeTick中是检查 sleep是否完成

不过未见uCOS中的任务切换服务函数 将要暂停的任务sleep掉(我没发现,或在哪里呢?) ,而且又设置多少Ticks?

难道是在uCOS(0x80)中断ISR中?

哦 你的意思任务切换啊,
假设高优先级任务在运行,一个低优先级的任务就绪不可能运行的啊,
你怎么把高优先级任务暂停
不还得需要OSTimeDly之类的函数把高优先级任务挂起来,才会运行低优先级的
我说的sleep就是ostimedly之类的函数
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

7
 
我想的是,不手动 Sleep,不等待任何同步的东西。。。

就是这样(很虚拟):
void oncreateTask()
{
         createTask(task,prio=0,..)
         createTask(task,prio=1,..)
         createTask(task,prio=2,..)
         createTask(task,prio=3,..)
}
task是个全部相同的极其简单的proc :
void task()
{
    while(1) {    }
}

然后指定请问uCOS 会不会在以上4个任务中做切换? 如何做到切换?
 
 
 

回复

47

帖子

0

TA的资源

一粒金砂(初级)

8
 
哦,刚才我已经感觉我错了只是没法回复了
对于第二个问题,应该是不会切换的了
我记得书上又说
任务的写法 必须是
While(1)
{
.......
delay();//睡眠之类的函数
}
这个形式的。

你那个关键是没有意义啊!!

 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

9
 
好久没看了  呵呵 刚才又看了看代码!
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

10
 
引用 8 楼 lyx_wq 的回复:
哦,刚才我已经感觉我错了只是没法回复了
对于第二个问题,应该是不会切换的了
我记得书上又说
任务的写法 必须是
While(1)
{
.......
delay();//睡眠之类的函数
}
这个形式的。

你那个关键是没有意义啊!!



你的书叫什么啊,既然都这么说了("必须是"),应该没什么疑问了。。。
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

11
 

还有一种形式就是
void YourTask(void *pdata)
{
   /*用户代码*、
    OSTaskDel(OS_PORI_SELF);
}
但是要用那种while循环的话,就必须是那种了
那本书忘记了!也可能在网上看的
只有个印象,书我就看了邵贝贝的那本
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

12
 
邵贝贝的第三章开头讲了这两种形式
void YourTask(void *pdata)
{
for(;;)
{
   /*用户代码*/
   调用uc/osII的某种系统服务:
    OSMboxPend();
    OSQPend();
    OSSemPend();
    OSTaskDel(OS_PORI_SELF);
    OSTaskSusPend(OS_PRIO_SELF);
    OSTimeDly();
    OSTimeDlyHMSM();
   /*用户代码*/
}
}
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

13
 
一般得有上面的系统服务之一吧,
没有的话就像你的 也不会错,可是没用啊!!!!
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

14
 
引用 13 楼 lyx_wq 的回复:
一般得有上面的系统服务之一吧,
没有的话就像你的 也不会错,可是没用啊!!!!

我只是想探明一下原理,这点还是要的。

如果说一定要在Task中写上一些***Pend(),***Dly(),之类的调用来促使系统产生任务切换的话
感觉uCOS更倾向于"不可剥削型"的系统了!
也就是说运行着的代码若不触及中断,也不调用以上函数,就不会发生调度?这样uCos也不是太简陋了点,觉得。
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

15
 
引用 14 楼 jkl9543 的回复:
引用 13 楼 lyx_wq 的回复:
一般得有上面的系统服务之一吧,
没有的话就像你的 也不会错,可是没用啊!!!!

我只是想探明一下原理,这点还是要的。

如果说一定要在Task中写上一些***Pend(),***Dly(),之类的调用来促使系统产生任务切换的话
感觉uCOS更倾向于"不可剥削型"的系统了!
也就是说运行着的代码若不触及中断,也不调用以上函数,就不会发生调度?这样uCos也不是太简陋了点,觉得。

不过那个时钟TICK是跟定时器有关的 定时中断会不会有任务切换呢???
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

16
 
晕了!!!^_^!!
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

17
 
似乎没有。。看一下代码..我下机了...
 
 
 

回复

87

帖子

0

TA的资源

一粒金砂(初级)

18
 
这个该怎么理解呢??
OSIntCtxSw
    LDR     R0, __OS_TaskSwHook                                 ; OSTaskSwHook();
    MOV     LR, PC
    BX      R0

    LDR     R0, __OS_PrioCur                                    ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, __OS_PrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, __OS_TCBCur                                     ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, __OS_TCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     SP, [R2]                                            ; SP = OSTCBHighRdy->OSTCBStkPtr;

                                                                ; RESTORE NEW TASK'S CONTEXT:
    LDMFD   SP!, {R0}                                           ;    Pop new task's CPSR,
    MSR     SPSR_cxsf, R0

    LDMFD   SP!, {R0-R12, LR, PC}^                              ;    Pop new task's context.
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

19
 
再说一句,我感觉,时钟中断,会调用上面函数,进而改变当前任务的。。
有时间讨论下!!!
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

20
 
今天用 uCOS  v2.84在Win32的port版本测试了如下:

  1. #include "includes.h"
  2. #define TASK_STK_SIZE   1024
  3. OS_STK  _Stk0[TASK_STK_SIZE];
  4. OS_STK  _Stk1[TASK_STK_SIZE];
  5. OS_STK  _Stk2[TASK_STK_SIZE];
  6. void Initialzer(void *pdata);
  7. void Task_prio_1(void *pdata);
  8. void Task_prio_2(void *pdata);
  9. int main(void)
  10. {
  11.     printf(" - uCOS-II V%4.2f Port Win,test suite\n", ((FP32)OSVersion())/100);
  12.     OSInit();
  13.     OSTaskCreate(Initialzer,(void *)0,&_Stk0[TASK_STK_SIZE],3);
  14.     OSStart();
  15.     printf(" -- never reach here --\n");
  16.     return 0;
  17. }
  18. void Initialzer(void *pdata)
  19. {
  20.         printf("Initialzer: ***** Now Begin Initialze *****\n");

  21.         printf("Initialzer: ***** Now is before the Creation of Task1 *****\n");
  22.     OSTaskCreate(Task_prio_1, (void *)0, &_Stk1[TASK_STK_SIZE], 1);
  23.        
  24.         printf("Initialzer: ***** Now is before the Creation of Task1 *****\n");
  25.     OSTaskCreate(Task_prio_2, (void *)0, &_Stk2[TASK_STK_SIZE], 2);
  26.        
  27.         printf("Initialzer: ***** Now Initialze Finished *****\n");
  28.         OSTaskSuspend(OS_PRIO_SELF);
  29.        
  30.         printf("Initialzer: -- this mesage never occur ! -- \n");
  31. }
  32. void DetectAndQuit(INT8U prio)
  33. {
  34.         if (_kbhit())
  35.         {
  36.                 if(prio!=1)OSTaskDel(1);
  37.                 if(prio!=2)OSTaskDel(2);
  38.                 if(prio!=3)OSTaskDel(3);
  39.                 exit(0);
  40.         }
  41. }
  42. void myDelay()
  43. {
  44.         INT32U i=0;       
  45.         while(i<100000000){
  46.                 //编译器要禁用优化,或启用调试模式
  47.                 i+=1;
  48.         }
  49. }
  50. void Task_prio_1(void *pdata)
  51. {
  52.         INT32U loopCnt=0;
  53. //测试主要是这里,1:用自己的延时函数避免printf过于频繁
  54. //                0:用OS的延时函数,这样任务调度正常
  55. #define TEST_MY_DELAY 1
  56.     while (1)
  57.     {
  58.         printf("Task_prio_1: ***** New loop %d for Working Task 1 *****\n",loopCnt++);
  59.                 DetectAndQuit(1);
  60. #if TEST_MY_DELAY
  61.                 myDelay();
  62. #else
  63.         OSTimeDly(1);
  64. #endif
  65.     }
  66. }
  67. void Task_prio_2(void *pdata)
  68. {
  69.     INT32U loopCnt=0;
  70.     while (1)
  71.     {
  72.         printf("Task_prio_2: ***** New loop %d for Working Task 2 *****\n",loopCnt++);
  73.                 DetectAndQuit(2);
  74.         OSTimeDly(1);
  75.     }
  76. }
复制代码

配置TEST_MY_DELAY宏为1
使用VC 6.0 编译后,输出只有Task_prio_1,因为OS调度任务总是选择prio最高的,
而最高的任务(Task_prio_1)总是在运行,且丝毫不让OS暂停自己,OS也没办法,就算在
中断ISR中调用OSIntExit()的检测任务调度也没用。

当采用配置TEST_MY_DELAY宏为0,
在每个循环中调用了OSTimeDly(),这样休眠自己,让OS有机会运行其他的任务。

我想这就是"实时"的需要吧,用户必须设置好任务的Prio,
并且最高优先级的任务必须根据逻辑,在相关的地方调用***Pend(),或***Dly(),让
OS有机会运行其他低优先级的任务,否则就成了单任务的DOS了。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表