e7f28502bc
结构债 S-2 的最后一步——**该族的 24 处手写跨模块裸 extern 就此全部清零**。 队列对象仍由 CubeMX 在 `MX_FREERTOS_Init()` 创建(**创建点不可外移**: `osKernelInitialize()` 之前的任何创建类 API 会杀死启动,见 `docs/架构设计/项目启动顺序管理.md`);改为创建后立刻在 `Src/freertos.c` 的 `USER CODE BEGIN RTOS_QUEUES` 区调用 `net_msg_queue_adopt(netMsgQueueHandle)`, 把句柄交给唯一使用者。`net_socket.c` 内改用 `static osMessageQueueId_t s_net_msg_queue`(21 处引用改名),BSP 对该全局变量的裸 `extern` 消失——现在 `netMsgQueueHandle` 只出现在生成文件自己的两处(定义 + 创建)。 两个刻意的设计决定: ① **不新建第二个队列**。自建队列 + 删 `.ioc` 里的 netMsgQueue 也能收口,但要 CubeMX 重生成(Ask-first),过渡期还会同时存在两个队列,白占 CCM 堆里 8 × `net_msg_t` 的空间——CCM 正是当下 87.9% 的红线。故选"创建后绑定"。 ② `adopt()` **拒绝重复绑定、保留首次句柄**。真出现两处绑定时,静默换句柄会让 已入队的请求留在旧队列里永不处理;拒掉第二个反而更容易暴露。绑定前的判空 是真实防线:丢了那一行,后果是"所有 net_* 请求被丢弃、网络全线静默不通", 不是崩溃。 **防回退**:`check_cubemx_survival.py` 新增存活项 `net-msgq-adopt`(region `RTOS_QUEUES`、`must_contain=["net_msg_queue_adopt"]`),易失清单 29 → 30 项全部 到位;基线已重建(有意的 USER CODE 区改动,按脚本文档流程 `--write`)。 **体量**:`Code` 213,204 → **213,236 B(+32)**、`ER_IROM1` **231,816 B(22.1%)**; `RW +4 / ZI −4` → `RW_IRAM1` 恒 **75,264 B(57.4%)**、`RW_CCM` 恒 **57,376 B (87.9%)**、`RW+ZI` 总量 132,688 B 不变(没有多占一个字节 RAM)。 **验证**:`@build` 0 错 0 警告;`@test` PASS——624 ms 到 `net init: OK`、`i104: listening on 2404`、无 `[ERR]`/Fault、`heap free=15800 min_ever=8464` 逐项不变。 另在真机跑了一次 FTP 控制通道往返:220 → `USER admin` 331 → `PASS admin` 230 → `PWD` 257 → `TYPE I` 200 → `QUIT` 221。每条命令都是一次过队列的 net_recv/net_send,证明绑定路径真在跑;`.map` 里 `freertos.o(MX_FREERTOS_Init) refers to net_socket.o(i.net_msg_queue_adopt)` 证明镜像含该行。 ⚠ **顺带揪出一条测试工具漂移(本次未修,等定夺)**: `test/host/ftp_up_dl_test.py:123/126` 仍写死 `USER anonymous` / `PASS test@test.com`,而设备自 N-19(2026-10-11)起按 `/config.ini [ftp]` 校验 admin/admin(SHA-256 `pwd_hash`)→ 该脚本必然登录失败。它是手工工具、不在任何 pre-commit 钩子里,所以 11 天没人发现,而 `docs/测试说明/FTP_Test_Guide.md` 把它 列为"推荐入口"。建议加 `--user/--password`(默认 admin/admin),并连 `ftp_speed_test.py` 一起核。 数字联动:两份 `data/` 快照重跑、`ram_baseline --update/--write`、 `check_mem_numbers --write`、FLASH 与任务栈两张配图常量重算并重新生成(逐文本按 字号与锚点复查越界 = 0)、报告 §1.3/§5.1/§5.4 与部署文档 §3.3 同步。报告 §0.4 的 S-2 行按「完成即销项」改写为已闭环,§9 拆出独立 S-2 行标 ✅。 门禁:`@build` 0/0、`@test` PASS、`layer-deps` / `cubemx-survival` / `mem-numbers` (本次改到台账受管区,scan 已过)/ `mem-budget`(57.4% / 87.9%)/ `task-table` / `doc-links --all`(146 文档 0 问题)/ `id-check --strict`(增量拦截通过、可判定 82.84%、存量债 640)全绿;14 个文件字节卫生 BOM 无 / CR 0 / U+FFFD 0 / 无尾空格。 未推送。
Src/ — CubeMX 生成的源文件
⚠️ 本目录文件由 STM32CubeMX 生成(
.ioc重生成会覆盖),不是自研代码。 但允许在USER CODE BEGIN/END标记区之间写自定义代码。
文件一览
| 文件 | 生成 | 作用 |
|---|---|---|
main.c |
CubeMX | 程序入口:HAL_Init → SystemClock_Config → 外设初始化 → app_main_init → osKernelStart |
freertos.c |
CubeMX | FreeRTOS 任务创建(MX_FREERTOS_Init)+ 任务栈/优先级定义 |
gpio.c / dma.c / spi.c / i2c.c / usart.c |
CubeMX | 各外设 MX_xxx_Init |
stm32f4xx_hal_msp.c |
CubeMX | HAL 外设底层初始化(时钟使能、NVIC、引脚复用) |
stm32f4xx_hal_timebase_tim.c |
自研覆盖 | HAL 时基改用 TIM7(非 SysTick),tick = 1ms |
stm32f4xx_it.c |
CubeMX | 中断服务函数(ISR) |
system_stm32f4xx.c |
CMSIS | 系统时钟初始化(SystemInit) |
⚠️ 修改约定(铁律)
- 自定义代码只写
USER CODE BEGIN xxx/USER CODE END xxx标记区之间—— 标记区外的内容在 CubeMX 重新生成时会被无条件覆盖丢失 - 本目录被 pre-commit 的 C 代码规范检查排除(因是生成代码,风格不受控)
Drivers/BSP/才是纯手工代码区;应用逻辑放App/
关键点
- HAL 时基 = TIM7,不是 SysTick;FreeRTOS 用 SysTick 之外的方式,tick = 1ms
- NVIC 4 位优先级分组;外设中断优先级 ≥ 5(0~4 预留给 FreeRTOS)
- 时钟:HSE 8MHz → PLL M=4/N=168/P=2 → 168MHz
相关文档
- 架构全景:
docs/架构设计/项目架构总览.md - 启动顺序:
docs/架构设计/项目启动顺序管理.md - 任务表(唯一事实源 =
freertos.c):根README.md