2026-07-17-freertos-ingest.md 31 KB

尚硅谷 FreeRTOS 笔记重构实现计划

目标:将尚硅谷 FreeRTOS 教程 V1.0.3(17 章笔记 + 22 个代码项目 + 48 张图片)转换为 16 篇结构化 Markdown 笔记 目标目录X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/ 设计规范docs/superpowers/specs/2026-07-17-freertos-silicon-valley-ingest-design.md 工作流参考docs/如何将他人文档整理为LLM-Wiki笔记.md

前置准备

需要删除的旧文件

  • X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/assets/ 下的旧图片(全部删除后重建)

源文件路径

内容 路径
完整笔记 F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\01_笔记\尚硅谷嵌入式技术之FreeRTOS实时操作系统1.0.3.md
原始图片 F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\01_笔记\images\media\(48 张 PNG)
代码项目 F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\03_代码\代码\(解压到临时目录)
原理图 F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\02_资料\02_按键案例\SCH_ZET6开发板_1_2024-07-01.pdf

提取代码项目到临时目录

Expand-Archive -LiteralPath "F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\03_代码\代码.zip" -DestinationPath "C:\Users\Administrator\AppData\Local\Temp\opencode\freertos_code" -Force

每篇笔记通用操作步骤

每个笔记的撰写流程如下:

  1. 读取源笔记对应章节:从 尚硅谷嵌入式技术之FreeRTOS实时操作系统1.0.3.md 读取相关章节内容
  2. 读取配套代码项目:读取对应项目的 Core/Src/freertos_demo.cCore/Inc/FreeRTOSConfig.h
  3. 筛选图片:从 images/media/ 中找出与该笔记相关的图片,筛选保留有用的,重命名后复制到 assets/
  4. 撰写笔记:按照设计文档中的模板撰写 Markdown 文件
  5. 写入目标路径:保存到 X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/

图片视觉验证命令模板(用于验证图片内容):

# 调用视觉 API 验证图片内容
function Test-Img {
  param($path, $question)
  $b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes($path))
  $body = @{ model = "qwen3.5-9b-uncensored-nothink"
    messages = @(@{ role = "user"; content = @(
      @{ type = "text"; text = $question }
      @{ type = "image_url"; image_url = @{ url = "data:image/png;base64,$b64" } }
    )})
    max_tokens = 60 } | ConvertTo-Json -Depth 10
  $r = Invoke-RestMethod -Uri "https://api.1808366.xyz/v1/chat/completions" ...
  return $r.choices[0].message.content
}

文件产出清单

目标:X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/

编号 文件名 来源章节 代码项目
01 01-实时操作系统基础.md 第 1 章
02 02-任务调度与状态管理.md 第 2 章
03 03-FreeRTOS移植指南.md 第 3 章(移植 + 源码结构) 00_HAL_Key
04 04-数据类型命名与配置详解.md 第 3 章(数据类型 + 命名 + 配置)
05 05-任务创建与删除.md 第 4 章 01, 02
06 06-任务挂起与恢复.md 第 5 章 03
07 07-中断管理与临界段.md 第 6 章 04
08 08-时间片调度与延时管理.md 第 7 章 + 第 9 章 05, 08
09 09-任务状态查询与运行时统计.md 第 8 章 06, 07
10 10-消息队列.md 第 10 章 09
11 11-信号量机制.md 第 11 章 10, 11, 12, 13
12 12-队列集.md 第 12 章 14
13 13-事件标志组.md 第 13 章 15
14 14-任务通知.md 第 14 章 16, 17, 18
15 15-软件定时器与Tickless低功耗.md 第 15 章 + 第 16 章 19, 20
16 16-内存管理.md 第 17 章 21

附加产出

  • X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/assets/ — 精选图片(15~25 张)
  • wiki/source-freertos.md — 重写资料摘要页
  • wiki/index.md — 更新 FreeRTOS 章节
  • wiki/log.md — 追加变更日志

任务 1:准备图片

1.1 复制全部图片到临时目录

$srcImages = "F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\01_笔记\images\media"
$tmp = "C:\Users\Administrator\AppData\Local\Temp\opencode\freertos_images"
New-Item -ItemType Directory -Path $tmp -Force
Copy-Item "$srcImages\*.png" $tmp

1.2 识别并筛选图片

使用视觉 API 验证每张图片内容。48 张图片的预期内容分类:

图片编号 预期内容 保留? 建议文件名
image1 感知并发 vs 实际多任务图 保留 multitasking_concurrent_vs_actual.png
image2 抢占式调度示意图 保留 scheduling_preemption.png
image3 时间片轮转调度图 保留 scheduling_timeslice.png
image4 任务状态转换图(运行/就绪/阻塞/挂起) 保留 task_state_diagram.png
image5 就绪列表位图 保留 ready_list_bitmap.png
image6 同优先级就绪列表 保留 ready_list_same_priority.png
image7 上下文切换步骤图(保存上下文) 保留 context_switch_save.png
image8 上下文切换步骤图(恢复上下文) 保留 context_switch_restore.png
image9 FreeRTOS 官网下载页面截图 删除
image10 GitHub 下载页面截图 删除
image11 RVDS 文件夹结构截图 删除(可文字描述)
image12 heap 文件列表截图 删除(可文字描述)
image13~image27 Keil 工程添加文件步骤截图 全部删除(IDE 操作截图)
image28~image29 寄存器版 Keil 添加截图 全部删除(IDE 操作截图)
image30~image43 配置截图/CubeMX 截图 全部删除(IDE 操作截图)
image44 队列结构图 保留 queue_structure.png
image45 事件标志组位结构图 保留 event_group_bits.png
image46 定时器状态切换图 保留 timer_state_diagram.png
image47 STM32 低功耗模式图 保留 stm32_low_power_modes.png
image48 三种 heap 算法结构对比 保留 heap_comparison.png

筛选后预计保留约 14 张图片,其余 34 张删除。

1.3 重命名并复制到 assets

$target = "X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/assets"
New-Item -ItemType Directory -Path $target -Force

# 保留的图片按映射命名复制
Copy-Item "$tmp\image1.png" "$target\multitasking_concurrent_vs_actual.png"
Copy-Item "$tmp\image2.png" "$target\scheduling_preemption.png"
Copy-Item "$tmp\image3.png" "$target\scheduling_timeslice.png"
Copy-Item "$tmp\image4.png" "$target\task_state_diagram.png"
Copy-Item "$tmp\image5.png" "$target\ready_list_bitmap.png"
Copy-Item "$tmp\image6.png" "$target\ready_list_same_priority.png"
Copy-Item "$tmp\image7.png" "$target\context_switch_save.png"
Copy-Item "$tmp\image8.png" "$target\context_switch_restore.png"
Copy-Item "$tmp\image44.png" "$target\queue_structure.png"
Copy-Item "$tmp\image45.png" "$target\event_group_bits.png"
Copy-Item "$tmp\image46.png" "$target\timer_state_diagram.png"
Copy-Item "$tmp\image47.png" "$target\stm32_low_power_modes.png"
Copy-Item "$tmp\image48.png" "$target\heap_comparison.png"

任务 2:笔记 01 — 实时操作系统基础.md

来源章节:源笔记第 1 章(操作系统介绍 = 什么是裸机开发/什么是操作系统/通用OS/RTOS/FreeRTOS简介/发展历史/优势/特点)

代码项目:无

图片:无

撰写要点

  • 解释裸机开发的局限性:所有代码在 while(1) 循环中顺序执行,实时性无法保证
  • 对比通用 OS(Linux/Windows)与 RTOS(FreeRTOS/uCOS)的核心区别
  • FreeRTOS 的七个特点:任务调度、任务通信、内存管理、定时器、社区、可移植性
  • 用安全气囊 30ms 响应时间的例子说明"强大计算能力 ≠ 实时性"
  • FreeRTOS 发展历史:2003 Richard Barry → 2017 AWS 收购
  • 开源免费 ≠ 免费用于商业产品

模板参考

---
tags: [source-summary]
type: source
source: "尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3 — 第1章:操作系统介绍 + FreeRTOS简介"
author: "尚硅谷研究院"
date: 2026-07-17
created: 2026-07-17
---

# 实时操作系统基础

> **用生活理解**:如果把单片机比作一个厨师——裸机开发就像厨师必须自己记住每道菜的所有步骤,亲力亲为;RTOS 就像是给厨师配了一个帮厨团队——帮厨(操作系统)负责管理炒菜顺序、准备材料、分配时间,厨师(应用程序)只需专注于做菜本身。

## 什么是裸机开发

### 基本概念
...

速查表内容

无 API 速查表。本笔记以概念为主。


任务 3:笔记 02 — 任务调度与状态管理.md

来源章节:源笔记第 2 章(多任务处理/任务调度/任务状态/滴答/上下文切换/空闲任务)

代码项目:无(概念篇)

图片:image1~image8

撰写要点

  • 多任务处理:单核处理器的"并发假象"——任务间快速切换
  • 调度策略三要素:抢占式(高优先级抢占低)、时间片轮询(同优先级轮流)、协程式(任务主动让出)
  • 四任务状态详解:运行、就绪、阻塞、挂起,以及转换关系
    • 阻塞态 vs 挂起态的本质区别:阻塞态等待事件自动恢复,挂起态需手动恢复
  • 滴答计数器:系统时基,SysTick 定时器产生
  • 上下文切换流程:
    1. TaskA 上下文保存到堆栈(R0-R12, SP, LR, PC, xPSR)
    2. 选择下一个任务
    3. TaskB 上下文从堆栈恢复到寄存器
    4. PendSV 异常处理(最低优先级,避免影响其他 ISR)
  • 触发上下文切换的三种情况:Tick 中断、任务执行完毕、任务主动挂起
  • 空闲任务:自动创建(最低优先级),三个作用(释放已删除任务内存、提供 CPU 空闲计数、进入低功耗模式)
  • 就绪列表:pxReadyTasksLists[x] 位图索引,32 位变量代表 0-31 优先级

图片引用

![感知并发 vs 实际多任务](assets/multitasking_concurrent_vs_actual.png)
![抢占式调度](assets/scheduling_preemption.png)
![时间片轮转](assets/scheduling_timeslice.png)
![任务状态转换图](assets/task_state_diagram.png)
![就绪列表位图](assets/ready_list_bitmap.png)
![同优先级就绪列表](assets/ready_list_same_priority.png)
![上下文切换 — 保存](assets/context_switch_save.png)
![上下文切换 — 恢复](assets/context_switch_restore.png)

任务 4:笔记 03 — FreeRTOS移植指南.md

来源章节:源笔记第 3 章(源码结构 + HAL 库移植 + 寄存器移植)

代码项目00_HAL_Key(无 FreeRTOS 的纯 HAL 基础工程)

撰写要点

  • 源码结构总览:FreeRTOS 内核(Source 7 个 .c + include + portable)
  • Source 目录 7 个核心文件:tasks.c、queue.c、timers.c、event_groups.c、croutine.c、list.c、stream_buffer.c
  • Portable 目录:不同编译器+内核的移植层,ARM_CM3 = port.c + portmacro.h
  • MemMang 5 种 heap:各有适用场景,初学用 heap_4
  • HAL 库移植步骤(逐条说明):
    1. 新建 FreeRTOS 文件夹
    2. 拷贝 7 个 .c 到 source
    3. 拷贝 portable 中 Keil/RVDS/MemMang
    4. 拷贝 include 头文件
    5. 拷贝 FreeRTOSConfig.h 并修改
    6. Keil 添加两个 Group(Source + Portable),添加 .c 文件
    7. 添加头文件路径
    8. 修改 FreeRTOSConfig.h(xPortPendSVHandler、vPortSVCHandler、INCLUDE_xTaskGetSchedulerState)
    9. 修改 stm32f1xx_it.c:注释 SVC_Handler 和 PendSV_Handler,添加 SysTick_Handler 回调
    10. 解决 HAL+SysTick 冲突问题(SYS 选择其他时钟源,中断优先级设为 1)
  • 寄存器移植:步骤类似,在 main.c 添加 SysTick_Handler
  • 配置文件说明:INCLUDE_ 前缀(函数使能)、config 前缀(功能配置)、其他

图片引用

使用文字描述代替 IDE 操作截图。可引用一张源码结构示意图(如有),但大多数 IDE 截图删除。

速查表

移植检查清单:

步骤 检查项 是否完成
1 FreeRTOS/Source 包含 7 个 .c
2 FreeRTOS/portable/RVDS/ARM_CM3 有 port.c + portmacro.h
3 MemMang 包含 heap_4.c
4 FreeRTOS/include 全部头文件
5 FreeRTOSConfig.h 已修改
6 stm32f1xx_it.c 中 SVC/PendSV 已注释
7 SysTick_Handler 已添加 xPortSysTickHandler 调用
8 HAL 定时器源已切换(避免与 FreeRTOS 冲突)

任务 5:笔记 04 — 数据类型命名与配置详解.md

来源章节:源笔记第 3 章后半(数据类型/命名规范/FreeRTOSConfig.h 配置说明)

代码项目:无

撰写要点

  • 数据类型表:
类型 描述 默认定义 配置决定
TickType_t 滴答计数值 uint32_t configUSE_16_BIT_TICKS
BaseType_t 最自然类型 uint32_t(Cortex-M3) 架构相关
StackType_t 堆栈单位 uint32_t 架构相关
  • 命名前缀表:
前缀 含义 示例
v 返回 void vTaskDelete
x 返回 BaseType_t 或非 void 结构体 xQueueCreate
ux 返回 UBaseType_t uxTaskGetNumberOfTasks
pv 返回 void* pvPortMalloc
h 句柄类型后缀 TaskHandle_t
pd 协议定义(projdefs.h) pdTRUE, pdPASS
  • FreeRTOSConfig.h 全配置项参考(分组列出所有项,标注默认值和课程常用值)

任务 6:笔记 05 — 任务创建与删除.md

来源章节:源笔记第 4 章(任务创建和删除)

代码项目:01(动态创建删除)、02(静态创建删除)

撰写要点

  • 任务 = 无限循环函数 + 堆栈 + TCB
  • 动态创建 vs 静态创建:xTaskCreate 自动分配 vs xTaskCreateStatic 预先分配
  • 完整代码展示 01 项目的 freertos_demo.c(作为通用模板参考)
  • 静态创建需要 vApplicationGetIdleTaskMemoryvApplicationGetTimerTaskMemory 钩子

代码提取(项目 01 — 动态创建删除)

03_代码/01_动态创建任务和删除/Core/Src/freertos_demo.c 提取:

  • freertos_start() 函数(创建 start_task + vTaskStartScheduler)
  • start_task() 函数(taskENTER_CRITICAL → 创建 3 个任务 → vTaskDelete(NULL) → taskEXIT_CRITICAL)
  • task1() LED 切换 + task2() LED 切换 + task3() 按键检测删除 task1

代码提取(项目 02 — 静态创建删除)

03_代码/02_静态创建任务和删除/Core/Src/freertos_demo.c 提取:

  • 使用 xTaskCreateStatic 的差异点
  • vApplicationGetIdleTaskMemoryvApplicationGetTimerTaskMemory 钩子实现

关键配置

// 静态分配需要开启
#define configSUPPORT_STATIC_ALLOCATION  1

// 软件定时器任务配置(静态创建需要)
#define configUSE_TIMERS                 1
#define configTIMER_TASK_PRIORITY        4
#define configTIMER_QUEUE_LENGTH         5
#define configTIMER_TASK_STACK_DEPTH     256

任务 7:笔记 06 — 任务挂起与恢复.md

来源章节:源笔记第 5 章(任务挂起与恢复)

代码项目:03(任务挂起与恢复)

撰写要点

  • 挂起态:任务暂停,不参与调度,需要手动恢复
  • 单任务控制:vTaskSuspend() / vTaskResume()
  • 调度器控制:vTaskSuspendAll() / xTaskResumeAll()
  • 挂起 vs 阻塞 vs 删除深度对比

代码提取(项目 03)

提取 03_代码/03_任务挂起与恢复/Core/Src/freertos_demo.c

  • KEY1 = vTaskSuspend(task1)
  • KEY2 = vTaskResume(task1)
  • KEY3 = vTaskSuspendAll()
  • KEY4 = xTaskResumeAll()
  • vTaskList() 打印当前任务状态

任务 8:笔记 07 — 中断管理与临界段.md

来源章节:源笔记第 6 章(中断管理)

代码项目:04(中断管理)

撰写要点

  • FreeRTOS 中断管理策略:关中断(临界区)/ BASEPRI(屏蔽低于阈值的中断)
  • taskENTER_CRITICAL() / taskEXIT_CRITICAL() — 嵌套计数器
  • portDISABLE_INTERRUPTS() / portENABLE_INTERRUPTS()
  • 中断安全 API 后缀:FromISR 版本(如 xQueueSendFromISR
  • configMAX_SYSCALL_INTERRUPT_PRIORITY:FreeRTOS 可管理的中断优先级阈值
  • 延迟中断处理(Deferred Interrupt Processing):ISR 中发信号通知任务处理

代码提取(项目 04)

提取 03_代码/04_中断管理/Core/Src/freertos_demo.c

  • KEY1 = portDISABLE_INTERRUPTS()
  • KEY2 = portENABLE_INTERRUPTS()

关键配置

#define configKERNEL_INTERRUPT_PRIORITY        (15 << 4)
#define configMAX_SYSCALL_INTERRUPT_PRIORITY   (5 << 4)

任务 9:笔记 08 — 时间片调度与延时管理.md

来源章节:源笔记第 7 章(时间片调度)+ 第 9 章(时间管理/延时函数)

代码项目:05(时间片调度)、08(延时函数对比)

撰写要点

  • 时间片调度:同优先级任务轮流执行一个 Tick 时间
  • configUSE_TIME_SLICING 控制开关
  • vTaskDelay() — 相对延时(从调用开始算,可能漂移)
  • vTaskDelayUntil() — 绝对延时(从上次唤醒算,固定周期)
  • HAL_Delay() vs vTaskDelay() 区别:前者忙等(不释放 CPU),后者阻塞(让出 CPU)

代码提取(项目 05)

提取 03_代码/05_时间片调度/Core/Src/freertos_demo.c

  • 2 个同优先级任务进入临界区 → 打印计数 → HAL_Delay(10) → 退出临界区
  • 演示时间片轮转效果

代码提取(项目 08)

提取 03_代码/08_时间延时函数/Core/Src/freertos_demo.c

  • task1 使用 vTaskDelay(500) 切换 LED1(漂移)
  • task2 使用 vTaskDelayUntil(&pxPreviousWakeTime, 500) 切换 LED2(固定周期)
  • 两者都额外使用 HAL_Delay(20) 模拟工作负载,观察漂移差异

关键配置

// 项目 05 将滴答频率降低到 50ms 方便观察时间片
#define configTICK_RATE_HZ         20
#define configUSE_TIME_SLICING     1

任务 10:笔记 09 — 任务状态查询与运行时统计.md

来源章节:源笔记第 8 章(任务相关 API 函数)

代码项目:06(任务状态查询)、07(运行时统计)

撰写要点

  • 任务查询 API 全家桶:
    • 优先级:uxTaskPriorityGet() / vTaskPrioritySet()
    • 数量:uxTaskGetNumberOfTasks()
    • 系统状态:uxTaskGetSystemState() / vTaskGetInfo()
    • 句柄:xTaskGetCurrentTaskHandle() / xTaskGetHandle()
    • 栈余量:uxTaskGetStackHighWaterMark()
    • 状态:eTaskGetState()
    • 列表:vTaskList()
  • 运行时统计需要额外硬件定时器提供高精度时钟源

代码提取(项目 06)

提取 03_代码/06_任务状态查询/Core/Src/freertos_demo.c

  • task2 中一次性调用所有查询 API 并打印结果

代码提取(项目 07)

提取 03_代码/07_任务时间统计/Core/Src/freertos_demo.c

  • task2 周期打印 vTaskGetRunTimeStats()

关键配置

#define configUSE_TRACE_FACILITY             1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define configGENERATE_RUN_TIME_STATS        1

任务 11:笔记 10 — 消息队列.md

来源章节:源笔记第 10 章(消息队列)

代码项目:09(消息队列)

撰写要点

  • 队列本质:内核对象,任务间传递数据的 FIFO 缓冲区
  • 写时拷贝(Copy by Value)而非引用传递
  • 队列内部结构:环形缓冲区 + 发送等待列表 + 接收等待列表
  • 阻塞机制:队列入队/出队时可选阻塞时间
  • xQueueCreate() 参数说明

代码提取(项目 09)

提取 03_代码/09_消息队列/Core/Src/freertos_demo.c

  • queue1 = xQueueCreate(2, sizeof(uint8_t)) — 按键值队列
  • big_queue = xQueueCreate(1, sizeof(char*)) — 大字符串指针队列
  • task1:KEY1/KEY2 → xQueueSend(queue1, &key, portMAX_DELAY)
  • task1:KEY3 → xQueueSend(big_queue, &big_data, portMAX_DELAY)
  • task2:xQueueReceive(queue1, &receive, portMAX_DELAY)
  • task3:xQueueReceive(big_queue, &receive_buff, portMAX_DELAY)

关键配置

#define configQUEUE_REGISTRY_SIZE   8

任务 12:笔记 11 — 信号量机制.md

来源章节:源笔记第 11 章(信号量 — 二值/计数/优先级翻转/互斥)

代码项目:10(二值信号量)、11(计数信号量)、12(优先级反转)、13(互斥信号量)

撰写要点

  • 信号量本质:基于队列实现,队列长度为 1(二值)或 N(计数)
  • 二值信号量:vSemaphoreCreateBinary → xSemaphoreGive → xSemaphoreTake
  • 计数信号量:xSemaphoreCreateCounting(max, init) → 每次 Give 计数值 +1
  • 优先级反转:低优先级任务持有信号量 → 高优先级等待 → 中优先级抢断 → 高优先级被阻塞
    • 类比"倒反天罡":低级任务反而"压"着高级任务
  • 互斥信号量:内置优先级继承机制,解决优先级反转
    • 当高优先级等待时,低优先级临时提升到高优先级(继承),完成后再降回原优先级
  • 区别对比表:
特性 二值信号量 计数信号量 互斥量
初始值 0 用户指定 1
最大值 1 用户指定 1
优先级继承
递归获取 可配置
适用场景 事件通知 资源计数 互斥访问

代码提取(项目 10 — 二值信号量)

提取 03_代码/10_二值信号量/Core/Src/freertos_demo.c

  • task1:KEY1 → xSemaphoreGive
  • task2:xSemaphoreTake(sem_handle, portMAX_DELAY) 阻塞等待

代码提取(项目 12 — 优先级反转)

提取 03_代码/12_优先级翻转/Core/Src/freertos_demo.c

  • task1(prio 2):持有信号量 → HAL_Delay(3000)
  • task2(prio 3):中等优先级持续运行
  • task3(prio 4):尝试获取信号量 → 被 task1 持有,等待

代码提取(项目 13 — 互斥信号量)

提取 03_代码/13_互斥信号量/Core/Src/freertos_demo.c

  • 与项目 12 相同结构,但使用 xSemaphoreCreateMutex() 替代 vSemaphoreCreateBinary()

关键配置

#define configUSE_COUNTING_SEMAPHORES   1
#define configUSE_MUTEXES               1
#define configUSE_RECURSIVE_MUTEXES     1

任务 13:笔记 12 — 队列集.md

来源章节:源笔记第 12 章(队列集)

代码项目:14(队列集)

撰写要点

  • 队列集解决"同时等待多个队列/信号量"的问题
  • 工作原理:将队列/信号量注册到集合 → 集合中任一成员有数据即通知
  • 限制:队列集中的队列/信号量不能被独立删除

代码提取(项目 14)

提取 03_代码/14_队列集/Core/Src/freertos_demo.c

  • xQueueCreateSet(queue_set_size) — 集合大小 = 成员项数之和
  • xQueueAddToSet(queue1, queue_set_handle) — 注册队列
  • xQueueAddToSet(sem_handle, queue_set_handle) — 注册信号量
  • xQueueSelectFromSet(queue_set_handle, portMAX_DELAY) — 等待任一成员
  • KEY1 → 加入队列,KEY2 → 给出信号量

关键配置

#define configUSE_QUEUE_SETS   1

任务 14:笔记 13 — 事件标志组.md

来源章节:源笔记第 13 章(事件标志组)

代码项目:15(事件标志组)

撰写要点

  • 事件标志组 = 24 位可用的位集合(RTOS 保留高 8 位)
  • xEventGroupWaitBits() 中的等待逻辑:AND(全部满足)vs OR(任一满足)
  • 清除模式:退出时自动清除(pdTRUE)或手动清除(pdFALSE)

代码提取(项目 15)

提取 03_代码/15_事件标志组/Core/Src/freertos_demo.c

  • event_group_handle = xEventGroupCreate()
  • task1:KEY1 → xEventGroupSetBits(event_group_handle, EVENTBIT_0)
  • task1:KEY2 → xEventGroupSetBits(event_group_handle, EVENTBIT_1)
  • task2:xEventGroupWaitBits(handle, BIT0|BIT1, pdTRUE, pdTRUE, portMAX_DELAY) — 等两个位都置1

图片引用

![事件标志组位结构](assets/event_group_bits.png)

任务 15:笔记 14 — 任务通知.md

来源章节:源笔记第 14 章(任务通知)

代码项目:16(通知模拟信号量)、17(通知模拟消息队列)、18(通知模拟事件标志组)

撰写要点

  • 任务通知:每个 TCB 内置 32 位通知值 + 8 位通知状态
  • 三种模式:
    1. 模拟信号量:xTaskNotifyGive() / ulTaskNotifyTake() — 计数值累加/递减
    2. 模拟消息队列:xTaskNotify(handle, value, eSetValueWithOverwrite) — 覆写通知值
    3. 模拟事件标志组:xTaskNotify(handle, bits, eSetBits) — 按位或置位
  • 优势:比独立 IPC 快 ~45%(无额外内核对象创建)
  • 限制:只能一对一(一个任务通知另一个),不能一对多

代码提取(项目 16 — 模拟信号量)

提取 03_代码/16_任务通知模拟信号量/Core/Src/freertos_demo.c

  • task1:KEY1 → xTaskNotifyGive(task2_handle)
  • task2:ulTaskNotifyTake(pdFALSE, portMAX_DELAY) — 计数值递减

代码提取(项目 17 — 模拟消息队列)

提取 03_代码/17_任务通知模拟消息队列/Core/Src/freertos_demo.c

  • task1:KEY1/KEY2 → xTaskNotify(task2_handle, key_value, eSetValueWithOverwrite)
  • task2:xTaskNotifyWait(ulBitsToClearOnEntry, ulBitsToClearOnExit, &notification_value, portMAX_DELAY)

代码提取(项目 18 — 模拟事件标志组)

提取 03_代码/18_任务通知模拟事件标志组/Core/Src/freertos_demo.c

  • task1:KEY1 → xTaskNotify(task2_handle, EVENTBIT_0, eSetBits)
  • task1:KEY2 → xTaskNotify(task2_handle, EVENTBIT_1, eSetBits)
  • task2:xTaskNotifyWait(0, ULONG_MAX, &notify_val, portMAX_DELAY) 并检查位

任务 16:笔记 15 — 软件定时器与Tickless低功耗.md

来源章节:源笔记第 15 章(软件定时器)+ 第 16 章(Tickless 低功耗模式)

代码项目:19(软件定时器)、20(Tickless 低功耗)

软件定时器部分

  • 软件定时器基于 Tick 计数(非硬件定时器)
  • 状态机:休眠 → 运行 → 暂停
  • 一次性(AutoReload = pdFALSE)vs 周期性(AutoReload = pdTRUE)
  • 定时器命令队列:所有 API 通过队列向定时器服务任务发送命令
  • 定时器服务任务:一个标准 FreeRTOS 任务,处理所有定时器回调

Tickless 部分

  • Tickless 模式:空闲任务进入低功耗模式,暂停 SysTick 中断以省电
  • configUSE_TICKLESS_IDLE:开启/关闭
  • configPRE_SLEEP_PROCESSING(x)configPOST_SLEEP_PROCESSING(x) — 用户在休眠前后执行的自定义操作
  • 最小空闲时间:configEXPECTED_IDLE_TIME_BEFORE_SLEEP(太短则不休眠)

代码提取(项目 19 — 软件定时器)

提取 03_代码/19_软件定时器/Core/Src/freertos_demo.c

  • timer1 = xTimerCreate("timer1", 500, pdFALSE, NULL, timer1_callback) — 一次性
  • timer2 = xTimerCreate("timer2", 1000, pdTRUE, NULL, timer2_callback) — 周期性
  • task1:KEY1 → xTimerStart(),KEY2 → xTimerStop()

代码提取(项目 20 — Tickless)

提取 03_代码/20_低功耗模式/Core/Src/freertos_demo.c

  • 信号量驱动:task1 KEY1 → xSemaphoreGive → task2 接收
  • configPRE_SLEEP_PROCESSING(x) → 休眠前关 GPIO 时钟
  • configPOST_SLEEP_PROCESSING(x) → 唤醒后开 GPIO 时钟

关键配置

// 软件定时器
#define configUSE_TIMERS              1
#define configTIMER_TASK_PRIORITY     4
#define configTIMER_QUEUE_LENGTH      5
#define configTIMER_TASK_STACK_DEPTH  256

// Tickless
#define configUSE_TICKLESS_IDLE       1

图片引用

![定时器状态切换图](assets/timer_state_diagram.png)
![STM32 低功耗模式](assets/stm32_low_power_modes.png)

任务 17:笔记 16 — 内存管理.md

来源章节:源笔记第 17 章(内存管理 — heap_1~5)

代码项目:21(内存管理)

撰写要点

  • FreeRTOS 内存分配发生在:任务创建(堆栈+TCB)、队列创建、信号量创建、定时器创建
  • 5 种 heap 算法对比:
算法 分配策略 释放 碎片 适用场景
heap_1 简单数组分配 不支持释放 不删除任务/队列
heap_2 最佳匹配链表 支持释放 随意分配释放
heap_3 包装 malloc/free 标准 C 库 取决于 C 库 线程安全需要
heap_4 首序匹配 + 合并 合并相邻空闲块 优干 heap_2 默认推荐
heap_5 同 heap_4 跨非连续 RAM 区域 同 heap_4 多 RAM 区域
  • pvPortMalloc() / vPortFree() / xPortGetFreeHeapSize()

代码提取(项目 21)

提取 03_代码/21_内存管理/Core/Src/freertos_demo.c

  • task1:KEY1 → buff = pvPortMalloc(20) → 打印 xPortGetFreeHeapSize()
  • task1:KEY2 → vPortFree(buff) → 打印堆大小

图片引用

![三种 heap 算法结构对比](assets/heap_comparison.png)

任务 18:更新 Wiki

18.1 重写 wiki/source-freertos.md

  • 笔记列表改为 16 篇新笔记映射
  • 代码项目映射表更新

18.2 更新 wiki/index.md

  • FreeRTOS 章节保持不变(wikilink 指向 wiki 页不受影响)
  • 确认原始笔记路径条目已更新到最新目录结构

18.3 追加 wiki/log.md

## 2026-07-17

- `lint`: 重构 FreeRTOS raw 笔记(16 篇)
    - 旧 11 篇笔记 → 新 16 篇笔记,按课程章节一对一/合并映射
    - 代码来源:22 个正式 Keil 项目
    - 图片精选:48 张 → 约 14 张(删除 IDE/Keil 配置截图)
    - 每篇标准结构:frontmatter + 生活类比 + 概念 + 实验代码 + API 速查表 + 避坑
    - 遵循设计规范:`docs/superpowers/specs/2026-07-17-freertos-silicon-valley-ingest-design.md`
    
    新笔记列表:
    - 01 ~ 16 覆盖:实时操作系统基础/任务调度与状态管理/移植指南/数据类型命名与配置/任务创建删除/挂起恢复/中断管理临界段/时间片调度延时管理/任务状态查询运行时统计/消息队列/信号量机制/队列集/事件标志组/任务通知/软件定时器与Tickless低功耗/内存管理

    更新 `wiki/source-freertos.md`、`wiki/index.md`、`wiki/log.md`

最终验证清单

  • 16 篇笔记全部写入目标目录
  • 每篇笔记 frontmatter 完整
  • 每篇笔记有 > **用生活理解**: 类比
  • 代码路径引用指向真实项目文件
  • API 调用行有中文注释
  • 图片路径引用(assets/xxx.png)有效
  • 无冗余 IDE 操作截图保留
  • wiki/source-freertos.md 已更新
  • wiki/index.md 已更新
  • wiki/log.md 已追加