(uC/OS-II学习笔记)关于共享资源与信号量

uC/os-ii中任务间相互通信的媒介叫做事件。

关于OS_EVENT数据结构

#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
    typedef struct os_event
    {
        INT8U    OSEventType;                    /* Type of event control block (see OS_EVENT_TYPE_xxxx)    */
        void    *OSEventPtr;                     /* Pointer to message or queue structure                   */
        INT16U   OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)          */
        OS_PRIO  OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
        OS_PRIO  OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */

#if OS_EVENT_NAME_EN > 0u
        INT8U   *OSEventName;
#endif
    } OS_EVENT;
#endif
OSEventType:事件类型(信号量、互斥信号量、邮箱、消息列队)
OSEventCnt:计数器
OSEventPtr:指向一个消息
OSEventGrp与OSEventTbl[OS_EVENT_TBL_SIZE]:等待事件任务(类似于OSRdyTbl[]和OSRdyGrp)

事件块实质是一个链表

不同的任务如果使用共享资源,可能会出错。信号量类似于共享资源访问的一个标志。
比如……我们把串口终端当做一个资源。
TASK_1与TASK_2(TASK1优先级高于TASK_2)

OS_EVENT MyFirstSem;
char * CommonzSoure = "";

void Task_1(void *pdata)
{
    U32 i;
    
#if OS_CRITICAL_METHOD == 3   //关中断的方法为3
    OS_CPU_SR cpu_sr;
#endif
    
    OS_ENTER_CRITICAL();
    OS_CPU_SysTickInit(100000000/OS_TICKS_PER_SEC);
    OS_EXIT_CRITICAL();
    
    OSStatInit();   //统计任务 优先级最低
       
    MyFirstSem = *(OSSemCreate(1));
    
    //PIT0_Init(50000000);
    UART4_Init(115200);
    init_LED();
    
    pdata = pdata;                                

    
    
    while(1)
    {
        CommonzSoure = "TASK1 Using Common source ";
        
        for(i=0;CommonzSoure[i];i++)
            Uart4_SendByte(CommonzSoure[i]);
        
        OSTimeDly(1);       
    }
    
}

void Task_2(void *pdata)
{
    U32 i;
    pdata = pdata;                                

    while(1)
    {
        CommonzSoure = "TASK2 Using Common source ";
        for(i=0;CommonzSoure[i];i++)
            Uart4_SendByte(CommonzSoure[i]);  
       
    }
  
}

任务1发送数据“TASK1 Using Common source”

任务2发送数据“TASK2 Using Common source”

任务切换的时候 数据发送会出错。(比如我们把串口终端当做一个实体的打印机)

如果加入信号量(标记共享资源)

OS_EVENT MyFirstSem;
char * CommonzSoure = "";

void Task_1(void *pdata)
{
    U32 i;
    U8 err;
    
#if OS_CRITICAL_METHOD == 3   //关中断的方法为3
    OS_CPU_SR cpu_sr;
#endif
    
    OS_ENTER_CRITICAL();
    OS_CPU_SysTickInit(100000000/OS_TICKS_PER_SEC);
    OS_EXIT_CRITICAL();
    
    OSStatInit();   //统计任务 优先级最低
       
    MyFirstSem = *(OSSemCreate(1));
    
    //PIT0_Init(50000000);
    UART4_Init(115200);
    init_LED();
    
    pdata = pdata;                                

    
    
    while(1)
    {

        OSSemPend(&MyFirstSem,0,&err);
        CommonzSoure = "TASK1 Using Common source ";
            
        for(i=0;CommonzSoure[i];i++)
            Uart4_SendByte(CommonzSoure[i]);
        OSSemPost(&MyFirstSem);
        
        OSTimeDly(1);       
    }
    
}

void Task_2(void *pdata)
{
    U32 i;
    U8 err;    
    pdata = pdata;                                

    while(1)
    {
        OSSemPend(&MyFirstSem,0,&err);

         
        CommonzSoure = "TASK2 Using Common source ";
        for(i=0;CommonzSoure[i];i++)
            Uart4_SendByte(CommonzSoure[i]); 
        OSSemPost(&MyFirstSem);
        
       
    }
  
}

OSSemAccept()可以无等待请求一个信号量。

该函数只简单返回OSEventCnt的值,并在OSEventCnt值为真的时候做OSEventCnt--;

调用OSSemAccept()函数,……不过目测资源都被TASK_2独占了。→_→

 同样,信号量也可以用于限制某个资源的任务个数。

关于优先级反转与互斥信号量。

信号量的使用可能会导致优先级反转。

比如……

由于任务C(低)得到信号量,任务A等待。任务B的优先级高于任务C,故任务B先运行。直到任务B,C运行完,任务C释放信号量,优先级最高的任务A才得到CPU资源。

防止优先级反转的方法,在任务C得到信号量时把任务C的优先级升高,结束后再恢复。

uC/OS-II,互斥信号量机制可以防止优先级反转。

由于uC/OS-II不支持相同优先级,互斥信号量机制,可以使某个人物得到信号量时,优先级提到共享相同资源任务最高。

OSMutexCreate(INT8U prio,INT8U *error)

创建互斥信号量。

uC/OS-II互斥信号量支持六种操作:创建、删除、等待、释放、无条件等待获取互斥信号量、获取互斥信号量当前状态。

原文地址:https://www.cnblogs.com/hebaichuanyeah/p/3244962.html