FreeRTOS内部机制(三)

7. 任务通知(Task Notification)

在这里插入图片描述

使用队列、信号量、互斥量、事件组等机制时,步骤都是这样的:

  • 创建对象
  • 写/Give
  • 读/Take

对于任务通知,不需要"创建对象",因为要操作的对象就在TCB里:

在这里插入图片描述

任务通知 (Task Notifications) 是一种轻量级、高速的机制,用于替代二值信号量、计数信号量、事件组和队列(在单数据传递场景下)。它直接操作 TCB(任务控制块)中的 ulNotifiedValueeNotifyState,无需额外的内核对象,因此速度最快且节省 RAM

7.1 任务核心: 通知状态、通知值

7.1.1 通知状态

一个任务的"通知状态"有三种:

  • taskNOT_WAITING_NOTIFICATION:任务没有在等待通知
  • taskWAITING_NOTIFICATION:任务在等待通知
  • taskNOTIFICATION_RECEIVED:任务接收到了通知,也被称为 pending(有数据了,待处理)

一个任务想等待别人发来通知,可以调用ulTaskNotifyTake xTaskNotifyWait

  • 可能别人早就发来通知:"通知状态"为taskNOTIFICATION_RECEIVED,那么函数立刻返回
  • 可能别人还没发来通知:这些函数把"通知状态"从taskNOT_WAITING_NOTIFICATION改为taskWAITING_NOTIFICATION,然后休眠

别的任务可以使用xTaskNotifyGivexTaskNotify 给某个任务发通知:

  • 会马上唤醒对方
  • 无条件唤醒对方,不管对方期待什么数据

在这里插入图片描述

7.1.2 通知值

一个整数,调用xTaskNotifyGivexTaskNotify 时,传入不同的参数可以去设置这个数值:

  • 不改变它的数值,只想唤醒任务
  • 增加1
  • 设置为某个数

8.软件定时器

8.1软件定时器核心:硬件定时器+链表+守护任务

8.1.1 硬件定时器

FreeRTOS 必须依赖一个硬件定时器(通常是 Cortex-M 的 SysTick 系统滴答定时器)

它做的唯一一件事:每隔固定时间产生一次中断 → 让系统时钟 +1

SysTick_Handler
    ->xPortSysTickHandler
    	->xTaskIncrementTick
    		const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
8.1.2 定时器列表

FreeRTOS 内核会维护两个双向链表():

  • pxCurrentTimerList 当前到期链表:当前时钟周期内会到期的定时器
  • pxOverflowTimerList 溢出链表:下一个时钟周期(溢出后) 才会到期的定时器

在这里插入图片描述

每当硬件滴答中断触发一次:

  1. xTickCount +1
  2. 内核检查有没有定时器到期
  3. 如果有,就把这个定时器的回调函数命令发送到「定时器队列」

注意:中断里只发命令,不执行回调!

问:定时器列表为什么有两个?

答:系统时钟是会溢出的,FreeRTOS 有一个全局变量:volatile TickType_t xTickCount,每次硬件定时器中断 +1,如果是 32 位:最大到 0xFFFFFFFF,加满后会溢出回 0;如果一个定时器的超时时间跨越了溢出点,内核怎么判断它有没有到期?用两个列表分开存放!

对于pxCurrentTimerList,要进行的操作是:

  • 内核每一个 tick 都会检查这个列表
  • 找到最近要到期的定时器
  • 时间一到 → 移入定时器队列 → 执行回调

对于pxOverflowTimerList,要进行的操作是:

  • 正常情况下不检查
  • 只有当 xTickCount 溢出归 0
  • 才把 整个溢出列表 直接替换给 Current

当系统时钟溢出(xTickCount 从最大值 → 0)执行一次切换动作:

  1. Current 清空
  2. Overflow 的所有定时器 全部移动到 Current
  3. 重置 Overflow 为空

在这里插入图片描述

8.1.3 守护任务

FreeRTOS 会自动创建一个系统任务,它的工作:

  1. 阻塞等待「定时器队列」的命令
  2. 收到命令 → 找到对应定时器
  3. 执行定时器回调函数
  4. 如果是周期定时器 → 重新挂载到链表

在这里插入图片描述

FreeRTOS 定时器守护任务的主循环由两个关键函数构成:

  1. prvProcessTimerOrBlockTask:负责等待事件,要么等定时器到期,要么等命令到来,无任务时阻塞休眠,不占用 CPU 资源
  2. prvProcessReceivedCommands:负责处理命令,被唤醒后一次性处理所有定时器控制命令

8.2 软件定时器流程

应用层
  xTimerCreate() → 创建定时器(休眠)
  xTimerStart()  → 发命令 → xTimerQueue

内核层(守护任务)
  阻塞等待 Queue
  ↓
  收到命令
  ↓
  插入定时器到 Current / Overflow 链表

9.中断

9.1两套API

在学习队列、信号量、互斥量时,我们会发现会有两套API,一套是普通的,另一套会有FromISR后缀,我们将队列作为示例来讲解:

xQueueSend( xQueue, pvItemToQueue, xTicksToWait )
xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken )

首先,为什么要有两套API?

中断上下文不能阻塞,必须专用 API

FreeRTOS 的很多 API(如 xQueueSend())内部会:

  • 等待队列空闲
  • 挂起任务
  • 进入死循环等待

但是!中断里不能等!

  • 中断必须快进快出
  • 中断没有任务调度的概念
  • 一旦阻塞 = 系统死机 / 卡死

所以,中断绝对不能直接调用任务级 API

pxHigherPriorityTaskWoken的作用是什么呢?

首先要知道的是:中断执行时,任务调度器是暂停的,而且中断里不能直接调用任务切换,因为假如下一时刻有一个优先级更高的任务在中断中被唤醒,那么任务切换会一直进行下去,操作系统的实时性得不到保障,因此在中断即将结束时,需要判断:要不要切换去执行更高优先级任务pxHigherPriorityTaskWoken将相当于一个标志位,用来标记是否唤醒了更高优先级的任务

// 1. 定义变量,初始化为 pdFALSE
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

// 2. 调用中断API,把地址传进去
xQueueSendFromISR( xQueue, pvItemToQueue, &xHigherPriorityTaskWoken );

// 3. 内核内部逻辑:
//    如果这个操作唤醒了一个更高优先级任务
//    内核会自动把 xHigherPriorityTaskWoken 设为 pdTRUE

// 4. 最后判断:需要切换就切换
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
9.2 两类中断

FreeRTOS 把 MCU 硬件中断分成两类,唯一区别是:能不能调用 FreeRTOS 的 API(FromISR)

  • 可管理中断(受控中断)

    ​ → 可以调用 FreeRTOS FromISR API

  • 不可管理中断(不受控中断)

    ​ → 绝对不能调用任何 FreeRTOS API

  1. 可管理中断(FreeRTOS 能管的)
  • 优先级 低于或等于 configMAX_SYSCALL_INTERRUPT_PRIORITY
  • FreeRTOS 会临时屏蔽这类中断(进入临界区时)
  • 可以安全调用 FromISR 系列 API

**用途:**普通外设中断(串口、定时器、GPIO、SPI、I2C 等)

需要和任务交互、发信号、发队列、启动定时器


  1. 不可管理中断(FreeRTOS 管不了的)
  • 优先级 高于 configMAX_SYSCALL_INTERRUPT_PRIORITY
  • FreeRTOS 永远不会屏蔽这类中断(即使临界区也不屏蔽)
  • 绝对不能调用任何 FreeRTOS API
  • 执行速度最快、最实时

**用途:**超高实时性要求场景:电机驱动、高精度采样、紧急保护中断等

#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	5

通过配置这个宏,我们可以区别两类中断

  • 优先级 0 ~ 4:不可管理中断(最高优先级)
  • 优先级 5 ~ 15:可管理中断
9.3 优先级

即使最低优先级的中断也可以打断优先级最高的任务

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐