ucos-iii 信号量、互斥信号量

目录

一  ucos-iii 信号量相关函数

二  使用信号量

三  互斥量(互斥信号量)常用函数

四  使用互斥信号量访问共享资源

五  任务内置信号量相关函数

六   使用任务内置信号量


一  ucos-iii 信号量相关函数

创建信号量OSSemCreate()OS_CFG_SEM_EN

OS_SEM SwSem;

OS_ERR err;

OSSemCreate(&SwSem, “Switch Semaphore”,
                         0,&err);

删除信号量OSSemDel()  

OS_CFG_SEM_EN

OS_CFG_SEM_DEL_EN

OS_SEM SwSem;

OS_ERR err;
OS_OBJ_QTY qty;

qty = OSSemDel(&SwSem,OS_OPT_DEL_ALWAYS,
           &err);

等待信号量OSSemPend()OS_CFG_SEM_EN

OS_SEM SwSem;

OS_ERR err;
CPU_TS ts;
OS_SEM_CTR ctr;

ctr = OSSemPend(&SwSem,0,
               OS_OPT_PEND_BLOCKING,&ts,&err);

取消等待OSSemPendAbort()

OS_CFG_SEM_EN

OS_CFG_SEM_PEND_ABORT_EN

OS_SEM SwSem;

OS_ERR err;
OS_OBJ_QTY nbr_tasks;

nbr_tasks = OSSemPendAbort(&SwSem,
                OS_OPT_PEND_ABORT_ALL,&err);

释放信号量OSSemPost() OS_CFG_SEM_EN

OS_SEM SwSem;

OS_ERR err;
OS_SEM_CTR ctr;

ctr = OSSemPost(&SwSem,
OS_OPT_POST_1 +OS_OPT_POST_NO_SCHED,
&err);

强制设置信号量的值OSSemSet() 

OS_CFG_SEM_EN

OS_CFG_SEM_SET_EN

OS_SEM SwSem;

OS_ERR err;

OSSemSet(&SwSem,0,&err);

二  使用信号量

使用信号量访问共享资源:

如果一个资源被多个任务访问,则在访问前调用OSSemPend()请求资源,在访问结束后调用OSSemPost ()函数释放资源

OS_SEM MY_SEM;  //定义一个信号量,用于访问共享资源
uint8_t share_res[30]; //共享资源区

//创建一个信号量
OSSemCreate ((OS_SEM*  )&MY_SEM, //指向信号量
                (CPU_CHAR*  )"MY_SEM", //信号量名字
                (OS_SEM_CTR )1, //信号量值为 1
                (OS_ERR* )&err);

void sem0_task(void *p_arg)
{
    OS_ERR err;
    uint8_t task0_str[]="sem0 Running!";
    p_arg = p_arg;
    while(1)
    {
        printf("sem0_task:\r\n");
        OSSemPend(&MY_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); // 请求信号量
        memcpy(share_res,task0_str,sizeof(task0_str));    // 向共享资源区拷贝数据
        OSTimeDly (100, OS_OPT_TIME_DLY, &err );          //相对性延时1000个时钟节拍(1s)
        OSSemPost (&MY_SEM,OS_OPT_POST_1,&err);           // 释放信号量
        OSTimeDly (100, OS_OPT_TIME_DLY, &err );          //相对性延时1000个时钟节拍(1s)
    }
}

void sem1_task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    uint8_t task1_str[]="sem1 Running!";
    while(1)
    {
        printf("sem1_task:\r\n");
        OSSemPend(&MY_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); // 请求信号量
        memcpy(share_res,task1_str,sizeof(task1_str));    // 向共享资源区拷贝数据
        OSTimeDly (100, OS_OPT_TIME_DLY, &err );          //相对性延时1000个时钟节拍(1s)
        OSSemPost (&MY_SEM,OS_OPT_POST_1,&err);           // 释放信号量
        OSTimeDly (100, OS_OPT_TIME_DLY, &err );          //相对性延时1000个时钟节拍(1s)
    }
}

使用信号量访问共享资源会导致优先级翻转,所以一般不推荐使用,下面举例说明:

1. 假设有ABC三个任务,优先级A>B>C,任务AC访问共享资源“res”,任务B不访问共享资源。
2. 现在C正在使用共享资源res,在使用过程中进行了任务调度,由于A的优先级最高,所以接下来执行任务A
3. 由于A需要访问共享资源res,而res正在被C访问,所以任务A进入挂起状态,任务C继续执行。
4. 此时任务C仍在访问共享资源,任务A为挂起态,任务B为就绪态,所以当任务C进行了任务调度后,接下来执行任务B

    在这种情况下,任务 A 的优先级实际上降到了任务 C 的优先级水平,任务 B 的优先级高于任务A。因为任务 A 要一直等待直到任务C释放其占用的那个共享资源。这就是优先级反转。

使用信号量实现任务同步:

任务一通过OSSemPost()发送信号量。
任务二通过OSSemPend()不断请求信号量,如果没有请求到信号量,则进行任务调度,执行下一个任务;如果请求到信号量,则继续运行该任务。

OS_SEM SYNC_SEM;  //定义一个信号量,用于访问共享资源

//创建一个信号量
OSSemCreate ((OS_SEM*  )&MY_SEM, //指向信号量
                (CPU_CHAR*  )"MY_SEM", //信号量名字
                (OS_SEM_CTR )1, //信号量值为 1
                (OS_ERR* )&err);

void sem0_task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    while(1)
    {
        OSSemPost(&SYNC_SEM,OS_OPT_POST_1,&err);//发送信号量
        OSTimeDly (100, OS_OPT_TIME_DLY, &err );//延时
    }
}

void sem1_task(void *p_arg)
{
    OS_ERR err;
    uint16_t num = 0;
    p_arg = p_arg;
    while(1)
    {
        OSSemPend(&SYNC_SEM,0,OS_OPT_PEND_BLOCKING,0,&err);// 请求信号量
        num++;
        printf("请求信号量次数: %d\r\n",num);
        OSTimeDly (1000, OS_OPT_TIME_DLY, &err );          //延时
    }
}

三  互斥量(互斥信号量)常用函数

创建互斥信号量OSMutexCreate() OS_CFG_MUTEX_EN

OS_MUTEX DispMutex;

OS_ERR err;

OSMutexCreate(&DispMutex, 

                          “Display Mutex”,&err);

删除互斥型信号量OSMutexDel()

OS_CFG_MUTEX_EN

OS_CFG_MUTEX_DEL_EN

OS_MUTEX DispMutex;

OS_ERR err;
OS_OBJ_QTY qty;

qty = OSMutexDel(&DispMutex,
                    OS_OPT_DEL_ALWAYS,&err);

等待互斥型信号量OSMutexPend()OS_CFG_MUTEX_EN

OS_MUTEX DispMutex;

OS_ERR err;

CPU_TS ts;

OSMutexPend(&DispMutex,0,
        OS_OPT_PEND_BLOCKING,&ts,&err);

取消等待OSMutexPendAbort()

OS_CFG_MUTEX_EN

OS_CFG_MUTEX_PEND_ABORT_EN

OS_MUTEX DispMutex;

OS_ERR err;
OS_OBJ_QTY qty;

qty = OSMutexPendAbort(&DispMutex,
            OS_OPT_PEND_ABORT_ALL,&err);

释放互斥型信号量OSMutexPost()OS_CFG_MUTEX_EN

OS_MUTEX DispMutex;

OS_ERR err;

OSMutexPost(&DispMutex,
                    OS_OPT_POST_NONE,&err);

四  使用互斥信号量访问共享资源

OS_MUTEX TEST_MUTEX;  //定义一个互斥信号量
uint8_t share_res[30]; //共享资源区

//创建一个互斥信号量
OSMutexCreate((OS_MUTEX* )&TEST_MUTEX,
            (CPU_CHAR* )"TEST_MUTEX",
            (OS_ERR* )&err);

void sem0_task(void *p_arg)
{
    OS_ERR err;
    uint8_t task0_str[]="sem0 Running!";
    p_arg = p_arg;
    while(1)
    {
        OSMutexPend (&TEST_MUTEX,0,OS_OPT_PEND_BLOCKING,0,&err);// 请求互斥信号量
        memcpy(share_res,task0_str,sizeof(task0_str));     
        OSMutexPost(&TEST_MUTEX,OS_OPT_POST_NONE,&err);// 释放互斥信号量
        OSTimeDly (100, OS_OPT_TIME_DLY, &err );//延时
    }
}


void sem1_task(void *p_arg)
{
    OS_ERR err;
    uint16_t num = 0;
    uint8_t task1_str[]="sem1 Running!";
    p_arg = p_arg;
    while(1)
    {
        OSMutexPend (&TEST_MUTEX,0,OS_OPT_PEND_BLOCKING,0,&err);// 请求互斥信号量
        memcpy(share_res,task1_str,sizeof(task1_str));      
        OSMutexPost(&TEST_MUTEX,OS_OPT_POST_NONE,&err);// 释放互斥信号量
        OSTimeDly (100, OS_OPT_TIME_DLY, &err );//延时
    }
}

五  任务内置信号量相关函数

等待任务信号量OSTaskSemPend()   

OS_ERR err;
OS_SEM_CTR ctr;
CPU_TS ts;

ctr = OSTaskSemPend(100,
         OS_OPT_PEND_BLOCKING,
         &ts,&err);

取消等待任务信号量OSTaskSemPendAbort() OS_CFG_TASK_SEM_PEND_ABORT_EN

OS_TCB CommRxTaskTCB;

OS_ERR err;
CPU_BOOLEAN aborted;

aborted = OSTaskSemPendAbort(&CommRxTaskTCB,
OS_OPT_POST_NONE,&err);

发送任务信号量OSTaskSemPost()  

OS_TCB CommRxTaskTCB;

OS_ERR err;

OS_SEM_CTR ctr;

ctr = OSTaskSemPost(&CommRxTaskTCB,
                    OS_OPT_POST_NONE,&err);

强行设置任务信号量计数OSTaskSemSet()  

OS_TCB TaskY;

OS_ERR err;

ctr = OSTaskSemSet(&TaskY,0,&err);

六   使用任务内置信号量

使用任务信号量不需要再定义与创建信号量,一般用作同步功能,如下列所示:

extern OS_TCB SEM1TaskTCB;  
void sem0_task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    while(1)
    {
        OSTaskSemPost(&SEM1TaskTCB, OS_OPT_POST_NONE,&err); // 使用系统内建信号量向任务发送信号量
        OSTimeDly (1000, OS_OPT_TIME_DLY, &err );//延时
    }
}

void sem1_task(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    while(1)
    {
        OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err); // 请求任务内建的信号量
        printf("成功请求到内置信号量\r\n");
        OSSched();  
    }
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值