uC/OS-II信号(OS_sem)块
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* SEMAPHORE MANAGEMENT
*
* (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
* All Rights Reserved
*
* File : OS_SEM.C
* By : Jean J. Labrosse
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include "includes.h"
#endif
#if OS_SEM_EN > 0
/*
*********************************************************************************************************
* 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
*********************************************************************************************************
*/
//无等待请求信号量--这函数function:当一个任务请求信号量时,如果希望在信
//量无效时准许任务不进入等待状态而继续运行,则不调用函数OSSPend 而是调用本函数OSSemAccept
#if OS_SEM_ACCEPT_EN > 0
INT16U OSSemAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
INT16U cnt;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
return (0);
}
#endif
OS_ENTER_CRITICAL();
cnt = pevent->OSEventCnt;
//See if resource is available
if (cnt > 0) { /* See if resource is available */
pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
}
OS_EXIT_CRITICAL();
return (cnt); /* Return semaphore count */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 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 clock (OS_EVENT) associated with the
* created semaphore
* == (void *)0 if no event control blocks were available
*********************************************************************************************************
*/
//This function creates a semaphore.
OS_EVENT *OSSemCreate (INT16U cnt)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
if (OSIntNesting > 0) { /* See if called from ISR ... */
return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
}
OS_ENTER_CRITICAL();
/* Get next free event control block */
pevent = OSEventFreeList; /* Get next free event control block */
if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) { /* Get an event control block */
pevent->OSEventType = OS_EVENT_TYPE_SEM; //OS_EVENT_TYPE_SEM信号量类型
pevent->OSEventCnt = cnt; /* Set semaphore value */
pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */
//初始化一个信号量 Initialize to 'nobody waiting' on sem.
OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */
}
return (pevent);
}
/*$PAGE*/
/*
*********************************************************************************************************
* 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.
*
* err is a pointer to an error code that can contain one of the following values:
* OS_NO_ERR 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.
*********************************************************************************************************
*/
//This function deletes a semaphore and readies all tasks pending on the semaphore opt指明信号量的删除条件
#if OS_SEM_DEL_EN > 0
OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN tasks_waiting;
//各种判断
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
return (pevent);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return (pevent);
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return (pevent);
}
#endif
OS_ENTER_CRITICAL();
//See if any tasks waiting on semaphore
if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on semaphore */
tasks_waiting = TRUE; /* Yes */
} else {
tasks_waiting = FALSE; /* No */
}
switch (opt) {
// Delete semaphore only if no task waiting
case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
if (tasks_waiting == FALSE) {
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;//0
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
// Semaphore has been deleted
return ((OS_EVENT *)0); /* Semaphore has been deleted */
} else {
OS_EXIT_CRITICAL();
*err = OS_EpeventRR_TASK_WAITING;
return ();
}
//Always delete the semaphore 无论如何都删除
case OS_DEL_ALWAYS: /* Always delete the semaphore */
while (pevent->OSEventGrp != 0x00) { /* Ready ALL tasks waiting for semaphore */
//若事件就绪不为0 说明有任务等待 --让任务就绪
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM);
}
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
if (tasks_waiting == TRUE) { /* Reschedule only if task(s) were waiting */
//若任务是在等待的话
OS_Sched(); /* Find highest priority task ready to run */
}
*err = OS_NO_ERR;
return ((OS_EVENT *)0); /* Semaphore has been deleted */
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pevent);
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 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).
*
* err is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_NO_ERR The call was successful and your task owns the resource
* or, the event you are waiting for occurred.
* OS_TIMEOUT The semaphore was not received within the specified
* timeout.
* 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.
*
* Returns : none
*********************************************************************************************************
*/
//This function waits for a semaphore. timeout--表示等待时延0也就是说防止
//得不到信号量而处于长期的等待状态,函数容许用时间延迟来设置一个时间限制---pevent表示被请求信号量的指针
void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
//各种判断
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return;
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return;
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return;
}
#endif
OS_ENTER_CRITICAL();
//成立 表示资源可用
if (pevent->OSEventCnt > 0) { /* If sem. is positive, resource available ... */
//信号量计数器减一
pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return;
}
//否则
/* Otherwise, must wait until event occurs */
OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */
OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready */
OS_ENTER_CRITICAL();
if (OSTCBCur->OSTCBStat & OS_STAT_SEM) { /* Must have timed out if still waiting for event*/
// to make a task ready to run because a timeout occurred.
OS_EventTO(pevent);
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* Indicate that didn't get event within TO */
return;
}
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
/*$PAGE*/
/*
*********************************************************************************************************
* 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_NO_ERR The call was successful and the semaphore was signaled.
* OS_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)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
//See if any task waiting for semaphore
if (pevent->OSEventGrp != 0x00) { /* See if any task waiting for semaphore */
//Ready highest prio task waiting on event
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); /* Ready highest prio task waiting on event */
OS_EXIT_CRITICAL();
//任务调度
OS_Sched(); /* Find highest priority task ready to run */
return (OS_NO_ERR);
}
//Make sure semaphore will not overflow
if (pevent->OSEventCnt < 65535) { /* Make sure semaphore will not overflow */
//信号计数器加1
pevent->OSEventCnt++; /* Increment semaphore count to register event */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */
return (OS_SEM_OVF);
}
/*$PAGE*/
/*
*********************************************************************************************************
* 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
*
* pdata is a pointer to a structure that will contain information about the
* semaphore.
*
* Returns : OS_NO_ERR 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.
*********************************************************************************************************
*/
//This function obtains/获取 information about a semaphore pdata存储信号量状态的结构OS_SEM_DATA---结构体指针
#if OS_SEM_QUERY_EN > 0
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
INT8U *psrc;
INT8U *pdest;
//判断
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &pdata->OSEventTbl[0];
#if OS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 7
*pdest = *psrc;
#endif
pdata->OSCnt = pevent->OSEventCnt; /* Get semaphore count */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif /* OS_SEM_QUERY_EN */
#endif /* OS_SEM_EN */
uC/OS-II信号(OS_sem)块的更多相关文章
- uC/OS II原理分析及源码阅读(一)
uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...
- 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II
SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...
- 【原创】uC/OS II 任务切换原理
今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引 ...
- uC/OS-II互斥信号(OS_mutex)块
/*************************************************************************************************** ...
- uC/OS II 函数说明 之–OSTaskCreate()与OSTaskCreateExt()
1. OSTaskCreate() OSTaskCreate()建立一个新任务,能够在多任务环境启动之前,或者执行任务中建立任务.注意,ISR中禁止建立任务,一个任务必须为无限循环结构. ...
- uc/os iii移植到STM32F4---IAR开发环境
也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...
- uc/os 任务删除
问题描述: uc/os 任务删除 问题解决: uc/os任务删除流程图 具体代码 注: 如上是关中断,以及取消优先级对应的就绪标志 关中断代码为: 取消就绪标志,实际上是将就绪表中指定 ...
- uc/os任务创建
问题描述: uc/os中任务创建 问题解决: 创建一个任务,任务从无到有.任务创建函数分两种, 一种是基本的创建函数OSTaskCreate, 另一种是扩展的任务创建函数OSTaskCrea ...
- uC/OS 的任务调度解析 (转)
uC/OS 的任务调度解析 1.任务调度器启动之后(初始化,主要是TCB的初始化),就可以创建任务,开始任务调度了,实际上第一个任务准确的说不是进行任务切换,而是进行启动当前最高优先级任务.uC/OS ...
随机推荐
- android之读取联系人信息
联系人信息被存放在一个contacts2.db的数据库中 主要的两张表 读取联系人 读取联系人需要知道联系人内容提供者的地址,以及对应的操作对象.一般情况下操作对象是的命名方式和表明是一致的. 布局文 ...
- HIbernate的基本包——八个,详细条目
antlr-2.7.6commons-collections-3.1dom4j-1.6.1hibernate3javassist-3.9.0.GAjta-1.1slf4j-api-1.5.8slf4j ...
- Eclipse添加代码注释模板
Eclipse支持我们自定义模板,比如文件的注释,类注释,函数注释等功能.eclipse自身有自带的模板,我们也可以自己定义.一次点击:windows->preference—>java- ...
- Rest API 开发 学习笔记(转)
Rest API 开发 学习笔记 概述 REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表示方式.获得这些表徵致使这些应用程序转变了其状态.随着 ...
- android开发------第一个android程序
好吧,现在我们就一起来写第一个android程序,看它带给了我们什么.sdk的使用和虚拟机的创建我就不说了.项目创建过程先略过,不太重要. 那第一个程序我们能学到什么知识呢?一起看吧.^-^ 在IDE ...
- SharePoint Web Part Error – The Specified Solution Was Not Found
If you develop, release and add a SharePoint 2010 sandboxed solution web part to a page, then change ...
- extJs学习基础5 理解mvvm的一个小案例
今天很是幸运,看到了一位大神的博客,学习了不少的东西.太感谢了.(满满的都是爱啊) 建议去学习这个大神的博客,真心不错. 博客地址:http://blog.csdn.net/column/detail ...
- Ceph常用维护操作
查看ceph 集群状态 1.ssh 登陆任一MON主机 2.执行 sudo ceph health detail 命令 启动.停止.重启.查看MON进程 1.登陆到MON的服务器,执行如下命令 sud ...
- Java创始人
詹姆斯·高斯林(英语:James Gosling,1955年5月19日-),出生于加拿大,软件专家,Java编程语言的共同创始人之一,一般公认他为“Java之父”. 在他12岁的时候,他已能设计电子游 ...
- 状态压缩 HDU 1565
多组数据 给你一个n*n的矩阵 不能相邻的取数 上下左右 求最大的和 #include<stdio.h> #include<algorithm> #include<str ...