搜索
bottom↓
回复: 24

uCOS-II创建了四个任务可最终只执行了两个任务

[复制链接]

出0入0汤圆

发表于 2011-1-10 16:19:56 | 显示全部楼层 |阅读模式
如题,用开发板调式看到只有两个任务执行,大家帮忙看看程序有什么问题。

#include <includes.h>

static OS_STK  GstkStart[TASK_START_STK_SIZE];                          /*  The stack of start task     */
                                                                        /*  启动任务的堆栈              */
static OS_STK  GstkLED1[TASK_LED_STK_SIZE];
static OS_STK  GstkLED2[TASK_LED_STK_SIZE];
static OS_STK  GstkLED3[TASK_LED_STK_SIZE];
static OS_STK  GstkLED4[TASK_LED_STK_SIZE];

OS_EVENT   *LEDCON;


/*********************************************************************************************************
   FUNCTION PROTOTYPES 函数声明
*********************************************************************************************************/
static void taskStart (void  *pdata);                                    /*  The start task  启动任务    */
static void taskLed1 (void  *pdata);
static void taskLed2 (void  *pdata);
static void taskLed3 (void  *pdata);
static void taskLed4 (void  *pdata);


int main (void)
{
    OSInit();                                          //  Initialize the kernel of uC/OS-II
                                                       // LEDCON:结构体成员变量,返回为结构体数据
    LEDCON = OSSemCreate(1);                           // 建立信号量LEDCON,
    OSTaskCreate( taskStart,                           //  Initialize the start task              
                  (void *)0,                           // 任务参数指针
                  &GstkStart[TASK_START_STK_SIZE-1],   // 任务栈顶指针
                  TASK_START_PRIO );                   //               
                                                               

    OSStart();                                         // Start uC/OS-II  启动uC/OS-II,在这之前必须创建至少一个任务
                                                         
    return(0);
}


static void taskStart (void  *pdata)
{
    (void)pdata;
    pdata = pdata;                              /* 避免编译器警告 */
    targetInit();                             /*  Initialize the target's MCU */
   
    #if OS_TASK_STAT_EN > 0
    OSStatInit();                                                                                                                    /*  使能统计功能                */
    #endif

    OSTaskCreate(taskLed1, (void *)0, &GstkLED1[TASK_LED_STK_SIZE-1], TASK_LED1_PRIO);  /*  建立LED的处理任务  */
    OSTaskCreate(taskLed2, (void *)0, &GstkLED2[TASK_LED_STK_SIZE-1], TASK_LED2_PRIO);
    OSTaskCreate(taskLed3, (void *)0, &GstkLED3[TASK_LED_STK_SIZE-1], TASK_LED3_PRIO);
    OSTaskCreate(taskLed4, (void *)0, &GstkLED4[TASK_LED_STK_SIZE-1], TASK_LED4_PRIO);
                                                               
    while (1) {                             
    /*
     *  OSTaskSuspend(OS_PRIO_SELF);
     *  The start task can be pended here. 启动任务可在这里挂起
     */
      OSTaskSuspend(OS_PRIO_SELF);
    }
}


static void taskLed1(void  *pdata)
{
    (void)pdata;
    INT8U err;
    pdata = pdata;
    for(;;)
    {
       OSSemPend(LEDCON,0,&err);                // uC/OS-II检查信号量LEDCON的状态
       LED_Toggle(LED1);                        // 反转LED1
       OSTimeDlyHMSM(0,0,0,500);                // 延时500ms
       LED_Toggle(LED1);
       OSTimeDlyHMSM(0,0,0,500);
       OSSemPost(LEDCON);                        // 释放信号量,同时一直在等待该信号量的taskLed2从挂起处开始执行
    }
}

static void taskLed2(void  *pdata)
{
    (void)pdata;
    pdata = pdata;
    INT8U err;
    for(;;)
    {
       OSSemPend(LEDCON,0,&err);                // uC/OS-II检查信号量LEDCON的状态
       LED_Toggle(LED2);                        //  反转LED1
       OSTimeDlyHMSM(0,0,0,500);                // 延时500ms
       LED_Toggle(LED2);
       OSTimeDlyHMSM(0,0,0,500);
       OSSemPost(LEDCON);                        // 释放信号量
    }
}


static void taskLed3(void  *pdata)
{
    (void)pdata;
    pdata = pdata;
    INT8U err;
    for(;;)
    {
       OSSemPend(LEDCON,0,&err);                // uC/OS-II检查信号量LEDCON的状态
       LED_Toggle(LED3);                        //  反转LED1
       OSTimeDlyHMSM(0,0,0,500);                // 延时500ms
       OSSemPost(LEDCON);                        // 释放信号量
    }
}


static void taskLed4(void  *pdata)
{
    (void)pdata;
    pdata = pdata;
    INT8U err;
    for(;;)
    {
       OSSemPend(LEDCON,0,&err);                // uC/OS-II检查信号量LEDCON的状态
       LED_Toggle(LED4);                        // 反转LED1
       OSTimeDlyHMSM(0,0,0,500);                // 延时500ms
       OSSemPost(LEDCON);                        // 释放信号量
    }
}


/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

阿莫论坛20周年了!感谢大家的支持与爱护!!

如果想吃一顿饺子,就得从冰箱里取出肉,剁馅儿,倒面粉、揉面、醒面,擀成皮儿,下锅……
一整个繁琐流程,就是为了出锅时那一嘴滚烫流油的热饺子。

如果这个过程,禁不住饿,零食下肚了,饺子出锅时也就不香了……《非诚勿扰3》

出0入0汤圆

发表于 2011-1-10 16:48:33 | 显示全部楼层
查os_cig.h 下的这两个设置
#define OS_MAX_TASKS             64    /* Max. number of tasks in your application, MUST be >= 2       */
#define OS_LOWEST_PRIO           64    /* Defines the lowest priority that can be assigned ...         */

出0入0汤圆

发表于 2011-1-10 16:56:36 | 显示全部楼层
这个和你的延时有关系的,任务1执行后就任务2,任务2执行后就任务1,任务2执行那个完毕后,发送信号量,当然是优先级高的执行,此时任务1 已经在等待了

出0入0汤圆

 楼主| 发表于 2011-1-10 17:04:04 | 显示全部楼层
我会依据你们的回答去查查看,谢了!

出0入0汤圆

 楼主| 发表于 2011-1-10 17:13:16 | 显示全部楼层
#define OS_MAX_TASKS          8
#define OS_LOWEST_PRIO        8
这两个我都设位8的,要是真的是与延时有关,那该怎么处理呢?本人刚接触嵌入式不久,望多多指教。

出0入0汤圆

发表于 2011-1-10 17:20:14 | 显示全部楼层
两个任务都要访问全局变量,如何实现资源同步?

  多任务运行后,任务A和任务B都请求对方发送信号量,如何解决:
       任务A等待任务B发送信号量,但是任务B又在等待任务A发送信号量,如何解决谁也不会给对方发送信号量?


  (1)、任务1  
            void  TaskA (void *pdata)      
           {   
              等待信号量;   
              程序实体;   
              发送信号量;   
            }   


     (2)、任务2  
            void  TaskB (void *pdata)      
           {   
              等待信号量;   
              程序实体;   
              发送信号量;   
            }   


   
   标准答案:

       在创建信号时,初始值必须为“1”。


(原文件名:未命名.JPG)

出0入0汤圆

发表于 2011-1-10 17:21:54 | 显示全部楼层
uC/OS-ii中:周期性执行任务的代码如下:

    void  MyTask (void *pdata)          //周期性执行的任务函数   
          {   
               进行准备工作的代码;   
               for (;;)      //无限循环,也可用 while (1)   
               {   
                  任务实体代码;   
                  OSTimeDly( )
               }   
           }  

   有四个周期性执行的任务,任务A(优先级=0)、任务B(优先级=1)、任务C(优先级=2)、任务D(优先级=3)

   如果每个任务的延时节拍时间OSTimeDly( )设置的不合理,可能会导致永远也执行不到“任务D”

   有没有设置“延时节拍时间OSTimeDly( )”的一般方法呢?
---------------------------------------------------------------------------------------------------------------------

只要确保在A进行延时的时间内,B能够执行所要执行的任务代码,并进入延时,这就能够保证C任务可以分配到时间。
一般情况下,在保证应用可靠的情况下,任务都尽可能少的占用处理器,能延时就尽量迟时,能延时多久,就延时多久,这样可以保证系统低优先级任务的运行顺畅。

出0入0汤圆

发表于 2011-1-10 17:24:57 | 显示全部楼层

(原文件名:11.JPG)



   如上:两个任务通过信号量实现资源同步

     第一个任务的  OSTimeDly( )  为  OSTimeDly(1000)  
     第二个任务的  OSTimeDly( )  为  OSTimeDly(2000)

出0入0汤圆

发表于 2011-1-10 17:31:16 | 显示全部楼层
楼主,可不可以把你看的资料(***程序设计基础)共享一下啊,谢谢啦

出0入0汤圆

发表于 2011-1-11 08:57:03 | 显示全部楼层
回复【8楼】Jigsaw
楼主,可不可以把你看的资料(***程序设计基础)共享一下啊,谢谢啦
-----------------------------------------------------------------------

到嵌入式论坛中寻找,我提供的有下载链接。

出0入0汤圆

发表于 2011-1-11 11:31:20 | 显示全部楼层
假设个例子,让任务1延时5秒,任务2延时4秒,任务3延时3秒,任务4延时2秒,那么在任务2完成后,任务1仍然处于挂起的时刻,那么任务3就可以执行了,

出0入0汤圆

发表于 2011-1-11 12:13:09 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2011-1-11 16:26:25 | 显示全部楼层
呵呵~~谢了!看来我得多看看书,接触不久相关的书还没得看呢。只是拿代码来调试。

出0入0汤圆

 楼主| 发表于 2011-1-19 18:02:48 | 显示全部楼层
现在我对OSTimeDlyHMSM这个延时函数还是不怎么懂,程序里建立了四个任务,每个任务的优先级都不同,按理说当程序里调用OSTimeDlyHMSM这个延时函数时,延时函数会去调用任务切换函数,这样会使优先级高的函数运行,可为什么四个函数还可以同时运行呢?

出0入0汤圆

发表于 2011-1-19 20:35:23 | 显示全部楼层
四个函数?是四个任务吧。
四个任务实际上并不是同时进行的,是分时运行的,每个任务轮流的占用CPU。


回复【2楼】dogbush  
这个和你的延时有关系的,任务1执行后就任务2,任务2执行后就任务1,任务2执行那个完毕后,发送信号量,当然是优先级高的执行,此时任务1 已经在等待了
-----------------------------------------------------------------------

2楼说得有一定的道理,但不完全对。

由于楼主的代码里没有提到各个任务的具体优先级,所以这里就假设四个任务优先级分别从任务1到任务4是从高到低的。
首先任务1运行到OSSemPend(LEDCON,0,&err); 时由于信号量的计数值初始化为为1,所以继续执行,不进行任务的调度。当执行到第1个OSTimeDlyHMSM(0,0,0,500); 时,OS开始进行任务的调度。
此时任务2处于最高的优先级,因此任务2得到运行的机会,执行到OSSemPend(LEDCON,0,&err); 时,由于此时任务1还没有释放信号量,所以任务2继续等待信号量,再次进行任务调度。
任务3 得到运行的机会,同任务2一样,到OSSemPend(LEDCON,0,&err);时,由于任务1还没有释放信号量,所以任务3也继续等待。
任务4得到运行机会,同上,由于任务1 还没有释放,所以也得继续等待。

直到任务1的OSTimeDlyHMSM(0,0,0,500);延时期满,任务1继续执行。到第2个OSTimeDlyHMSM(0,0,0,500);时,再次进行任务的调度,但由于此时信号量还没有释放,所以过程和第1个OSTimeDlyHMSM(0,0,0,500);基本一样,直到延时期满。任务1执行OSSemPost(LEDCON),释放信号量,并开始任务的调度。

此时任务2处于最高优先级,并且处于等等信号量中,由于任务1已经释放了信号量,所以任务2继续执行,而且不进行任务调度,直到第1个OSTimeDlyHMSM(0,0,0,500);,此时开始任务的调度。
任务1此时处于最高的优先级中 ,所以第1个运行的任务是任务1,直到执行OSSemPend(LEDCON,0,&err); 时,由于任务2还没有释放信号量,所以任务1等待,并开始任务调度。
任务3得到机会,但任务2还没有释放,所以任务3继续等待,并开始任务调度。
任务4得到机会,同3一样,继续等待,并开始任务调度。

直到任务2的第1个OSTimeDlyHMSM(0,0,0,500)延时期满,任务2继续执行。直到第2个OSTimeDlyHMSM(0,0,0,500),并开始任务调度,但由于任务2没有释放信号量,而且所以其他任务都处于等待信号量中,所以直到延时期满,任务2继续执行。直到释放信号量。

任务2释放信号量时,开始任务调试。注意此时任务1是处于等待信号量中的,而且是最高优先级,所以任务1得到运行机会,而不是任务3和任务4。接下来的过程就是以上所述的循环,任务3和任务4永远得不到运行的机会,所以看起来建立了四个任务,实际上只有两个在运行。

出0入0汤圆

发表于 2011-1-20 08:59:50 | 显示全部楼层
问题就在你信号量的发送,你第一个任务执行完时才释放信号量,第二第三第四个任务都就绪了,但由于第二个任务优先级高自然接下来先执行第二个任务,可是由于第一个任务执行完才释放信号量那马上就又回到就绪状态,而你第二个任务也是执行完以后才释放信号量,由于第一个任务优先级最高,那第二个任务结束就会执行第一个任务,第二个任务执行完释放信号量又马上就绪,这样不断重复,那第三第四个任务就永远无法执行。所以你要想让这四个任务都执行就要处理好信号量在什么时候释放,不要等到任务最后才释放,这样就会出现只有两个任务可以执行了。

出0入0汤圆

 楼主| 发表于 2011-1-20 09:34:44 | 显示全部楼层
感谢楼上的分析!

出0入0汤圆

发表于 2011-3-8 13:08:47 | 显示全部楼层
OSSemPend(LEDCON,0,&err); // uC/OS-II检查信号量LEDCON的状态
       LED_Toggle(LED1);                        // 反转LED1
       OSTimeDlyHMSM(0,0,0,500);                // 延时500ms
       LED_Toggle(LED1);
       OSTimeDlyHMSM(0,0,0,500);
       OSSemPost(LEDCON); // 释放信号量,同时一直在等待该信号量的taskLed2从挂起处开始执行


这种写法不太好吧,
一般情况下信号量应该是执行的时候Pend,然后执行完逻辑后就Post,然后释放cpu控制权。
    OSSemPend(LEDCON,0,&err); // uC/OS-II检查信号量LEDCON的状态
    //功能相关。。。。。。
       OSSemPost(LEDCON); // 释放信号量,同时一直在等待该信号量的taskLed2从挂起处开始执行
      OSTimeDlyHMSM(0,0,0,500);

出0入0汤圆

发表于 2011-8-19 10:13:37 | 显示全部楼层
问题就在你信号量的发送,你第一个任务执行完时才释放信号量,第二第三第四个任务都就绪了,但由于第二个任务优先级高自然接下来先执行第二个任务,可是由于第一个任务执行完才释放信号量那马上就又回到就绪状态,而你第二个任务也是执行完以后才释放信号量,由于第一个任务优先级最高,那第二个任务结束就会执行第一个任务,第二个任务执行完释放信号量又马上就绪,这样不断重复,那第三第四个任务就永远无法执行。
要想是第三和第四个任务能够执行,可以建立四个信号量,传递顺序为1-2-3-4-1;
具体为:
int main (void)
{
    OSInit();                                          //  Initialize the kernel of uC/OS-II  
                                                       // LEDCON:结构体成员变量,返回为结构体数据
    //LEDCON = OSSemCreate(1);                           // 建立信号量LEDCON,
    //添加部分:   
        task1_Sem = OSSemCreate(1);
        task2_Sem = OSSemCreate(0);
        task3_Sem = OSSemCreate(0);
        task4_Sem = OSSemCreate(0);
然后在
static void taskLed1(void  *pdata)
{
   ……
   {
      ……
      //OSSemPost(LEDCON); // 释放信号量,同时一直在等待该信号量的taskLed2从挂起处开始执行
    OSSemPost(task2_Sem);  // 释放信号量,同时一直在等待该信号量的taskLed2从挂起处开始执行
   }
}
static void taskLed2(void  *pdata)
{
   ……
   {
      ……
      //OSSemPost(LEDCON); // 释放信号量
    OSSemPost(task3_Sem);  // 释放信号量,同时一直在等待该信号量的taskLed3从挂起处开始执行
   }
}
static void taskLed3(void  *pdata)
{
   ……
   {
      ……
      //OSSemPost(LEDCON); // 释放信号量
    OSSemPost(task4_Sem);  // 释放信号量,同时一直在等待该信号量的taskLed4从挂起处开始执行
   }
}
static void taskLed4(void  *pdata)
{
   ……
   {
      ……
      //OSSemPost(LEDCON); // 释放信号量,同时一直在等待该信号量的taskLed2从挂起处开始执行
    OSSemPost(task1_Sem);  // 释放信号量,同时一直在等待该信号量的taskLed2从挂起处开始执行
   }
}

出0入0汤圆

发表于 2011-8-19 16:10:34 | 显示全部楼层
ls的讨论精彩,学习了。

出0入0汤圆

发表于 2011-9-24 11:36:12 | 显示全部楼层
呵呵 先记下 回头看!!!!

出0入0汤圆

发表于 2011-9-24 13:00:02 | 显示全部楼层
请问楼主是在哪种单片机上移植uCOS的?

出0入0汤圆

发表于 2011-9-24 16:16:24 | 显示全部楼层
mark!

出0入0汤圆

发表于 2014-6-5 08:14:07 | 显示全部楼层
kevinzcp 发表于 2011-1-10 16:48
查os_cig.h 下的这两个设置
#define OS_MAX_TASKS             64    /* Max. number of tasks in your app ...

谢谢。我碰到的情况就是如此。自定义的优先级太低了,小于OS_LOWEST_PRIO,导致不能运行。

出10入0汤圆

发表于 2014-10-13 16:33:41 | 显示全部楼层
学习了,我对ucos不熟悉也遇到这个情况,解决方法:1:在while中加系统延时。2:在while中加等待信号事件。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-28 18:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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