信息发布型网站建设的特点,自建网站 服务器,临沂网站,wordpress+代码质量1、任务通知
任务通知#xff1a; 用来通知任务的#xff0c;任务控制块中的结构体成员变量ulNotifiedValue就是这个通知值 使用队列、信号量、事件标志组时都需另外创建一个结构体#xff0c;通过中间的结构体进行间接通信#xff01; 使用任务通知时#xff0c;任务结…1、任务通知
任务通知 用来通知任务的任务控制块中的结构体成员变量ulNotifiedValue就是这个通知值 使用队列、信号量、事件标志组时都需另外创建一个结构体通过中间的结构体进行间接通信 使用任务通知时任务结构体TCB中就包含了内部对象可以直接接收别人发过来的通知 也就是说任务通知实现任务之间不同过中间结构体完成消息通讯
任务通知值的更新方式 不覆盖接受任务的通知值 覆盖接受任务的通知值 更新接受任务通知值的一个或多个bit 增加接受任务的通知值 只要合理灵活的利用任务通知的特点可以在一些场合中替代队列、信号量、事件标志组
任务通知的优势及劣势 任务通知的优势 效率更高使用任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快得多 使用内存更小 使用其他方法时都要先创建对应的结构体使用任务通知时无需额外创建结构体 任务通知的劣势 无法发送数据给ISRISR没有任务结构体所以无法给ISR发送数据。但是ISR可以使用任务通知的功能发数据给任务。 无法广播给多个任务 任务通知只能是被指定的一个任务接收并处理 无法缓存多个数据任务通知是通过更新任务通知值来发送数据的任务结构体中只有一个任务通知值只能保持一个数据。 发送受阻不支持阻塞发送方无法进入阻塞状态等待
2任务通知值和通知状态
任务都有一个结构体任务控制块TCB它里边有两个结构体成员变量
任务通知值 任务通知值的更新方式有多种类型 计数值数值累加类似信号量 相应位置一类似事件标志组 任意数值支持覆写和不覆写类似队列
任务通知状态 其中任务通知状态共有3种取值
任务未等待通知 任务通知默认的初始化状态 等待通知接收方已经准备好了调用了接收任务通知函数等待发送方给个通知 等待接收发送方已经发送出去调用了发送任务通知函数等待接收方接收
3任务通知相关API函数介绍熟悉
任务通知API函数主要有两类①发送通知 ②接收通知。 注意发送通知API函数可以用于任务和中断服务函数中接收通知API函数只能用在任务中。 ①发送通知相关API函数
#define xTaskNotifyAndQuery( xTaskToNotify , ulValue , eAction , pulPreviousNotifyValue ) \ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ),( pulPreviousNotifyValue ) )#define xTaskNotify ( xTaskToNotify , ulValue , eAction ) \ xTaskGenericNotify( ( xTaskToNotify ) , ( tskDEFAULT_INDEX_TO_NOTIFY ) , ( ulValue ) , ( eAction ) , NULL )#define xTaskNotifyGive( xTaskToNotify ) \ xTaskGenericNotify( ( xTaskToNotify ) , ( tskDEFAULT_INDEX_TO_NOTIFY ) , ( 0 ) , eIncrement , NULL )BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,UBaseType_t uxIndexToNotify,uint32_t ulValue,eNotifyAction eAction,uint32_t * pulPreviousNotificationValue )任务通知方式共有以下几种
typedef enum
{ eNoAction 0, /* 无操作 */eSetBits /* 更新指定bit */eIncrement /* 通知值加一 */eSetValueWithOverwrite /* 覆写的方式更新通知值 */eSetValueWithoutOverwrite /* 不覆写通知值 */
} eNotifyAction;当任务通知用作于信号量时使用函数获取信号量ulTaskNotifyTake() 当任务通知用作于事件标志组或队列时使用此函数来获取 xTaskNotifyWait()
#define ulTaskNotifyTake( xClearCountOnExit , xTicksToWait ) \
ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), \ ( xClearCountOnExit ), \ ( xTicksToWait ) ) 此函数用于接收任务通知值可以设置在退出此函数的时候将任务通知值清零或者减一
#define xTaskNotifyWait( ulBitsToClearOnEntry, \ ulBitsToClearOnExit, \ pulNotificationValue, \ xTicksToWait) \
xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, \ ( ulBitsToClearOnEntry ), \ ( ulBitsToClearOnExit ), \ ( pulNotificationValue ), \ ( xTicksToWait ) ) 此函数用于获取通知值和清除通知值的指定位值适用于模拟队列和事件标志组使用该函数来获取任务通知 。
BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t * pulNotificationValue, TickType_t xTicksToWait ); 4任务通知模拟信号量实验掌握
1、实验目的学习使用 FreeRTOS 中的任务通知功能模拟二值信号量和计数型信号量 2、实验设计将设计三个任务start_task、task1、task2 三个任务的功能如下 start_task 用来创建task1和task2任务 task1 用于按键扫描当检测到按键KEY0被按下时将发送任务通知 task2 用于接收任务通知并打印相关提示信息 #include freertos_demo.h
#include ./SYSTEM/usart/usart.h
#include ./BSP/LED/led.h
#include ./BSP/LCD/lcd.h
#include ./BSP/KEY/key.h
#include ./SYSTEM/delay/delay.h
#include ./MALLOC/malloc.h
/*FreeRTOS*********************************************************************************************/
#include FreeRTOS.h
#include task.h
#include event_groups.h
/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
/* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1( void * pvParameters );/* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2( void * pvParameters );/*** brief FreeRTOS例程入口函数* param 无* retval 无*/void freertos_demo(void)
{ xTaskCreate((TaskFunction_t) start_task,(char *) start_task,(configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,(void *) NULL,(UBaseType_t) START_TASK_PRIO,(TaskHandle_t *)start_task_handler);//开启任务调度vTaskStartScheduler();}
void start_task( void * pvParameters )
{taskENTER_CRITICAL(); /* 进入临界区 任何任务和中断都不能打断当前程序运行*/xTaskCreate((TaskFunction_t) task1,(char *) task1,(configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,(void *) NULL,(UBaseType_t) TASK1_PRIO,(TaskHandle_t *)task1_handler );xTaskCreate((TaskFunction_t) task2,(char *) task2,(configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,(void *) NULL,(UBaseType_t) TASK2_PRIO,(TaskHandle_t *)task2_handler );vTaskDelete(NULL);//删除当前任务也就是开始任务taskEXIT_CRITICAL();}
/* 任务一,用于扫描按键当KEY0按下发送任务通知值 */
void task1( void * pvParameters )
{uint8_t key;while(1){keykey_scan(0);if(keyKEY0_PRES){printf(任务通知模拟二值信号量释放\r\n);//发送通知不带通知值 参数为通知的任务句柄xTaskNotifyGive(task2_handler);}vTaskDelay(10);}}
/* 任务二读取队列集中的消息并打印*/
void task2( void * pvParameters )
{uint32_t rev 0 ;while(1){//返回值为任务调用期间接收到的任务通知次数revulTaskNotifyTake(pdTRUE,portMAX_DELAY);if(rev!0){printf(接收任务通知成功模拟获取二值信号量\r\n);printf(rev val is %ld\r\n,rev);}}
}
5任务通知模拟消息邮箱实验掌握
1、实验目的学习使用 FreeRTOS 中的任务通知功能模拟消息邮箱 2、实验设计将设计三个任务start_task、task1、task2 三个任务的功能如下 start_task 用于按键扫描将按下的按键键值通过任务通知发送给指定任务 task2 用于接收任务通知并根据接收到的数据做相应动作 #include freertos_demo.h
#include ./SYSTEM/usart/usart.h
#include ./BSP/LED/led.h
#include ./BSP/LCD/lcd.h
#include ./BSP/KEY/key.h
#include ./SYSTEM/delay/delay.h
#include ./MALLOC/malloc.h
/*FreeRTOS*********************************************************************************************/
#include FreeRTOS.h
#include task.h
#include event_groups.h
/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );/* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1( void * pvParameters );/* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2( void * pvParameters );/******************************************************************************************************/
/*** brief FreeRTOS例程入口函数* param 无* retval 无*/
void freertos_demo(void)
{ xTaskCreate((TaskFunction_t ) start_task,(char * ) start_task,(configSTACK_DEPTH_TYPE ) START_TASK_STACK_SIZE,(void * ) NULL,(UBaseType_t ) START_TASK_PRIO,(TaskHandle_t * ) start_task_handler );vTaskStartScheduler();
}void start_task( void * pvParameters )
{taskENTER_CRITICAL(); /* 进入临界区 */xTaskCreate((TaskFunction_t ) task1,(char * ) task1,(configSTACK_DEPTH_TYPE ) TASK1_STACK_SIZE,(void * ) NULL,(UBaseType_t ) TASK1_PRIO,(TaskHandle_t * ) task1_handler );xTaskCreate((TaskFunction_t ) task2,(char * ) task2,(configSTACK_DEPTH_TYPE ) TASK2_STACK_SIZE,(void * ) NULL,(UBaseType_t ) TASK2_PRIO,(TaskHandle_t * ) task2_handler );vTaskDelete(NULL);taskEXIT_CRITICAL(); /* 退出临界区 */
}/* 任务一发送任务通知值 */
void task1( void * pvParameters )
{uint8_t key 0;while(1) {key key_scan(0);if((key ! 0) (task2_handler ! NULL)){printf(任务通知模拟消息邮箱发送发送的键值为%d\r\n,key);xTaskNotify( task2_handler, key, eSetValueWithOverwrite );}vTaskDelay(10);}
}/* 任务二接收任务通知值 */
void task2( void * pvParameters )
{uint32_t noyify_val 0;while(1){xTaskNotifyWait( 0, 0xFFFFFFFF, noyify_val, portMAX_DELAY );switch(noyify_val){case KEY0_PRES:{printf(接收到的通知值为%d\r\n,noyify_val);LED0_TOGGLE();break;}case KEY1_PRES:{printf(接收到的通知值为%d\r\n,noyify_val);LED1_TOGGLE();break;}default : break;}}
}任务通知模拟事件标志组实验掌握
1、实验目的学习使用 FreeRTOS 中的任务通知功能模拟事件标志组 2、实验设计将设计三个任务start_task、task1、task2 三个任务的功能如下 start_task 用来创建task1和task2任务 task1 用于按键扫描当检测到按键按下时发送任务通知设置不同标志位 task2 用于接收任务通知并打印相关提示信息
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1( void * pvParameters );/* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2( void * pvParameters );#define EVENTBIT_0 (1 0)
#define EVENTBIT_1 (1 1)/*** brief FreeRTOS例程入口函数* param 无* retval 无*/void freertos_demo(void)
{ xTaskCreate((TaskFunction_t) start_task,(char *) start_task,(configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,(void *) NULL,(UBaseType_t) START_TASK_PRIO,(TaskHandle_t *)start_task_handler);//开启任务调度vTaskStartScheduler();}
void start_task( void * pvParameters )
{taskENTER_CRITICAL(); /* 进入临界区 任何任务和中断都不能打断当前程序运行*/xTaskCreate((TaskFunction_t) task1,(char *) task1,(configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,(void *) NULL,(UBaseType_t) TASK1_PRIO,(TaskHandle_t *)task1_handler );xTaskCreate((TaskFunction_t) task2,(char *) task2,(configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,(void *) NULL,(UBaseType_t) TASK2_PRIO,(TaskHandle_t *)task2_handler );vTaskDelete(NULL);//删除当前任务也就是开始任务taskEXIT_CRITICAL();}
/* 任务一,用于扫描按键当KEY0按下发送任务通知值 */
void task1( void * pvParameters )
{uint8_t key;while(1){keykey_scan(0);if(keyKEY0_PRES){printf(将bit0位置为1\r\n);xTaskNotify(task2_handler,EVENTBIT_0,eSetBits);}else if(keyKEY1_PRES){printf(将bit1位置为1\r\n);xTaskNotify(task2_handler,EVENTBIT_1,eSetBits);}vTaskDelay(10);}}
/* 任务二读取队列集中的消息并打印*/
void task2( void * pvParameters )
{uint32_t rev 0 ;uint32_t event_bit 0;while(1){//接收前通知值不清零接收后通知值全部清零通知值给到revxTaskNotifyWait(0,0xFFFFFFFF,rev,portMAX_DELAY);if(revEVENTBIT_0){event_bit|EVENTBIT_0;}if(revEVENTBIT_1){event_bit|EVENTBIT_1;}if(event_bit(EVENTBIT_0|EVENTBIT_1)){printf(任务通知模拟事件标志组接收成功\r\n);event_bit0;}}
}
7、模拟计数信号量
#include freertos_demo.h
#include ./SYSTEM/usart/usart.h
#include ./BSP/LED/led.h
#include ./BSP/LCD/lcd.h
#include ./BSP/KEY/key.h
#include ./SYSTEM/delay/delay.h
#include ./MALLOC/malloc.h
/*FreeRTOS*********************************************************************************************/
#include FreeRTOS.h
#include task.h
#include event_groups.h
/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
/* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1( void * pvParameters );/* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2( void * pvParameters );/*** brief FreeRTOS例程入口函数* param 无* retval 无*/void freertos_demo(void)
{ xTaskCreate((TaskFunction_t) start_task,(char *) start_task,(configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,(void *) NULL,(UBaseType_t) START_TASK_PRIO,(TaskHandle_t *)start_task_handler);//开启任务调度vTaskStartScheduler();}
void start_task( void * pvParameters )
{taskENTER_CRITICAL(); /* 进入临界区 任何任务和中断都不能打断当前程序运行*/xTaskCreate((TaskFunction_t) task1,(char *) task1,(configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,(void *) NULL,(UBaseType_t) TASK1_PRIO,(TaskHandle_t *)task1_handler );xTaskCreate((TaskFunction_t) task2,(char *) task2,(configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,(void *) NULL,(UBaseType_t) TASK2_PRIO,(TaskHandle_t *)task2_handler );vTaskDelete(NULL);//删除当前任务也就是开始任务taskEXIT_CRITICAL();}
/* 任务一,用于扫描按键当KEY0按下发送任务通知值 */
void task1( void * pvParameters )
{uint8_t key;while(1){keykey_scan(0);if(keyKEY0_PRES){printf(任务通知模拟计数信号量被释放\r\n);xTaskNotifyGive(task2_handler);}vTaskDelay(10);}}
/* 任务二读取队列集中的消息并打印*/
void task2( void * pvParameters )
{uint32_t rev 0 ;while(1){revulTaskNotifyTake(pdFALSE,portMAX_DELAY);if(rev!0){printf(rev:%d\r\n,rev);}vTaskDelay(1000);}
}