Sfoglia il codice sorgente

docs: 更新转化流程文档,支持多语言和有机整合

OpenCode 2 settimane fa
parent
commit
ab1c2fe76a

+ 120 - 0
docs/markdown-to-code-workflow.md

@@ -0,0 +1,120 @@
+# 学习笔记 → 示例代码 转化流程
+
+将 `raw/` 中的 Markdown 学习笔记转化为可编译、通过 linter 检查的示例代码。
+
+## 核心原则
+
+**有机整合,不要割裂。** 一个文档的多个知识点应该融入同一段代码,而非每个知识点单独写一个示例。
+
+反例(割裂):
+
+```cpp
+// 知识点1:封装
+class A { public: int x; };
+
+// 知识点2:继承
+class B : public A {};
+
+// 知识点3:多态
+// ...又一个独立的类
+```
+
+正例(整合):
+
+```cpp
+// 一个 Vehicle 继承体系,同时覆盖封装、构造析构、深拷贝、继承、多态
+class Vehicle { ... };
+class Car : public Vehicle { ... };
+class Truck final : public Vehicle { ... };
+```
+
+## 流程
+
+### 1. 读取原始笔记
+
+读取目标 `.md` 文件,通读全部知识点。
+
+### 2. 提取核心知识点
+
+从笔记中提炼出所有需要演示的知识点,按主题分组。
+
+### 3. 设计代码结构
+
+根据语言特性和知识点类型选择组织方式:
+
+**OOP 语言(C++、Java、C# 等)**:用 2~3 个有继承关系的类,让父类承载大部分知识点,子类演示扩展和多态。
+
+**过程式语言(C 等无类语言)**:按功能模块组织,一个 `.c` 文件覆盖多个知识点,用函数分组,用注释标注知识点编号。
+
+**算法示例**:一个完整的算法实现(如排序、查找、链表操作),在实现过程中自然覆盖该文档的所有知识点。
+
+设计目标:
+
+- 知识点之间有逻辑关联,不是孤立的
+- 代码能体现知识点之间的协作关系
+- 结构紧凑,没有为了凑知识点而加的冗余代码
+
+### 4. 编写代码
+
+- 简洁为上,不引入不必要的复杂度
+- 关键字和概念处加注释,说明"这是什么"和"为什么这样写"
+- 不使用语言级别的 namespace/import 全局导入,标准库类型显式限定
+- 魔法数字用命名常量替代
+- 变量名语义清晰,长度符合 linter 要求
+- 不写冗余代码:能一行的不写三行,能省略的模板代码不重复
+
+### 5. 按编号标注知识点
+
+注释中用 `1.` `2.` `3.` 等简单编号标注每个知识点对应的代码位置,便于查阅。
+
+### 6. 运行 linter / 静态分析
+
+使用项目根目录下的 linter 配置文件:
+
+```bash
+# C++
+clang-tidy "文件路径" -p "项目根目录" -- -std=c++17
+
+# C
+clang-tidy "文件路径" -p "项目根目录" -- -std=c11
+
+# Python
+ruff check "文件路径"
+
+# JavaScript / TypeScript
+eslint "文件路径"
+
+# Go
+golangci-lint run
+```
+
+### 7. 重新检查直到用户代码 0 警告
+
+重复步骤 4-6,直到 linter 只报告外部依赖的警告,用户代码无警告。
+
+### 8. 验证逻辑正确性
+
+手动确认:
+
+- 静态成员计数正确(构造时 `++`、析构时 `--`)
+- 深拷贝真正分配了新资源
+- 虚析构/析构函数存在(父类指针释放子类不泄漏)
+
+## 语言适配
+
+| 语言       | 组织方式                    | 注意事项                                     |
+| ---------- | --------------------------- | -------------------------------------------- |
+| C++        | 类继承体系                  | 虚析构、Rule of Five、const 成员函数         |
+| C          | 按功能模块分函数组          | 结构体 + 函数指针模拟多态,static 文件作用域 |
+| Java       | 接口 + 抽象类 + 实现类      | 强制 Rule of Five,接口隔离                  |
+| Python     | 基类 + 子类,或函数式       | `@property`、`__init__`、`abc.ABC`     |
+| Go         | 结构体 + 方法,接口隐式实现 | 无继承,用组合替代                           |
+| JavaScript | 原型链或 class 语法         | `class`、`extends`、`static`           |
+| 算法       | 单文件完整实现              | 主函数演示 + 核心算法函数,注释标注复杂度    |
+
+## 注意事项
+
+- 注释精简,只在关键知识点处标注,不写大段重复解释
+- 语言特有属性(如 C++ 的 `[[nodiscard]]`)按项目 linter 配置要求添加
+- `friend` 等破坏封装的用法,注释中说明"谨慎使用"
+- 不要为了覆盖知识点而写无意义的代码,每个知识点都应有实际用途

+ 0 - 0
docs/如何将他人文档整理为LLM-Wiki笔记.md → docs/organize-documents-into-wiki.md


+ 0 - 805
docs/superpowers/plans/2026-07-15-stm32-ingest.md

@@ -1,805 +0,0 @@
-# 尚硅谷 STM32 笔记导入实现计划
-
-> **For agentic workers:** REQUIRED SUB-SKILL: 使用 `subagent-driven-development` 或 `executing-plans` 逐任务执行。复选框 `- [ ]` 标记跟踪进度。
-
-**目标**:将尚硅谷 STM32 全套 4 份 DOCX 笔记 + 配套源码转换为 21 篇结构化 Markdown 笔记,存入 `X-Knowledge-Base/raw/Joplin/嵌入式+Linux/STM32学习笔记/`
-
-**处理方法**:每批次:pandoc 转 MD → 按章节拆篇 → 逐篇扩写(参考手册引用 + 原理图引用 + 网络资料补充)→ 从源码复制代码 + 逐行注释 → 图片 API 验证 → git 提交
-
-**参考资料**:
-
-- `docs/如何将他人文档整理为LLM-Wiki笔记.md`
-- `docs/superpowers/specs/2026-07-15-stm32-silicon-valley-ingest-design.md`
-- `X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/01-*.md`(自由格式参考)
-
-**图片 API**:使用视觉模型逐张验证图片内容,仅保留寄存器位域图/框图/时序图/原理图
-
-**最终提交**:全部 4 批次完成后,统一次提交 `ingest: 尚硅谷STM32全套笔记导入`
-
----
-
-## 文件产出清单
-
-### 目标目录:`X-Knowledge-Base/raw/Joplin/嵌入式+Linux/STM32学习笔记/`
-
-| 编号 | 文件名                                | 来源 DOCX | 代码项目         |
-| ---- | ------------------------------------- | --------- | ---------------- |
-| 01   | `01-STM32概述与开发环境搭建.md`       | 基础篇    | —                |
-| 02   | `02-GPIO寄存器详解与三步进化法.md`    | 基础篇    | —                |
-| 03   | `03-GPIO输出:LED控制.md`             | 基础篇    | stm32_base/01~04 |
-| 04   | `04-GPIO输入与NVIC中断系统.md`        | 基础篇    | stm32_base/05~06 |
-| 05   | `05-系统时钟RCC详解.md`               | 基础篇    | —                |
-| 06   | `06-串口USART通信.md`                 | 基础篇    | stm32_base/07~12 |
-| 07   | `07-I2C通信与EEPROM 24C02.md`         | 进阶篇    | stm32_base/13~15 |
-| 08   | `08-SysTick与通用定时器TIM.md`        | 进阶篇    | stm32_base/16~19 |
-| 09   | `09-TIM高级应用:PWM与输入捕获.md`    | 进阶篇    | stm32_base/20~27 |
-| 10   | `10-DMA数据传输.md`                   | 进阶篇    | stm32_base/28~31 |
-| 11   | `11-ADC模数转换.md`                   | 进阶篇    | stm32_base/32~35 |
-| 12   | `12-SPI通信与FSMC总线.md`             | 进阶篇    | stm32_base/36~42 |
-| 13   | `13-CAN通信协议与bxCAN外设.md`        | 高级篇    | stm32/01~04      |
-| 14   | `14-以太网通信与W5500.md`             | 高级篇    | stm32/05~09      |
-| 15   | `15-WiFi通信与ESP32-C3.md`            | 高级篇    | stm32/10~11      |
-| 16   | `16-BLE低功耗蓝牙.md`                 | 高级篇    | stm32/12         |
-| 17   | `17-LoRa远距离通信.md`                | 高级篇    | stm32/13~14      |
-| 18   | `18-电源管理与低功耗模式.md`          | 扩展篇    | stm32/15~20      |
-| 19   | `19-BKP备份寄存器与RTC实时时钟.md`    | 扩展篇    | stm32/21~26      |
-| 20   | `20-看门狗IWDG与WWDG.md`              | 扩展篇    | stm32/27~28      |
-| 21   | `21-附录:HAL库架构与Keil MDK深入.md` | 扩展篇    | —                |
-
-### 附加产出
-
-- `X-Knowledge-Base/raw/Joplin/嵌入式+Linux/STM32学习笔记/assets/` — 精选图片
-- `wiki/source-stm32-*.md` — 资料摘要页
-- `wiki/index.md` — 更新全局索引
-- `wiki/log.md` — 追加变更日志
-
----
-
-## 各批次通用步骤模板
-
-每篇笔记的处理步骤一致,以下为每篇的标准操作流程:
-
-1. **读取 pandoc 转换后的 MD 中对应章节内容**
-2. **读取对应源码项目文件**(main.c, driver.h, driver.c)
-3. **处理该章节图片**:用视觉 API 验证 → 重命名 → 复制到 assets/
-4. **撰写笔记**:
-   - 从原 DOCX 保留原意,但补充参考手册页码/原理图引用/网络资料
-   - 代码块直接从源文件复制,标注文件路径,每行位操作加注释
-   - 寄存器+HAL 双版
-   - 添加核心函数速查表 + 常见问题
-5. **写入目标路径**
-6. **追加 log 信息**
-
----
-
-## 批次 1:基础篇(笔记 01~06)
-
-**来源 DOCX**:`上部-基础篇/01_笔记/01_尚硅谷嵌入式技术之STM32单片机(基础篇)1.0.2.docx`
-**代码目录**:`上部-基础篇/03_代码/stm32/`
-**参考手册**:`上部-基础篇/02_资料/02_stm32官方资料/1-STM32F10x-中文参考手册_最新.pdf`
-**原理图**:`上部-基础篇/02_资料/05_原理图/STM32-F103ZET6开发板.pdf`
-
-### 任务 1.1:准备阶段 — 转换基础篇 DOCX
-
-- [ ] **步骤 1.1.1:pandoc 转换 + 提取图片**
-
-```powershell
-pandoc "上部-基础篇/01_笔记/01_尚硅谷嵌入式技术之STM32单片机(基础篇)1.0.2.docx" -t markdown --wrap=none --extract-media="C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_basic_media" -o "C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_basic.md"
-```
-
-- [ ] **步骤 1.1.2:阅读转换结果概览**
-      读取 `stm32_basic.md` 前 500 行,确认章节结构和图片引用
-
-### 任务 1.2:笔记 01 — STM32概述与开发环境搭建
-
-**来源章节**:基础篇 DOCX 第1~3章(STM32概述 + Keil安装 + 最小系统)
-
-- [ ] **步骤 1.2.1:读取相关章节内容**
-      从 pandoc 输出的 MD 中读取 STM32概述、ARM Cortex-M3、命名规则、Keil安装、最小系统等章节
-
-- [ ] **步骤 1.2.2:读取参考资料**
-  - STM32F103ZET6 数据手册 §1~3(命名规则、引脚定义)
-  - 原理图 PDF 最小系统部分(电源/时钟/复位/下载调试电路)
-  - Cortex-M3 权威指南(内核架构)
-  - 代码项目 `stm32/01_led_register` 的工程结构
-
-- [ ] **步骤 1.2.3:处理本章图片**
-  - 定位本章节涉及的图片(image1~image33)
-  - 视觉 API 逐张验证内容
-  - 筛选保留:最小系统框图、命名规则图、开发板实物图
-  - 删除:IDE 安装界面截图(image12~image23)
-  - 重命名图片到 `assets/`
-
-- [ ] **步骤 1.2.4:撰写笔记 01**
-
-```markdown
----
-tags: [source-summary]
-type: source
-source: "尚硅谷嵌入式技术之STM32单片机(基础篇)V1.0.2 — 第1~3章"
-author: "尚硅谷研究院"
-date: 2026-07-15
-created: 2026-07-15
----
-
-# STM32概述与开发环境搭建
-
-> **用生活理解**:如果把STM32比作一台微型电脑——ARM内核就像电脑的CPU,而Keil MDK就像Visual Studio,开发板就是一台迷你主机。
-
-## STM32概述
-
-### 关于ARM内核
-
-- ARM = Advanced RISC Machines
-- Cortex-M3 内核特性:32位RISC、3级流水线、Thumb-2指令集、NVIC中断控制器
-- 参考:Cortex-M3 权威指南 第2章
-
-### 什么是STM32
-
-- ST = STMicroelectronics(意法半导体)
-- M = Microcontroller(微控制器)
-- 32 = 32位处理器
-- 基于 ARM Cortex-M 内核的32位MCU
-
-### STM32应用场景
-
-- 工业自动化、电机控制、物联网终端、消费电子、医疗设备
-
-### STM32系列MCU命名规则
-
-- STM32 F 103 Z E T 6 含义逐段解析
-- 参考:STM32F103xCDE 数据手册 §1(器件概览)
-
-## 开发板简介
-
-### 开发板实物图
-
-![开发板资源图](assets/xxx.png)
-
-### STM32F103ZET6 最小系统
-
-最小系统 = STM32芯片 + 电源 + 时钟 + 复位 + 下载调试
-
-**电源电路**:
-
-- 双路供电:USB Type-C (5V) → AMS1117 → 3.3V
-- ST-Link 直接提供 3.3V
-- 参考:原理图第1页(电源部分)
-
-**时钟电路**:
-
-- 外部8MHz晶振(HSE) + 32.768KHz晶振(LSE)
-- 原理图第2页
-
-**复位电路**:
-
-- NRST 引脚 + 按键 + RC电路
-- 原理图第3页
-
-**下载调试电路**:
-
-- SWD接口(SWDIO/SWCLK)+ ST-Link
-- 参考:原理图第3页
-
-## STM32开发方式
-
-三种开发方式对比:
-
-| 方式       | 特点                                     |
-| ---------- | ---------------------------------------- |
-| **寄存器** | 直接操作内存地址,代码最小、最深理解硬件 |
-| **标准库** | 官方封装寄存器操作,函数名规范           |
-| **HAL库**  | CubeMX图形化配置,移植性好,代码量大     |
-
-## 开发工具
-
-### Keil MDK
-
-- 下载 → 安装 → 离线芯片支持包 → 注册
-- 芯片包选型:STM32F103ZET6 → Keil.STM32F1xx_DFP
-
-### 项目文件结构
-```
-
-Project/
-├── Start/ # 启动文件 startup_stm32f10x_hd.s
-├── User/ # main.c + 用户代码
-├── Hardware/ # 外设驱动(LED/KEY等)
-├── Library/ # 标准库文件
-├── System/ # system_stm32f1xx.c
-└── Objects/ # 编译输出
-
-```
-
-### 启动文件选择
-| 文件 | 适用芯片 |
-|------|---------|
-| startup_stm32f10x_ld.s | 16~32KB Flash |
-| startup_stm32f10x_md.s | 64~128KB Flash |
-| startup_stm32f10x_hd.s | 256~512KB Flash |
-
-STM32F103ZET6 = 512KB Flash → 选 **hd**
-
-## 烧录方法
-- ST-Link SWD 方式(4线:SWDIO/SWCLK/VCC/GND)
-
-## 核心函数速查
-
-(环境搭建篇无代码 API,但列出常用概念)
-
-## 常见问题与避坑
-- 芯片支持包在线安装太慢 → 离线下载安装
-- Keil MDK 需注册 → 使用注册机
-- 下载失败 → 检查 ST-Link 驱动、SWD 接线
-```
-
-- [ ] **步骤 1.2.5:写入文件**
-
-写入 `X-Knowledge-Base/raw/Joplin/嵌入式+Linux/STM32学习笔记/01-STM32概述与开发环境搭建.md`
-
-### 任务 1.3:笔记 02 — GPIO寄存器详解与三步进化法
-
-**来源章节**:基础篇 DOCX 第4~5章(点亮LED + GPIO详解)
-**代码项目**:`stm32/01_led_register`
-
-- [ ] **步骤 1.3.1:读取 DOCX 相关章节 + 源码**
-      读取:GPIO 8种模式、7个寄存器、三步进化法
-      读取源码:`stm32/01_led_register/User/main.c`
-
-- [ ] **步骤 1.3.2:网络补充**
-      搜索补充:GPIO 内部结构框图(P-MOS/N-MOS/施密特触发器)、输出速度与EMI关系
-
-- [ ] **步骤 1.3.3:处理图片**
-      GPIO 寄存器位域图、内部结构框图保留;IDE截图删除
-
-- [ ] **步骤 1.3.4:撰写笔记 02**
-      内容要点:
-  - GPIO 内部结构框图 + 逐部件分析
-  - 8种工作模式表格(推挽/开漏/浮空/上拉/下拉/模拟/复用推挽/复用开漏)
-  - 关键寄存器表格:
-    | 寄存器 | 地址偏移 | 功能 |
-    | CRL | 0x00 | 低8位端口配置(MODE + CNF) |
-    | CRH | 0x04 | 高8位端口配置 |
-    | IDR | 0x08 | 输入数据寄存器 |
-    | ODR | 0x0C | 输出数据寄存器 |
-    | BSRR | 0x10 | 位设置/清除寄存器 |
-    | BRR | 0x14 | 位清除寄存器 |
-    | LCKR | 0x18 | 锁定寄存器 |
-  - "三步进化法"完整演示:
-    - 步骤1:裸地址操作(`*(uint32_t *)(0x40010800 + 0x0C)`)
-    - 步骤2:结构体宏定义(`GPIOA->ODR`)
-    - 步骤3:位宏定义(`GPIOA->ODR |= GPIO_ODR_ODR0`)
-  - 代码从 `01_led_register/User/main.c` 复制
-  - 原生代码包含注释"改进1/改进2/改进3",保留并扩展
-  - 参考手册 §8 寄存器位域
-  - 原理图 LED 电路
-
-- [ ] **步骤 1.3.5:写入文件**
-
-### 任务 1.4:笔记 03 — GPIO输出:LED控制
-
-**来源章节**:基础篇 第6章(LED流水灯)
-**代码项目**:`stm32/02_led_flow_register`、`stm32/03_led_flow_pro_register`、`stm32/04_led_flow_pro_hal`
-
-- [ ] **步骤 1.4.1:读取源码**
-  - `02_led_flow_register/User/main.c`
-  - `03_led_flow_pro_register/User/main.c`
-  - `03_led_flow_pro_register/Hardware/LED/led.c`、`led.h`
-  - `03_led_flow_pro_register/User/Delay.h`、`Delay.c`
-  - `04_led_flow_pro_hal/User/main.c`
-  - `04_led_flow_pro_hal/Hardware/LED/led.c`、`led.h`
-
-- [ ] **步骤 1.4.2:撰写笔记 03**
-      内容要点:
-  - LED 电路原理(低电平点亮、限流电阻计算)
-  - 寄存器版:流水灯三种实现(移位法/查表法/状态机法)
-  - 模块化封装:Driver_LED.h + Driver_LED.c
-  - Delay 模块:软件延时 vs SysTick 硬件定时差异
-  - HAL 版:CubeMX 配置 + HAL_GPIO_WritePin
-  - 代码复制:从源文件复制完整 main.c/led.c/led.h,每行注释
-  - 位运算注释示例:
-    ```c
-    GPIOA->ODR &= ~GPIO_ODR_ODR0;   // &=~ 按位与+取反: 保留其他位不变, 只将ODR0位清0 → PA0输出低电平
-    ```
-
-- [ ] **步骤 1.4.3:写入文件**
-
-### 任务 1.5:笔记 04 — GPIO输入与NVIC中断系统
-
-**来源章节**:基础篇 第7章(按键 + 中断)
-**代码项目**:`stm32/05_key_led_register`、`stm32/06_key_led_hal`
-
-- [ ] **步骤 1.5.1:读取源码**
-  - `05_key_led_register/User/main.c` + `Hardware/KEY/key.c` + `Hardware/LED/led.c`
-  - `06_key_led_hal/User/main.c`
-
-- [ ] **步骤 1.5.2:撰写笔记 04**
-      内容要点:
-  - 机械按键消抖(硬件RC消抖 / 软件延时10~15ms消抖)
-  - 原理图 KEY 电路(PF10 上拉输入)
-  - EXTI 外部中断配置流程(GPIO配置→中断线选择→触发条件→NVIC使能→中断服务函数)
-  - NVIC 优先级分组(4种组别:NVIC_PriorityGroup_0~4)
-  - 中断优先级 = 抢占优先级 + 子优先级
-  - 寄存器版代码 + HAL 版代码,分别展示
-  - 参考手册 §9 EXTI 寄存器、§8 NVIC 寄存器
-
-- [ ] **步骤 1.5.3:写入文件**
-
-### 任务 1.6:笔记 05 — 系统时钟RCC详解
-
-**来源章节**:基础篇 第5章后半部分(RCC时钟树)
-**代码项目**:无需特定项目(系统初始化代码)
-
-- [ ] **步骤 1.6.1:读取参考资料**
-  - 参考手册 §7 RCC 寄存器
-  - 启动文件中的 SystemInit 调用
-  - `system_stm32f1xx.c` 中的 SystemInit() 源码
-  - 原理图晶振电路
-
-- [ ] **步骤 1.6.2:网络补充**
-      搜索补充:STM32F103 时钟树完整框图、PLL 配置限制
-
-- [ ] **步骤 1.6.3:撰写笔记 05**
-      内容要点:
-  - 时钟树逐级分析:
-    ```
-    HSE(8MHz) → PLL(x9) → SYSCLK(72MHz) → AHB(72MHz) → APB1(36MHz) → APB2(72MHz)
-    ```
-  - 5个时钟源详解:HSI/HSE/PLL/LSI/LSE
-  - SystemInit() 源码逐行解析(参考手册 §7.2 时钟配置)
-  - HAL 版 SystemClock_Config() 对照分析
-  - RCC 关键寄存器:CR(时钟控制)/CFGR(时钟配置)/BDCR/CIR
-  - 修改主频注意事项(Flash 等待周期需同步调整)
-
-- [ ] **步骤 1.6.4:写入文件**
-
-### 任务 1.7:笔记 06 — 串口USART通信
-
-**来源章节**:基础篇 第8章(USART通信)
-**代码项目**:`stm32/07_usart_register` ~ `stm32/12_usart_printf_hal`
-
-- [ ] **步骤 1.7.1:读取源码**
-  - `07_usart_register/User/main.c` + `Hardware/USART/usart.c`
-  - `08_usart_iterrupt_register/User/main.c`
-  - `11_usart_printf_register/User/main.c`
-  - `12_usart_printf_hal/User/main.c`
-
-- [ ] **步骤 1.7.2:撰写笔记 06**
-      内容要点:
-  - 异步串行通信协议帧格式(起始位+数据位+校验位+停止位)
-  - 单工/半双工/全双工区别
-  - 同步/异步区别
-  - 波特率计算公式:`Baud = fCK / (16 × USARTDIV)`
-  - USART 功能框图分析
-  - 寄存器版:轮询方式收发 + 中断方式收发
-  - printf 重定向原理(Keil 微库 + fputc 重写)
-  - HAL 库版:CubeMX 配置 + HAL_UART_Transmit/Receive
-  - 参考手册 §18 USART 寄存器(SR/DR/BRR/CR1~CR3)
-
-- [ ] **步骤 1.7.3:写入文件**
-
-### 任务 1.8:提交批次 1
-
-- [ ] **步骤 1.8.1:更新 wiki/source-stm32-basic.md**
-
-- [ ] **步骤 1.8.2:追加 wiki/log.md**
-
-- [ ] **步骤 1.8.3:git 提交**
-
-```bash
-git add .
-git commit -m "ingest: 尚硅谷STM32 基础篇笔记导入(01~06)"
-```
-
----
-
-## 批次 2:进阶篇(笔记 07~12)
-
-**来源 DOCX**:`上部-基础篇/01_笔记/02_尚硅谷嵌入式技术之STM32单片机(进阶篇)1.0.1.docx`
-**代码目录**:`上部-基础篇/03_代码/stm32/`(项目 13~42)
-
-### 任务 2.1:转换进阶篇 DOCX
-
-- [ ] **步骤 2.1.1:pandoc 转换**
-
-```powershell
-pandoc "上部-基础篇/01_笔记/02_尚硅谷嵌入式技术之STM32单片机(进阶篇)1.0.1.docx" -t markdown --wrap=none --extract-media="C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_medium_media" -o "C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_medium.md"
-```
-
-### 任务 2.2:笔记 07 — I2C通信与EEPROM 24C02
-
-**代码项目**:`stm32/13_i2c_software_register`、`stm32/14_i2c_hardware_register`、`stm32/15_i2c_hardware_hal`
-
-- [ ] **步骤 2.2.1:读取 DOCX 章节 + 源码**
-- [ ] **步骤 2.2.2:撰写笔记 07**
-      内容要点:
-  - I2C 协议时序逐段分析(起始条件S、从机地址+R/W、应答ACK/非应答NACK、数据字节、停止条件P)
-  - 软件模拟 I2C:GPIO 位操作模拟 SCL/SDA 时序
-  - 硬件 I2C:状态寄存器分析(SR1/SR2 事件标志)
-  - 24C02 EEPROM:页写(最多8字节)、页写限制(跨页自动回卷)、随机读/顺序读
-  - 参考手册 §16 I2C 寄存器(CR1/CR2/OAR1/DR/SR1/SR2/TRISE)
-  - 代码双版复刻
-- [ ] **步骤 2.2.3:写入文件**
-
-### 任务 2.3:笔记 08 — SysTick与通用定时器TIM
-
-**代码项目**:`stm32/16_led_twinkle_systick_register` ~ `stm32/19_led_twinkle_tim_hal`
-
-- [ ] **步骤 2.3.1:读取源码**
-- [ ] **步骤 2.3.2:撰写笔记 08**
-      内容要点:
-  - SysTick 寄存器详解:CTRL(第0位ENABLE/第1位TICKINT/第2位CLKSOURCE)、LOAD、VAL、CALIB
-  - SysTick 定时时间计算:`Time = (LOAD+1) / (AHB/8)`
-  - TIM 时基单元结构框图:PSC 预分频器 → CNT 计数器 → ARR 自动重装载 → 更新事件(UEV)
-  - 溢出时间公式:`Tout = (ARR+1) × (PSC+1) / Tclk`
-  - TIM 与 SysTick 对比(精度/功能/用途)
-  - 代码双版
-- [ ] **步骤 2.3.3:写入文件**
-
-### 任务 2.4:笔记 09 — TIM高级应用:PWM与输入捕获
-
-**代码项目**:`stm32/20_led_breathe_register` ~ `stm32/27_pwm_n_cycle_hal`
-
-- [ ] **步骤 2.4.1:读取源码**
-- [ ] **步骤 2.4.2:撰写笔记 09**
-      内容要点:
-  - PWM 频率 = Tclk / (PSC+1) / (ARR+1);占空比 = CCR / (ARR+1)
-  - 呼吸灯原理:逐渐改变 CCR 值 → 改变占空比 → LED 亮度渐变
-  - 占空比/周期独立控制(ARR 固定改 CCR vs 两者都变)
-  - PWM 模式1 vs 模式2:向上计数时 CNT<CCR 输出有效电平
-  - 输入捕获:测量外部信号频率/脉宽
-  - TIM_CCMR/TIM_CCER/TIM_CNT/TIM_DIER 寄存器详解
-- [ ] **步骤 2.4.3:写入文件**
-
-### 任务 2.5:笔记 10 — DMA数据传输
-
-**代码项目**:`stm32/28_dma_mem2mem_register` ~ `stm32/31_dma_mem2uart_hal`
-
-- [ ] **步骤 2.5.1:读取源码**
-- [ ] **步骤 2.5.2:撰写笔记 10**
-      内容要点:
-  - DMA 框图:5个总线矩阵 + 仲裁器 + DMA1(7通道)/DMA2(5通道)
-  - 传输流程:外设请求→CPU 让出总线→DMA 传输→完成中断
-  - 存储器到存储器(M2M):Flash → SRAM 复制
-  - 存储器到外设(M2P):SRAM → USART DR 寄存器(自动发送)
-  - DMA 通道映射表:
-    | 通道 | 外设请求 |
-    | TIM1_CH1 | ADC1 |
-    | SPI1_RX/TX | USART1_TX |
-    | ... |
-  - 关键寄存器:CCR/CNDTR/CPAR/CMAR
-  - 增量模式 vs 固定模式
-- [ ] **步骤 2.5.3:写入文件**
-
-### 任务 2.6:笔记 11 — ADC模数转换
-
-**代码项目**:`stm32/32_adc_single_register` ~ `stm32/35_adc_double_hal`
-
-- [ ] **步骤 2.6.1:读取源码**
-- [ ] **步骤 2.6.2:撰写笔记 11**
-      内容要点:
-  - SAR ADC 工作原理(逐次逼近:二分法比较)
-  - STM32F103ZET6: 3个ADC(ADC1/2/3),12位精度,18个通道
-  - 采样时间 = 采样周期 × ADC 时钟周期;采样周期可编程(1.5~239.5 个周期)
-  - 转换时间 = 采样时间 + 12.5 个周期(12位精度)
-  - 规则组(最多16通道)vs 注入组(最多4通道)
-  - 单次转换 / 连续转换 / 扫描模式
-  - 定时器触发 ADC + DMA 传输
-  - 参考手册 §11 ADC 寄存器(SR/CR1/CR2/SMPR1~~2/SQR1~~3/DR)
-- [ ] **步骤 2.6.3:写入文件**
-
-### 任务 2.7:笔记 12 — SPI通信与FSMC总线
-
-**代码项目**:`stm32/36_spi_software_register` ~ `stm32/42_lcd_hal`
-
-- [ ] **步骤 2.7.1:读取源码**
-- [ ] **步骤 2.7.2:撰写笔记 12**
-      内容要点:
-  - SPI 四种模式(CPOL/CPHA 组合)时序图
-  - 3线/4线 SPI(NSS 片选管理)
-  - 软件模拟 SPI(GPIO 位操作)vs 硬件 SPI(寄存器配置)
-  - W25Q64 Flash:读(03h)/写(02h)/擦除(D8h/D7h)/状态寄存器(05h) 指令集
-  - FSMC 地址映射:Bank1(0x60000000~0x6FFFFFFF) → NOR/PSRAM/SRAM/LCD
-  - FSMC 时序参数配置(地址建立时间/数据保持时间)
-  - 参考手册 §23 SPI + §19 FSMC
-- [ ] **步骤 2.7.3:写入文件**
-
-### 任务 2.8:提交批次 2
-
-- [ ] **步骤 2.8.1:更新 wiki/source-stm32-medium.md**
-- [ ] **步骤 2.8.2:追加 wiki/log.md**
-- [ ] **步骤 2.8.3:git 提交**
-
-```bash
-git add .
-git commit -m "ingest: 尚硅谷STM32 进阶篇笔记导入(07~12)"
-```
-
----
-
-## 批次 3:高级篇(笔记 13~17)
-
-**来源 DOCX**:`下部-高级篇/2-笔记/1.笔记/03_尚硅谷嵌入式技术之STM32单片机(高级篇)2.0.1.docx`
-**代码目录**:`下部-高级篇/3-代码/stm32/`(项目 01~25)
-
-### 任务 3.1:转换高级篇 DOCX
-
-```powershell
-pandoc "下部-高级篇/2-笔记/1.笔记/03_尚硅谷嵌入式技术之STM32单片机(高级篇)2.0.1.docx" -t markdown --wrap=none --extract-media="C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_advanced_media" -o "C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_advanced.md"
-```
-
-### 任务 3.2:笔记 13 — CAN通信协议与bxCAN外设
-
-**代码项目**:`stm32/01_can_test_register` ~ `stm32/04_can_rx_hal`
-
-- [ ] **步骤 3.2.1:读取 DOCX + 源码**
-- [ ] **步骤 3.2.2:网络补充**
-      CAN 2.0A vs 2.0B 标准补充、CAN FD 后续发展
-- [ ] **步骤 3.2.3:撰写笔记 13**
-      内容要点:
-  - CAN 协议基础:车用总线、多主从仲裁、广播式通信
-  - CAN 数据帧逐位分析:帧起始(SOF) 1位 → 仲裁段(11/29位ID+RTR) → 控制段(IDE+res+r0+DLC) → 数据段(0~8字节) → CRC段(15位CRC+界定符) → ACK段(2位) → 帧结束(EOF 7位)
-  - 位时序 & 同步(同步段/传播段/相位缓冲段1/2)
-  - bxCAN 外设:3个发送邮箱 + 2个3级深度FIFO + 14个过滤器组
-  - 三种工作模式:初始化/正常/睡眠
-  - 三种测试模式:静默/环回/环回静默
-  - 过滤器配置:列表模式(精确匹配)vs 掩码模式(模糊匹配)
-  - 寄存器版:双机通信(一收一发)
-  - HAL 版:CubeMX 配置 + HAL_CAN_Start/HAL_CAN_AddTxMessage
-  - 参考手册 §22 bxCAN 寄存器
-- [ ] **步骤 3.2.4:写入文件**
-
-### 任务 3.3:笔记 14 — 以太网通信与W5500
-
-**代码项目**:`stm32/05_ethernet_test_register` ~ `stm32/09_ethernet_webserver_register`
-
-- [ ] **步骤 3.3.1:读取源码**
-- [ ] **步骤 3.3.2:撰写笔记 14**
-      内容要点:
-  - OSI 7层模型 vs TCP-IP 4层模型
-  - 以太网 vs 互联网概念区分
-  - W5500 芯片:全硬件 TCP/IP 协议栈,SPI 接口,8个独立 Socket
-  - W5500 内部架构:SPI口 → 寄存器管理 → 内核 → MAC/PHY → 以太网口
-  - 可变长数据帧模式(VDM) vs 固定长数据帧模式(FDM)
-  - 官方库移植步骤:wizchip_conf.h → SPI 读写注册函数 → socket API
-  - 实验:Ping 通测试 → TCP Server → TCP Client → UDP → WebServer
-  - 参考:W5500 数据手册
-- [ ] **步骤 3.3.3:写入文件**
-
-### 任务 3.4:笔记 15 — WiFi通信与ESP32-C3
-
-**代码项目**:`stm32/10_wifi_test_hal`、`stm32/11_wifi_tcp_server_hal`
-
-- [ ] **步骤 3.4.1:读取源码**
-- [ ] **步骤 3.4.2:撰写笔记 15**
-      内容要点:
-  - ESP32-C3 规格:RISC-V 32位、2.4GHz WiFi + BLE 5.0
-  - AT 指令模式:通过串口发送 AT 指令控制
-  - 常用 AT 指令表:AT+CWMODE(Station/AP/Station+AP)、AT+CWJAP(连接WiFi)、AT+CIPSTART(建立TCP)、AT+CIPMODE(透传)、AT+CIPSEND(发送数据)
-  - 实验1:AT 指令交互测试
-  - 实验2:TCP 通信(AT+CIPSTART 建立连接 → 数据收发)
-  - 透传模式 vs 非透传模式
-- [ ] **步骤 3.4.3:写入文件**
-
-### 任务 3.5:笔记 16 — BLE低功耗蓝牙
-
-**代码项目**:`stm32/12_ble_server_hal`
-
-- [ ] **步骤 3.5.1:读取源码**
-- [ ] **步骤 3.5.2:撰写笔记 16**
-      内容要点:
-  - BLE vs 经典蓝牙(功耗/吞吐量/应用场景)
-  - BLE 协议栈架构:Physical → Link Layer → HCI → L2CAP → SMP → ATT → GATT → GAP
-  - GAP 角色:Broadcaster/Observer/Peripheral/Central
-  - GATT 角色:Server/Client,Service → Characteristic → Descriptor 层级
-  - BLE 通信流程:广播 → 扫描 → 连接 → 数据收发 → 断开
-  - STM32 + BLE 模块(AT 指令控制)
-- [ ] **步骤 3.5.3:写入文件**
-
-### 任务 3.6:笔记 17 — LoRa远距离通信
-
-**代码项目**:`stm32/13_lora_node_hal`、`stm32/14_lora_gateway_hal`
-
-- [ ] **步骤 3.6.1:读取源码**
-- [ ] **步骤 3.6.2:撰写笔记 17**
-      内容要点:
-  - LPWAN 技术阵营对比(LoRa vs NB-IoT vs Sigfox)
-  - LoRa 扩频技术:SF(扩频因子)、BW(带宽)、CR(编码率) 三参数决定速率/灵敏度
-  - CAD(信道活动检测):低功耗监听模式
-  - 星型组网拓扑:节点 ↔ 网关 ↔ 服务器
-  - AT 指令配置:频率/功率/扩频因子/数据速率
-  - 节点 → 网关 数据发送 + 接收确认
-- [ ] **步骤 3.6.3:写入文件**
-
-### 任务 3.7:提交批次 3
-
-- [ ] **步骤 3.7.1:更新 wiki/source-stm32-advanced.md**
-- [ ] **步骤 3.7.2:追加 wiki/log.md**
-- [ ] **步骤 3.7.3:git 提交**
-
-```bash
-git add .
-git commit -m "ingest: 尚硅谷STM32 高级篇笔记导入(13~17)"
-```
-
----
-
-## 批次 4:扩展篇(笔记 18~21)
-
-**来源 DOCX**:`下部-高级篇/2-笔记/1.笔记/04_尚硅谷嵌入式技术之STM32单片机(扩展篇)1.0.0.docx`
-**代码目录**:`下部-高级篇/3-代码/stm32/`(项目 15~28)
-
-### 任务 4.1:转换扩展篇 DOCX
-
-```powershell
-pandoc "下部-高级篇/2-笔记/1.笔记/04_尚硅谷嵌入式技术之STM32单片机(扩展篇)1.0.0.docx" -t markdown --wrap=none --extract-media="C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_extension_media" -o "C:\Users\Administrator\AppData\Local\Temp\opencode\stm32_extension.md"
-```
-
-### 任务 4.2:笔记 18 — 电源管理与低功耗模式
-
-**代码项目**:`stm32/15_lowpower_sleep_register` ~ `stm32/20_lowpower_standby_hal`
-
-- [ ] **步骤 4.2.1:读取 DOCX + 源码**
-- [ ] **步骤 4.2.2:撰写笔记 18**
-      内容要点:
-  - 电源框图逐区域分析:Vdda(模拟) → Vdd(数字) → 1.8V(内核) → Vbat(备份)
-  - 电压调节器三种模式:运转/停止(低功耗)/待机(关闭)
-  - 上电复位(POR) vs 掉电复位(PDR):阈值电压及迟滞
-  - PVD 可编程电压检测器:PLS[2:0] 选择阈值 → 电压低于阈值产生中断
-  - 三种低功耗模式对比:
-    | 模式 | 唤醒源 | 功耗 | 恢复时间 |
-    | 睡眠 | 任意中断/事件 | ~mA | 几μs |
-    | 停止 | 任意EXTI | ~μA | 几μs |
-    | 待机 | RTC/WKUP/NRST | ~nA | 几ms |
-  - 睡眠模式:SLEEP-NOW vs SLEEP-ON-EXIT
-  - 停止模式:调压器配置(正常工作 vs 低功耗)
-  - 待机模式:SRAM/寄存器全部丢失,仅备份域保留
-  - 低功耗设计建议(时钟门控/外设禁用)
-  - 参考手册 §5 PWR 寄存器
-- [ ] **步骤 4.2.3:写入文件**
-
-### 任务 4.3:笔记 19 — BKP备份寄存器与RTC实时时钟
-
-**代码项目**:`stm32/21_bkp_test_register` ~ `stm32/26_rtc_calendar_hal`
-
-- [ ] **步骤 4.3.1:读取源码**
-- [ ] **步骤 4.3.2:撰写笔记 19**
-      内容要点:
-  - 备份域电路:Vbat 引脚供电 → RTC + LSE + BKP 寄存器 在 Vdd 断电后继续工作
-  - BKP:42 个 16 位备份寄存器 + 防侵入功能(TAMPER)
-  - BKP 访问使能:PWR_CR.DBP = 1 后允许读写
-  - RTC 三时钟源选择:LSE(32.768KHz) / LSI(~40KHz) / HSE(8MHz 分频)
-  - RTC 预分频器:异步分频(7位) + 同步分频(15位) → 精确的 1Hz
-  - RTC 闹钟:RTC_ALR 与 RTC_CNT 比较匹配 → 中断
-  - Unix 时间戳:1970-01-01 起秒数
-  - 日历实验:初始化 → 读取 → 显示 年月日时分秒
-  - 参考手册 §6 BKP + §17 RTC
-- [ ] **步骤 4.3.3:写入文件**
-
-### 任务 4.4:笔记 20 — 看门狗IWDG与WWDG
-
-**代码项目**:`stm32/27_iwdg_test_register`、`stm32/28_iwdg_test_hal`
-
-- [ ] **步骤 4.4.1:读取源码**
-- [ ] **步骤 4.4.2:撰写笔记 20**
-      内容要点:
-  - IWDG 独立看门狗:LSI(~40KHz) 时钟源,完全独立
-  - IWDG 超时时间计算:`Tout = (RL+1) × 4 × 2^PR / 40KHz`
-  - IWDG 预分频系数-超时速查表:
-    | PR[2:0] | 分频系数 | 最大超时(RL=0xFFF) |
-    | 000 | 4 | ~0.82s |
-    | 011 | 32 | ~6.55s |
-    | 111 | 256 | ~52.43s |
-  - WWDG 窗口看门狗:APB1 时钟,有窗口限制(必须在窗口内喂狗)
-  - WWDG 窗口机制:CNT>T[6:0] 时喂狗 → 复位;CNT 减到 0x3F → 复位
-  - WWDG 早期唤醒中断(EWI):在 CNT=0x40 时产生中断,可提前处理
-  - 两者对比(独立 vs 窗口)和应用场景选择
-  - 参考手册 §14 IWDG + §15 WWDG
-- [ ] **步骤 4.4.3:写入文件**
-
-### 任务 4.5:笔记 21 — 附录:HAL库架构与Keil MDK深入
-
-**来源章节**:扩展篇 DOCX 附录
-
-- [ ] **步骤 4.5.1:读取 DOCX 附录章节**
-- [ ] **步骤 4.5.2:撰写笔记 21**
-      内容要点:
-  - HAL 库驱动框架:三层模式(轮询 Polling / 中断 IT / DMA)
-  - HAL 库关键宏:UNUSED()、IS_XXX() 参数校验
-  - HAL 库初始化流程:HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init()
-  - HAL_StatusTypeDef 返回状态
-  - Keil MDK 编译四阶段:
-    1. 编译(armcc/armasm):源文件 → .o 目标文件
-    2. 链接(armlink):多个 .o + 库 → .axf(.elf)
-    3. 格式转换(fromelf):.elf → .bin/.hex
-    4. 下载:烧录到 Flash/ROM
-  - 程序在存储器中的分布:
-    | 段 | 含义 | 存储位置 |
-    | Code | 程序代码 | Flash |
-    | RO-data | 只读数据(const) | Flash |
-    | RW-data | 已初始化全局变量 | Flash 初值 + RAM 运行 |
-    | ZI-data | 零初始化全局变量 | RAM |
-  - 编译输出信息解读(Code/RO/RW/ZI 大小含义)
-- [ ] **步骤 4.5.3:写入文件**
-
-### 任务 4.6:提交批次 4
-
-- [ ] **步骤 4.6.1:更新 wiki/source-stm32-extension.md**
-- [ ] **步骤 4.6.2:追加 wiki/log.md**
-- [ ] **步骤 4.6.3:git 提交**
-
-```bash
-git add .
-git commit -m "ingest: 尚硅谷STM32 扩展篇笔记导入(18~21)"
-```
-
----
-
-## 最终阶段:完成全部提交
-
-- [ ] **步骤 5.1:更新 wiki/index.md**
-      添加 STM32 章节到索引页,包含全部 21 篇笔记的链接:
-
-```markdown
-## STM32 嵌入式开发(尚硅谷)
-
-> 来源:[[source-stm32-basic|尚硅谷 STM32 基础篇]] · [[source-stm32-medium|进阶篇]] · [[source-stm32-advanced|高级篇]] · [[source-stm32-extension|扩展篇]]
-
-原始笔记(含 4 种代码 + 通俗解释):
-`raw/Joplin/嵌入式+Linux/STM32学习笔记/`
-
-Wiki 页面:
-
-- [[stm32-gpio|GPIO 与寄存器操作]]
-- [[stm32-timer|定时器与 PWM]]
-- [[stm32-communication|通信外设串口/I2C/SPI/FSMC]]
-- [[stm32-advanced-comm|物联网通信 CAN/ETH/WiFi/BLE/LoRa]]
-- [[stm32-power|低功耗与电源管理]]
-```
-
-- [ ] **步骤 5.2:更新 wiki/log.md 追加最终日志**
-
-```markdown
-## 2026-07-15
-
-- `ingest`: 导入尚硅谷 STM32 全套 4 份教程笔记
-
-  原始资料归档:
-  - `raw/Joplin/嵌入式+Linux/STM32学习笔记/01~21` 共 21 篇笔记
-  - `raw/Joplin/嵌入式+Linux/STM32学习笔记/assets/` 精选图片
-
-  新建 Wiki 页面:
-  - `wiki/source-stm32-basic.md`
-  - `wiki/source-stm32-medium.md`
-  - `wiki/source-stm32-advanced.md`
-  - `wiki/source-stm32-extension.md`
-  - `wiki/stm32-gpio.md`
-  - `wiki/stm32-timer.md`
-  - `wiki/stm32-communication.md`
-  - `wiki/stm32-advanced-comm.md`
-  - `wiki/stm32-power.md`
-
-  更新 `wiki/index.md`、`wiki/log.md`
-```
-
-- [ ] **步骤 5.3:最终全部提交**
-
-```bash
-git add .
-git commit -m "ingest: 尚硅谷STM32全套笔记导入完成(含基础篇/进阶篇/高级篇/扩展篇 共21篇笔记 + wiki更新)"
-```
-
----
-
-## 执行顺序说明
-
-整个项目按 **4 批次 + 1 次最终提交** 执行,每批次内部按笔记编号顺序串行处理。
-
-每篇笔记的撰写是核心耗时点,遵循模板规格(FreeRTOS 风格的 frontmatter + 原 DOCX 章节结构 + 源码直接复制 + 注释扩展)。
-
-即使某些笔记纯知识型(如 01/05/21 无对应代码),仍需要:
-
-- 参考手册页码引用
-- 原理图分析
-- 网络知识补充
-- 图片处理

+ 0 - 824
docs/superpowers/plans/2026-07-17-freertos-ingest.md

@@ -1,824 +0,0 @@
-# 尚硅谷 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`    |
-
-### 提取代码项目到临时目录
-
-```powershell
-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.c` 和 `Core/Inc/FreeRTOSConfig.h`
-3. **筛选图片**:从 `images/media/` 中找出与该笔记相关的图片,筛选保留有用的,重命名后复制到 `assets/`
-4. **撰写笔记**:按照设计文档中的模板撰写 Markdown 文件
-5. **写入目标路径**:保存到 `X-Knowledge-Base/raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/`
-
-**图片视觉验证命令模板**(用于验证图片内容):
-
-```powershell
-# 调用视觉 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 复制全部图片到临时目录
-
-```powershell
-$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
-
-```powershell
-$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 收购
-- 开源免费 ≠ 免费用于商业产品
-
-### 模板参考
-
-```markdown
----
-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 优先级
-
-### 图片引用
-
-```markdown
-![感知并发 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`(作为通用模板参考)
-- 静态创建需要 `vApplicationGetIdleTaskMemory` 和 `vApplicationGetTimerTaskMemory` 钩子
-
-### 代码提取(项目 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` 的差异点
-- `vApplicationGetIdleTaskMemory` 和 `vApplicationGetTimerTaskMemory` 钩子实现
-
-### 关键配置
-
-```c
-// 静态分配需要开启
-#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()
-
-### 关键配置
-
-```c
-#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) 模拟工作负载,观察漂移差异
-
-### 关键配置
-
-```c
-// 项目 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()`
-
-### 关键配置
-
-```c
-#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)
-
-### 关键配置
-
-```c
-#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()`
-
-### 关键配置
-
-```c
-#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 → 给出信号量
-
-### 关键配置
-
-```c
-#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
-
-### 图片引用
-
-```markdown
-![事件标志组位结构](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 时钟
-
-### 关键配置
-
-```c
-// 软件定时器
-#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
-```
-
-### 图片引用
-
-```markdown
-![定时器状态切换图](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)` → 打印堆大小
-
-### 图片引用
-
-```markdown
-![三种 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`
-
-```markdown
-## 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` 已追加

+ 0 - 169
docs/superpowers/specs/2026-07-15-stm32-silicon-valley-ingest-design.md

@@ -1,169 +0,0 @@
-# 设计文档:尚硅谷 STM32 全套 4 份笔记导入计划
-
-**日期**:2026-07-15
-**来源**:尚硅谷嵌入式技术之STM32单片机(基础篇 V1.0.2 + 进阶篇 V1.0.1 + 高级篇 V2.0.1 + 扩展篇 V1.0.0)
-**目标目录**:`raw/Joplin/嵌入式+Linux/STM32学习笔记/`
-**目标芯片**:STM32F103ZET6
-**参考文件组织格式**:FreeRTOS 学习笔记(`raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/`)
-
-## 1. 笔记分篇(共 21 篇)
-
-### 基础篇 — 6 篇
-
-| #   | 篇名                       | 对应源章节             | 核心扩展                                                                               |
-| --- | -------------------------- | ---------------------- | -------------------------------------------------------------------------------------- |
-| 01  | STM32概述与开发环境搭建    | 概述 + Keil + 最小系统 | 命名规范、数据手册§1~3引用、原理图最小系统逐元件分析、Keil项目文件结构、芯片支持包选型 |
-| 02  | GPIO寄存器详解与三步进化法 | GPIO 8模式+7寄存器     | GPIO内部框图、参考手册§8寄存器位域表、原理图LED/KEY电路、三步进化(裸地址→结构体→位宏)  |
-| 03  | GPIO输出:LED控制          | 点亮LED+流水灯         | 模块化驱动封装、流水灯三种实现、Delay模块、源码复制+每行注释                           |
-| 04  | GPIO输入与NVIC中断系统     | 按键+中断              | 按键消抖、EXTI中断配置、NVIC优先级分组、中断向量表                                     |
-| 05  | 系统时钟RCC详解            | RCC时钟树              | 时钟树逐级分析、SystemInit()源码解析、HAL版配置对照、参考手册§7 RCC寄存器              |
-| 06  | 串口USART通信              | USART轮询/中断/printf  | 串行协议帧格式、USART框图、波特率计算、printf重定向、代码双版                          |
-
-### 进阶篇 — 6 篇
-
-| #   | 篇名                       | 对应源章节           | 核心扩展                                                        |
-| --- | -------------------------- | -------------------- | --------------------------------------------------------------- |
-| 07  | I2C通信与EEPROM 24C02      | I2C软件+硬件+24C02   | I2C协议时序分析、软件模拟、硬件I2C状态寄存器、24C02页写限制     |
-| 08  | SysTick与通用定时器TIM     | SysTick+TIM时基      | SysTick 4寄存器详解、TIM时基单元、溢出时间计算公式、参考手册§14 |
-| 09  | TIM高级应用:PWM与输入捕获 | TIM PWM+捕获         | PWM频率/占空比计算、呼吸灯、输入捕获测频、PWM模式1/2区别        |
-| 10  | DMA数据传输                | DMA内存到内存/到串口 | DMA框图、传输流程、通道映射表、存储器与外设增量模式             |
-| 11  | ADC模数转换                | ADC单次/连续/多通道  | SAR ADC原理、采样/转换时间计算、规则组vs注入组                  |
-| 12  | SPI通信与FSMC总线          | SPI+FSMC             | SPI四模式时序图、W25Q64 Flash驱动、FSMC地址映射与Bank选择       |
-
-### 高级篇 — 5 篇
-
-| #   | 篇名                   | 对应源章节       | 核心扩展                                                     |
-| --- | ---------------------- | ---------------- | ------------------------------------------------------------ |
-| 13  | CAN通信协议与bxCAN外设 | CAN协议+双机通信 | 数据帧逐位分析、位时序与同步、bxCAN滤波器、3种工作/测试模式  |
-| 14  | 以太网通信与W5500      | ETH+W5500        | OSI/TCP-IP分层、W5500架构、官方库移植、TCP Server/Client/UDP |
-| 15  | WiFi通信与ESP32-C3     | WiFi AT指令+TCP  | ESP32-C3规格、AT指令集、Station/AP模式、透传模式             |
-| 16  | BLE低功耗蓝牙          | BLE协议+通信     | BLE vs 经典蓝牙、协议栈分层、角色模型、连接流程              |
-| 17  | LoRa远距离通信         | LoRa节点+网关    | LoRa扩频技术、CAD检测、星型组网、AT指令配置                  |
-
-### 扩展篇 — 4 篇
-
-| #   | 篇名                          | 对应源章节       | 核心扩展                                          |
-| --- | ----------------------------- | ---------------- | ------------------------------------------------- |
-| 18  | 电源管理与低功耗模式          | PWR低功耗        | 电源框图分析、三种模式对比表、PVD电压检测         |
-| 19  | BKP备份寄存器与RTC实时时钟    | BKP+RTC日历/闹钟 | 备份域电路、RTC三时钟源、预分频器配置、Unix时间戳 |
-| 20  | 看门狗IWDG与WWDG              | IWDG+WWDG        | IWDG超时速查表、WWDG窗口机制、喂狗时机计算        |
-| 21  | 附录:HAL库架构与Keil MDK深入 | HAL库+Keil附录   | HAL驱动三层抽象、Keil编译四阶段、程序存储分布     |
-
-## 2. 处理批次
-
-| 批次  | DOCX   | 产出笔记 | 代码来源                  | 代码项目数 |
-| ----- | ------ | -------- | ------------------------- | ---------- |
-| 批次1 | 基础篇 | 01~06    | `上部\stm32/01~12`        | 12         |
-| 批次2 | 进阶篇 | 07~12    | `上部\stm32/13~42`        | 30         |
-| 批次3 | 高级篇 | 13~17    | `下部\stm32/01~25`        | 25         |
-| 批次4 | 扩展篇 | 18~21    | `下部\stm32/15~28` + 资料 | 14         |
-
-## 3. 每篇笔记模板
-
-结构镜像原 DOCX 章节组织方式(外设介绍 → 硬件设计 → 代码实验),代码直接从源文件复制并标注文件名,方便只看 MD 即可复现。
-
-````markdown
----
-tags: [source-summary]
-type: source
-source: "尚硅谷嵌入式技术之STM32单片机 — {来源章节} + 配套代码{编号}"
-author: "尚硅谷研究院"
-date: YYYY-MM-DD
-created: YYYY-MM-DD
----
-
-# {外设名称}
-
-> **用生活理解**:{一句话类比}
-
-## {外设}介绍
-
-### 基本概念
-
-{是什么、有什么用、应用场景}
-
-### 工作原理(框图 + 文字说明)
-
-> 参考:STM32F103ZET6 参考手册 §X.X
-> 参考:开发板原理图第X页 {引脚}
-
-### {外设}的寄存器详解
-
-| 寄存器 | 地址偏移 | 位域 | 说明 |
-| ------ | -------- | ---- | ---- |
-| CR1    | 0x00     | ...  | ...  |
-
-## {外设}硬件电路设计
-
-![电路原理图](assets/xxx.png)
-{引脚连接说明}
-
-## {实验/案例标题}
-
-### 需求描述
-
-### 硬件电路设计(如与通用硬件不同则补充)
-
-### 软件设计(寄存器版)
-
-**文件:{项目路径}/User/main.c**
-
-```c
-// 注释说明这段代码的功能
-// 重要位操作行有详细注释
-```
-````
-
-**文件:{项目路径}/Hardware/{外设}/{driver}.h**
-
-```c
-// 头文件内容
-```
-
-**文件:{项目路径}/Hardware/{外设}/{driver}.c**
-
-```c
-// 驱动源码 + 逐行注释
-```
-
-### 软件设计(HAL库版)
-
-**文件:{项目路径}/User/main.c**
-
-```c
-// HAL版代码,直接从源码项目复制
-```
-
-**文件:{项目路径}/Hardware/{外设}/{driver}.c**
-
-```c
-
-```
-
-## 核心函数速查表
-
-| 函数 | 参数 | 功能简述 |
-| ---- | ---- | -------- |
-| xxx  | ...  | ...      |
-
-## 常见问题与避坑
-
-```
-
-## 4. 图片策略
-
-- 保留所有原 DOCX 图片
-- pandoc `--extract-media` 提取到临时目录
-- 视觉 API 逐张验证内容(寄存器位域图/框图/时序图/原理图)
-- 重命名为有意义名称(`{外设}_{内容}.png`)
-- 复制到对应笔记的 `assets/` 子目录
-- 引用使用相对路径
-
-## 5. Wiki 更新
-
-每批次完成后:
-1. 更新 `wiki/source-stm32-{关键词}.md`
-2. 更新 `wiki/index.md` 添加 STM32 章节
-3. 追加 `wiki/log.md`
-4. 提交 `ingest: 尚硅谷STM32 {批次名称}`
-```

+ 0 - 459
docs/superpowers/specs/2026-07-17-freertos-silicon-valley-ingest-design.md

@@ -1,459 +0,0 @@
-# 设计文档:尚硅谷 FreeRTOS 笔记重构计划
-
-**日期**:2026-07-17
-**来源**:尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3
-**目标目录**:`raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/`
-**目标芯片**:STM32F103ZET6(Cortex-M3)
-**参考设计**:`docs/superpowers/specs/2026-07-15-stm32-silicon-valley-ingest-design.md`
-**工作流参考**:`docs/如何将他人文档整理为LLM-Wiki笔记.md`
-
----
-
-## 1. 笔记分篇(共 16 篇)
-
-### 总览
-
-| #   | 文件名                             | 对应课程章节                                                          | 配套代码项目   |
-| --- | ---------------------------------- | --------------------------------------------------------------------- | -------------- |
-| 01  | `01-实时操作系统基础.md`           | 第 1 章(操作系统介绍 + FreeRTOS 简介)                               | —              |
-| 02  | `02-任务调度与状态管理.md`         | 第 2 章(多任务/调度策略/任务状态/滴答/上下文切换/空闲任务)          | —              |
-| 03  | `03-FreeRTOS移植指南.md`           | 第 3 章(源码结构 + HAL 移植 + 寄存器移植 + 配置文件说明)            | 00_HAL_Key     |
-| 04  | `04-数据类型命名与配置详解.md`     | 第 3 章后半(数据类型/命名规范/FreeRTOSConfig.h 全项)                | —              |
-| 05  | `05-任务创建与删除.md`             | 第 4 章(动态创建 + 静态创建 + 删除)                                 | 01, 02         |
-| 06  | `06-任务挂起与恢复.md`             | 第 5 章(单任务挂起/恢复 + 调度器挂起/恢复)                          | 03             |
-| 07  | `07-中断管理与临界段.md`           | 第 6 章(临界区/BASEPRI/中断安全 API/延迟中断处理)                   | 04             |
-| 08  | `08-时间片调度与延时管理.md`       | 第 7 章 + 第 9 章(时间片/vTaskDelay/vTaskDelayUntil)                | 05, 08         |
-| 09  | `09-任务状态查询与运行时统计.md`   | 第 8 章(状态查询 API/vTaskList/vTaskGetRunTimeStats)                | 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 章(定时器/一次性/周期/Tickless 模式)               | 19, 20         |
-| 16  | `16-内存管理.md`                   | 第 17 章(heap_1~5 算法/pvPortMalloc/vPortFree/xPortGetFreeHeapSize) | 21             |
-
-### 分篇依据
-
-- 每篇对应课程中一个独立概念群,确保每篇可独立阅读
-- 代码项目按功能归属分配到对应笔记
-- 以"介绍 → 工作原理 → API → 实验 → 速查表 → 避坑"结构组织
-
----
-
-## 2. 每篇笔记模板
-
-统一的 Markdown 模板,参考 STM32 笔记格式:
-
-````markdown
----
-tags: [source-summary]
-type: source
-source: "尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3 — {对应课程章节}"
-author: "尚硅谷研究院"
-date: 2026-07-17
-created: 2026-07-17
----
-
-# {主题名称}
-
-> **用生活理解**:{一句话类比,用生活中的例子解释}
-
-## {概念}介绍
-
-### 基本概念
-
-{是什么、有什么用、解决什么问题}
-
-### 工作原理
-
-{框图说明 + 文字描述}
-
-> 参考:FreeRTOS 官方文档 §X.X
-
-### 核心 API
-
-| 函数 | 参数 | 功能简述 |
-| ---- | ---- | -------- |
-| xxx  | ...  | ...      |
-
-## {实验/案例}
-
-### 需求描述
-
-{实验要实现的功能}
-
-### 软件设计
-
-**文件:{代码项目相对路径}/Core/Src/freertos_demo.c**
-
-```c
-// 核心代码段,直接从项目复制,保留完整函数
-// 每行 API 调用标注通俗解释
-```
-````
-
-### 关键配置
-
-```c
-// FreeRTOSConfig.h 中本实验特有的配置项
-```
-
-## 核心函数速查表
-
-| 函数 | 参数 | 返回值 | 功能简述 |
-| ---- | ---- | ------ | -------- |
-| xxx  | ...  | ...    | ...      |
-
-## 常见问题与避坑
-
-````
-
-### 硬性要求
-
-1. **Frontmatter**:必须包含 `tags: [source-summary]`, `type: source`, `source`, `author`, `date`, `created`
-2. **通俗类比**:每篇开头必须有一句 `> **用生活理解**:`,用生活场景类比技术概念
-3. **代码注释**:代码中每行 API 调用必须有中文注释说明其作用;保留 `// 按位或: 保持其他位不变` 这类位操作注释(如有)
-4. **文件标注**:每段代码前标注来源文件路径(相对于 FreeRTOS 学习笔记根目录或外部源码目录)
-5. **API 速查表**:每篇结尾汇总本笔记涉及的 API 函数
-6. **常见问题**:每篇结尾必须有"常见问题与避坑"章节
-
----
-
-## 3. 代码策略
-
-### 3.1 代码来源
-
-所有代码示例直接来源于`F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\03_代码\`下的 22 个 Keil 项目(编号 00~21)。
-
-### 3.2 提取规则
-
-- 核心演示代码从 `Core/Src/freertos_demo.c` 提取
-- 保留完整函数体,不打断逻辑
-- 删除重复的模板代码(`start_task` 骨架在不同项目中几乎一致,在 05 笔记中完整展示一次即可,后续笔记中简写)
-- 删除 HAL 初始化骨架(`main.c` 中的 `HAL_Init()`, `SystemClock_Config()`, `MX_GPIO_Init()` 等,与 FreeRTOS 无关)
-- `FreeRTOSConfig.h` 中与本实验**特殊相关**的配置项(非通用基线)必须在笔记中说明
-
-### 3.3 通用模板代码简化
-
-所有项目共有的 `start_task` → `taskENTER_CRITICAL()` → 创建工作任务的模式,在 05 笔记完整展示后,从 06 起可简写为:
-
-```c
-// 创建工作任务的代码与 05 笔记相同,此处省略
-// 完整模板见 05-任务创建与删除.md
-````
-
-### 3.4 代码路径引用格式
-
-```
-**代码来源**:`03_代码/09_消息队列/Core/Src/freertos_demo.c`
-```
-
----
-
-## 4. 图片策略
-
-### 4.1 源图片
-
-原始笔记 `F:\Baidu\尚硅谷\尚硅谷嵌入式技术之FreeRTOS实时操作系统\01_笔记\images\media\` 包含 48 张 PNG 图片(`image1.png` ~ `image48.png`)。
-
-### 4.2 筛选标准
-
-| 保留           | 删除                                     |
-| -------------- | ---------------------------------------- |
-| 调度策略对比图 | IDE 安装/配置截图                        |
-| 任务状态转换图 | Keil 工程添加文件步骤截图                |
-| 就绪列表位图   | CubeMX 配置截图                          |
-| 上下文切换流程 | 下载链接/官网页面截图                    |
-| 队列结构图     | 文件目录结构截图(源码结构等可文字描述) |
-| 信号量机制图   | 选项框勾选截图                           |
-| 优先级反转时序 | 数值/文字设置截图                        |
-| 事件组位结构图 | 代码编辑界面截图(代码已在正文中)       |
-| heap 算法对比  | 与 FreeRTOS 功能无关的配图               |
-| 定时器状态机   |                                          |
-
-### 4.3 重命名规则
-
-- 全部小写英文蛇形命名:`{主题}_{内容}.png`
-- 示例:`task_state_diagram.png`, `scheduling_preemption_vs_cooperative.png`
-- 映射表在实现计划中详细列出
-
-### 4.4 存放位置
-
-精选后的图片存放在 `raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/assets/`,笔记内用相对路径引用:
-
-```markdown
-![任务状态转换图](assets/task_state_diagram.png)
-```
-
----
-
-## 5. 每篇笔记内容大纲
-
-### 01-实时操作系统基础.md
-
-| 章节         | 内容概要                                      |
-| ------------ | --------------------------------------------- |
-| 基本概念     | 裸机开发的局限性、OS vs 裸机、通用 OS vs RTOS |
-| 工作原理     | 计算机系统三层模型(硬件/OS/应用)            |
-| FreeRTOS简介 | 发展历史(2003→2017 AWS收购)、特点、优势     |
-| 核心API      | —                                             |
-| 速查表       | —                                             |
-| 常见问题     | 开源≠免费?RTOS 与 Linux 的区别               |
-
-### 02-任务调度与状态管理.md
-
-| 章节     | 内容概要                                                                                                        |
-| -------- | --------------------------------------------------------------------------------------------------------------- |
-| 基本概念 | 任务、内核、多任务处理                                                                                          |
-| 工作原理 | 调度策略(抢占式/时间片/协程式)、4 种任务状态(运行/就绪/阻塞/挂起)、就绪列表位图、滴答计数器、上下文切换流程 |
-| 空闲任务 | 自动创建、作用(释放内存/计数/低功耗)                                                                          |
-| 核心API  | —                                                                                                               |
-| 速查表   | —                                                                                                               |
-| 常见问题 | 阻塞 vs 挂起本质区别、时间片提前结束条件                                                                        |
-
-### 03-FreeRTOS移植指南.md
-
-| 章节         | 内容概要                                                                                                                                             |
-| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 源码结构     | FreeRTOS/FreeRTOS-Plus/Tools,Source 目录 7 个 .c + include + portable                                                                               |
-| HAL库移植    | 目录添加源码、Keil 工程添加 Group、FreeRTOSConfig.h 修改(xPortPendSVHandler/vPortSVCHandler)、stm32f1xx_it.c 修改(SVC/PendSV 注释、SysTick 回调) |
-| 寄存器移植   | 同上 + main.c 添加 SysTick_Handler                                                                                                                   |
-| 配置文件说明 | 三类配置项:INCLUDE_、config开头、其他                                                                                                               |
-| 移植检查清单 | 关键步骤核对表                                                                                                                                       |
-| 常见问题     | HAL+SysTick 冲突、卡死排查                                                                                                                           |
-
-### 04-数据类型命名与配置详解.md
-
-| 章节             | 内容概要                                                          |
-| ---------------- | ----------------------------------------------------------------- |
-| 数据类型         | TickType_t/BaseType_t/StackType_t 等定义与场景                    |
-| 命名规范         | 前缀规则(v/x/ux/pv/h等)、函数命名、宏命名、数据类型命名         |
-| FreeRTOSConfig.h | 全部配置项分组说明(基础/内存/钩子/时间片/中断/函数使能)带推荐值 |
-| 速查表           | 数据类型、命名前缀对照表                                          |
-| 常见问题         | config 值设置不当的后果                                           |
-
-### 05-任务创建与删除.md
-
-| 章节     | 内容概要                                                                         |
-| -------- | -------------------------------------------------------------------------------- |
-| 基本概念 | 任务控制块 TCB、任务堆栈、任务句柄                                               |
-| 工作原理 | xTaskCreate 动态分配 vs xTaskCreateStatic 静态分配                               |
-| 核心API  | xTaskCreate/xTaskCreateStatic/vTaskDelete                                        |
-| 实验1    | 动态创建 3 个任务,task3 按键删除 task1(项目 01)                               |
-| 实验2    | 静态创建 3 个任务(项目 02),涉及 vApplicationGetIdleTaskMemory/TimerTaskMemory |
-| 关键配置 | configSUPPORT_STATIC_ALLOCATION=1                                                |
-| 速查表   | 创建/删除 API                                                                    |
-| 常见问题 | 删除后句柄置 NULL 的重要性                                                       |
-
-### 06-任务挂起与恢复.md
-
-| 章节     | 内容概要                                                          |
-| -------- | ----------------------------------------------------------------- |
-| 基本概念 | 挂起态本质(暂停,不参与调度)                                    |
-| 核心API  | vTaskSuspend/vTaskResume/vTaskSuspendAll/xTaskResumeAll/vTaskList |
-| 实验     | 4 个按键控制:挂起/恢复单任务、挂起/恢复调度器(项目 03)         |
-| 速查表   | 挂起/恢复 API                                                     |
-| 常见问题 | 挂起 vs 阻塞 vs 删除深度对比                                      |
-
-### 07-中断管理与临界段.md
-
-| 章节     | 内容概要                                                                                         |
-| -------- | ------------------------------------------------------------------------------------------------ |
-| 基本概念 | Cortex-M 中断优先级、BASEPRI 寄存器                                                              |
-| 工作原理 | 临界区(taskENTER_CRITICAL/EXIT_CRITICAL)、中断安全 API(FromISR 后缀)、延迟中断处理(PendSV) |
-| 核心API  | taskENTER_CRITICAL/taskEXIT_CRITICAL/portDISABLE_INTERRUPTS/portENABLE_INTERRUPTS                |
-| 实验     | KEY1 禁用中断、KEY2 启用中断(项目 04)                                                          |
-| 关键配置 | configMAX_SYSCALL_INTERRUPT_PRIORITY                                                             |
-| 速查表   | 中断管理 API                                                                                     |
-| 常见问题 | 临界区内不要调用阻塞 API                                                                         |
-
-### 08-时间片调度与延时管理.md
-
-| 章节     | 内容概要                                                                        |
-| -------- | ------------------------------------------------------------------------------- |
-| 基本概念 | 时间片轮转调度、相对延时 vs 绝对延时                                            |
-| 工作原理 | 同等优先级任务轮流执行一个时间片、vTaskDelay 漂移问题、vTaskDelayUntil 固定周期 |
-| 核心API  | vTaskDelay/vTaskDelayUntil/xTaskGetTickCount                                    |
-| 实验1    | 同优先级 2 个任务时间片轮转(项目 05),临界区保护临界段                        |
-| 实验2    | vTaskDelay vs vTaskDelayUntil 对比(项目 08)                                   |
-| 关键配置 | configUSE_TIME_SLICING、configTICK_RATE_HZ                                      |
-| 速查表   | 时间管理 API                                                                    |
-| 常见问题 | vTaskDelayUntil 必须使用 while(1) 开头获取 tick                                 |
-
-### 09-任务状态查询与运行时统计.md
-
-| 章节     | 内容概要                                                                                                                                                                                                      |
-| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 基本概念 | 任务运行时信息、堆栈余量                                                                                                                                                                                      |
-| 核心API  | uxTaskPriorityGet/vTaskPrioritySet/uxTaskGetNumberOfTasks/uxTaskGetSystemState/vTaskGetInfo/xTaskGetCurrentTaskHandle/xTaskGetHandle/uxTaskGetStackHighWaterMark/eTaskGetState/vTaskList/vTaskGetRunTimeStats |
-| 实验1    | 完整状态查询 API 套件一次性演示(项目 06)                                                                                                                                                                    |
-| 实验2    | 运行时统计打印(项目 07),需高精度定时器                                                                                                                                                                     |
-| 关键配置 | configUSE_TRACE_FACILITY、configUSE_STATS_FORMATTING_FUNCTIONS、configGENERATE_RUN_TIME_STATS                                                                                                                 |
-| 速查表   | 查询/统计 API                                                                                                                                                                                                 |
-| 常见问题 | 运行时间统计需要额外硬件定时器                                                                                                                                                                                |
-
-### 10-消息队列.md
-
-| 章节     | 内容概要                                                     |
-| -------- | ------------------------------------------------------------ |
-| 基本概念 | 队列是什么(任务间数据传递的 FIFO 缓冲区)、队列长度/项大小  |
-| 工作原理 | 队列内部结构(环形缓冲区/等待列表)、写时拷贝                |
-| 核心API  | xQueueCreate/xQueueSend/xQueueReceive                        |
-| 实验     | 2 个队列:queue1 传按键值、big_queue 传指针(项目 09)       |
-| 关键配置 | configQUEUE_REGISTRY_SIZE                                    |
-| 速查表   | 队列 API                                                     |
-| 常见问题 | portMAX_DELAY 等待、队列满时的阻塞、消息队列与全局变量的选择 |
-
-### 11-信号量机制.md
-
-| 章节     | 内容概要                                                                                                                |
-| -------- | ----------------------------------------------------------------------------------------------------------------------- |
-| 基本概念 | 信号量是"钥匙"还是"计数器"?二值/计数/互斥的区别                                                                        |
-| 工作原理 | 基于队列实现、计数信号量累加、互斥信号量的优先级继承机制                                                                |
-| 核心API  | vSemaphoreCreateBinary/xSemaphoreCreateCounting/xSemaphoreCreateMutex/xSemaphoreGive/xSemaphoreTake/uxSemaphoreGetCount |
-| 实验1    | 二值信号量:task1 Give → task2 Take(项目 10)                                                                          |
-| 实验2    | 计数信号量:KEY1 累加计数(项目 11)                                                                                    |
-| 实验3    | 优先级反转:低优先级任务持有信号量被高优先级等待(项目 12)                                                             |
-| 实验4    | 互斥信号量:优先级继承解决反转(项目 13)                                                                               |
-| 关键配置 | configUSE_COUNTING_SEMAPHORES、configUSE_MUTEXES、configUSE_RECURSIVE_MUTEXES                                           |
-| 速查表   | 信号量 API                                                                                                              |
-| 常见问题 | 二值信号量与互斥量的选择、优先级反转的触发条件与解决方案                                                                |
-
-### 12-队列集.md
-
-| 章节     | 内容概要                                           |
-| -------- | -------------------------------------------------- |
-| 基本概念 | 队列集用于同时等待队列和信号量                     |
-| 工作原理 | 队列集内部机制:成员注册、事件通知                 |
-| 核心API  | xQueueCreateSet/xQueueAddToSet/xQueueSelectFromSet |
-| 实验     | 队列集包含一个队列和一个二值信号量(项目 14)      |
-| 关键配置 | configUSE_QUEUE_SETS=1                             |
-| 速查表   | 队列集 API                                         |
-| 常见问题 | 队列集中不要单独删除成员                           |
-
-### 13-事件标志组.md
-
-| 章节     | 内容概要                                                            |
-| -------- | ------------------------------------------------------------------- |
-| 基本概念 | 事件标志组是位的集合,任务等待特定位组合                            |
-| 工作原理 | 24 位可用(RTOS 保留高 8 位)、等待逻辑(AND/OR)                   |
-| 核心API  | xEventGroupCreate/xEventGroupSetBits/xEventGroupWaitBits            |
-| 实验     | KEY1 置位 BIT0、KEY2 置位 BIT1、task2 等待两个位全部置位(项目 15) |
-| 速查表   | 事件标志组 API                                                      |
-| 常见问题 | 等待完成后自动清除位(pdTRUE)的使用                                |
-
-### 14-任务通知.md
-
-| 章节     | 内容概要                                                                          |
-| -------- | --------------------------------------------------------------------------------- |
-| 基本概念 | 任务通知是轻量级 IPC,每个 TCB 内置 32 位通知值                                   |
-| 工作原理 | 通知值可作信号量(计数递减)/消息队列(覆写值)/事件组(置位),比独立 IPC 快 45% |
-| 核心API  | xTaskNotifyGive/ulTaskNotifyTake/xTaskNotify/xTaskNotifyWait                      |
-| 实验1    | 通知模拟信号量(项目 16)                                                         |
-| 实验2    | 通知模拟消息队列(项目 17)使用 eSetValueWithOverwrite                            |
-| 实验3    | 通知模拟事件标志组(项目 18)使用 eSetBits                                        |
-| 速查表   | 任务通知 API                                                                      |
-| 常见问题 | 通知不能用于 ISR 到多任务的分发、v10.4 后通知数组支持                             |
-
-### 15-软件定时器与Tickless低功耗.md
-
-| 章节     | 内容概要                                                                                                                     |
-| -------- | ---------------------------------------------------------------------------------------------------------------------------- |
-| 基本概念 | 软件定时器基于 Tick 计数、不同于硬件定时器                                                                                   |
-| 工作原理 | 定时器状态(休眠/运行/暂停)、一次性 vs 周期型、定时器命令队列、定时器服务任务                                               |
-| Tickless | 低功耗模式原理、configUSE_TICKLESS_IDLE、PRE_SLEEP_PROCESSING/POST_SLEEP_PROCESSING                                          |
-| 核心API  | xTimerCreate/xTimerStart/xTimerStop(软件定时器)、configUSE_TICKLESS_IDLE(低功耗)                                         |
-| 实验1    | 一次性定时器 + 周期型定时器,按键启动/停止(项目 19)                                                                        |
-| 实验2    | Tickless 模式:休眠时关闭 GPIO 时钟(项目 20)                                                                               |
-| 关键配置 | configUSE_TIMERS、configTIMER_TASK_PRIORITY、configTIMER_QUEUE_LENGTH、configTIMER_TASK_STACK_DEPTH、configUSE_TICKLESS_IDLE |
-| 速查表   | 定时器 API + Tickless 配置项                                                                                                 |
-| 常见问题 | 定时器回调中不要调用阻塞 API、Tickless 模式的最小空闲时间配置                                                                |
-
-### 16-内存管理.md
-
-| 章节     | 内容概要                                                |
-| -------- | ------------------------------------------------------- |
-| 基本概念 | FreeRTOS 内存管理需求、5 种 heap 算法的设计哲学         |
-| 工作原理 |                                                         | 算法                | 适用场景       | 优点           | 缺点 |
-|          | ----                                                    | ---------           | ------         | ------         |
-|          | heap_1                                                  | 不删除任务或队列    | 简单、确定性强 | 不能释放       |
-|          | heap_2                                                  | 随意分配释放        | 支持释放       | 碎片化         |
-|          | heap_3                                                  | 需要线程安全 malloc | 包装 C 库函数  | 依赖编译器     |
-|          | heap_4                                                  | 默认推荐            | 合并相邻空闲块 | 大块释放后碎片 |
-|          | heap_5                                                  | 不连续 RAM 堆       | 跨内存区域分配 | 实现复杂       |
-| 核心API  | pvPortMalloc/vPortFree/xPortGetFreeHeapSize             |
-| 实验     | KEY1 分配 20 字节、KEY2 释放(项目 21)                 |
-| 关键配置 | configTOTAL_HEAP_SIZE、configSUPPORT_DYNAMIC_ALLOCATION |
-| 速查表   | 内存管理 API                                            |
-| 常见问题 | heap 大小不足时的处理策略、碎片化监控                   |
-
----
-
-## 6. 目标目录结构
-
-```
-raw/Joplin/嵌入式+Linux/FreeRTOS学习笔记/
-├── assets/                           # 精选图片(预计 15~25 张)
-│   ├── task_state_diagram.png
-│   ├── scheduling_preemption.png
-│   ├── scheduling_timeslice.png
-│   ├── ready_list_bitmap.png
-│   ├── ready_list_same_priority.png
-│   ├── context_switch.png
-│   ├── queue_structure.png
-│   ├── priority_inversion.png
-│   ├── priority_inheritance.png
-│   ├── event_group_bits.png
-│   ├── timer_states.png
-│   ├── heap_comparison.png
-│   └── ...(根据实际图片内容命名)
-├── 01-实时操作系统基础.md
-├── 02-任务调度与状态管理.md
-├── 03-FreeRTOS移植指南.md
-├── 04-数据类型命名与配置详解.md
-├── 05-任务创建与删除.md
-├── 06-任务挂起与恢复.md
-├── 07-中断管理与临界段.md
-├── 08-时间片调度与延时管理.md
-├── 09-任务状态查询与运行时统计.md
-├── 10-消息队列.md
-├── 11-信号量机制.md
-├── 12-队列集.md
-├── 13-事件标志组.md
-├── 14-任务通知.md
-├── 15-软件定时器与Tickless低功耗.md
-└── 16-内存管理.md
-```
-
----
-
-## 7. Wiki 更新
-
-重构完成后必须执行的维基更新:
-
-### 7.1 更新 `wiki/source-freertos.md`
-
-- 笔记列表改为 16 篇新笔记
-- 更新代码项目映射表
-
-### 7.2 更新 `wiki/index.md`
-
-- FreeRTOS 章节保持与已有 Wiki 页面的 `[[wikilink]]` 连接
-- 更新原始笔记路径映射
-
-### 7.3 追加 `wiki/log.md`
-
-- 记录本次重构操作
-- 注明 11 篇旧笔记被 16 篇新笔记替代
-
----
-
-## 8. 硬性约束
-
-1. **不修改 `raw/` 以外的文件**(Wiki 除外:`source-freertos.md`, `index.md`, `log.md`)
-2. **所有代码必须来自真实项目文件**,不凭空编写代码
-3. **每行 API 代码必须标注通俗解释注释**
-4. **每篇必须有通俗类比**(`> **用生活理解**:`)
-5. **图片必须经过筛选**,不盲目全部复制
-6. **16 篇一次完成**,不分批次
-7. **旧 11 篇笔记覆盖前先确认备份**(实际已不存在,直接新建)

+ 0 - 295
tools/extract.py

@@ -1,295 +0,0 @@
-# /// script
-# dependencies = ["requests", "silero-vad", "torch"]
-# ///
-"""Extract timed text from video subtitles; transcribe via ASR; grab frames.
-
-Commands:
-  parse       <input> [--outdir <dir>]           extract timed text from subtitles
-  transcribe  <video> [--outpath <path>]          transcribe speech via VAD+ASR
-  frame       <video> <timestamp> --outpath <p>   extract single frame
-"""
-
-import argparse
-import os
-import re
-import subprocess
-import sys
-import tempfile
-from pathlib import Path
-
-SRT_PATTERN = re.compile(
-    r"(\d+)\s+(\d{2}:\d{2}:\d{2}[.,]\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2}[.,]\d{3})\s*((?:(?!\n\n).)*)",
-    re.DOTALL,
-)
-ASS_DIALOGUE = re.compile(
-    r"^Dialogue:\s*\d+,(\d:\d{2}:\d{2}\.\d{2}),(\d:\d{2}:\d{2}\.\d{2}),.*?,(.*?)$",
-    re.MULTILINE,
-)
-ASS_TAG = re.compile(r"\{[^}]*\}")
-ASS_LINEBREAK = re.compile(r"\\[Nn]")
-
-
-def find_subtitle(video_path: Path) -> Path | None:
-    """Return matching .srt (prefer Chinese) or .ass for video_path, or None."""
-
-    def _candidates(base: str) -> list[Path]:
-        parent = video_path.parent
-        out: list[Path] = []
-        for f in parent.iterdir():
-            if not f.is_file():
-                continue
-            stem = f.stem
-            if not stem.startswith(base):
-                continue
-            if f.suffix == ".srt" and "_英文" not in stem and "_English" not in stem:
-                out.append(f)
-            elif f.suffix == ".ass":
-                out.append(f)
-        return out
-
-    base = video_path.stem
-    cands = _candidates(base)
-    srt = [c for c in cands if c.suffix == ".srt"]
-    ass = [c for c in cands if c.suffix == ".ass"]
-    chosen = srt[0] if srt else (ass[0] if ass else None)
-
-    if chosen is None:
-        shorter = base.split("-")[0] if "-" in base else base
-        if shorter != base:
-            cands = _candidates(shorter)
-            srt = [c for c in cands if c.suffix == ".srt"]
-            ass = [c for c in cands if c.suffix == ".ass"]
-            chosen = srt[0] if srt else (ass[0] if ass else None)
-    return chosen
-
-
-def _ts_to_sec(ts: str) -> float:
-    ts = ts.replace(",", ".")
-    parts = ts.split(":")
-    h, m = int(parts[0]), int(parts[1])
-    s = float(parts[2]) if len(parts) == 3 else 0.0
-    return h * 3600 + m * 60 + s
-
-
-def sec_to_ts(sec: float) -> str:
-    h = int(sec // 3600)
-    m = int((sec % 3600) // 60)
-    s = sec % 60
-    return f"{h:02d}:{m:02d}:{s:06.3f}"
-
-
-def parse_srt(path: Path) -> list[tuple[float, str]]:
-    text = path.read_text(encoding="utf-8-sig")
-    segs: list[tuple[float, str]] = []
-    for m in SRT_PATTERN.finditer(text):
-        start = _ts_to_sec(m.group(2))
-        raw = m.group(4).strip().replace("\n", " ")
-        if raw:
-            segs.append((start, raw))
-    return segs
-
-
-def parse_ass(path: Path) -> list[tuple[float, str]]:
-    text = path.read_text(encoding="utf-8-sig")
-    segs: list[tuple[float, str]] = []
-    for m in ASS_DIALOGUE.finditer(text):
-        start = _ts_to_sec(m.group(1))
-        raw = m.group(3).strip()
-        raw = ASS_TAG.sub("", raw)
-        raw = ASS_LINEBREAK.sub(" ", raw)
-        if raw:
-            segs.append((start, raw))
-    return segs
-
-
-def collect_videos(input_path: Path) -> list[Path]:
-    if input_path.is_file():
-        return [input_path]
-    return sorted(input_path.rglob("*.mp4"))
-
-
-def cmd_parse(args: argparse.Namespace) -> None:
-    input_path = Path(args.input)
-    outdir = Path(args.outdir)
-    videos = collect_videos(input_path)
-
-    for vp in videos:
-        sub = find_subtitle(vp)
-        if sub is None:
-            print(f"[WARN] No subtitle for: {vp.name}", file=sys.stderr)
-            continue
-        segs: list[tuple[float, str]] = []
-        if sub.suffix == ".srt":
-            segs = parse_srt(sub)
-        elif sub.suffix == ".ass":
-            segs = parse_ass(sub)
-
-        if input_path.is_dir():
-            rel = vp.relative_to(input_path)
-            out = outdir / rel.with_suffix(".txt")
-        else:
-            out = outdir / vp.with_suffix(".txt").name
-        out.parent.mkdir(parents=True, exist_ok=True)
-
-        lines = [f"[{sec_to_ts(s)}] {t}" for s, t in segs]
-        out.write_text("\n".join(lines), encoding="utf-8")
-        print(f"[OK] {vp.name} -> {out}  ({len(segs)} segments)")
-
-
-def parse_ts(s: str) -> float:
-    s = s.strip()
-    if ":" in s:
-        parts = s.split(":")
-        h, m = int(parts[0]), int(parts[1])
-        sec = float(parts[2]) if len(parts) == 3 else 0.0
-        return h * 3600 + m * 60 + sec
-    return float(s)
-
-
-def cmd_frame(args: argparse.Namespace) -> None:
-    video = Path(args.video)
-    if not video.exists():
-        print(f"[ERR] Video not found: {video}", file=sys.stderr)
-        sys.exit(1)
-    ts = parse_ts(args.timestamp)
-    out = Path(args.outpath)
-    out.parent.mkdir(parents=True, exist_ok=True)
-
-    cmd = [
-        "ffmpeg", "-ss", str(ts), "-i", str(video),
-        "-vframes", "1", "-q:v", "2", "-y", str(out),
-    ]
-    result = subprocess.run(cmd, capture_output=True, text=True)
-    if result.returncode != 0:
-        print(f"[ERR] ffmpeg failed: {result.stderr.strip()}", file=sys.stderr)
-        sys.exit(1)
-    print(f"[OK] Frame saved -> {out}")
-
-
-def extract_audio(video_path: Path, out_wav: Path) -> None:
-    """Extract 16kHz mono WAV from video."""
-    cmd = [
-        "ffmpeg", "-y", "-i", str(video_path),
-        "-vn", "-ar", "16000", "-ac", "1",
-        str(out_wav),
-    ]
-    subprocess.run(cmd, capture_output=True, check=True)
-
-
-def read_audio_tensor(wav_path: Path) -> "torch.Tensor":
-    """Read WAV file as mono float32 tensor (compat with silero-vad)."""
-    import numpy as np
-    import torch
-    # Use ffmpeg to decode to raw PCM float32
-    result = subprocess.run(
-        ["ffmpeg", "-y", "-i", str(wav_path),
-         "-f", "f32le", "-ac", "1", "-ar", "16000", "-"],
-        capture_output=True, check=True,
-    )
-    arr = np.frombuffer(result.stdout, dtype=np.float32).copy()
-    return torch.from_numpy(arr).squeeze()
-
-
-def _find_model_dir(model_size: str) -> str | None:
-    """Find cached faster-whisper model directory."""
-    repo = f"Systran/faster-whisper-{model_size}"
-    cache = Path(os.path.expanduser("~/.cache/huggingface/hub"))
-    repo_dir = cache / f"models--{repo.replace('/', '--')}"
-    if not repo_dir.exists():
-        return None
-    snapshots = repo_dir / "snapshots"
-    if not snapshots.exists():
-        return None
-    snaps = list(snapshots.iterdir())
-    return str(snaps[0]) if snaps else None
-
-
-def cmd_transcribe(args: argparse.Namespace) -> None:
-    video = Path(args.video)
-    if not video.exists():
-        print(f"[ERR] Video not found: {video}", file=sys.stderr)
-        sys.exit(1)
-
-    outpath = Path(args.outpath) if args.outpath else None
-    model_size = args.model
-
-    model_dir = _find_model_dir(model_size)
-    if model_dir is None:
-        print(f"[ERR] Model '{model_size}' not cached locally", file=sys.stderr)
-        sys.exit(1)
-
-    print(f"[...] Extracting audio from {video.name} ...", file=sys.stderr)
-    wav = Path(tempfile.mktemp(suffix=".wav"))
-    try:
-        extract_audio(video, wav)
-
-        print(f"[...] Loading faster-whisper ({model_size}) ...", file=sys.stderr)
-        import os as _os
-        _os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1"
-        from faster_whisper import WhisperModel
-        model = WhisperModel(model_dir, device="cpu", compute_type="int8")
-
-        print(f"[...] Transcribing. This may take a few minutes ...", file=sys.stderr)
-        segments, _info = model.transcribe(
-            str(wav), beam_size=5, vad_filter=True,
-            vad_parameters=dict(min_silence_duration_ms=300),
-        )
-
-        segs: list[tuple[float, str]] = []
-        for seg in segments:
-            text = seg.text.strip()
-            if text:
-                segs.append((seg.start, text))
-
-        print(f"[...] {len(segs)} segments", file=sys.stderr)
-        for s, t in segs:
-            print(f"  [{sec_to_ts(s)}] {t[:80]}", file=sys.stderr)
-
-    finally:
-        wav.unlink(missing_ok=True)
-
-    if not segs:
-        print(f"[WARN] No speech transcribed", file=sys.stderr)
-        return
-
-    lines = [f"[{sec_to_ts(s)}] {t}" for s, t in segs]
-    if outpath:
-        outpath.parent.mkdir(parents=True, exist_ok=True)
-        outpath.write_text("\n".join(lines), encoding="utf-8")
-        print(f"[OK] Transcribed -> {outpath}  ({len(segs)} segments)")
-    else:
-        print("\n".join(lines))
-
-
-def main() -> None:
-    parser = argparse.ArgumentParser(description="Video subtitle extractor & frame grabber")
-    sub = parser.add_subparsers(dest="command")
-
-    p = sub.add_parser("parse", help="Extract timed text from subtitles")
-    p.add_argument("input", help="Video file or directory")
-    p.add_argument("--outdir", default="./transcripts", help="Output directory")
-
-    p = sub.add_parser("transcribe", help="Transcribe speech via local faster-whisper")
-    p.add_argument("video", help="Path to video file")
-    p.add_argument("--outpath", help="Output transcript path (default: stdout)")
-    p.add_argument("--model", default="base", help="Model size: tiny/base/small/medium/large")
-
-    p = sub.add_parser("frame", help="Extract single frame as JPEG")
-    p.add_argument("video", help="Path to video file")
-    p.add_argument("timestamp", help="Timestamp (HH:MM:SS or seconds)")
-    p.add_argument("--outpath", required=True, help="Output image path")
-
-    args = parser.parse_args()
-    if args.command == "parse":
-        cmd_parse(args)
-    elif args.command == "transcribe":
-        cmd_transcribe(args)
-    elif args.command == "frame":
-        cmd_frame(args)
-    else:
-        parser.print_help()
-        sys.exit(1)
-
-
-if __name__ == "__main__":
-    main()