162 lines
6.0 KiB
Markdown
162 lines
6.0 KiB
Markdown
# 静态检查告警审查说明
|
|||
|
|
|
||
|
|
本文件用于记录人工确认后的静态检查告警处理结论。原则:
|
||
|
|
|
||
|
|
- 不为消除低风险 warning 引入会改变实时行为的代码。
|
||
|
|
- 裸机系统级单例、编译期常量、ISR/主循环共享状态分别分类说明。
|
||
|
|
- 对涉及实时路径的并发项,优先记录访问边界和偏离理由;只有经过实机验证后再做逻辑修复。
|
||
|
|
|
||
|
|
## SUP-GLB-001:文件作用域对象
|
||
|
|
|
||
|
|
### 编译期常量
|
||
|
|
|
||
|
|
以下 `constexpr` 对象为编译期常量,非可变全局状态,无运行期写入、并发访问或动态初始化顺序风险:
|
||
|
|
|
||
|
|
- `device/ADC.cpp`: `ADC_SCALE`, `TEMP_FACTOR`, `VCC_FACTOR`, `CURRENT_FACTOR`
|
||
|
|
- `sys/health.cpp`: `PROTECT_TIME`
|
||
|
|
- `sys/config.h`: 版本号、Flash 地址、协议 ID、滤波/PID 参数、数学常量、Timer 参数等 `constexpr` 配置项
|
||
|
|
|
||
|
|
处理结论:按静态检查误报/偏离处理。
|
||
|
|
|
||
|
|
### 系统级硬件/模块单例
|
||
|
|
|
||
|
|
以下对象对应裸机固件中的唯一硬件资源或唯一管理器:
|
||
|
|
|
||
|
|
- `Algorithm/FOC.cpp`: `FOC_Controller FOC`
|
||
|
|
- `device/ADC.cpp`: `sampler sampler`
|
||
|
|
- `device/Can.cpp`: `CAN_transmiter CAN0_transmiter`
|
||
|
|
- `device/ang_sensor.cpp`: `angle_sensor KTH7823`
|
||
|
|
- `sys/health.cpp`: `ThermalController thermalController`
|
||
|
|
- `sys/initial.cpp`: `VersionManager Version`
|
||
|
|
|
||
|
|
访问边界:
|
||
|
|
|
||
|
|
- 初始化顺序由 `main::hardware_init()` 显式控制,例如 `KTH7823.init()`、`sampler.init()`、`CAN0_transmiter.init()`、`FOC.init()`。
|
||
|
|
- `VersionManager Version` 构造仅复制 `constexpr` 版本号常量,不依赖外设初始化。
|
||
|
|
- 运行期主要由主循环任务访问;CAN 命令路径会更新 FOC 目标值和参数。
|
||
|
|
|
||
|
|
处理结论:接受系统级单例设计,保留文件作用域对象,并通过注释说明初始化顺序和访问边界。
|
||
|
|
|
||
|
|
### ISR/主循环共享状态
|
||
|
|
|
||
|
|
#### `main.cpp`: `TaskScheduler scheduler`
|
||
|
|
|
||
|
|
- `TIMER2_IRQHandler()` 置位任务标志。
|
||
|
|
- main 循环短关中断后读取快照并清除已处理任务位。
|
||
|
|
|
||
|
|
处理结论:已有短临界区保护,接受。
|
||
|
|
|
||
|
|
#### `device/Can.cpp`: CAN RX/TX 队列索引
|
||
|
|
|
||
|
|
涉及:
|
||
|
|
|
||
|
|
- `rx_queue_head`, `rx_queue_tail`, `rx_queue_count`
|
||
|
|
- `tx_queue_head`, `tx_queue_tail`, `tx_queue_count`
|
||
|
|
|
||
|
|
访问边界:
|
||
|
|
|
||
|
|
- RX/TX 队列被主循环、CAN 中断、DMA 完成中断共同访问。
|
||
|
|
- 队列 push/pop/peek/disable 通过 `CAN_EnterCritical()` / `CAN_ExitCritical()` 保护。
|
||
|
|
- `CAN_ExitCritical()` 使用 `__set_PRIMASK(primask)` 恢复进入前中断状态,而不是直接 `__enable_irq()`,避免误打开外层已关闭的中断。
|
||
|
|
|
||
|
|
处理结论:已有临界区保护,接受。
|
||
|
|
|
||
|
|
#### `device/ADC.cpp`: injected 电流采样缓存
|
||
|
|
|
||
|
|
涉及:
|
||
|
|
|
||
|
|
- `adc_current_value[3]`
|
||
|
|
- `adc_current_frame_ready`
|
||
|
|
|
||
|
|
访问边界:
|
||
|
|
|
||
|
|
- `ADC0_1_IRQHandler()` 写入 U/V/W injected 同步采样值,并置位 `adc_current_frame_ready`。
|
||
|
|
- `sampler::update_current()` 在主循环任务中看到 ready 后读取三相采样并更新滤波缓存,随后清 ready。
|
||
|
|
- 该路径属于高频电机采样/控制链路。此前尝试在读取侧加入 PRIMASK 快照后,实机出现上电连续重启;回滚后恢复正常。
|
||
|
|
|
||
|
|
处理结论:当前不再为消除 warning 增加临界区逻辑,避免改变高频实时路径时序。保留现有 `volatile` 共享标志设计,作为实机已验证的稳定实现;如后续需要修正,应单独建立实验分支并做示波/日志验证。
|
||
|
|
|
||
|
|
#### `sys/systick.cpp`: DWT CPU 占用率统计变量
|
||
|
|
|
||
|
|
涉及:
|
||
|
|
|
||
|
|
- `task_enter_cyccnt`
|
||
|
|
- `busy_cycles_accum`
|
||
|
|
- `sample_seconds`
|
||
|
|
- `cpu_usage`
|
||
|
|
- `dwt_initialized`
|
||
|
|
|
||
|
|
访问边界:
|
||
|
|
|
||
|
|
- `busy_task_enter()` / `busy_task_exit()` 在主循环任务侧记录和累加忙碌周期。
|
||
|
|
- `SysTick_Handler()` 每 1 秒读取并清零统计值,更新 `cpu_usage`。
|
||
|
|
- 此路径仅用于诊断 CPU 使用率,不参与控制闭环。
|
||
|
|
- 此前尝试在 `busy_task_exit()` 加入 PRIMASK 临界区后,与 ADC 临界区改动同轮导致实机上电连续重启;已回滚并恢复正常。
|
||
|
|
|
||
|
|
处理结论:当前不再为该诊断统计项增加临界区,避免影响高频任务时序。允许 1 秒窗口内存在极小统计误差,作为诊断值可接受。
|
||
|
|
|
||
|
|
#### `device/ang_sensor.cpp`: SPI DMA 完成标志
|
||
|
|
|
||
|
|
涉及:
|
||
|
|
|
||
|
|
- `spi_dma_tx_complete`
|
||
|
|
- `spi_dma_rx_complete`
|
||
|
|
|
||
|
|
访问边界:
|
||
|
|
|
||
|
|
- SPI 传输前清零标志。
|
||
|
|
- DMA ISR 完成后置位。
|
||
|
|
- 轮询函数等待标志或超时。
|
||
|
|
|
||
|
|
处理结论:典型 ISR/轮询共享 volatile 标志,接受。
|
||
|
|
|
||
|
|
#### `device/Timer.cpp`: `total_us100_counter`
|
||
|
|
|
||
|
|
访问边界:
|
||
|
|
|
||
|
|
- 仅在 `TIMER2_IRQHandler()` 内作为 100us 调度索引写入和使用。
|
||
|
|
|
||
|
|
处理结论:虽然为文件作用域变量,但无跨上下文并发写风险,接受。后续可考虑改为 ISR 内 `static`,但当前不为 warning 改运行逻辑。
|
||
|
|
|
||
|
|
#### `sys/health.cpp`: 电压管理状态
|
||
|
|
|
||
|
|
涉及:
|
||
|
|
|
||
|
|
- `voltage_state`
|
||
|
|
- `last_vbus_slow`
|
||
|
|
|
||
|
|
访问边界:
|
||
|
|
|
||
|
|
- 仅 `power_manage()` 慢速任务访问。
|
||
|
|
- 文件内 `static` 封装。
|
||
|
|
|
||
|
|
处理结论:模块私有状态机变量,接受。
|
||
|
|
|
||
|
|
## SUP-CMP-001:浮点比较
|
||
|
|
|
||
|
|
### `normalizeAngle360()` 边界判断
|
||
|
|
|
||
|
|
代码形态:
|
||
|
|
|
||
|
|
```cpp
|
||
|
|
while (angle >= 360.0f) angle -= 360.0f;
|
||
|
|
while (angle < 0.0f) angle += 360.0f;
|
||
|
|
```
|
||
|
|
|
||
|
|
结论:该比较用于角度归一化边界判断,目标区间严格定义为 `[0, 360)`,不是浮点相等性判断,也不是传感器阈值判定。不需要容差。
|
||
|
|
|
||
|
|
## printf / snprintf 类检查
|
||
|
|
|
||
|
|
- FOC 齿槽校准打印位于 `#if FOC_DEBUG`,正式配置 `FOC_DEBUG=0` 时不参与编译。
|
||
|
|
- `VersionManager::versionToString()` 已从 `snprintf()` 改为固定格式的轻量手写拼接,避免格式化库引入。
|
||
|
|
|
||
|
|
## AUTO-MET-001:圈复杂度
|
||
|
|
|
||
|
|
已拆分以下函数,降低单函数圈复杂度:
|
||
|
|
|
||
|
|
- `FOC_Controller::calibrate_cogging_tick()`:拆分为状态派发和各状态处理函数。
|
||
|
|
- `CAN_transmiter::communication_check()`:拆分为周期发送、接收分发、特殊消息、节点消息等处理函数。
|
||
|
|
- `do_task()`:拆分为高频采样/电机控制、低频维护、CAN 任务。
|
||
|
|
|
||
|
|
处理结论:拆分后原目标函数复杂度已显著下降;实编仍需在 Keil/CMSIS/cbuild 环境验证。
|