搜索
bottom↓
回复: 15

请教UCOS中信号量的使用

[复制链接]

出0入0汤圆

发表于 2014-6-11 00:53:47 | 显示全部楼层 |阅读模式
最近在学习UCOS,在论坛上找一个例程,移植平台是AVRStudio+WINAVR.使用ATMEGA128的开发板来测试。
系统中建立三个任务,分别为TASK0,TASK1,TASK3.
其中TASK0,TASK1,用信号量来控制PB口的LED灯闪烁,TASK3整个任务用延时实现PC口LED灯闪烁。
程序如下:
#include <includes.h>



/* 在AVR Studio上仿真时值要设置的小些,如20 */
#define        LED_DELAY_MS        200                                                                        /* LED 延时, 用于任务 */
#define        LED_ON()        { DDRB = 0xff; PORTB = 0x00; }
#define        LED_OFF()        ( PORTB = 0xff )

#define        LED_ON2()        { DDRC = 0xff; PORTC = 0x00; }
#define        LED_OFF2()        ( PORTC = 0xff )


// Variablen
OS_STK        Task1Stack[OS_TASK_1_STK_SIZE];                // startup task stack
OS_STK        Task2Stack[OS_TASK_2_STK_SIZE];
OS_STK        Task3Stack[OS_TASK_3_STK_SIZE];

OS_EVENT * sem;



void task0( void * pdata )
{
        INT8U error;
       
        TimerInit();       
        while(1)
        {
                OSSemPend( sem, 0, &error );
                LED_ON();                                                                                                /* 点亮LED */
                OSTimeDlyHMSM(0,0,0,LED_DELAY_MS );
                OSSemPost( sem );
        }
       
}

void task1(void * pdata )
{
        INT8U error;
       
        while(1)
        {
                OSSemPend(sem, 0, &error);
                LED_OFF();                                                                                                /* 熄灭LED */
                OSTimeDlyHMSM(0,0,0,LED_DELAY_MS );
                OSSemPost(sem);
        }
       
}

void task3(void * pdata)
{
        for(;;)
        {
                LED_ON2();
                OSTimeDlyHMSM(0,0,0,2*LED_DELAY_MS );
                LED_OFF2();
                OSTimeDlyHMSM(0,0,0,2*LED_DELAY_MS );
        }       
}

int        main()
{
        OSInit();
    sem = OSSemCreate( 1 );
        OSTaskCreate( task0, (void *)OS_TASK_1_STK_SIZE, &Task1Stack[OS_TASK_1_STK_SIZE-1], OS_TASK_1_PRIO );
        OSTaskCreate( task1, (void *)OS_TASK_2_STK_SIZE, &Task2Stack[OS_TASK_2_STK_SIZE-1], OS_TASK_2_PRIO );
        OSTaskCreate( task3, (void *)OS_TASK_3_STK_SIZE, &Task3Stack[OS_TASK_3_STK_SIZE-1], OS_TASK_3_PRIO );
        OSStart();
        return        0;
}


下载到板子上测试,PB口LED灯只会全亮不会闪烁,PC口LED灯闪烁。我想要的效果应该PB口LED灯会闪烁,为什么不会呢?
其中的信号建立与使用我也参考网上许多人的程序,并不觉得有错。请各位大神们解解我这个小白的疑惑。

出0入0汤圆

发表于 2014-6-11 08:37:14 | 显示全部楼层
本帖最后由 M.dd 于 2014-6-11 08:41 编辑

TASK0优先级高一点吧,应该在post后边(加一个)调用OSTimeDlyHMSM延时,否则就自己发发,自己收收,

出20入12汤圆

发表于 2014-6-11 12:28:50 | 显示全部楼层
需先发一个信号来激发task0,task1,然后这两个任务才会跑起来

出0入0汤圆

 楼主| 发表于 2014-6-11 14:40:00 | 显示全部楼层
M.dd 发表于 2014-6-11 08:37
TASK0优先级高一点吧,应该在post后边(加一个)调用OSTimeDlyHMSM延时,否则就自己发发,自己收收, ...

自己收发就不用信号量了。是不是信号使用前一定有任务先post??

出0入0汤圆

 楼主| 发表于 2014-6-11 14:46:04 | 显示全部楼层
gaolf_2012 发表于 2014-6-11 12:28
需先发一个信号来激发task0,task1,然后这两个任务才会跑起来

信号量在建立的时候已经为1,按道理来说当我调用等待信号函数OSSemPend时他会检测是该信号量是不是有在用,
没有在使用就可以执行后面的语句,再释放信号量。我不知道我理解对不对。像你这样说在使用前必须有任务发送信号才可以 使用?

出0入0汤圆

发表于 2014-6-11 19:08:06 来自手机 | 显示全部楼层
看到了,初始为1,2楼应该是真相

出0入0汤圆

发表于 2014-6-11 19:47:15 | 显示全部楼层
你在信号量初始化为1的话,就是所谓的二值信号量,跟互斥信号量的区别就是不支持优先级翻转.

你的Task0一直占用着信号量,Task1得不到信号量,所以Task1一直就无法执行。

出0入0汤圆

 楼主| 发表于 2014-6-11 22:49:30 | 显示全部楼层
Eric2013 发表于 2014-6-11 19:47
你在信号量初始化为1的话,就是所谓的二值信号量,跟互斥信号量的区别就是不支持优先级翻转.

你的Task0一 ...

应该怎么改程序才能运行呢?

出0入0汤圆

发表于 2014-6-12 08:49:10 | 显示全部楼层
mii 发表于 2014-6-11 22:49
应该怎么改程序才能运行呢?

用二值值信号量做这种测试不合适,要让task0释放信号量资源可以在post函数后面加个延时函数就可。

出0入0汤圆

 楼主| 发表于 2014-6-13 08:46:33 | 显示全部楼层
Eric2013 发表于 2014-6-12 08:49
用二值值信号量做这种测试不合适,要让task0释放信号量资源可以在post函数后面加个延时函数就可。 ...

增加了还是不行。我现在就纠结了啊

出0入0汤圆

发表于 2014-6-13 11:39:25 | 显示全部楼层
mii 发表于 2014-6-13 08:46
增加了还是不行。我现在就纠结了啊

今天专门花了些时间专门测试了,你的函数不用修改可以正常运行(在我的F407板子上面测试了,也是LED闪烁),前面我没有认真的分析,
今天看了一Pend和Post的函数。为什么能运行,简单的分析如下:

1.  首先上电后首先指向task0的:
      OSSemPend( sem, 0, &error );
      LED_ON();                                                                                            
      OSTimeDlyHMSM(0,0,0,LED_DELAY_MS );   ---------------------> 执行到这里的时候切换到task1中执行
      OSSemPost( sem );         

2.  task1执行:
     OSSemPend(sem, 0, &error);   //由于信号量被task0占用,任务task1被挂起
     LED_OFF();                                                                                       
     OSTimeDlyHMSM(0,0,0,LED_DELAY_MS );
     OSSemPost(sem);      

3.  等task0延迟时间到以后,继续执行post函数 :
    OSSemPost( sem );     这个函数很重要,这个函数会在源码的这个地方退出,特别注意退出的时候pevent->OSEventCnt计数没有执行加一,也就是
    信号量资源仍然是不可以用。
   
    /* 在下面的这个if语句中会把task1从挂起链表中删除,并重新加入到就绪链表 */
    if (pevent->OSEventGrp != 0u) {                                                
        (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
        OS_EXIT_CRITICAL();
        OS_Sched();                                       
        return (OS_ERR_NONE);
    }
    /* 函数没有执行到这里,也就是pevent->OSEventCnt没有执行加1 */
    if (pevent->OSEventCnt < 65535u) {         
        pevent->OSEventCnt++;                       
        OS_EXIT_CRITICAL();
        return (OS_ERR_NONE);
    }
4.  在task0中执行完post函数后,继续执行 OSSemPend( sem, 0, &error );
     切换到task1中就靠这个函数了,切换位置如下:
     
     /* 第3步说了,pevent->OSEventCnt已经是0了,不可以用,继续执行下面 */
     if (pevent->OSEventCnt > 0u) {                 
        pevent->OSEventCnt--;                       
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return;
     }
     
    /* 继续执行下面程序 */                                            
    OSTCBCur->OSTCBStat     |= OS_STAT_SEM;      
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
    OSTCBCur->OSTCBDly       = timeout;           
    OS_EventTaskWait(pevent);                     
    OS_EXIT_CRITICAL();
    OS_Sched();                                 
    OS_ENTER_CRITICAL();
    执行到这里时候就开始切换到task1中去执行了。


你的程序不能运行,估计是你那里的参数配置有问题,或者移植有问题。      
   
                                                                                

出0入0汤圆

发表于 2014-6-30 16:36:38 | 显示全部楼层
本帖最后由 woaidamimi 于 2014-6-30 17:02 编辑

顶11楼,正解

出0入0汤圆

发表于 2015-2-8 19:22:35 | 显示全部楼层
mii 发表于 2014-6-11 14:40
自己收发就不用信号量了。是不是信号使用前一定有任务先post??

信号量创建时,可以赋值为1,使其可用。应该不是移植的问题,可以先确定led_on和led_off等函数是不是有问题。

出0入0汤圆

发表于 2015-2-8 19:24:53 | 显示全部楼层
Eric2013 发表于 2014-6-13 11:39
今天专门花了些时间专门测试了,你的函数不用修改可以正常运行(在我的F407板子上面测试了,也是LED闪烁 ...

第三条不应该是不能用,而是这个资源已经分给了pending的task1,这是task1已经ready了。

出0入0汤圆

发表于 2015-2-8 19:25:32 | 显示全部楼层
Eric2013 发表于 2014-6-13 11:39
今天专门花了些时间专门测试了,你的函数不用修改可以正常运行(在我的F407板子上面测试了,也是LED闪烁 ...

第三条不应该是不能用,而是这个资源已经分给了pending的task1。这是task1已经ready了。

出0入0汤圆

发表于 2015-3-11 01:37:08 | 显示全部楼层
mii 发表于 2014-6-11 14:46
信号量在建立的时候已经为1,按道理来说当我调用等待信号函数OSSemPend时他会检测是该信号量是不是有在用 ...

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

本版积分规则

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

GMT+8, 2024-5-10 01:38

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

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