OS_FLAG.C(2)
本篇介绍OS_FLAG.C文件中的创建事件标志组函数*OSFlagCreate (OS_FLAGS flags,INT8U *perr)和删除事件标志组函数 *OSFlagDel (OS_FLAG_GRP *pgrp,INT8U opt,INT8U *perr)。
OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags,INT8U *perr)创建事件标志组:
/*$PAGE*/
/*
*********************************************************************************************************
* CREATE AN EVENT FLAG
* 创建事件标志组
* Description: This function is called to create an event flag group.
*描述:该函数是用来创建一个事件标志组。
* Arguments : flags Contains the initial value to store in the event flag group.
*参数: --flags:事件标志组的事件标志初值
* perr is a pointer to an error code which will be returned to your application:
* OS_ERR_NONE if the call was successful.
* OS_ERR_CREATE_ISR if you attempted to create an Event Flag from an
* ISR.
* OS_ERR_FLAG_GRP_DEPLETED if there are no more event flag groups
* --perr:指向错误码的指针,该指针将会返回到你的应用程序中。OS_ERR_NONE:无错误类型,说明调用成功。OS_ERR_CREATE_ISR:从中断中创建一个事件标志OS_ERR_FLAG_GRP_DEPLETED:如果系统中没有剩余的空闲事件标志组,需要更改OS_CFG.H中的事件标志组数目配置
* Returns : A pointer to an event flag group or a NULL pointer if no more groups are available.
*返回值:指向事件标志组的指针,如果没有可以返回的可用指针,返回null。
* Called from: Task ONLY
只能被任务调用
*********************************************************************************************************
*/OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags,INT8U *perr)
{OS_FLAG_GRP *pgrp; /*指向事件标志组的指针*/
#if OS_CRITICAL_METHOD == 3u /*中断类型被设置为3*/OS_CPU_SR cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICAL /*如果定义了安全中断*/if (perr == (INT8U *)0) /*如果错误码为0*/{OS_SAFETY_CRITICAL_EXCEPTION(); /*调用安全中断异常函数*/}
#endif#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();}
#endifif (OSIntNesting > 0u) /* 如果是从中断函数调用 */{ *perr = OS_ERR_CREATE_ISR; /* 将错误码指针设置为OS_ERR_CREATE_ISR,不能从中断函数调用 */return ((OS_FLAG_GRP *)0); /*返回0*/}OS_ENTER_CRITICAL(); /*关中断(进入中断)*/pgrp = OSFlagFreeList; /*pgrp指向空闲事件标志列表,来得到一个空闲事件标志组*/ if (pgrp != (OS_FLAG_GRP *)0) /*有空闲的事件标志组*/{ OSFlagFreeList = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList; /*分配后,调整系统空闲事件标志组链表指针*/pgrp->OSFlagType = OS_EVENT_TYPE_FLAG; /* 将标志类型设置为事件标志类型*/pgrp->OSFlagFlags = flags; /* 事件标志初始化*/pgrp->OSFlagWaitList = (void *)0; /*等待任务链接表指针初始化为NULL*/#if OS_FLAG_NAME_EN > 0u /*如果标志有名字的话,将名字初始化为未命名*/pgrp->OSFlagName = (INT8U *)(void *)"?";#endifOS_EXIT_CRITICAL(); /*退出中断*/*perr = OS_ERR_NONE; /*将错误类型设置为OS_ERR_NONE*/} else /*没有空闲的事件标志组*/{OS_EXIT_CRITICAL(); /*退出中断*/*perr = OS_ERR_FLAG_GRP_DEPLETED;/*将错误码设置为OS_ERR_FLAG_GRP_DEPLETED*/}return (pgrp); /* Return pointer to event flag group */
}
流程图如下:
其中,上面的“进行相应处理”为:
这四个步骤对应代码为:
OSFlagFreeList = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList; /*分配后,调整系统空闲事件标志组链表指针*/pgrp->OSFlagType = OS_EVENT_TYPE_FLAG; /* 将标志类型设置为事件标志类型*/pgrp->OSFlagFlags = flags; /* 事件标志初始化*/pgrp->OSFlagWaitList = (void *)0; /*等待任务链接表指针初始化为NULL*/
删除事件标志组函数: *OSFlagDel (OS_FLAG_GRP *pgrp,INT8U opt,INT8U *perr)
/*$PAGE*/
/*
*********************************************************************************************************
* DELETE AN EVENT FLAG GROUP
* 删除事件标志组
* Description: This function deletes an event flag group and readies all tasks pending on the event flag
* group.
*描述:该功能删除事件标志组并且将事件标志组中所有挂起的任务设为就绪
* Arguments : pgrp is a pointer to the desired event flag group.
*参数: --pgrp:指向事件标志组的指针
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Deletes the event flag group ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the event flag group even if tasks are
* waiting. In this case, all the tasks pending will be
* readied.
* --opt:删除的方式可以有以下几种选择:OS_DEL_NO_PEND:只有当没有任务挂起时才能删除事件标志组OS_DEL_ALWAYS:即使任务处于等待状态,也要删除事件标志组。这种情况下所有挂起的任务将会处于就绪态。
* 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 event flag group was deleted
* OS_ERR_DEL_ISR If you attempted to delete the event flag group from an ISR
* OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to an event flag group
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_TASK_WAITING One or more tasks were waiting on the event flag
* group.
* --perr:指向错误码的指针,该指针可以设置为以下值:OS_ERR_NONE:调用成功,事件标志组被删除OS_ERR_DEL_ISR:尝试从中断中调用删除函数OS_ERR_FLAG_INVALID_PGRP:如果pgrp为空指针OS_ERR_EVENT_TYPE:pgrp不是指向事件标志组的指针;OS_ERR_INVALID_OPT:opt参数不是指定的值;OS_ERR_TASK_WAITING:如果opt参数为OS_DEL_NO_PEND,那么此时有任务等待事件标志组
* Returns : pgrp upon error
* (OS_EVENT *)0 if the event flag group was successfully deleted.
*返回值:如果事件标志组被删除,组则返回空指针;如果没有删除,则仍然返回指向该事件标志组的指针。后一种情况需要检查出错代码,找出事件标志的失败的原因。
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the event flag group MUST check the return code of OSFlagAccept() and OSFlagPend().
* 2) 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 event flag group.注释:1)该功能需要小心使用,期望事件标志组的任务一定要检测OSFlagAccept()和OSFlagPend()两个函数的返回码。2)该函数有可能长时间关闭中断,其时间长短决定于标志组的任务个数。
*********************************************************************************************************
*/#if OS_FLAG_DEL_EN > 0u
OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp,INT8U opt,INT8U *perr)
{BOOLEAN tasks_waiting; /*有等待任务标志*/OS_FLAG_NODE *pnode; /*标志节点*/OS_FLAG_GRP *pgrp_return; /*返回指针*/
#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICAL /*安全中断*/if (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}
#endif#if OS_ARG_CHK_EN > 0u /*检查参数*/if (pgrp == (OS_FLAG_GRP *)0) /*有效化pgrp*/{ *perr = OS_ERR_FLAG_INVALID_PGRP;return (pgrp);}
#endifif (OSIntNesting > 0u) /*看是否从中断中调用的*/{ *perr = OS_ERR_DEL_ISR; return (pgrp);}if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) /*有效化事件组类型*/{ *perr = OS_ERR_EVENT_TYPE;return (pgrp);}OS_ENTER_CRITICAL(); /*进入中断*/if (pgrp->OSFlagWaitList != (void *)0) /*看任务正在等待事件标志是否为空*/{ tasks_waiting = OS_TRUE; /*有*/}else{tasks_waiting = OS_FALSE; /*无*/}switch (opt) /*选择删除的方式*/{case OS_DEL_NO_PEND: /*无任务挂起才删除*/if (tasks_waiting == OS_FALSE) /*没有任务正在等待*/{#if OS_FLAG_NAME_EN > 0upgrp->OSFlagName = (INT8U *)(void *)"?";/*名称初始化*/#endifpgrp->OSFlagType = OS_EVENT_TYPE_UNUSED;/*标志类型设置为未被使用*/pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /*将该事件标志组加入到事件标志组空闲链表中*/pgrp->OSFlagFlags = (OS_FLAGS)0; /*将标志位设为0*/OSFlagFreeList = pgrp; /*空闲列表指针指向新的(进行过删除事件标志组函数)链表*/OS_EXIT_CRITICAL(); /*退出中断*/*perr = OS_ERR_NONE; /*错误类型设置为无错误类型*/pgrp_return = (OS_FLAG_GRP *)0; /*事件标志组已经被删除,因而返回为0*/} else /*有任务正在等待*/{OS_EXIT_CRITICAL();/*退出中断*/*perr = OS_ERR_TASK_WAITING;/*将错误类型设置为OS_ERR_TASK_WAITING*/pgrp_return = pgrp; /*将pgrp赋给pgrp_return*/}break;case OS_DEL_ALWAYS: /*如果为无论有没有挂起,都删除*/pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; /*指向等待事件组的节点链表*/while (pnode != (OS_FLAG_NODE *)0) /*遍历该链表*/{ (void)OS_FlagTaskRdy(pnode, (OS_FLAGS)0); /*将该链表中的节点指向的任务转为就绪状态*/pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;}#if OS_FLAG_NAME_EN > 0u /*如果有名字,将名字初始化*/pgrp->OSFlagName = (INT8U *)(void *)"?";#endifpgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; /*将标志类型设置为未使用类型*/pgrp->OSFlagWaitList = (void *)OSFlagFreeList;/* 将该组返回到空闲列表中*/pgrp->OSFlagFlags = (OS_FLAGS)0;OSFlagFreeList = pgrp;OS_EXIT_CRITICAL(); /*退出中断*/if (tasks_waiting == OS_TRUE) { /*如果之前是有任务在等待事件标志组*/OS_Sched(); /*进行调度(执行最高优先级的任务)*/}*perr = OS_ERR_NONE; /*将错误类型设置为无错误类型*/pgrp_return = (OS_FLAG_GRP *)0; /* 事件标志组已经被删除,返回空*/break;default: /*其他情况下*/OS_EXIT_CRITICAL(); /*退出中断*/*perr = OS_ERR_INVALID_OPT; /*将错误码设置为OS_ERR_INVALID_OPT*/pgrp_return = pgrp; /*将pgrp赋值给pgrp_return*/break;}return (pgrp_return); /*返回pgrp_return*/
}
#endif
删除函数流程图为:
其中,删除操作为(针对OS_DEL_NO_PEND删除类型):
如果删除类型是OS_DEL_ALWAYS:则在上述操作步骤之前加一个:将等待事件组的节点链表中的节点指向的任务转为就绪状态。
对应的代码段为:
#if OS_FLAG_NAME_EN > 0upgrp->OSFlagName = (INT8U *)(void *)"?";/*名称初始化*/
#endif
pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED;/*标志类型设置为未被使用*/
pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /*将该事件标志组加入到事件标志组空闲链表中*//*下图<1>*/
pgrp->OSFlagFlags = (OS_FLAGS)0; /*将标志位设为0*/
OSFlagFreeList = pgrp; /*空闲列表指针指向新的(进行过删除事件标志组函数)链表*//*下图2*/
可能直接理解有点困难,我们图解一下:
上图即从原始状态经过程序之后的转化状态。<1><2>对应的代码上面注释也写清楚了。
OS_FLAG.C(2)相关推荐
- OS_FLAG.C(3)
上篇我们介绍了创建和删除事件标志组函数,后来在接着看源代码的时候,发现倒着来更有助于理解.所以后面几篇我会选择较为合适的方式来不定期更博,方便大家理解. 1.介绍删除节点函数OS_FlagUnlink ...
- OS_FLAG.C(1)
本篇介绍OS_FLAG.C中的检测事件标志组的标志状态函数 OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp,OS_FLAGS flags,INT8U wait_t ...
- OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3
OpenAPI使用(swagger3) demo见Gitte 一.背景及名词解释 OpenAPI是规范的正式名称.规范的开发工作于2015年启动,当时SmartBear(负责Swagger工具开发的公 ...
- 2022-2028年中国第五代移动通信技术(5G)市场研究及前瞻分析报告
[报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国第五代移动通信技术(5G)行业市场行业相 ...
- 2021-2027全球与中国经颅磁刺激仪(TMS)市场现状及未来发展趋势
[报告类型]产业研究 [报告价格]¥4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了全球与中国经颅磁刺激仪(TMS)行业市场行 ...
- Go 学习笔记(84)— Go 项目目录结构
1. 目录规范 一个好的目录结构至少要满足以下几个要求. 命名清晰:目录命名要清晰.简洁,不要太长,也不要太短,目录名要能清晰地表达出该目录实现的功能,并且目录名最好用单数.一方面是因为单数足以说明这 ...
- Redis 笔记(16)— info 指令和命令行工具(查看内存、状态、客户端连接数、监控服务器、扫描大key、采样服务器、执行批量命令等)
Info 命令返回关于 Redis 服务器的各种信息和统计数值.通过给定可选的参数 section ,可以让命令只返回某一部分的信息. 1. 显示模块 server : 一般 Redis 服务器信息, ...
- Redis 笔记(12)— 单线程架构(非阻塞 IO、多路复用)和多个异步线程
Redis 使用了单线程架构.非阻塞 I/O .多路复用模型来实现高性能的内存数据库服务.Redis 是单线程的.那么为什么说是单线程呢? Redis 在 Reactor 模型内开发了事件处理器,这个 ...
- Redis 笔记(10)— 发布订阅模式(发布订阅单个信道、订阅信道后的返回值分类、发布订阅多个信道)
1. 发布-订阅概念 发布-订阅 模式包含两种角色,分别为发布者和订阅者. 订阅者可以订阅一个或者若干个频道(channel): 而发布者可以向指定的频道发送消息,所有订阅此频道的订阅者都可以收到此消 ...
最新文章
- Spring Boot 2.x基础教程:使用Redis的发布订阅功能
- Ubunt pip升级到指定版本
- SpringBoot @Valid各种注解使用说明
- fluent p1模型_Fluent辐射传热模型理论以及相关设置-转载 于 作者:Libo Chen
- 故乡与文学:一场别开生面的跨年代文学对话(一)
- 操作系统习题——(习题二)
- linux 共享库目录,Linux共享库
- 朋友的身份证被骗子注册了支付宝开通了花呗,消费了三千被催债才知道花呗被盗如何处理?
- Nokia Widget 应用开发培训笔记
- 基于LSTM+Attention机制的IMDB影评数据分类学习实践
- cognos安装教程linux,Cognos安装步骤Linux
- 一天搞懂深度学习—学习笔记4(knowledge and tricks)
- sprintf函数的用法linux,sprintf函数用法解析
- linux 蓝牙驱动 chi,linux下的蓝牙驱动程序详解
- python语言程序设计袁方答案_北邮“爱课堂”教学平台
- 【合天网安】利用sqlmap辅助手工注入
- Halcon region区域提取及区域转图像
- 【日记本砸】21.01.08-12 最快的成长方式就是慢慢来
- seaborn做图技巧
- sk_buff属性详解