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 ...
随机推荐
- EditPlus v4.5 简体中文
优秀的代码编辑器! 下载地址: EditPlus v4.00 build 465 简体中文汉化增强版 http://yunpan.cn/cVCSIZsKK7VFF 访问fe58 http://p ...
- golang: 把sql结果集以json格式输出
func getJSON(sqlString string) (string, error) { stmt, err := db.Prepare(sqlString) if err != nil { ...
- 1017关于EXPLAIN的语法
转自博客 http://blog.csdn.net/zhuxineli/article/details/14455029 explain显示了MySQL如何使用索引来处理select语句以及连接表.可 ...
- 02python算法-二分法简介
老规矩: 什么是二分法: 其实是一个数学领域的词,但是在计算机领域也有广泛的使用. 为什么需要二分法? 当穷举算法性能让你崩溃时. 二分法怎么用呢? 让我们先玩一个游戏先,我心里想一个100以内的整数 ...
- SPDY 是什么?如何部署 SPDY?
摘要:当老迈的 HTTP 协议逐渐不能满足人们需求的时候,Google 的 SPDY 协议出现在面前,那么这个长期以来一直被认为是 HTTP 2.0 唯一可行选择的 SPDY 是什么呢?当下我们如何能 ...
- Spark Shell & Spark submit
Spark 的 shell 是一个强大的交互式数据分析工具. 1. 搭建Spark 2. 两个目录下面有可执行文件: bin 包含spark-shell 和 spark-submit sbin 包含 ...
- 【caffe】loss function、cost function和error
@tags: caffe 机器学习 在机器学习(暂时限定有监督学习)中,常见的算法大都可以划分为两个部分来理解它 一个是它的Hypothesis function,也就是你用一个函数f,来拟合任意一个 ...
- 【bzoj1082】 SCOI2005—栅栏
http://www.lydsy.com/JudgeOnline/problem.php?id=1082 (题目链接) 题意 给出m块木柴,以及n块木板,要求将m块木柴做木板,要求将木柴切割成与木板一 ...
- 网易免费/付费163企业邮smtp服务器地址
免费:smtp.ym.163.com 25/pop.ym.163.com 110 付费:smtp.qiye.163.com 25/pop.qiye.163.com 110
- 分区还原工具(DiskGenius)
不小心删除的分区可以实用DiskGenius进行还原. 下载地址:http://www.upantool.com/qidong/2012/DiskGenius_3.7.1.html 操作方法: 打开D ...