FreeRTOS学习之任务通知
来源:互联网 发布:淘宝店铺怎么换客服 编辑:程序博客网 时间:2024/05/17 01:17
1. 作用
任务通知功能是干什么用的呢?举个例子,假设一种场景,当按下按键时,LED灯会亮。比较简单的实现代码如下:
void func(void){ if(pressed) led on;}
在基于时间片任务调度下,基于模块化的考虑,或者基于可读性的考虑,也可以按照如下代码实现
unsigned char button_state;void led(void){ if (button_state == PRESSED) led on;}void button(void){ while (button_gpio == PRESSED) button_state = PRESSED; }void func(void){ while(1) { button(); led(); }}
但是在有操作系统的情况下,每个任务都是一个死循环,那么这两个函数之间该如何通讯呢?这就是任务通知干的活。当然队列、信号量等都可以使用,这儿我们只讨论用任务通知如何实现该功能.
2. 任务通知的优点:
用事件通知解除阻塞任务会比二值信号量快45%并且使用更少的RAM空间。
3. 性能优势和使用限制
在实现相同功能的情况下,任务通知具有速度和RAM空间的双重优势。但是这种优势也有一定的限制:
- 只有唯一的任务可以接受通知的情况下,才可以使用。这个条件已经可以满足大部分的应用了。
- 只有以下情况,任务通知才可以替代队列:当有一个处在阻塞状态下的任务等待通知时,那个发送通知的任务如果不能马上完成发送,必须不能进入阻塞状态等待发送完成。
4. 裸机实例
说了这么多,到底是干嘛用的,估计还是不清楚,简短的例子是最好的老师,举个例子。看下面一段代码
我们先用裸机代码实现如下功能,功能很简单:
static void RecFunc(void);static void SendFunc(void);unsigned int send_val;unsigned int rec_val;static void SendFunc(void){ for(;;) { delay_5ms(); if (send_val == 5) { send_val = 0; } else { send_val++; } }}static void RecFunc(void){ for(;;) { rec_val = 0; /*wait here until send_val == 5*/ while(send_val != 5); rec_val = 1; delay_5ms(); }} void main(void){ SendFunc(); RecFunc();}
5. 带操作系统实例
再用带操作系统的代码实现以上功能,乍看一下,代码很长,去掉注释,仔细分析一下,核心代码就两三行,耐心看完:
/** ****************************************************************************** * @file test_task_notification.c * @author cyf * @version V1.0 * @date 2016-7-29 10:19:12 * @brief 学习FreeRTOS的任务通知功能使用方法 *//* *这个例子没有实际的使用意义,仅仅是为了演示任务通知功能的使用 * *在函数SendFunc()中,send_val 的值会每间隔5ms自增1,当send_val=5时,会通知RecFunc(),条件已满足, *你可以执行操作了,通知完后,会清零send_val. * *函数Recfunc()里的rec_val值会一直为0,只有在接收到任务通知时,会使rec_val=1,设置为1后,马上就会变为0,等待下一次任务通知 * */#include "FreeRTOS.h"#include "task.h"static void RecFunc(void *pvParameters);static void SendFunc(void *pvParameters);/*TN is short for Task Notification*/#define TN_STACK_SIZE configMINIMAL_STACK_SIZE#define TN_PRIORITY ( tskIDLE_PRIORITY + 2 )unsigned int send_val;unsigned int rec_val;static TaskHandle_t xRecTask = NULL;/* * 任务通知发送函数 */static void SendFunc(void *pvParameters){ TickType_t xDelay = 5/portTICK_PERIOD_MS; for(;;) { vTaskDelay(xDelay); if (send_val == 5) { /*Send a notificaton to RecFunc(),bringing it out of the Blocked state*/ xTaskNotifyGive(xRecTask); send_val = 0; } else { send_val++; } }}/* * 任务通知接收函数 */static void RecFunc(void *pvParameters){ TickType_t xDelay = 5/portTICK_PERIOD_MS; for(;;) { rec_val = 0; /*Block to wait for SendFunc() to notify this task*/ ulTaskNotifyTake(pdTRUE,portMAX_DELAY); rec_val = 1; vTaskDelay(xDelay); }}/* * 生产两个任务实例,本函数在main函数中被调用 * 函数SendFunc设置条件 * 函数RecFunc接收条件,当满足条件后,执行操作 * */void vCreateTaskNotification(void){ xTaskCreate(SendFunc,"Send",TN_STACK_SIZE,NULL,TN_PRIORITY,NULL); xTaskCreate(RecFunc,"Send",TN_STACK_SIZE,NULL,TN_PRIORITY,&xRecTask);}/***************************************** END OF FILE ********************************************************/
6. 调试分析
编译后,我们进入keil的调试功能:
1. 调出“Logic Analyzer”窗口
2. 调出“Symbol Window”的串口
3. 把变量send_val、rec_val加入到Logic Analyzer”窗口中
如下图
4. 单击”Run”按钮运行
得到如下图
仔细观察图片中蓝色虚线所表示的位置,当send_val的值为0的时候,rec_val的值为1,结合程序源码,应该不难理解任务通知的功能。
前后对比,感受一下任务通知的功能及使用方法。
7. 总结
任务通知功能主要使用了两个函数来实现,一个是xTaskNotifyGive(),一个是ulTaskNotifyTake(),
我给你,你才能拿,拿到了,才能去干活, 拿不到就等着。
当然,这里只是举例两个简单的函数,还有一下其他的函数及参数,具体的可以去看一下官网的介绍,解释的很详细。
- FreeRTOS学习之任务通知
- FreeRTOS 任务通知
- HEXIWEAR---FreeRTOS之任务
- FreeRTOS之任务基础知识
- FreeRTOS系列第14篇---FreeRTOS任务通知
- FreeRTOS高级篇8---FreeRTOS任务通知分析
- FreeRTOS系列第14篇---FreeRTOS任务通知
- FreeRTOS高级篇8---FreeRTOS任务通知分析
- FreeRTOS 学习笔记 3 —— 任务状态机之阻塞
- Freertos学习--初识任务函数
- Freertos学习--初识任务函数
- FreeRTOS 学习三:任务管理
- FREERTOS之任务创建删除
- FREERTOS之任务调度vPortYield
- FreeRTOS之任务创建删除
- FreeRTOS 任务管理之任务创建
- FreeRTOS 任务管理之任务转移
- FreeRTOS 任务管理之任务删除
- ES6学习-let和const
- Android ToolBar使用总结
- android 日期的各种转换
- Blockchian区块链:IBM HyperLedger fabric 简述
- 现在市面上网络监控系统分析!
- FreeRTOS学习之任务通知
- 初识Java回调机制
- controller层响应客户端json数据
- SQL语句创建表
- Android热补丁动态修复实践
- jdk1.5、1.6、1.7新特性详细介绍(整理)
- asp.net C#中对Web.Config字符串加密与解密的方法
- 源码分析之最近算法
- matlab /bin/bash: ffmpeg: command not found 解决办法