FreeRTOS学习--53讲 任务通知

任务通知定义

        a.任务通知像个用于通知的任务,由一个32位无符号整数和8位的通知状态组成,通过任务通知函数改写其他任务的32位无符号整数数据。

        b.改写方式如下(1.可以让这个整数加1: 模拟信号量 2. 设置该整数的指定的某些位:模拟事件组 3.直接选择覆盖或者不覆盖写入: 模拟消息队列)

        c.发送通知 可用于任务和中断服务函数中,接收通知 只能用于任务中

任务通知中,任务的三种状态

 a.未等待通知状态:就是任务的初始状态

b.等待通知状态:当任务在没有通知的时候接收通知时(也就是任务没有接收到通知的时候调用了接收通知的函数,则此时必定接收不到通知,把该任务标记为等待通知状态(去等别的任务发给我通知),任务进入阻塞态),这样做的用处是什么呢? 答:当另外一个任务发通知给该任务时,此时发现任务处于等待通知的状态,然后就可以即可把该任务唤醒。

c.等待接收通知状态:当有其他任务向任务发送通知,但任务还未接收这一通知的这段期间内(当其他任务给该任务发了通知,但是该任务还没有接收,则将该任务标记为等待接收通知状态),这样做的用处就是当该任务调用了接收通知的函数,发现自身的状态为等待接收通知状态,则不用进入阻塞,直接接收通知值。
 

发送任务通知的核心函数

FreeRTOS学习--53讲 任务通知_第1张图片

FreeRTOS学习--53讲 任务通知_第2张图片

发送通知函数:

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");
        }
        
    }
}

你可能感兴趣的:(学习)