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

时间:2023-01-27 14:44:25

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)

事件块实质是一个链表

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

 

不同的任务如果使用共享资源,可能会出错。信号量类似于共享资源访问的一个标志。
比如……我们把串口终端当做一个资源。
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”

 

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

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

 

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

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);


}

}

 

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

 

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

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

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

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

 

 

 

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

 

 

 

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

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

比如……

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

由于任务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互斥信号量支持六种操作:创建、删除、等待、释放、无条件等待获取互斥信号量、获取互斥信号量当前状态。