? ? ? ? a.任务通知像个用于通知的任务,由一个32位无符号整数和8位的通知状态组成,通过任务通知函数改写其他任务的32位无符号整数数据。
? ? ? ? b.改写方式如下(1.可以让这个整数加1: 模拟信号量 2. 设置该整数的指定的某些位:模拟事件组 3.直接选择覆盖或者不覆盖写入: 模拟消息队列)
? ? ? ? c.发送通知 可用于任务和中断服务函数中,接收通知 只能用于任务中
?a.未等待通知状态:就是任务的初始状态
b.等待通知状态:当任务在没有通知的时候接收通知时(也就是任务没有接收到通知的时候调用了接收通知的函数,则此时必定接收不到通知,把该任务标记为等待通知状态(去等别的任务发给我通知),任务进入阻塞态),这样做的用处是什么呢? 答:当另外一个任务发通知给该任务时,此时发现任务处于等待通知的状态,然后就可以即可把该任务唤醒。
c.等待接收通知状态:当有其他任务向任务发送通知,但任务还未接收这一通知的这段期间内(当其他任务给该任务发了通知,但是该任务还没有接收,则将该任务标记为等待接收通知状态),这样做的用处就是当该任务调用了接收通知的函数,发现自身的状态为等待接收通知状态,则不用进入阻塞,直接接收通知值。
?
发送通知函数:
xTaskNotify(xTaskToNotify,ulValue,eAction)? ? ? ? ? ? ? ? 发送通知,带有通知值
参数:目标任务句柄,通知值,通知方式
xTaskNotifyAndQuery(xTaskToNotify,ulValue,eAction,pulPreviousNotifyValue)
? 发送通知,带有通知值并且保留接收任务的原通知值
参数:目标任务句柄,通知值,通知方式,给原通知值保存的变量
xTaskNotifyGive(xTaskToNotify)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 发送通知,不带通知值
参数:目标句柄
接收任务通知函数
ulTaskNotifyTake()该函数就是专门服务与模拟二值信号量/计数型信号量的
ulTaskNotifyTake(xClearCountOnExit,xTicksToWait)
参数:
???参数1 在成功接收通知后,将通知值清零或减1(分别对应二值信号量,计数型信号量)
???参数2 阻塞等待任务通知值的最大时间
函数返回值 0:接收失败,非 0: 接收成功,返回任务通知的通知值(当前计数值)
xTaskNotifyWait()该函数一般用来模拟队列或者事件组的接收
xTaskNotifyWait( ulBitsToClearOnEntry, ?????等待前指定清零的任务通知通知值比特位(0则不清零)
????????????????????????????ulBitsToClearOnExit, ?????????成功等待后指定清零的任务通知通知值比特位
????????????????????????????pulNotificationValue,???????????等待超时后任务通知的通知值
????????????????????????????xTicksToWait)??????????????????????阻塞等待任务通知值的最大时间
返回值:pdTRUE 等待任务通知成功,pdFALSE 等待任务通知失败
//freertos_demo.c
#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"
/************************************************************************************/
/*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* pv);
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2(void* pv);
/***************************************************************************************/
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t ) start_task, //创建开始任务
(char* ) "start_task",
(unsigned portSHORT) START_TASK_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) START_TASK_PRIO,
(TaskHandle_t* ) &start_task_handler );
vTaskStartScheduler();
}
void start_task(void* pvPara)
{
taskENTER_CRITICAL(); //进入临界区
xTaskCreate((TaskFunction_t ) task1, //创建任务一
(char* ) "task1",
(unsigned portSHORT) TASK1_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) TASK1_PRIO,
(TaskHandle_t* ) &task1_handler );
xTaskCreate((TaskFunction_t ) task2, //创建任务二
(char* ) "task2",
(unsigned portSHORT) TASK2_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) TASK2_PRIO,
(TaskHandle_t* ) &task2_handler );
vTaskDelete(NULL); //删除start_task任务
taskEXIT_CRITICAL(); //退出临界区
}
//任务一 发送任务通知值
void task1(void* pv)
{
uint8_t key = 0;
printf("连接成功!\r\n");
while(1)
{
key = key_scan(0);
if(key == KEY0_PRES)
{
printf("任务通知模拟二值信号量释放!!!\r\n");
xTaskNotifyGive(task2_handler); //发送通知值给任务二
}
vTaskDelay(500);
}
}
//任务二 接收任务通知值
void task2(void* pv)
{
uint32_t rev = 0;
while(1)
{
rev = ulTaskNotifyTake(pdTRUE,portMAX_DELAY);//接收任务通知值,参数1是将通知值清零,参数2是阻塞时间;接收成功解除阻塞
if(rev != 0)
{
printf("接收任务通知成功,模拟获取二值信号量!!\r\n");
}
}
}