当前位置: 首页 > ops >正文

嵌入式学习笔记 - freeRTOS vTaskPlaceOnEventList()函数解析

vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );

函数第一个参数为消息队列等待插入链表,

void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
{
    configASSERT( pxEventList );

    /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
    SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */

    /* Place the event list item of the TCB in the appropriate event list.
    This is placed in the list in priority order so the highest priority task
    is the first to be woken by the event.  The queue that contains the event
    list is locked, preventing simultaneous access from interrupts. */
    vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );//将当前任务的事件属性插入消息队列等待插入链表

    prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );//将当前任务的状态属性部分插入延时链表
}

结论:

也就是说一个任务有两个属性,

一个是状态属性,可能位于就绪列表,延时列表,挂起列表,其中一个

另一个是事件属性,可能位于挂起等待列表,或者消息队列等待列表

这种设计实现了事件与状态管理的分离

以下是deepseek关于PendingReadyList的解释,待证实供参考

FreeRTOS 会将 xPendingReadyList(或类似机制)中的任务转移出去,主要发生在以下两个关键时机:

  1. 调度请求发生时(任务切换前)‌:当系统需要执行任务切换时(例如调用 taskYIELD()、调用某些可能导致任务切换的 API、中断服务程序(ISR)结束时请求调度 portYIELD_FROM_ISR())18,调度器核心函数 vTaskSwitchContext() 会被调用。在该函数的执行过程中,会检查并处理 xPendingReadyList28。

  2. 系统节拍中断(SysTick)结束时‌:在系统节拍中断服务程序(SysTick ISR)的执行流程中,当它处理完时间相关的任务(如更新阻塞任务的延时计时器、处理时间片轮询)后,在退出中断前通常会触发一个 PendSV 中断(通过向中断控制寄存器写入特定值)1。后续 PendSV 中断服务程序被执行时,其主要工作就是执行上下文切换(任务切换),此时同样会调用 vTaskSwitchContext() 函数,从而处理 xPendingReadyList12。

在 vTaskSwitchContext() 中具体做了什么?

  1. 检查调度器状态‌:首先确认调度器未被挂起或锁定,否则不能进行任务切换1。
  2. 查找最高优先级就绪任务‌:调用类似 taskSELECT_HIGHEST_PRIORITY_TASK() 的宏来查找下一个应该运行的任务18。
  3. 处理 PendingReady List‌:‌正是在查找最高优先级就绪任务之前或过程中,调度器会检查 xPendingReadyList‌27。对于 xPendingReadyList 中的每个任务:
    • 将其 xEventListItem 从 xPendingReadyList 中移除。
    • 根据该任务的优先级,将其 xStateListItem 插入到对应的优先级就绪列表 (pxReadyTasksLists[priority]) 中2。至此,该任务就被真正转移到了就绪态列表,具备了被调度执行的资格
  4. 选择并切换任务‌:完成 xPendingReadyList 的处理后,调度器继续执行查找最高优先级就绪任务的操作(此时刚转移过来的任务也参与了优先级比较),最终确定并切换到下一个要运行的任务 (更新 pxCurrentTCB)18。

为什么会有 xPendingReadyList

  • 分离事件与状态管理‌:xEventListItem 用于事件相关的阻塞和解阻塞操作(如等待信号量、队列、事件组等),而 xStateListItem 用于任务在状态列表(就绪列表、阻塞列表等)中的管理2。
  • 效率与原子性‌:当一个任务在‌中断服务程序(ISR)‌ 中被事件唤醒(如 ISR 释放了一个信号量或向队列发送了数据),该任务需要从阻塞态转移到就绪态。直接在 ISR 中操作就绪列表 (pxReadyTasksLists) 会增加 ISR 执行时间,且可能涉及到复杂的临界区管理。将其临时放入 xPendingReadyList 是一个轻量级的操作27。
  • 延迟处理‌:实际的转移操作(从 xPendingReadyList 到 pxReadyTasksLists)被推迟到调度器下一次执行任务切换的上下文(在 vTaskSwitchContext() 中)进行,这通常是在退出中断后的任务级上下文或 PendSV 中断中,此时进行复杂的状态列表操作更安全、更高效,也确保了任务状态变更的原子性28。

总结:

FreeRTOS 在 ‌任务调度请求发生时(包括显式调用 taskYIELD() 或相关 API)‌ 和 ‌系统节拍中断(SysTick)触发 PendSV 中断后‌,执行任务切换的核心函数 vTaskSwitchContext()。‌正是在 vTaskSwitchContext() 函数中查找下一个要运行的任务之前,系统会检查 xPendingReadyList,将其中的所有任务转移到它们对应优先级的就绪列表 (pxReadyTasksLists) 中‌。这种设计主要是为了高效、安全地处理从中断上下文中唤醒的任务,分离事件处理和状态管理12。

http://www.xdnf.cn/news/12550.html

相关文章:

  • VirtualBox启动失败@Ubuntu22.04 说是配置文件有问题
  • 使用ORM Bee (ormbee) ,如何利用SQLAlchemy的模型生成数据库表.
  • “组件、路由懒加载”,在 Vue3 和 React 中分别如何实现? (copy)
  • 使用Python和Flask构建简单的机器学习API
  • MySQL事务与锁中的MVCC 深度解析与面试题讲解
  • Spring AI 核心工作流
  • 每日Prompt:治愈动漫插画
  • 基于深度学习的金枪鱼各类别目标检测含完整数据集
  • Strong Baseline: Multi-UAV Tracking via YOLOv12 with BoT-SORT-ReID 2025最新无人机跟踪
  • 【C/C++】实现固定地址函数调用
  • 2种官方方法关闭Windows防火墙
  • iOS、Android、鸿蒙、Web、桌面 多端开发框架Kotlin Multiplatform
  • 将单体架构项目拆分成微服务时的两种工程结构
  • 阿里云MaxCompute入门
  • 堆排序的详细解读
  • 5.3.2_2二叉树的线索化
  • 物联网协议之MQTT(二)服务端
  • web端rtmp推拉流测试、抽帧识别计数,一键式生成巡检报告
  • 【第六篇】 SpringBoot的日志基础操作
  • 主流大语言模型安全性测试(三):阿拉伯语越狱提示词下的表现与分析
  • 408第一季 - 数据结构 - 树与二叉树
  • 数 据 结 构 进 阶:哨 兵 位 的 头 结 点 如 何 简 化 链 表 操 作
  • btstack协议栈---Ubuntu驱动CSR8510 USB Dongle
  • 数学:花括号在数学中的应用详解
  • 35 C 语言字符串转数值函数详解:strtof、strtod、strtold(含 errno 处理、ERANGE 错误)
  • Ubuntu挂载本地镜像源(像CentOS 一样挂载本地镜像源)
  • 什么是高考?高考的意义是啥?
  • Ubuntu下有关UDP网络通信的指令
  • Linux 下关于 ioremap 系列接口
  • 虚幻引擎5-Unreal Engine笔记之SET节点的输出引脚获取设置后的最新变量值