当前位置:文档之家› 【RTX操作系统教程】第13章 事件标志组

【RTX操作系统教程】第13章 事件标志组


13.3 实验例程说明(任务间通信)
安富莱 STM32-V4 开发板 RTX 教程
13.3.1 STM32F103 开发板实验
配套例子:
V4-409_RTX 实验_事件标志组
实验目的:
1. 学习 RTX 的事件标志组
1. 当要求的事件标志位都被设置为 1 时或者设置的超时时间溢出时,函数 os_evt_wait_and 才会返回。
2. 如果函数 os_evt_wait_and 返回前所要求的事件标志位都设置了,那么此函数会在返回前将相应的事
件标志位清零,其它位不受此影响。如果初学者不是太理解这个问题,可以看本章节配套的例子,这
这里用 U16 类型的变量 event_flag 就可以设置,变量 event_flag 的那位设置为 1,那么 RTX 任务
的事件标志就等待那个位被设置为 1。而且要所有要求的位都被设置为 1 才可以。比如设置变量
event_flag = 0x0003 就表示 RTX 任务在等待事件标志的位 0 和位 1 都被设置为 1。
中断服务程序中一定要调用专用于中断的事件标志设置函数 isr_evt_set。
在 RTX 操作系统中实现中断函数跟裸机编程是一样的。
另外强烈推荐用户将 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407 的
NVIC 优先级分组设置为 4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这样中断
入到挂起态 任务 Task2 设置了任务 Task1 的事件标志,任务 Task1 由挂起态进入到就绪态,在调度器的作用下
由就绪态又进入到运行态。
上面就是一个简单 RTX 任务间事件标志通信过程。
13.1.3 RTX 中断方式事件标志组的实现
RTX 中断方式事件标志组的实现是指中断函数和 RTX 任务之间使用事件标志。下面我们通过如下的 框图来说明一下 RTX 事件标志的实现,让大家有一个形象的认识。
1. 此函数是用于中断服务程序中调用的,故不可以在任务中调用此函数,任务中使用的是 os_evt_set。
2. 事件标志函数 isr_evt_set 的调用不能太频繁,太频繁的话会大大增加系统内核的开销,会造成事件标
志得不到及时处理从而造成丢失事件标志的情况。
使用举例:
#include <rtl.h>
while(1) {
/* 1. 等待 K2 按键按下设置 bit0 和 K3 按键按下设置 bit1,都设置了执行 OS_R_EVT 消息 2. 退出前 bit0 和 bit1 被清除,这里是 bit0 和 bit1 都被设置才表示“退出”。 3. 每个任务都有自己的 16 位事件标志位,也就是 os_evt_wait_and 的第一个参数是无符号 16 位整形。
第13章 事件标志组
前面的章节我们已经讲解了任务管理和时间管理,从本章节开始讲解任务间的通信和同步机制。首先 讲解任务间的通信和同步机制之一,事件标志组。
本章教程配套的例子含 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407。 13.1 事件标志组 13.2 事件标志组 API 函数 13.3 实验例程说明(任务间通信) 13.4 实验例程说明(中断方式通信) 13.5 总结
第 2 个参数表示设在的等待时间,范围 0-0xFFFF,当参数设置为 0-0xFFFE 时,表示等这么多个时
钟节拍,参数设置为 0xFFFF 时表示无限等待直到事件标志满足要求。
函数返回 OS_R_EVT 表示等待的事件标志位都被设置了,也就是返回成功。返回 OS_R_TMO 表示
超时。
使用这个函数要注意以下问题:
其余位没有变化。
第 2 个参数是任务 ID。
使用这个函数要注意以下问题:
1. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是
isr_evt_set
使用举例:
2015年12月10日
版本:1.0
第 4 页 共 33 页
#include <rtl.h>
武汉安富莱电子有限公司
任务的事件标志相应位就设置为 1。变量 event_flag 设置为 0 的位对 RTX 任务的事件标志相应位没
有影响。比如设置变量 event_flag = 0x0003 就表示将 RTX 任务事件标志的位 0 和位 1 设置为 1,
其余位没有变化。
第 2 个参数是任务 ID。
使用这个函数要注意以下问题:
个问题:
中断函数的执行时间越短越好,防止其它低于这个中断优先级的异常不能得到及时响应。
实际应用中,建议不要在中断中实现消息处理,用户可以在中断服务程序里面发送消息通知任务,在
任务中实现消息处理,这样可以有效的保证中断服务程序的实时响应。同时此任务也需要设置为高优
先级,以便退出中断函数后任务可以得到及时行。
__task void task1 (void) { .. os_evt_set (0x0003, tsk2); ..
}
13.2.2函数 isr_evt_set
安富莱 STM32-V4 开发板 RTX 教程
函数原型:
void isr_evt_set ( U16 event_flags, OS_TID task );
2015年12月10日
版本:1.0
第 1 页 共 33 页
武汉安富莱电子有限公司
安富莱 STM32-V4 开发板 RTX 教程
运行条件: 创建 2 个任务 Task1 和 Task2 运行过程描述如下: 任务 Task1 运行过程中调用函数 os_evt_wait_and,等待事件标志位被设置,任务 Task1 由运行态进
运行条件:
2015年12月10日
版本:1.0
第 2 页 共 33 页
武汉安富莱电子有限公司
安富莱 STM32-V4 开发板 RTX 教程
创建 1 个任务和一个串口接收中断
运行过程描述如下:
任务 Task1 运行过程中调用函数 os_evt_wait_and,等待事件标志位被设置,任务 Task1 由运行态进
13.1 事件标志组
13.1.1 为什么要使用事件标志
事件标志组是实现多任务同步的有效机制之一。也许有不理解的初学者会问采用事件标志组多麻烦, 搞个全局变量不是更简单,其实不然。在裸机编程时,使用全局变量的确比较方便,但是在加上 RTOS 后 就是另一种情况了。使用全局变量相比事件标志组主要有如下三个问题: 使用事件标志组可以让 RTOS 内核有效的管理任务,全局变量是无法做到的,任务的超时等机制需要
入到挂起态
Task1 挂起的情况下,串口接收到数据进入到了串口中断服务程序,在串口中断服务程序中设置 Task1
的事件标志,任务 Task1 由挂起态进入到就绪态,在调度器的作用下由就绪态又进入到运行态。
上面就是一个简单 RTX 中断方式事件标志通信过程。实际应用中,中断方式的消息机制切记注意以下四个
用户自己去实现。 使用了全局变量就要防止多任务的访问冲突,使用事件标志组已经处理好了这个问题。用户无需担心。 使用事件标志组可以有效的解决中断服务程序和任务之间的同步问题。
13.1.2 RTX 任务间事件标志组的实现
任务间事件标志组的实现是指各个任务之间使用事件标志组实现任务的通信或者同步机制。 RTX 每个任务创建的时候,会自动创建 16 个事件标志,事件标志被存储到每个任务的任务控制块中。 也就是说每个任务支持 16 个事件标志。下面我们通过如下的框图来说明一下 RTX 事件标志的实现,让大 家有一个形象的认识。
/* 16 位的事件标志设置 */ /* 要设置事件标志的任务 ID */
函数描述:
函数 isr_evt_set 用于设置指定任务的事件标志。
第 1 个参数表示 16 个可设置的事件标志位。因为 RTX 的每个任务创建时有 16 个可设置的事件标志,
这里用 U16 类型的变量 event_flag 就可以表示,变量 event_flag 的某个位设置为 1,那么指定 RTX
*/ xResult = os_evt_wait_and (BIT_ALL, usMaxBlockTime);
switch (xResult) {
/* 接收到 bit1 和 bit0 都被设置的消息 */ case OS_R_EVT:
printf("接收到 bit0 和 bit1 都被设置的消息\r\n"); break;
2015年12月10日
版本:1.0
第 3 页 共 33 页
武汉安富莱电子有限公司
安富莱 STM32-V4 开发板 RTX 教程
这里我们重点的说一下函数 os_evt_set,isr_evt_set 和 os_evt_wait_and,因为本章节配套的例子使用的 是这三个函数。
void EXTI0_IRQHandler (void){ .. isr_evt_set (0x0003, tsk2); ..
}
13.2.3函数 os_evt_wait_and
函数原型:
OS_RESULT os_evt_wait_and ( U16 wait_flags, /* 16 位的事件标志等待 */ U16 timeout ); /* 超时时间设置 */
/* 超时 */ case OS_R_TMO:
bsp_LedToggle(1); bsp_LedToggle(4); break;
/* 其他值不处理 */ default:
2015年12月10日
版本:1.0
第 6 页 共 33 页
相关主题