Files
Motor_v2/docs/review/Motor_v2_专家评审_2026-10-19.html
T

64 lines
39 KiB
HTML
Raw Normal View History

2026-10-20 21:11:29 +08:00
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Motor_v2 专家评审 2026-10-19</title><style>body{font-family:-apple-system,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;margin:0;background:#f5f6f8;color:#1f2328;line-height:1.6}
main{max-width:1200px;margin:0 auto;padding:24px}h1{font-size:26px;margin:0 0 4px}h2{border-left:4px solid #2f6feb;padding-left:10px;margin-top:36px}
.meta{color:#57606a;font-size:14px}.card{background:#fff;border-radius:8px;padding:16px 20px;box-shadow:0 1px 3px rgba(0,0,0,.08);margin:12px 0}
table{border-collapse:collapse;width:100%;background:#fff;font-size:13px}th,td{border:1px solid #d0d7de;padding:6px 8px;vertical-align:top;text-align:left}
th{background:#eef2f7;position:sticky;top:0}code{font-size:12px;background:#f0f2f5;padding:1px 4px;border-radius:3px;word-break:break-all}
.b{display:inline-block;padding:1px 8px;border-radius:10px;color:#fff;font-size:12px;white-space:nowrap}.b0{background:#b91c1c}.b1{background:#ea580c}.b2{background:#ca8a04}.b3{background:#2563eb}
tr.s0 td{background:#fef2f2}.kpi{display:flex;gap:12px;flex-wrap:wrap}.kpi div{flex:1;min-width:120px;background:#fff;border-radius:8px;padding:12px;text-align:center;box-shadow:0 1px 3px rgba(0,0,0,.08)}
.kpi b{font-size:28px;display:block}pre{background:#0d1117;color:#e6edf3;padding:14px;border-radius:8px;overflow:auto;font-size:13px}</style></head><body><main>
<h1>Motor_v2 电机固件专家评审</h1>
<div class="meta">仓库 cbb/Motor_v2 · 分支 master · 评审基线提交 <code>86ca766</code>(2026-10-13 “feat(motor): 引入运行禁止机制重构电机控制安全系统”)· 评审日期 2026-10-19 · 静态评审,未实编/未上机</div>
<div class="kpi"><div><b style="color:#b91c1c">2</b>致命</div><div><b style="color:#ea580c">15</b>严重</div><div><b style="color:#ca8a04">22</b>一般</div><div><b style="color:#2563eb">11</b>建议</div><div><b>5.6</b>综合评分/10</div></div>
<h2>1. 项目概述与架构</h2>
<div class="card">GD32C103CB(Cortex-M4F,120 MHz)上的无刷电机 FOC 驱动固件,配 DRV8313 门驱动、KTH7823 磁编码器,CAN-FD(仲裁 1 Mbps / 数据 5 Mbps)与上位机通信;CMSIS-Toolbox csolution + AC6(microlib) 构建;应用位于 0x08012000,配合独立 BOOT 实现 OTA。最新提交引入了 <code>RunInhibit</code> 位图式“运行禁止”闸门,作为功率级唯一执行者。</div>
<pre>┌──────────────── GD32C103CB (Cortex-M4F @120MHz, APP @0x08012000) ────────────────┐
│ 中断层 │
│ ADC0 注入组(TIMER1 CH3 TRGO 触发) ─► 写三相电流 + 置 TASK_CURRENT_UPDATE [prio 0,0] │
│ TIMER2 50µs 节拍 ─► 置任务位(角度/速度/电机控制/1ms CAN …) [prio 0,1] │
│ TIMER1 中心对齐 PWM ≈20.0067kHz (ARR=2999) [prio 0,2] │
│ SysTick 1ms(delay/CPU 统计) [0] CAN RX0/TX/DMA0-CH4 [prio 1] │
├──────────────────────────────────────────────────────────────────────────────────┤
│ 主循环 main.cpp:关中断取任务位快照 → do_task() │
│ ├ 高频:KTH7823 SPI 读角度 → α-β/卡尔曼 → run_inhibit.update() → FOC 模式分发 │
│ │ Clarke/Park → PID(电流/速度/位置/MIT) → 逆Park → SVPWM → Set_3Pwm │
│ ├ 低频:health(热模型/欠压/nFAULT) · power_manage · 喂狗 │
│ └ CAN:CAN-FD(仲裁1M/数据5M) 命令解析 · 周期反馈帧 · 参数持久化(flash.cpp EEPROM) │
├──────────────────────────────────────────────────────────────────────────────────┤
│ 存储:EEPROM 模拟 0x0801F800-0x08020000(2×1KB) · 节点ID 乒乓双备份+CRC · OTA/备份区 │
└──────────────────────────────────────────────────────────────────────────────────┘</pre>
<table><tr><th>目录</th><th>主要文件</th><th>职责</th><th>规模(行)</th></tr><tr><td><code>Algorithm/</code></td><td>FOC.cpp/h、pid、Filter(α-β/卡尔曼)</td><td>坐标变换、SVPWM、多模式控制环、零位校准</td><td>~1.8k</td></tr><tr><td><code>device/</code></td><td>Can、ADC、Timer、ang_sensor、motor</td><td>CAN-FD 协议栈、注入采样、PWM、KTH7823 SPI、DRV8313 使能</td><td>~3.6k</td></tr><tr><td><code>sys/</code></td><td>flash、health、run_inhibit、initial、systick、config</td><td>参数持久化/OTA、保护、运行禁止闸门、初始化、时基</td><td>~3.0k</td></tr><tr><td><code>顶层</code></td><td>main.cpp、tasks.cpp</td><td>调度主循环、任务拆分</td><td>~0.4k</td></tr><tr><td><code>RTE/</code></td><td>GD32C10x 标准库、启动文件、链接脚本</td><td>厂商库(含本地修改)</td><td>—</td></tr></table>
<h2>2. 评审范围与方法</h2>
<div class="card"><ul>
<li>范围:Robot_V2/ 下全部应用源码(Algorithm、device、sys、main、tasks,约 9.6k 行)、RTE 启动文件/时钟/链接区域/中断文件、csolution/cproject/cbuild-pack/vcpkg、.gitignore、IDE 配置;厂商标准库仅比对与 .base 的差异。</li>
<li>专家组:①电机控制算法/FOC ②实时性/中断/DMA/MCU 架构 ③CAN-FD 通信协议 ④功能安全与故障保护 + Flash 存储 ⑤代码质量、构建与仓库卫生。各视角独立通读后交叉核对,关键结论由主评审逐行复核(M01、M02、M04、M07、M10、M19 等)。</li>
<li>既有记录:全仓搜索 .md/.html,仅根目录 <code>STATIC_ANALYSIS_NOTES.md</code>。逐条核对见第 4 节,修订版见 <a href="STATIC_ANALYSIS_NOTES_复核_2026-10-19.md">STATIC_ANALYSIS_NOTES_复核_2026-10-19.md</a>(原文件保留未改)。</li>
<li>严重度:<b>致命</b>=可能导致失控/烧毁/伤人;<b>严重</b>=保护失效、控制失效或数据丢失;<b>一般</b>=功能缺陷/可靠性隐患;<b>建议</b>=质量与可维护性。</li>
<li>局限:未编译、未上机、未示波;行号基于 86ca766。</li></ul></div>
<h2>3. 问题清单(50 条)</h2>
<table><tr><th>编号</th><th>严重度</th><th>领域</th><th>文件:行号</th><th>标题 / 现象</th><th>风险</th><th>修改建议</th></tr><tr class="s0"><td>M01</td><td><span class="b b0">致命</span></td><td>CAN/FOC</td><td><code>device/Can.cpp:1128-1132;Algorithm/pid.cpp:50,126</code></td><td><b>控制帧目标电流/速度直接作为 PID 限幅,未校验符号与有限性</b><br>目标电流 target_current、目标速度 target_velocity 被原样传入 set_limit();pid.cpp:50 _constrain(x,-limit,limit) 在 limit&lt;0 时上下界颠倒;NaN/Inf 未过滤。</td><td>mode3/4/5 下发负值时 PID 输出被钉在 +|limit|,与误差方向无关,可导致反向满压、电机失控;电流环限幅(电压量纲)被设为电流值,单位错配。</td><td>协议层对所有浮点字段做 isfinite() 与范围夹紧;set_limit 内取 fabsf 并拒绝非正值;电流环输出限幅改用 limit_voltage/v_safe,与目标电流分离。</td></tr><tr class="s0"><td>M02</td><td><span class="b b0">致命</span></td><td>Flash/安全</td><td><code>sys/flash.cpp:304-321,393-404,887-899(format 后 save_system_config);sys/flash.cpp:77-84</code></td><td><b>EEPROM 页满重建时丢失电角度零位校准角</b><br>任一写入触发页满 → format() 擦除两页 → save_system_config(false) 只重写 6 个控制参数、CRC 与两个刷新周期,不重写 ADDR_CALIBRATION_ANGLE(0x07);若正是写校准角触发的页满,新校准角同样不会写入。上电回退默认 83°。</td><td>换向角错误 → 力矩方向/大小错误,速度环可能正反馈失控,且无任何告警(init 认为读取失败属正常首启)。</td><td>save_system_config 重建路径同时重写校准角(及将来所有独立记录);或改为双页轮转搬运最新有效记录;无有效校准角时置 INHIBIT 位禁止闭环并上报。</td></tr><tr class="s1"><td>M03</td><td><span class="b b1">严重</span></td><td>CAN/安全</td><td><code>sys/run_inhibit.h:19-29;device/Can.cpp(无命令超时逻辑)</code></td><td><b>无通信超时/心跳丢失停机</b><br>禁止来源仅 nFAULT/欠压/过热/采样失效/未使能,无 CAN 超时来源;收到最后一条控制帧后电机持续执行。</td><td>上位机死机、线缆脱落、总线 Bus-Off 时电机按最后目标一直运行(速度模式下持续转动)。</td><td>新增 INHIBIT_COMM_TIMEOUT:控制帧到达刷新时间戳,超时(可配置,如 100 ms)request(),收到新控制帧再 release;超时阈值可经 CAN 配置并持久化。</td></tr><tr class="s1"><td>M04</td><td><span class="b b1">严重</span></td><td>FOC/安全</td><td><code>Algorithm/FOC.cpp:59-63;sys/systick.cpp:164-168</code></td><td><b>零位校准在主循环阻塞约 1 s 且持续喂狗</b><br>calibrate_zero_position() 直接 motor_resume() + Set_3Pwm(ALIGN_PWM_DUTY) + delay_1ms(1000);delay_1ms 循环内 fwdgt_counter_reload()。</td><td>1 s 内欠压快检、nFAULT 轮询、热模型、CAN 处理全部停摆,看门狗也被持续喂而失去意义;对齐电流无限流、对齐后未判转子静止。</td><td>改为非阻塞状态机(每 50 µs 推进),期间 run_inhibit/保护任务照常运行;对齐时做电流闭环或占空比按 Vbus 归一;delay_1ms 内不得喂狗。</td></tr><tr class="s1"><td>M05</td><td><span class="b b1">严重</span></td><td>安全/FOC</td><td><code>Algorithm/FOC.cpp:426-431;sys/config.h(MAX_VCC 仅作读数有效判定)</code></td><td><b>无过压保护,Vbus&gt;36 V 时 SVPWM 按旧电压归一</b><br>update_power 仅接受 8–36 V,超出时保留旧 Vdc;固件无过压禁止位,回馈泵升无处理。</td><td>制动/回馈时母线抬升,实际相电压被放大,叠加功率器件超压,存在击穿 MOSFET/驱动风险。</td><td>增加 INHIBIT_OVERVOLTAGE(带回差与防抖);超限时继续用实测 Vbus 归一;必要时短路制动或限制回馈电流。</td></tr><tr class="s1"><td>M06</td><td><span class="b b1">严重</span></td><td>实时性/安全</td><td><cod
<h2>4. 既有评审(STATIC_ANALYSIS_NOTES.md)结论跟踪</h2>
<table><tr><th>条目</th><th>原结论</th><th>当前状态</th><th>证据 / 说明</th></tr><tr><td>SUP-GLB-001 编译期常量(ADC/health/config constexpr)</td><td>误报/偏离</td><td><b>仍成立</b></td><td>ADC.cpp:22-47;health.cpp:107;config.h 全部为 constexpr</td></tr><tr><td>硬件单例 FOC / sampler / CAN0_transmiter / KTH7823 / thermalController / Version</td><td>接受单例</td><td><b>仍成立</b></td><td>FOC.cpp:28;ADC.cpp:60;Can.cpp:86;ang_sensor.cpp:39;health.cpp:104;initial.cpp:218</td></tr><tr><td>TaskScheduler scheduler 短临界区</td><td>已保护,接受</td><td><b>仍成立</b></td><td>main.cpp:68-72 关中断取快照并清位;taskFlags volatile(initial.h:75);两写入方同抢占级</td></tr><tr><td>CAN RX/TX 队列临界区与 PRIMASK 恢复</td><td>已保护,接受</td><td><b>基本成立,但有遗漏</b></td><td>Can.cpp:644-731、480;遗漏:主循环 CANFD_AsyncSend 直接写邮箱与 TX ISR 竞争(Can.cpp:1395/744,见M21)</td></tr><tr><td>ADC injected 电流缓存不加临界区</td><td>保留现状</td><td><b>风险仍在</b></td><td>ADC.cpp:62-63、467-481 存在三相撕裂/丢 ready(M33);建议序号双读而非 PRIMASK</td></tr><tr><td>“加 PRIMASK 后实机连续重启”归因于时序</td><td>归因时序</td><td><b>归因不成立</b></td><td>10 周期级临界区不足以致复位;更可能是 update_current 提前返回分支(ADC.cpp:468)未恢复中断 + 与 systick 改动捆绑未隔离 + 50 ms 看门狗(IRC40K)余量小;无复位原因记录无法定位</td></tr><tr><td>systick DWT CPU 占用统计</td><td>允许小误差</td><td><b>仍成立</b></td><td>systick.cpp:75-79、193-206;仅诊断值</td></tr><tr><td>ang_sensor SPI DMA 完成标志</td><td>接受 volatile 标志</td><td><b>已过时</b></td><td>已改为寄存器轮询 spi_rw_half_word_polling(ang_sensor.cpp:57-82),标志不存在;新问题:TRANS 等待无超时(:78)</td></tr><tr><td>Timer total_us100_counter</td><td>仅 ISR 使用,接受</td><td><b>仍成立</b></td><td>Timer.cpp:19、149-153;可改为 ISR 内 static</td></tr><tr><td>health voltage_state / last_vbus_slow</td><td>模块私有,接受</td><td><b>仍成立(有残留)</b></td><td>health.cpp:112-113 文件内 static;last_vbus_slow 只写不读</td></tr><tr><td>SUP-CMP-001 normalizeAngle360 浮点比较</td><td>无需容差</td><td><b>比较结论成立,但有新缺陷</b></td><td>ang_sensor.h:103-111 输入 Inf/NaN 时死循环(M16)</td></tr><tr><td>printf:FOC 齿槽校准打印位于 FOC_DEBUG</td><td>正式版不编译</td><td><b>已过时</b></td><td>9fbd9c3 已移除齿槽补偿;FOC_DEBUG 仅剩 motor.cpp:245 一处</td></tr><tr><td>versionToString 去 snprintf</td><td>已改</td><td><b>仍成立</b></td><td>initial.cpp:302-346</td></tr><tr><td>AUTO-MET-001 calibrate_cogging_tick 拆分</td><td>已拆分</td><td><b>已过时</b></td><td>函数随齿槽功能删除;Can.cpp:1186 bit4 改为保留位</td></tr><tr><td>AUTO-MET-001 communication_check 拆分</td><td>已拆分</td><td><b>已落实</b></td><td>Can.cpp:841-1115</td></tr><tr><td>AUTO-MET-001 do_task 拆分</td><td>已拆分</td><td><b>已落实</b></td><td>tasks.cpp:296-399</td></tr><tr><td>“实编仍需在 Keil/CMSIS/cbuild 环境验证”</td><td>待验证</td><td><b>仍未验证</b></td><td>本次评审为静态评审,未实编;cproject -O3 覆盖 build-types(M38)需一并处理</td></tr></table>
<h2>5. 亮点</h2>
<div class="card"><ul>
<li><code>RunInhibit</code> 位图闸门:功率级动作收拢为单一执行者,上电默认 INHIBIT_NOT_ENABLED,闸门位于模式分发之前,非法模式也能封住输出。</li>
<li>节点 ID 双页乒乓 + 魔数 + 计数器 + CRC,写后校验重试,写成功才回 ACK。</li>
<li>ADC0 只跑注入组、VBUS/温度移到 ADC1 连续模式,消除规则/注入组互扰;电流零点配平带独立错误位上报。</li>
<li>Clarke/Park/逆 Park 与 SVPWM 数值正确;PID Tustin 积分 + 测量值微分低通 + 条件积分抗饱和设计合理。</li>
<li>CAN DLC 合法化(CANFD_NormalizeLength)、DWT 按任务统计负载、Doxygen 注释完整。</li></ul></div>
<h2>6. 优先级修复路线图</h2><div class="card"><ol>
<li><b>P0(上电机前必须修,1–2 天)</b>:M01 控制帧输入校验与 PID 限幅取正;M02/M10 EEPROM 重建重写校准角并修正 system_config_saved;M03 通信超时禁止;M06 HardFault 先关 PWM;M07 motReset 交给闸门;M16 NaN/Inf 过滤。</li>
<li><b>P1(一周内)</b>:M04 零位校准非阻塞化、delay 不喂狗;M05 过压保护;M08 运行中禁止 Flash 擦写;M09 广播改 ID 防护;M12 故障解除需重新使能;M17 编码器故障禁止;M19 深睡眠位优先级 bug。</li>
<li><b>P2(迭代内)</b>:M13/M14/M15 由 ADC 中断驱动 FOC、影子寄存器、丢拍计数;M11 EEPROM 双页原子化;M33 电流序号双读;Bus-Off/错误中断;看门狗前移与复位原因上报;补软件过流/堵转。</li>
<li><b>P3(持续改进)</b>:构建选项清理(-O3、诊断抑制)、厂商库还原、README/协议文档/CI/主机单元测试、死代码清理、Id 闭环。</li></ol></div>
<h2>7. 总结评分</h2>
<table><tr><th>维度</th><th>评分</th><th>说明</th></tr><tr><td>功能安全与故障保护</td><td><b>5.0</b> / 10</td><td>有统一运行禁止闸门与上电默认禁止,但缺通信超时/过压/过流/编码器故障禁止,故障后自动恢复</td></tr><tr><td>电机控制算法</td><td><b>6.5</b> / 10</td><td>变换与离散化正确;限幅符号、NaN、windup、采样窗口问题</td></tr><tr><td>实时性与中断</td><td><b>6.0</b> / 10</td><td>执行模型清晰、临界区合理;节拍与 PWM 不同步、无丢拍检测、异常不关 PWM</td></tr><tr><td>CAN 通信协议</td><td><b>5.5</b> / 10</td><td>DLC 合法化、ACK 回写较好;输入校验、Bus-Off、广播防护不足</td></tr><tr><td>参数存储/Flash</td><td><b>4.5</b> / 10</td><td>节点 ID 存储设计好;EEPROM 重建丢校准角、无原子性、标志位逻辑缺陷</td></tr><tr><td>代码质量与可维护性</td><td><b>6.5</b> / 10</td><td>注释充分(Doxygen)、函数已拆分;头文件/死代码/魔数</td></tr><tr><td>构建与仓库卫生</td><td><b>5.0</b> / 10</td><td>csolution 规范;-O3 覆盖、诊断抑制、厂商库改动、无 README/CI</td></tr><tr><td><b>综合</b></td><td><b>5.6</b> / 10</td><td>架构方向正确、近期在安全闸门上投入明显;但输入校验、通信超时、参数存储一致性三处缺陷可直接导致失控,修完 P0 前不建议无人值守或带负载运行。</td></tr></table>
<p class="meta">本报告由专家评审生成,仅新增 docs/ 文件,未改动任何源码。</p>
</main></body></html>