lisemi 发表于 2011-1-10 16:19:56

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

如题,用开发板调式看到只有两个任务执行,大家帮忙看看程序有什么问题。

#include <includes.h>

static OS_STKGstkStart;                        /*The stack of start task   */
                                                                        /*启动任务的堆栈            */
static OS_STKGstkLED1;
static OS_STKGstkLED2;
static OS_STKGstkLED3;
static OS_STKGstkLED4;

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_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_LED1_PRIO);/*建立LED的处理任务*/
    OSTaskCreate(taskLed2, (void *)0, &GstkLED2, TASK_LED2_PRIO);
    OSTaskCreate(taskLed3, (void *)0, &GstkLED3, TASK_LED3_PRIO);
    OSTaskCreate(taskLed4, (void *)0, &GstkLED4, 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
*********************************************************************************************************/

kevinzcp 发表于 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 ...         */

dogbush 发表于 2011-1-10 16:56:36

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

lisemi 发表于 2011-1-10 17:04:04

我会依据你们的回答去查查看,谢了!

lisemi 发表于 2011-1-10 17:13:16

#define OS_MAX_TASKS          8
#define OS_LOWEST_PRIO      8
这两个我都设位8的,要是真的是与延时有关,那该怎么处理呢?本人刚接触嵌入式不久,望多多指教。

ba_wang_mao 发表于 2011-1-10 17:20:14

两个任务都要访问全局变量,如何实现资源同步?

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


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


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


   
   标准答案:

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

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_610261RSUJDW.JPG
(原文件名:未命名.JPG)

ba_wang_mao 发表于 2011-1-10 17:21:54

uC/OS-ii中:周期性执行任务的代码如下:

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

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

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

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

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

ba_wang_mao 发表于 2011-1-10 17:24:57

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_610262S9LHH5.JPG
(原文件名:11.JPG)



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

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

Jigsaw 发表于 2011-1-10 17:31:16

楼主,可不可以把你看的资料(***程序设计基础)共享一下啊,谢谢啦

ba_wang_mao 发表于 2011-1-11 08:57:03

回复【8楼】Jigsaw
楼主,可不可以把你看的资料(***程序设计基础)共享一下啊,谢谢啦
-----------------------------------------------------------------------

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

dogbush 发表于 2011-1-11 11:31:20

假设个例子,让任务1延时5秒,任务2延时4秒,任务3延时3秒,任务4延时2秒,那么在任务2完成后,任务1仍然处于挂起的时刻,那么任务3就可以执行了,

qsx201 发表于 2011-1-11 12:13:09

mark

lisemi 发表于 2011-1-11 16:26:25

呵呵~~谢了!看来我得多看看书,接触不久相关的书还没得看呢。只是拿代码来调试。

lisemi 发表于 2011-1-19 18:02:48

现在我对OSTimeDlyHMSM这个延时函数还是不怎么懂,程序里建立了四个任务,每个任务的优先级都不同,按理说当程序里调用OSTimeDlyHMSM这个延时函数时,延时函数会去调用任务切换函数,这样会使优先级高的函数运行,可为什么四个函数还可以同时运行呢?

ididr 发表于 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永远得不到运行的机会,所以看起来建立了四个任务,实际上只有两个在运行。

rockt 发表于 2011-1-20 08:59:50

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

lisemi 发表于 2011-1-20 09:34:44

感谢楼上的分析!

zhangyang86 发表于 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);

chen_dq 发表于 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从挂起处开始执行
   }
}

Adrian 发表于 2011-8-19 16:10:34

ls的讨论精彩,学习了。

l09046162 发表于 2011-9-24 11:36:12

呵呵 先记下 回头看!!!!

jiyibolo 发表于 2011-9-24 13:00:02

请问楼主是在哪种单片机上移植uCOS的?

final9 发表于 2011-9-24 16:16:24

mark!

liuerbin 发表于 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,导致不能运行。

mainbp 发表于 2014-10-13 16:33:41

学习了,我对ucos不熟悉也遇到这个情况,解决方法:1:在while中加系统延时。2:在while中加等待信号事件。
页: [1]
查看完整版本: uCOS-II创建了四个任务可最终只执行了两个任务