版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
任务间简单通个信,A告诉B你LED亮一下。这种问题可以用信号量来处理,UCOSii中关于信号量的函数也就八个,今天简单总结下。
- 函数列表
/*
*********************************************************************************************************
* CREATE A SEMAPHORE
*
* Description: This function creates a semaphore.
*
* Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is
* available (or no event has occurred). You initialize the semaphore to a
* non-zero value to specify how many resources are available (e.g. if you have
* 10 resources, you would initialize the semaphore to 10).
*
* Returns : != (void *)0 is a pointer to the event control block (OS_EVENT) associated with the
* created semaphore
* == (void *)0 if no event control blocks were available
*********************************************************************************************************
*/
OS_EVENT *OSSemCreate (INT16U cnt);
/*
*********************************************************************************************************
* POST TO A SEMAPHORE
*
* Description: This function signals a semaphore
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* Returns : OS_ERR_NONE The call was successful and the semaphore was signaled.
* OS_ERR_SEM_OVF If the semaphore count exceeded its limit. In other words, you have
* signalled the semaphore more often than you waited on it with either
* OSSemAccept() or OSSemPend().
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*********************************************************************************************************
*/
INT8U OSSemPost (OS_EVENT *pevent);
/*
*********************************************************************************************************
* PEND ON SEMAPHORE
*
* Description: This function waits for a semaphore.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for the resource up to the amount of time specified by this argument.
* If you specify 0, however, your task will wait forever at the specified
* semaphore or, until the resource becomes available (or the event occurs).
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE The call was successful and your task owns the resource
* or, the event you are waiting for occurred.
* OS_ERR_TIMEOUT The semaphore was not received within the specified
* 'timeout'.
* OS_ERR_PEND_ABORT The wait on the semaphore was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
*
* Returns : none
*********************************************************************************************************
*/
void OSSemPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr);
/*
*********************************************************************************************************
* ABORT WAITING ON A SEMAPHORE
*
* Description: This function aborts & readies any tasks currently waiting on a semaphore. This function
* should be used to fault-abort the wait on the semaphore, rather than to normally signal
* the semaphore via OSSemPost().
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* opt determines the type of ABORT performed:
* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
* semaphore
* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
* semaphore
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE No tasks were waiting on the semaphore.
* OS_ERR_PEND_ABORT At least one task waiting on the semaphore was readied
* and informed of the aborted wait; check return value
* for the number of tasks whose wait on the semaphore
* was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : == 0 if no tasks were waiting on the semaphore, or upon error.
* > 0 if one or more tasks waiting on the semaphore are now readied and informed.
*********************************************************************************************************
*/
INT8U OSSemPendAbort (OS_EVENT *pevent,
INT8U opt,
INT8U *perr);
/*
*********************************************************************************************************
* ACCEPT SEMAPHORE
*
* Description: This function checks the semaphore to see if a resource is available or, if an event
* occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
* resource is not available or the event did not occur.
*
* Arguments : pevent is a pointer to the event control block
*
* Returns : > 0 if the resource is available or the event did not occur the semaphore is
* decremented to obtain the resource.
* == 0 if the resource is not available or the event did not occur or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass a pointer to a semaphore
*********************************************************************************************************
*/
INT16U OSSemAccept (OS_EVENT *pevent);
/*
*********************************************************************************************************
* DELETE A SEMAPHORE
*
* Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* perr is a pointer to an error code that can contain one of the following values:
* OS_ERR_NONE The call was successful and the semaphore was deleted
* OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : pevent upon error
* (OS_EVENT *)0 if the semaphore was successfully deleted.
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the semaphore MUST check the return code of OSSemPend().
* 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
* they check 'pevent' to see that it's a NULL pointer.
* 3) This call can potentially disable interrupts for a long time. The interrupt disable
* time is directly proportional to the number of tasks waiting on the semaphore.
* 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
* applications where the semaphore is used for mutual exclusion because the resource(s)
* will no longer be guarded by the semaphore.
*********************************************************************************************************
*/
OS_EVENT *OSSemDel (OS_EVENT *pevent,
INT8U opt,
INT8U *perr);
/*
*********************************************************************************************************
* QUERY A SEMAPHORE
*
* Description: This function obtains information about a semaphore
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore
*
* p_sem_data is a pointer to a structure that will contain information about the
* semaphore.
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non semaphore.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
* OS_ERR_PDATA_NULL If 'p_sem_data' is a NULL pointer
*********************************************************************************************************
*/
INT8U OSSemQuery (OS_EVENT *pevent,
OS_SEM_DATA *p_sem_data);
/*
*********************************************************************************************************
* SET SEMAPHORE
*
* Description: This function sets the semaphore count to the value specified as an argument. Typically,
* this value would be 0.
*
* You would typically use this function when a semaphore is used as a signaling mechanism
* and, you want to reset the count value.
*
* Arguments : pevent is a pointer to the event control block
*
* cnt is the new value for the semaphore count. You would pass 0 to reset the
* semaphore count.
*
* perr is a pointer to an error code returned by the function as follows:
*
* OS_ERR_NONE The call was successful and the semaphore value was set.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
* OS_ERR_TASK_WAITING If tasks are waiting on the semaphore.
*********************************************************************************************************
*/
void OSSemSet (OS_EVENT *pevent,
INT16U cnt,
INT8U *perr);
使用
1.创建信号量
2.发送信号量
3.等待信号量
这三个几乎应付了绝大部分场景了
OS_EVENT *OSSemCreate (INT16U cnt);
INT8U OSSemPost (OS_EVENT *pevent);
void OSSemPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr);
//结构体指针声明
OS_EVENT *sem;
//信号量初始,10以下自己随意定义
INT8U cnt = 0;
int main()
{
/*
LED_Init();
OSInit();
OSTaskCreate(start_task,(void *)0, (OS_STK *)&START_TASK_STK[START_STK_SIZE-1],\
START_TASK_PRID);
OSStart();
*/
}
void start_task(void* pdata)
{
/*
OS_CPU_SR cpu_sr = 0;
pdata = pdata;
OSStatInit();
OS_ENTER_CRITICAL();
OSTaskCreate(led0_task,(void*)0, (OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],\
LED0_TASK_PRIO);
OSTaskCreate(led1_task,(void*)0, (OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],\
LED1_TASK_PRIO);
OSTaskSuspend(START_TASK_PRID);
*/
sem = OSSemCreate(cnt); //初始化信号量指针
/*
OS_EXIT_CRITICAL();
*/
}
void led0_task(void* pdata)
{
/*
uint8_t num = 0;
while(1)
{
num++;
LED0 = 0;
delay_ms(80);
LED0 = 1;
if((num % 10 == 0))
{
*/
OSSemPost(sem); //发送信号量
/*
printf("发送信号%d 次\r\n", num/10);
}
delay_ms(400);
}
*/
}
void led1_task(void* pdata)
{
INT8U err = 0;
/*
while(1)
{
*/
OSSemPend(sem, 0, &err); //一直等待信号到来,等待超时0
/*
LED1 = 0;
delay_ms(300);
LED1 = 1;
delay_ms(300);
}
*/
}
4.接收信号量
INT16U OSSemAccept (OS_EVENT *pevent);
基本代码不变,这里只改动task1的代码
void led1_task(void* pdata)
{
INT8U ac;
/*
while(1)
{
*/
ac = OSSemAccept(sem);
if(ac == 1){ //接受成功返回1
/*
printf("我已经接收到信号了\r\n");
LED1 = 0;
delay_ms(300);
LED1 = 1;
delay_ms(300);
*/
}
else//接收不成功返回0
{
/*
printf("我还没成功的接收到信号了呢\r\n");
delay_ms(500);
*/
}
/*
}
*/
}
5.删除信号量
OS_EVENT *OSSemDel (OS_EVENT *pevent,
INT8U opt,
INT8U *perr);
void led0_task(void* pdata)
{
uint8_t num = 0, err = 0;
/*
while(1)
{
num++;
LED0 = 0;
delay_ms(80);
LED0 = 1;
if(num == 10)
{
*/
//删除后sem为null
sem = OSSemDel(sem, OS_DEL_ALWAYS,&err);
/*
printf("我已经删除了信号sem\r\n");
}
delay_ms(400);
}
*/
}
void led1_task(void* pdata)
{
INT8U err = 0;
/*
while(1)
{
*/
if(sem != NULL){ //判断信号量指针是否为空,是的话代表已经被删除了
/*
OSSemPend(sem, 0, &err);
LED1 = 0;
delay_ms(300);
LED1 = 1;
delay_ms(300);
*/
}
else{
/*
printf("任务被删除了\r\n");
*/
}
/*}*/
}
6.忽略优先级的等待信号量
INT8U OSSemPendAbort (OS_EVENT *pevent,
INT8U opt,
INT8U *perr);
void led1_task(void* pdata)
{
INT8U err = 0;
/*
while(1)
{
*/
OSSemPendAbort(sem, OS_PEND_OPT_NONE, &err); //忽视优先级的等待函数
/*
LED1 = 0;
delay_ms(300);
LED1 = 1;
delay_ms(300);
}
*/
}
7.信号量信息查询
INT8U OSSemQuery (OS_EVENT *pevent,
OS_SEM_DATA *p_sem_data);
OS_SEM_DATA mdata;
void led1_task(void* pdata)
{
INT8U err = 0;
INT8U ac;
while(1)
{
OSSemPend(sem, 0, &err); //等待有效信号到来才执行后面的
LED1 = 0;
delay_ms(300);
LED1 = 1;
delay_ms(300);
ac = OSSemQuery(sem, &mdata);//mdata不能用指针初始化,没有地方给他分配内存
if(ac == OS_ERR_NONE)
{
/*
printf("成功\r\n");
printf("hi 看看我是多少 %d %d\r\n", ac,mdata.OSCnt);
*/
}
}
}
8.信号量设置
void OSSemSet (OS_EVENT *pevent,
INT16U cnt,
INT8U *perr);
void led1_task(void* pdata)
{
INT8U err = 0;
INT8U ac;
while(1)
{
OSSemPend(sem, 0, &err); //等待有效信号到来才执行后面的
LED1 = 0;
delay_ms(300);
LED1 = 1;
delay_ms(300);
OSSemSet (sem, 5, &err); //重新设置信号量为5
}
}