Files
STM32F4-Base/AGENTS.md
T

10 KiB
Raw Blame History

STM32F4-Base

STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);仅 Keil MDK-ARM v5 (ARMCC, C99) 工具链;FreeRTOS V10.3.1 / CMSIS-RTOS2;192KB SRAM / 1MB Flash。

任何代码修改后必须先 @build 验证(0 错误 0 警告)再提交;硬件闭环用 @test。

铁律:源码编辑与编码

  • 改代码只用 Edit 工具(精确子串替换);批量替换用 Edit 的 replaceAll。绝不用 Get-Content/Set-Content/cmd 重写含中文的文件——整文件重写会按系统默认编码重解码 → U+FFFD 乱码且不可逆
  • 字符串字面量必须纯 ASCII(2026-09-15 实测):本机 ARMCC 对无 BOM 源文件按 CP936 解读,字符串内含奇数个汉字时末尾高字节吞掉结束引号 → 编译错(偶数个汉字侥幸通过);中文只写注释(注释不参与解析)。带 BOM 的 UI 系文件(Drivers/BSP/UI/*、App/task/ui_task.c、Lib/lv_conf.h)经 BOM 按 UTF-8 解码,不受此条限制
  • 确需脚本级重写:工程源码为 UTF-8(多数文件无 BOM,UI 系带 BOM),按原样同编码回写、保持 BOM 状态;拿不准就别碰
  • 发现乱码:先统计 EF BF BD 字节数确认真损坏(勿信终端/Read 渲染);不要急著 git checkout(会丢弃全部未提交工作)——先用 Edit 只修坏行

构建与验证

  • @build = & "MDK-ARM\build.bat"(仓库根目录用相对路径);退出码 0 = 0 错误 0 警告,1 = 有警告或错误(查 MDK-ARM/build_log.txt);build.bat 硬编码本机 Keil 路径 C:\Keil_v5\UV4\UV4.exe(换机需改)
  • @test / test/run_boot_test.ps1 一键闭环:开串口+清日志 → 烧录(MDK-ARM/download.bat,下载后 Reset&Run)→ wait-idle(等 RX 静默 8s,超时 30s)→ test/verify_log.ps1 标记校验;退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法/预检错误
  • 默认校验标记:Required App init OK / Network Init / net init: OK;Forbidden FAIL / ERROR / HardFault;按模块定制标记(网络/存储/RTC/ADC/RS485/UI)见 docs/测试说明/自动化测试流程.md
  • ⚠️ 旧绝对路径 D:\Code\DTU 程序\... 出现即失效(仓库已搬迁),一律改用仓库相对路径

Python 环境

  • 统一入口 & '.venv\Scripts\python.exe'(3.12,fontTools/Pillow 已装);PATH 默认 python 是 msys64 的,不要用它跑依赖第三方库的脚本;纯标准库脚本任意 python3 均可
  • 重建/换机:& 'C:\ProgramData\anaconda3\python.exe' -m venv .venv + pip install -r requirements.txt(.venv/ 已 gitignore)
  • requirements.txt 必须纯 ASCII(Windows 下 pip 按 GBK 代码页解码,中文注释会 UnicodeDecodeError)

提交门禁(pre-commit)

  • 任一失败即拦截:cppcheck(warning/performance/portability/style)+ C 代码规范机械检查 + U+FFFD 乱码检查 + gitlint;范围仅项目代码(第三方 Lib//Middlewares//CMSIS/HAL/lftpd/dhara/MDK-ARM/test/ 排除;规范检查另排除 CubeMX 生成的 Src//Inc/)
  • 提交信息:单行中文标题 <100 字符(gitlint),UTF-8 无 BOM + git commit -F <文件>(防终端转码破坏)
  • 代码规范 V1.0:小写下划线命名(g_/s_/p_/a_ 前缀)、头文件保护宏 XXX_H、常量在右、文件头模块注释块 → docs/代码规范/
  • 全库扫描 pre-commit run --all-files;详见 docs/代码规范/pre-commit使用说明.md

平台约束

  • Inc//Src/ 中 CubeMX 生成文件带 USER CODE BEGIN/END 标记:自定义代码只写标记区之间;Drivers/BSP/ 为纯手工代码
  • FreeRTOS V10.3.1(CMSIS-RTOS V2);HAL 时基 = TIM7(非 SysTick),tick = 1ms;NVIC 4 位优先级分组,外设中断优先级 ≥ 5
  • CH395F SPI:每次事务须 ch395f_spi_begin()/end() 包裹;分频系数必须为 8(PCB 约束,勿"优化")
  • 内存预算紧张:新增任何任务/缓冲/栈前必须先核算 RAM 余量(docs/内存管理/、待处理内容.md)
Task 栈 (words) 优先级
defaultTask 512 Normal
netTask 1024 Normal
ftpTask 1024 Normal
testTask 1024 BelowNormal
uiTask 4096 BelowNormal
timeSyncTask 512 Normal

(实际值以 Src/freertos.c 为准,六任务栈合计 32KB;改动栈/缓冲前先核对此表与实测)

架构要点

Src/main.c(CubeMX 初始化)→ app_main_init → osKernelStart → 6 任务

  • app_main_init(时间子系统优先,使后续日志带时间戳):sd2506_init → sys_clock_init(墙钟;RTC 故障时降级默认时间基准并返回 -1 触发"时钟芯片异常"自检;sys_clock_get 每 30 天惰性再基准化防 49.7 天 tick 回绕)→ rs485_init → gd5f2gq5ue_init → tpafe5160_init → SD2506 诊断 → tpafe5160_start_conv_irq
  • 就绪屏障(App/sys_events.h Event Flags,取代魔法延时):SYS_EVT_NET_READY(netTask 置位)/ STORAGE_READY(defaultTask:卷挂载 + 网络配置加载完成)/ FTP_READY / TIMESYNC_READY;消费者用 osEventFlagsWait 阻塞等待
  • netTask:net_stack_bring_up(配置已由 defaultTask 在屏障前加载,本任务只读 RAM 副本 → net_init + PHY 强制 100M 全双工 → 递增网络代次号)→ 置 NET_READY → 循环 net_poll + net_process_messages;消费 SYS_EVT_NET_RECONFIG → 立即重建网络(新 IP 免重启生效,各 TCP 服务据代次号重建监听)
  • defaultTask:f_mount forced(无卷自动 f_mkfs FAT32)→ 网络配置加载(net_cfg_load,首启含旧档迁移)→ STORAGE_READY → LED 闪烁;同时是 syslog(/log/run.log·selftest.log,定长 64B 记录)的唯一写者与配置引擎属主(cfg_file 静态态单任务收敛于此:UI 保存请求执行 net_cfg_save_run + 2s cfg_file_poll,经 SYS_EVT_CFG_SAVE 事件唤醒;netTask/uiTask 不得直接触碰配置引擎,见 P1-3)
  • 全景 docs/项目架构总览.md(六层分层 / 启动时序 / 存储·网络·UI 栈 / 目录组织)

硬件引脚

外设 接口 引脚
CH395F 以太网 SPI2 PB12 CS, PB13 SCK, PB14 SDO, PB15 SDI
GD5F2GQ5UE NAND SPI1 PE0 CS, PB3 SCK, PB4 MISO, PB5 MOSI, PB8 WP, PE1 HOLD
TPAFE5160 ADC 并行16位 PG0-PG15 数据, PD3 RD, PD4 CONVST, PD7 BUSY
USART1 调试串口 UART PA9 TX, PA10 RX (115200)
RS-485 UART5 PC12 TX, PD2 RX, PD0 DE(半双工)
6x LED GPIO PC4, PC5, PB1, PB2, PF11, PF12(低电平点亮)

模块约定

  • CH395F 单连接 socket:监听与数据通道复用同一 Socket(CONNECT 后转数据通道,DISCONNECT/TIMEOUT 后重开 → LISTEN);所有 CH395F 中断在 net_poll() 内经 GET_GLOB_INT_STATUS 集中读取并清除,不得在 ISR 或其他地方单独处理
  • 所有 net_* socket 操作经 netMsgQueue 消息队列在 netTask 串行执行(线程安全);非 netTask 任务直接调 net_* API,勿直接碰 CH395F 驱动
  • 网口配置:/config.ini [network] 段(工厂默认 192.168.1.100/24、gw .1;MAC 全零 = 芯片内置;UI 保存立即生效;旧档 /cfg/netcfg.bin 首启自动迁移)→ docs/网络配置说明.md
  • 新 .c 文件必须手动注册到两处才能双端编译:MDK-ARM/STM32F407-Demo.uvprojx + simulator/CMakeLists.txt(用 new-source-file skill)
  • 测试构建:test/test_config.h 的 TEST_SUITE_CH395F/STORAGE/GD5F/RTC 互斥(一次只能启用一个,#error);全部注释 = 产品构建;CH395F 套件 test/ch395f_test.h:硬件层 Phase 15 与 NET 层 Phase 611 互斥;CH395F 硬件层模式下 netTask(基础线程:无条件创建、全构建唯一实例)入口自挂起(不运行),testTask 独占 CH395F
  • 改驱动前先读对应 docs/问题记录/*_Trap_Records.md(CH395F / GD5F2GQ5UE / SD2506);各模块测试指南见 docs/测试说明/

串口助手 serial_tool

  • 入口:& '.venv\Scripts\python.exe' tools/serial_tool/serial_tool.py <命令>(daemon 自动拉起;全部命令 5s 超时、JSON 输出、exit 0/1/2/3)
  • 全量历史 = 日志文件 tools/serial_tool/state/serial.log(RX/TX/SYS 时间戳行);agent 直接 Read/Grep 文件,无采集窗口仪式;20MB 上限自动截头保尾 10MB
  • 常用:open(幂等)/ send <文本>(或 --hex 0D0A)/ log --tail N --grep P / clear(代际+1)/ wait-idle --settle-ms 8000 --max-ms 30000 / status / close
  • 串口端口单一配置源:.opencode/serial_config.json(当前 COM6);端口变化只改这个文件
  • 命令/工作流/故障排查 docs/测试说明/串口助手使用指南.md;契约/daemon 行为/陷阱 docs/测试说明/串口助手设计说明.md

LVGL PC 模拟器

  • simulator/(CMake + SDL2 预编译库)与 MCU 端共用 UI 源码(ui_menu.c、ui_font_cn_12.c),免烧录开发 UI:cmake -B build -G "Visual Studio 16 2019" -A x64; cmake --build build --config Debug → 运行 simulator\build\Debug\lvgl_sim.exe
  • 自检:--cfgtest(配置闭环)/ --logtest(日志引擎)/ --standby shot.bin(待机屏截图)/ --idle <秒>
  • UI 改动一律走 ui-verify skill 五步门禁;含新汉字的 UI 文案提交前先跑 font-regen skill 重生成中文字体

文档与图形

  • 配置文件 docs/配置文件设计说明.md;墙钟 docs/系统墙钟时间维护说明.md;代码规范 docs/代码规范/;测试说明 docs/测试说明/;审计发现 docs/项目审计改进清单.md;已知待办 待处理内容.md(内存预算);引用关系图 docs/引用关系图说明.md
  • 图形走 draw-diagram skill:精确布局图(协议帧/分层/屏障)用 tools/arch_diagram/gen_*.py 生成器(产物放 docs/images/,脚本与 .svg 一并提交);拓扑图(流程/时序/状态机)用 Mermaid;勿手绘 ASCII 框图
  • 文件引用关系图走 tools/refgraph:& 'tools\refgraph\gen_refgraph.bat' 生成文件级 + 模块级引用图(产物 docs/images/引用关系图.*,脚本与 .dot/.svg/.json 一并提交,PNG 本地预览不提交);项目文件变化后重跑更新;渲染依赖 Graphviz(winget 可装)