1.开发背景
直达任务通知,FreeRTOS 的线程任务提供的接口,可以用作线程唤醒,或者是传递数据,因为是基于线程本身的操作,是轻量级,速度响应更快,适合小内存芯片使用。
事实上本人使用得比较少,常用的项目内存都比较多,对响应时间也没有特别苛刻,需要快速响应的最好还是硬实时中断。直达任务通知实际上操作的都是一个 32bit 的数据,操作的类型有5 种,如下。
/* Actions that can be performed when vTaskNotify() is called. */
typedef enum
{
eNoAction = 0, /* Notify the task without updating its notify value. */
eSetBits, /* Set bits in the task's notification value. */
eIncrement, /* Increment the task's notification value. */
eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */
eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */
} eNotifyAction;
2.开发需求
设计实验:
创建 2 个线程,一个线程等待唤醒,另一个线程则是通过不同的方式定时唤醒
3.开发环境
window10 + MDK + STM32F429 + FreeRTOS10.3.1
4.实现步骤
4.1 实现编码
xTaskNotifyWait 接收需要注意的参数是
ulBitsToClearOnEntry 写入 0xFFFFFFFF 在调用前清除所有位
ulBitsToClearOnExit 写入 0xFFFFFFFF 在成功触发后清除所有位
#include "appTest.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mspDwt.h"
#include "mspGpio.h"
#include "mspExti.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stream_buffer.h"
#include "event_groups.h"
#include "appLog.h"
typedef struct
{
/* 任务线程 */
TaskHandle_t task1; // 线程
TaskHandle_t task2; // 线程
}Ctrl_t;
/* 文件指针 */
static Ctrl_t s_ctrl = {0};
static Ctrl_t *p = &s_ctrl;
static void Task1(void *pvParameters);
static void Task2(void *pvParameters);
/* 接收线程 */
static void Task1(void *pvParameters)
{
vTaskDelay(100);
/* 唤醒 */
vTaskDelay(100);
xTaskNotifyGive(p->task2);
Log_Debug("%s xTaskNotifyGive\r\n", __func__);
/* 唤醒 */
vTaskDelay(100);
xTaskNotify(p->task2, 0, eNoAction);
Log_Debug("%s xTaskNotify eNoAction\r\n", __func__);
/* 传递数据 */
vTaskDelay(100);
unsigned int value = 0x12345678;
xTaskNotify(p->task2, value, eSetValueWithoutOverwrite);
Log_Debug("%s xTaskNotify eSetValueWithoutOverwrite\r\n", __func__);
xTaskNotify(p->task2, value << 4, eSetValueWithOverwrite);
Log_Debug("%s xTaskNotify eSetValueWithOverwrite\r\n", __func__);
/* 数据自增 */
vTaskDelay(100);
xTaskNotify(p->task2, 0, eIncrement);
Log_Debug("%s xTaskNotify eIncrement\r\n", __func__);
/* 修改部分位 */
vTaskDelay(100);
xTaskNotify(p->task2, 0xAB00, eSetBits);
Log_Debug("%s xTaskNotify eSetBits\r\n", __func__);
for ( ; ; )
{
vTaskDelay(1000);
}
}
/* 发送线程 */
static void Task2(void *pvParameters)
{
vTaskDelay(100);
/* 等待唤醒 */
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
Log_Debug("%s ulTaskNotifyTake OK\r\n", __func__);
/* 等待唤醒 */
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
Log_Debug("%s ulTaskNotifyTake OK\r\n", __func__);
for ( ; ; )
{
/* 等待接收数据 */
unsigned int value = 0;
xTaskNotifyWait(0xFFFFFFFF, 0xFFFFFFFF, &value, portMAX_DELAY);
Log_Debug("%s xTaskNotifyWait OK, value = 0x%.8X\r\n", __func__, value);
vTaskDelay(10);
}
}
/* 测试初始化 */
void aTest_Init(void)
{
/* 创建动态任务 */
xTaskCreate(Task1, "Task1", 500, NULL, 5, &p->task1);
xTaskCreate(Task2, "Task2", 500, NULL, 5, &p->task2);
}
/* Key2 PC13 Key0 PH3 Key1 PH2 */
void Exti13_TriggerInterrupt(void)
{
mspExti_Close(13);
if (mspGpio_GetInput("PC13") == 0)
{
}
}