ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU

[应用相关] FreeRTOS 消息队列

[复制链接]
378|36
 楼主 | 2018-9-12 21:05 | 显示全部楼层
为什么要使用事件标志
事件标志组是实现多任务同步的有效机制之一。也许有不理解的初学者会问采用事件标志组多麻烦,
搞个全局变量不是更简单?其实不然,在裸机编程时,使用全局变量的确比较方便,但是在加上 RTOS 后
就是另一种情况了。
 楼主 | 2018-9-12 21:05 | 显示全部楼层
使用全局变量相比事件标志组主要有如下三个问题:
 使用事件标志组可以让 RTOS 内核有效地管理任务,而全局变量是无法做到的,任务的超时等机制需
要用户自己去实现。
 使用了全局变量就要防止多任务的访问冲突,而使用事件标志组则处理好了这个问题,用户无需担心。
 使用事件标志组可以有效地解决中断服务程序和任务之间的同步问题。
 楼主 | 2018-9-12 21:09 | 显示全部楼层
FreeRTOS 任务间事件标志组的实现
任务间事件标志组的实现是指各个任务之间使用事件标志组实现任务的通信或者同步机制。
下面我们来说说 FreeRTOS 中事件标志的实现,根据用户在 FreeRTOSConfig.h 文件中的配置:
 #define configUSE_16_BIT_TICKS 1
配置宏定义 configUSE_16_BIT_TICKS 为 1 时,每创建一个事件标志组,用户可以使用的事件标志是8 个。
 楼主 | 2018-9-12 21:09 | 显示全部楼层
#define configUSE_16_BIT_TICKS 0
配置宏定义 configUSE_16_BIT_TICKS 为 0 时,每创建一个事件标志组,用户可以使用的事件标志是24 个。
 楼主 | 2018-9-12 21:09 | 显示全部楼层
上面说的 8 个和 24 个事件标志应该怎么理解呢?其实就是定义了一个 16 位变量,仅使用了低 8bit或者定义了一个 32 位变量,仅使用了低 24bit。每一个 bit 用 0 和 1 两种状态来代表事件标志。 反映到FreeRTOS 上就是将事件标志存储到了 EventBits_t 类型的变量中, 这个变量又是怎么回事呢?
 楼主 | 2018-9-12 21:10 | 显示全部楼层
定义如下:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2018-9-12 21:10 | 显示全部楼层
由上面定义可以看出,TickType_t 数据类型可以是 16 位数或者 32 位数,这样就跟上面刚刚说的
configUSE_16_BIT_TICKS 宏定义呼应上了。教程配套的例子都是配置宏定义 configUSE_16_BIT_TICKS
为 0, 即用户每创建一个事件标志组, 有 24 个标志可以设置。 如下图所示,这里仅使用 bit0, bit1 和 bit2。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2018-9-12 21:11 | 显示全部楼层
下面我们通过如下的框图来说明一下 FreeRTOS 事件标志的实现,让大家有一个形象的认识。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2018-9-12 21:11 | 显示全部楼层
FreeRTOS 中断方式事件标志组的实现
FreeRTOS 中断方式事件标志组的实现是指中断函数和 FreeRTOS 任务之间使用事件标志。 下面我们
通过如下的框图来说明一下 FreeRTOS 事件标志的实现,让大家有一个形象的认识。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2018-9-12 21:11 | 显示全部楼层
任务 Task1 运行过程中调用函数 xEventGroupWaitBits,等待事件标志位被设置,任务 Task1 由运行态进入到阻塞态。Task1 阻塞的情况下,串口接收到数据进入到了串口中断服务程序,在串口中断服务程序中设置 Task1等待的事件标志,任务 Task1 由阻塞态进入到就绪态,在调度器的作用下由就绪态又进入到运行态。
上面就是一个简单的 FreeRTOS 中断方式事件标志通信过程。
 楼主 | 2018-9-12 21:12 | 显示全部楼层
实际应用中,中断方式的消息机制要注意以下四个问题:
中断函数的执行时间越短越好,防止其它低于这个中断优先级的异常不能得到及时响应。
 实际应用中,建议不要在中断中实现消息处理,用户可以在中断服务程序里面发送消息通知任务,在
任务中实现消息处理,这样可以有效地保证中断服务程序的实时响应。同时此任务也需要设置为高优
先级,以便退出中断函数后任务可以得到及时执行。
 中断服务程序中一定要调用专用于中断的事件标志设置函数,即以 FromISR 结尾的函数。
 在操作系统中实现中断服务程序与裸机编程的区别。
 如果 FreeRTOS 工程的中断函数中没有调用 FreeRTOS 的事件标志组 API 函数,与裸机编程是
一样的。
 如果 FreeRTOS 工程的中断函数中调用了 FreeRTOS 的事件标志组的 API 函数,退出的时候要
检测是否有高优先级任务就绪,如果有就绪的,需要在退出中断后进行任务切换,这点跟裸机编
程稍有区别,详见 实验例程说明(中断方式):
 另外强烈推荐用户将 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407, F429
的 NVIC 优先级分组设置为 4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这样中
断优先级的管理将非常方便。
 用户要在 FreeRTOS 多任务开启前就设置好优先级分组,一旦设置好切记不可再修改。
 楼主 | 2018-9-12 21:12 | 显示全部楼层
事件标志组 API 函数
使用如下 11 个函数可以实现 FreeRTOS 的事件标志组:
 xEventGroupCreate()
 xEventGroupCreateStatic()
 vEventGroupDelete()
 xEventGroupWaitBits()
 xEventGroupSetBits()
 xEventGroupSetBitsFromISR()
 xEventGroupClearBits()
 xEventGroupClearBitsFromISR()
 xEventGroupGetBits()
 xEventGroupGetBitsFromISR()
 楼主 | 2018-9-12 21:13 | 显示全部楼层
这里我们重点的说以下 4 个函数:
 xEventGroupCreate()
 xEventGroupWaitBits()
 xEventGroupSetBits()
 xEventGroupSetBitsFromISR()
 楼主 | 2018-9-12 21:13 | 显示全部楼层
函数 xEventGroupCreate
函数原型:
EventGroupHandle_t xEventGroupCreate( void );
函数描述:
函数 xEventGroupCreate 用于创建事件标志组。
 返回值,如果创建成功, 此函数返回事件标志组的句柄,如果 FreeRTOSConfig.h 文件中定义的 heap
空间不足会返回 NULL
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) )

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2018-9-12 21:13 | 显示全部楼层
函数 xEventGroupSetBits
函数原型:
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */
const EventBits_t uxBitsToSet ); /* 事件标志位设置 */
函数描述:
函数 xEventGroupSetBits 用于设置指定的事件标志位为 1。
 第 1 个参数是事件标志组句柄。
 第 2 个参数表示 24 个可设置的事件标志位,EventBits_t 是定义的 32 位变量,
低 24 位用于事件标志设置。变量 uxBitsToSet 的低 24 位的某个位设置为 1,那么被设置的
事件标志组的相应位就设置为 1。 变量 uxBitsToSet 设置为 0 的位对事件标志相应位没有影响。比
如设置变量 uxBitsToSet = 0x0003 就表示将事件标志的位 0 和位 1 设置为 1,其余位没有变化。

 返回当前的事件标志组数值。
 楼主 | 2018-9-12 21:14 | 显示全部楼层
使用这个函数要注意以下问题:
1. 使用前一定要保证事件标志组已经通过函数 xEventGroupCreate 创建了。
2. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是
xEventGroupSetBitsFromISR
3. 用户通过参数 uxBitsToSet 设置的标志位并不一定会保留到此函数的返回值中,下面举两种情况:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2018-9-12 21:14 | 显示全部楼层
a. 如果设置一个位导致等待该位的任务离开阻塞(注意是离开阻塞态,即使没有进入运行态,只要离开阻塞态即可)状态,则该位可能会被自动清除(请参阅xEventGroupWaitBits()的xClearBitOnExit参数)。
 楼主 | 2018-9-12 21:14 | 显示全部楼层
b. 调用此函数的任务是一个低优先级任务,通过此函数设置了事件标志后,让一个等待此事件标志
的高优先级任务就绪了,会立即切换到高优先级任务去执行,相应的事件标志位会被函数
xEventGroupWaitBits 清除掉,等从高优先级任务返回到低优先级任务后,函数xEventGroupSetBits 的返回值已经被修改。
 楼主 | 2018-9-12 21:15 | 显示全部楼层
函数 xEventGroupSetBitsFromISR
函数原型:
BaseType_t xEventGroupSetBitsFromISR(
EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */
const EventBits_t uxBitsToSet, /* 事件标志位设置 */
BaseType_t *pxHigherPriorityTaskWoken ); /* 高优先级任务是否被唤醒的状态保存 */
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

快速回复 返回顶部 返回列表