generated from hulk/gd32f4xx_template_cmake_vscode
207 lines
16 KiB
Markdown
207 lines
16 KiB
Markdown
# FilmForge — AGENTS.md
|
||
|
||
## 项目约定
|
||
|
||
- **用途**:自制热压模具温控固件——塑型 PC 膜,负责加热驱动与测温(NTC),
|
||
对外走 RS485 数据口。基于 GD32F4xx 工程模板
|
||
(`https://gitea.hulk.wang/hulk/gd32f4xx_template_cmake_vscode`,源自
|
||
celalkismiroglu/gd32e23x-demo-suites-cmake 体系)。
|
||
- **命名**:仓库 `FilmForge`,固件工程 `FilmForge_FW`(产物自动命名
|
||
`FilmForge_FW_V<版本>_APP_<日期>.bin`),协议板卡类型码 `BOARD_TYPE_CODE 41`。
|
||
- **目标芯片**:GD32F405RET6(设备宏 `GD32F405`,IRC16M PLL 168MHz——板上无外部
|
||
晶振;硬件 FPU fpv4-sp-d16 / hard ABI;512K Flash,链接脚本 xE)。
|
||
- **串口角色与 PC 端映射**:
|
||
- debug 串口 = USART1(PA2 TX / PA3 RX,AF7,纯串口)→ PC 端 **COM4**;
|
||
printf 重定向到 USART1(`DEBUG_UART` 宏),`DEBUG_MODE` 打开后输出。
|
||
- 数据口 RS485 = USART0(PA9 TX / PA10 RX,AF7)+ DE 引脚 PA8(GPIO 手动切换
|
||
收发)→ PC 端 **COM5**(115200-8-N-1)。拉通阶段主循环回显。
|
||
- 注意 GD 外设编号比 STM32 小 1:PA9/PA10=USART0、PA2/PA3=USART1。
|
||
- **NTC 测温**:PC5(ADC0_IN15),硬件 10K 上拉、NTC 接 GND 侧。B 值公式换算,
|
||
`NTC_B_VALUE` 宏(3950/3435 未定,默认 3950,确认后修改);`R_PULL/NTC_R25`
|
||
均为宏,换料只改宏。
|
||
- **语言/工具链**:C(gnu11)+ ARM GCC(xpack 15.2.1 已验证)、CMake ≥ 3.20 +
|
||
Ninja、VSCode + CMake Tools + cortex-debug;工具链路径经 `GD32_GCC_BIN`。
|
||
- **目录约定**(沿用模板):
|
||
- `Build/` —— 构建树与产物(gitignore);
|
||
- `SDK/` —— CMSIS、标准外设库 V3.3.3、SEGGER_RTT、USB 库(`GD32_ENABLE_USB`
|
||
开关,默认 OFF,当前未用);
|
||
- `LD/` —— 链接脚本(默认 xE 512K);
|
||
- `Inc/`+`Src/` —— 应用层,板级引脚/开关集中在 `Inc/board_config.h`;
|
||
- `OpenOCD/` —— 工程内会话配置(GD-LINK/CMSIS-DAP + stm32f4x);
|
||
- `doc/` —— 芯片文档(数据手册/用户手册/固件库指南/AN,已齐备);
|
||
- `GUI/` —— 温控上位机(PySide6-Fluent,详见其 `README.md`,运行态
|
||
`filmforge_gui.json`/`logs/`/`build/`/`release/` 由 `GUI/.gitignore` 挡)。
|
||
- **编译方法**:
|
||
```bash
|
||
cmake --preset Debug && cmake --build Build/Debug
|
||
cmake --preset Release && cmake --build Build/Release
|
||
```
|
||
- **Git/网络经验**:origin = HTTPS(`https://gitea.hulk.wang/hulk/FilmForge.git`),
|
||
该实例 HTTPS/SSH 直传大包均不稳,已在本仓库配置
|
||
`http.proxy http://127.0.0.1:6789` + `http.sslVerify=false`(仓库级),
|
||
代理端口变化时用 `git config http.proxy http://127.0.0.1:<新端口>` 更新。
|
||
- **printf 浮点**:`--specs=nano.specs` 默认裁剪 `%f`(输出空白),已在
|
||
`cmake/project.cmake` 启用 `-u _printf_float`(F405 flash 充裕,ROM +8~10KB 无感)。
|
||
- **在线排查寄存器地址速查**(GD32F4xx):ADC0=0x40012000(RDATA@0x4C)、
|
||
USART0=0x40011000、USART1=0x40004400、GPIOA=0x40020000(OCTL@0x14)、
|
||
RCU:CTL0=0x40023800 / **PLL=0x40023804** / **CFG0=0x40023808**。
|
||
|
||
## 开发进度
|
||
|
||
### 已完成
|
||
|
||
- 模板就位(GD32F405RET6 / IRC16M 168MHz / 硬件 FPU / 上板验证过的模板体系)。
|
||
- **debug 串口**:USART1 PA2/PA3 @115200,printf 重定向 + RBNE 中断收环形缓冲
|
||
(模板已有,COM4 观测)。
|
||
- **RS485 数据口驱动**(`rs485.h/rs485.c`):USART0 PA9/PA10 AF7 + DE PA8 GPIO
|
||
手动切换;独立接收环形缓冲(预留一格策略 + PRIMASK 临界区);阻塞发送
|
||
(DE→TBE→TC→DE,防尾字节截断);`rs485_rx_clear()` 清接收缓冲。
|
||
- **NTC 测温驱动**(`ntc.h/ntc.c`):PC5 模拟输入 + ADC0 常规通道(软件触发单次
|
||
转换 + 校准),16 次采样均值 + 分压反解阻值 + B 值公式换算摄氏度
|
||
(含开路/短路电源轨检测)。
|
||
- `debug_uart_write()` 助手(uart.c):debug 口阻塞单字节发送。
|
||
- **命令协议框架移植**(`command.h/command.c`,自 E23x 移植):D5 帧协议
|
||
(D5 BOARD_TYPE LEN [cmd] CRC 累加和校验)+ B5 响应;数据源改为 RS485 收缓冲
|
||
(`rs485_rx_*`),响应经 `rs485_send` 发出(DE 自动切换);帧状态机 + CRC +
|
||
参数解析工具(uint_to_str/parse_uint_dec/parse_timer_parameter/find_parameter_value)
|
||
全套保留;通用命令骨架:**M888 软复位 / M999 版本号 / M9999 进 OTA**;
|
||
业务命令(加热/控温)待定义,switch 中扩展(TODO 注释有格式示例)。
|
||
- **命令协议 v1.0 定稿**(权威定义见根目录 `protocols.md`,帧 hex 全部脚本生成):
|
||
- M1 查温度 / M2 查上报状态 / M2S<ms> 上报间隔+开关(M2S0 停)/ M3 加热开关
|
||
(M3S1/M3S0/M3 查询)/ M4 目标温度(M4S<temp>/M4 查询)/ M888 / M999 / M9999
|
||
- **加热驱动 + PID 闭环实装**(`heat.h/heat.c`,PB12=HEAT_EN):
|
||
- 执行器:慢 PWM(载波 1s、占空 10% 步进 → 脉宽恒 >=100ms、开关频率恒 1Hz,
|
||
满足 2N7002K→VBE2412 PMOS 驱动电路 <=10Hz 约束)
|
||
- PID:500ms 周期(NTC 采样 100ms),位置式 + 积分限幅 + 输出量化 10% 档;
|
||
参数 Kp=8/Ki=0.05/Kd=0(初值,宏在 board_config.h,待整定)
|
||
- 安全:上电默认关;NTC 故障(OPEN/SHRT)强制关断;过温 150℃ 滞回保护;
|
||
未使能关断;使能切换/故障时复位 PID 积分
|
||
- 实测 30℃ 闭环(NTC 贴 PTC 鳍片):30s 爬升、超调 1.4℃(7%)、60s 收敛中
|
||
- M3/M4 已从软件桩切到 heat 模块(协议帧不变)
|
||
- 协议要点:全幂等(ack 丢可重发)、响应超时建议 300ms×3 次、温度一律 ASCII
|
||
- **PID 抗积分饱和**(5b24b95):条件积分(back-calculation lite)抑制输出限幅
|
||
期间的积分累积。
|
||
- **50℃→40℃ 阶跃验证脚本**(`temp_test_com.py`,工作区修改未提交):M2S500
|
||
全曲线采样,输出超调/settle 时间/稳态误差/降温段统计(结果以实跑为准)。
|
||
- **电源保持 PA11 实装**(`pwr_hold.h/pwr_hold.c`):上电最先拉高 PA11 维持
|
||
PMOS 自锁供电(先于一切外设初始化);`pwr_hold_off()` 预留软关机(置低即失电)。
|
||
- **专用 GUI 上位机 v0.1.0 完成**(`GUI/`,参照 DLPilot 分层:协议模块纯标准库 +
|
||
PySide6-Fluent 界面 + 自检 + PyInstaller):
|
||
- 文件角色:`filmforge_rs485.py`(帧/解析/串口线程 FF485)、`app_fluent.py`
|
||
(双栏仪表盘 + **自绘温度曲线**,未引第三方图表库)、`config.py`(设置记忆
|
||
filmforge_gui.json)、`filmforge_gui.py`(入口+CLI `--port/--cmd/--seconds-report`)、
|
||
`selftest_rs485.py`/`selftest_gui.py`(协议向量 / 离屏渲染+派发回归)、
|
||
`build_exe.py` → `release/FilmForge.exe`+发布 zip、`publish_gitea.py`
|
||
(tag `FilmForge-GUI-vX.Y.Z`)
|
||
- 功能:实测温度曲线+目标温度阶梯线同图(闭环监视)、M2 上报帧直采 / 上报关闭时
|
||
上位机自动轮询 M1 补点、NTC OPEN/SHRT 断口+故障标记、时间窗/暂停/窗口统计、
|
||
目标(M4S 0~200)/加热(M3S1 确认)/上报(M2S 100~60000)控制、连接自动同步
|
||
版本/上报/加热/目标、M888/M9999 二次确认+复位后重查、收发日志、CSV 记录
|
||
- **COM5 真机全链路验证通过**:M999=v41.0.0.1、M1/M2/M3/M4 查询、M2S500 上报
|
||
3s 收 6 帧、M2S0 停止;GUI 端到端(串口线程→队列→派发→曲线/状态芯片)实测通过
|
||
- 关键教训(勿重蹈,详见 `GUI/README.md`):①应答派发必须是 **FIFO 队列**(半双工
|
||
应答按发送序返回;单 pending 槽在连接序列 150ms 连发下被乱序击穿,实测 M2 的
|
||
OFF 被 M3 槽吃掉、M4 目标值混入曲线);②时间戳在串口线程读取点打(SerialMate
|
||
教训);③M4 目标应答路由窗口取条目生命周期 1.2s(适配器换向延迟实测可 >0.5s,
|
||
上报开启时才收紧 0.5s);④Fluent 控件样式走 setCustomStyleSheet(DLPilot 同款坑)
|
||
- 发布策略:GUI 产物(release/)暂不入库,本地 `python build_exe.py` 生成;发布走
|
||
`publish_gitea.py` 上传 zip(tag `FilmForge-GUI-vX.Y.Z`,与固件 tag 区分)
|
||
- **SerialMate 串口工具问题已定位**(见
|
||
`E:\Hulk-Coding\HW-Debug-Tools\SerialMate\ISSUE_rx_timestamp_and_lag.md`):
|
||
时间戳在 GUI 消费时打导致失真 + 接收日志无限增长致卡顿;待该工具修复后
|
||
再做长时间曲线联调。
|
||
- 工程改名:`FilmForge_FW`、`BOARD_TYPE_CODE 41`。
|
||
|
||
### 计划 / TODO(已提出尚未实现)
|
||
|
||
- [x] **RS485 拉通上板验证**:命令收发/响应/上报实测通过(固件端零丢字节,
|
||
响应 10ms 级实时);遗留为 USB-RS485 适配器方向切换丢包(换适配器解决)
|
||
与 SerialMate 显示层问题(见 ISSUE 文档)。
|
||
- [x] **NTC 测温上板验证**:NTC 支路修复后读数正常(23.6~25.9℃ 稳定)。
|
||
- [ ] **B 值确认**:温度计对照实测定 `NTC_B_VALUE`(3950/3435 二选一)。
|
||
- [ ] **适配器更换**:换可靠的 USB-RS485 适配器(当前自动方向切换间歇丢响应)。
|
||
- [x] **加热驱动 + PID 闭环**(PB12 慢 PWM 1s/10% 步进 + PID 500ms 周期,
|
||
安全保护齐全;实测 30℃ 闭环通过:30s 爬升、超调 1.4℃、60s 收敛中)。
|
||
- [ ] **PID 参数整定**:初值 Kp=8/Ki=0.05/Kd=0(board_config.h 宏),按真实
|
||
工况温度(80~120℃)与负载重新整定,抑制 ~7% 超调。
|
||
- [x] **专用 GUI 上位机 v0.2.0**:v0.1.0 已完成 COM5 真机全链路验证;v0.2.0 与
|
||
实装固件对齐——去除"固件预留/仅软件状态"旧表述(协议模块预设说明、温控
|
||
卡片标题/备注、开启加热确认弹窗改为真实控温警示、ack 提示),GUI README
|
||
与 publish_gitea 发布说明模板同步,protocols.md M3 表项去"预留";
|
||
监控逻辑简化:温度监控统一走 M2 周期上报(移除"M1 自动轮询"双通道及
|
||
poll 配置项,M1 仅手动单点查询),目标温度滑条范围 0~200→0~120(协议
|
||
上限 200 仍可手输)。**v0.2.1 真机回归修复**(COM5 实测暴露):①M4 查询
|
||
应答与周期上报帧同为 ASCII 浮点被误占(目标 chip 显示成实测值)→ 查目标
|
||
改应答驱动"暂停上报 M2S0→M4→自动恢复 M2S<ms>"链;②设定 ok 延迟 >1.2s
|
||
超时清队后状态 chip 与设备脱节(实测 M2S100 ok 迟到、chip 停 OFF)→ 8s
|
||
内晚到 ok 按发送时计划补偿应用;③断开按钮偶发不切换、断开后日志仍刷 →
|
||
连接按钮改意图驱动(点击即翻转、2s 未建立判丢失回退),已连接/已断开/
|
||
丢失全部入日志,连接同步序列每步发送前确认在线(修复序列整组被
|
||
"未连接串口"丢弃)。selftest 全过(新增 8 项回归用例);已打包冒烟并发布
|
||
Gitea Release `FilmForge-GUI-v0.2.1`(无应用图标——`logos/filmforge.ico`
|
||
仍缺位)。
|
||
- **GUI v0.2.2~v0.2.4(已修复待真机确认,未发布)**:
|
||
- v0.2.2:串口线程 `read(256)` 在持续帧流下攒满 256 字节才返回(win32 字节
|
||
间隔超时因帧间隔更短永不触发,100ms 上报 ≈2.5s 一批),曲线/命令/响应全部
|
||
3 秒一卡、一股脑一大坨——真机日志确认每簇 ≈25 帧、间隔恒 3s。已改
|
||
`read(in_waiting or 1)`,真机复测曲线实时、命令即发即回。
|
||
- v0.2.3:发送入口幂等去重——同命令未决时忽略重复发送(真机连点"停止"12 次
|
||
挤爆 8 条 pending 队列、"丢弃积压命令"刷屏),状态栏提示"应答中"。
|
||
- v0.2.4:目标阶梯线渲染 bug(v0.1.0 起潜伏)——`_target_points` 对最后一次
|
||
目标变更只画终点,从旧值斜拉直线到图表右缘(实测 57→41 被画成 2 分钟斜坡,
|
||
截图确认);改为纯阶梯(变更时刻垂直落变+水平延伸),数据本身无误。
|
||
- v0.2.5:排版调整——串口连接卡片从右列移到左列顶部,左列图表卡/右列日志卡
|
||
弹性拉伸填充,两列底边对齐。
|
||
- v0.2.6:对齐修复——双列改放同一滚动容器(整页统一滚动):原先两列各自包
|
||
QScrollArea 独立滚动,窗口化下底边错位(全屏正常);现两列高度锁定一致,
|
||
不足一屏各自拉伸到底、超出一屏整页滚动。
|
||
- v0.2.7:图标接入(logos/ 下 ico/png/svg 已就位)——exe 嵌入图标
|
||
(build_exe.py --icon,此前缺文件自动跳过)、窗口标题栏/任务栏/弹窗图标
|
||
(app+window 两级 setWindowIcon,_icon_path() 兼容源码态与 _MEIPASS 打包态)、
|
||
Windows 任务栏独立标识 AppUserModelID "hulk.FilmForgeGUI"。README"无应用
|
||
图标"遗留项关闭。
|
||
- v0.2.8:**慢性卡顿修复**——`_log()` 手工 cursor 裁剪(`cursor.Start`/
|
||
`BlockUnderCursor` 实例级枚举访问)在 PySide6 6.11 上必然抛 AttributeError,
|
||
日志超 500 行(100ms 上报 ≈50s)后每个 100ms tick 异常中止 `_tick` 后半段:
|
||
应答超时清理失效(pending 永不清 → "停止"点击被幂等去重永久拦截,实拍状态栏
|
||
"M2S0 应答中,已忽略重复发送")、RX 队列积压 ratchet(帧处理滞后 54ms→均值
|
||
1037ms/峰值 2701ms,日志/chip/曲线显示滞后数秒,"停止 5s 后才见命令发出"实为
|
||
日志显示积压,TX 本身 5~166ms 即出)、日志无限增长、CPU +30%。改原生
|
||
`setMaximumBlockCount(500)` 环形裁剪;selftest 新增"500 行封顶/封顶后可追加/
|
||
最新行在末尾"3 条回归。离屏 A/B 实测(GUI/_diag_latency_buggy.py,假固件
|
||
100ms 上报+定时点击):buggy 组 5.5 分钟异常 2241 次、修复组全程漂移 ≤15ms/
|
||
零异常/零积压。v0.2.7 exe(2026-10-10 打包)内嵌同版本 PySide6 6.11.2,
|
||
同带此 bug,需重新打包生效。
|
||
- v0.2.9:**整体审查修复 5 项**——①CSV 写失败(磁盘满/记录盘被拔)自动停记录
|
||
并提示,不再沿 _tick 帧处理路径抛 OSError 中止主循环(与 v0.2.8 日志裁剪同款
|
||
失效管道);②故障标记 faults 封顶 1000 条(曾是唯一无上限缓冲:NTC 抖动时
|
||
10 条/s 无限增长,且 _draw_faults 每 paint 全量扫描);③串口写超时单独捕获
|
||
SerialTimeoutException——只丢该条命令、链路保留,不再按 OSError 当"设备拔出"
|
||
关端口断链(适配器停滞曾迫使手动重连);④日志自动滚动仅在贴底时跟随(上报
|
||
运行时可上翻历史,不再被拽回底部);⑤冻结视图切片右缘同样二分(暂停时长不再
|
||
增加 render 成本)。selftest 新增 7 项回归(封顶/滚动跟随/CSV 失败自停/冻结
|
||
切片)共 59 项全过。整体审查报告(2026-10-12)其余 P3 遗留:selftest 未覆盖
|
||
_tick 主循环(超时清理/丢失判定)、"全部"窗口全量切片有 MAX_SAMPLES 兜底、
|
||
_last_set 单槽位罕见误补偿(8s 自愈)、build_exe remove_stale 无提示强杀
|
||
运行实例、M888 后固定 2s 重查可能早于固件就绪、_danger_reset 把去重忽略记成
|
||
"已下发"。协议建议的 300ms×3 自动重发维持不做(设计决策,用户拍板)。
|
||
- selftest 全过(累计新增 15 项回归用例,含窗口图标非空检查);exe 已本地
|
||
打包冒烟,Gitea 发布待用户确认后执行。
|
||
遗留见其 README"已知事项":USB-RS485 适配器更换。
|
||
- [x] **GUI 慢性卡顿修复(根因已定位并修复 v0.2.8,待真机确认)**:
|
||
根因/机理/实测数据见上方 v0.2.8 条目(`cursor.Start` 实例级枚举访问在
|
||
PySide6 6.11 必抛 → tick 异常中止 → 应答超时清理失效 + RX 积压 ratchet +
|
||
日志无限增长)。复现/验证脚本:`GUI/_diag_latency.py`(修复基线)/
|
||
`GUI/_diag_latency_buggy.py`(带 bug 对照,假固件 100ms 上报+定时点击)。
|
||
遗留:待真机长时间运行确认 + 重新打包 exe。
|
||
- [ ] **LED 引脚确认**:FilmForge 自制板 LED 引脚未定(当前沿用模板默认 PA15,
|
||
仅为构建占位),按原理图修改。
|
||
- [ ] **delay_10us 校准**:M4@168MHz 系数为估算值(/300000),需实测修正。
|
||
|
||
## 备注
|
||
|
||
- 本机凭据/发布约定见用户级 `C:\Users\Lenovo\.zcode\AGENTS.md`。
|
||
- 模板工程位置:`E:\Hulk-Coding\gd32f4xx_template_cmake_vscode`(模板对标工程,
|
||
Gitea: gd32f4xx_template_cmake_vscode)。
|
||
- E23x 工程位置:`E:\Hulk-Coding\gd32e23x_template_cmake_vscode`(协议/驱动参考)。
|