diff --git a/AMI.dbc b/AMI.dbc index e18d000..9188d58 100644 --- a/AMI.dbc +++ b/AMI.dbc @@ -1,4 +1,4 @@ -VERSION "AMI-2.4-2026-10-03" +VERSION "AMI-2.5-2026-10-04" NS_ : NS_DESC_ @@ -39,6 +39,12 @@ BO_ 768 AMI_TaskRequest: 8 AMI SG_ Request_Source : 24|8@1+ (1,0) [1|1] "" VCU SG_ MCU_Uptime : 32|32@1+ (1,0) [0|4294967295] "ms" VCU +BO_ 769 AMI_Heartbeat: 8 AMI + SG_ Protocol_Version : 0|8@1+ (1,0) [1|1] "" VCU + SG_ Reserved : 8|8@1+ (1,0) [0|0] "" VCU + SG_ Heartbeat_Sequence : 16|16@1+ (1,0) [0|65535] "" VCU + SG_ MCU_Uptime : 32|32@1+ (1,0) [0|4294967295] "ms" VCU + BO_ 1696 SDC_Heartbeat: 8 SDC_ACQ_DAC SG_ Board_Identifier : 0|8@1+ (1,0) [0|255] "" AMI SG_ Protocol_Version : 8|8@1+ (1,0) [0|255] "" AMI @@ -85,7 +91,7 @@ BO_ 2556444915 BMS_Status_Extended: 8 BMS BO_ 2556510451 BMS_Extremes_Extended: 8 BMS SG_ Maximum_Cell_Temperature : 39|8@0+ (1,-40) [-40|215] "degC" AMI -CM_ "AMI CAN interface v2.4. CAN1: 500000 bit/s; CAN2: 250000 bit/s. Both use Classic CAN, identical IDs, parsing and task request capability. This file is CAN1; use AMI_CAN2_250k.dbc for CAN2. Frames are not bridged between buses. SDC fields follow SDC_ACQ_DAC.dbc VERSION 1.1. BMS consumed fields follow BmsMonitor-CANTest commit e65c95203d1689df05343775982d7e85bd782646. AMI_DrivetrainDisplay and AMI_VCUStatus are custom instrument inputs to be implemented by VCU. Native motor-controller protocols, calibrated vehicle speed and AMI heartbeat are not defined."; +CM_ "AMI CAN interface v2.5. CAN1: 500000 bit/s; CAN2: 250000 bit/s. Both use Classic CAN, identical IDs, parsing and task request capability. This file is CAN1; use AMI_CAN2_250k.dbc for CAN2. Frames are not bridged between buses. SDC fields follow SDC_ACQ_DAC.dbc VERSION 1.1. BMS consumed fields follow BmsMonitor-CANTest commit e65c95203d1689df05343775982d7e85bd782646. AMI_DrivetrainDisplay and AMI_VCUStatus are custom instrument inputs to be implemented by VCU. Native motor-controller protocols, calibrated vehicle speed are not defined. AMI heartbeat is standard 0x301 every 100 ms on CAN1 only."; CM_ BU_ AMI "Instrument MCU. UART HMI task confirmation produces AMI_TaskRequest. Display values come from SDC, BMS and custom VCU display inputs."; CM_ BU_ VCU "Task request receiver and authoritative sender for actual task, lock and EBS display states plus drivetrain data. Vehicle execution and safety outputs remain VCU responsibilities."; CM_ BU_ SDC_ACQ_DAC "Source of ADC, capture frequencies and raw PD0-PD14 states; both SDC CAN ports carry the same protocol."; @@ -182,3 +188,6 @@ BA_ "GenMsgCycleTime" BO_ 387 100; BA_ "GenMsgCycleTime" BO_ 1696 100; BA_ "GenMsgCycleTime" BO_ 1697 500; BA_ "GenMsgCycleTime" BO_ 1698 20; + +CM_ BO_ 769 "Standard 0x301, Classic CAN DLC 8. CAN1 (500 kbit/s) only, every 100 ms regardless of RX activity. Version 1, reserved 0, uint16 sequence and uint32 uptime in ms, little-endian. Sequence starts at 0 and increments each scheduled period even if transmission is skipped. Keep one TX FIFO slot for tasks; busy/error periods are skipped without software retry. Hardware automatic retransmission still applies."; +BA_ "GenMsgCycleTime" BO_ 769 100; diff --git a/AMI_CAN2_250k.dbc b/AMI_CAN2_250k.dbc index 0381234..f99a0ce 100644 --- a/AMI_CAN2_250k.dbc +++ b/AMI_CAN2_250k.dbc @@ -1,4 +1,4 @@ -VERSION "AMI-2.4-2026-10-03" +VERSION "AMI-2.5-2026-10-04" NS_ : NS_DESC_ @@ -85,7 +85,7 @@ BO_ 2556444915 BMS_Status_Extended: 8 BMS BO_ 2556510451 BMS_Extremes_Extended: 8 BMS SG_ Maximum_Cell_Temperature : 39|8@0+ (1,-40) [-40|215] "degC" AMI -CM_ "AMI CAN interface v2.4. CAN1: 500000 bit/s; CAN2: 250000 bit/s. Both use Classic CAN, identical IDs, parsing and task request capability. This file is CAN2; use AMI.dbc for CAN1. Frames are not bridged between buses. SDC fields follow SDC_ACQ_DAC.dbc VERSION 1.1. BMS consumed fields follow BmsMonitor-CANTest commit e65c95203d1689df05343775982d7e85bd782646. AMI_DrivetrainDisplay and AMI_VCUStatus are custom instrument inputs to be implemented by VCU. Native motor-controller protocols, calibrated vehicle speed and AMI heartbeat are not defined."; +CM_ "AMI CAN interface v2.5. CAN1: 500000 bit/s; CAN2: 250000 bit/s. Both use Classic CAN, identical IDs, parsing and task request capability. This file is CAN2; use AMI.dbc for CAN1. Frames are not bridged between buses. SDC fields follow SDC_ACQ_DAC.dbc VERSION 1.1. BMS consumed fields follow BmsMonitor-CANTest commit e65c95203d1689df05343775982d7e85bd782646. AMI_DrivetrainDisplay and AMI_VCUStatus are custom instrument inputs to be implemented by VCU. Native motor-controller protocols, calibrated vehicle speed are not defined. AMI heartbeat 0x301 is CAN1 only and is not included in this CAN2 file."; CM_ BU_ AMI "Instrument MCU. UART HMI task confirmation produces AMI_TaskRequest. Display values come from SDC, BMS and custom VCU display inputs."; CM_ BU_ VCU "Task request receiver and authoritative sender for actual task, lock and EBS display states plus drivetrain data. Vehicle execution and safety outputs remain VCU responsibilities."; CM_ BU_ SDC_ACQ_DAC "Source of ADC, capture frequencies and raw PD0-PD14 states; both SDC CAN ports carry the same protocol."; diff --git a/README.md b/README.md index eaa5e09..6cdb802 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # AMI +2026-10-04:新增 AMI `0x301` 标准心跳帧(DLC 8),仅 CAN1(500 kbit/s)100 ms 一次,CAN2 不发送心跳,包含版本、uint16 序号和 uint32 运行毫秒值,小端。源码和 DBC 已更新,已烧录并全量回读一致;CAN1 实测 121 帧,间隔 99.952~100.180 ms。完整定义见 [DBC 说明](docs/AMI_CAN_DBC说明.md)。 + YMR A11 仪表,使用淘晶驰 TJC4827X543_011 串口屏,分辨率 480 × 272。 当前屏幕接口 **1.4**,MCU CAN 输入 **v2.4(CAN1 500 kbit/s、CAN2 250 kbit/s,2026-10-03)**。新增标准 `0x183`,由 VCU 反馈实际当前任务、锁定状态和 EBS 状态;两路保留相同解码和任务收发功能。工程使用 USART HMI 1.68.1.3037 编辑、编译。 @@ -16,10 +18,10 @@ v2.3 按用户接线表将 `0x6A6` 的 PD0~PD14 映射到 DEBUG:`d0,d5,d2,d6 ## 工程与交接资料 -- [CAN1 DBC](AMI.dbc):500 kbit/s,12 条报文、49 个信号,含标准/扩展帧。 -- [CAN2 DBC](AMI_CAN2_250k.dbc):250 kbit/s,报文布局与 CAN1 相同。 +- [CAN1 DBC](AMI.dbc):500 kbit/s,13 条报文、53 个信号,含标准/扩展帧。 +- [CAN2 DBC](AMI_CAN2_250k.dbc):250 kbit/s,不含 0x301 心跳,其余报文布局与 CAN1 相同。 - [DBC 对应说明](docs/AMI_CAN_DBC说明.md):信号布局、枚举、字节序、样例与复现检查。 -- [CAN 报文说明 PDF](output/pdf/AMI_CAN报文说明.pdf):当前 v2.4 协议的中文打印版,包含两路速率和全部 12 条报文。 +- [CAN 报文说明 PDF](output/pdf/AMI_CAN报文说明.pdf):当前 v2.5 协议的中文打印版,含两路速率、13 条报文及仅 CAN1 发送的 0x301 心跳。 - [VCU 状态发送工具](scripts/send_vcu_status_can.py):预览或发送实际任务、锁定和 EBS 显示反馈。 - [CAN 显示发送工具](scripts/send_drivetrain_can.py):通过 python-can 发送扭矩千分和两路温度,支持预览字节、有效标志和适配器参数。 - [v2.2 显示 CAN 测试报告](docs/AMI自定义显示CAN测试报告.md):新帧烧录回读和 CAN2 数据、失效、异常帧测试。 diff --git a/docs/AMI_CAN_DBC说明.md b/docs/AMI_CAN_DBC说明.md index 5e7c672..dbdff71 100644 --- a/docs/AMI_CAN_DBC说明.md +++ b/docs/AMI_CAN_DBC说明.md @@ -1,6 +1,6 @@ # AMI CAN DBC 说明 -版本:`AMI-2.4-2026-10-03`。由 [AMI.dbc](../AMI.dbc) 自动生成,12 条报文、49 个信号。 +版本:`AMI-2.5-2026-10-04`。由 [AMI.dbc](../AMI.dbc) 自动生成,13 条报文、53 个信号。 ## 使用范围 @@ -11,16 +11,32 @@ CAN1 为 500 kbit/s,CAN2 为 250 kbit/s,均为 Classic CAN、87.5% 采样点 | CAN1 | 500 kbit/s | PA11 / PA12 | [AMI.dbc](../AMI.dbc) | | CAN2 | 250 kbit/s | PB0 / PB1 | [AMI_CAN2_250k.dbc](../AMI_CAN2_250k.dbc) | -DBC 的 `Baudrate` / `AMIPort` 分别标注所属总线。每份 DBC 均含 12 条报文、49 个信号;同一份报文表适用于两路。CAN 工具必须按接入端口设置速率,导入 DBC 不一定自动改硬件速率。实际接法:SDC 500 kbit/s 接 CAN1,BMS 250 kbit/s 接 CAN2。 +DBC 的 `Baudrate` / `AMIPort` 分别标注所属总线。CAN1 DBC 含 13 条报文、53 个信号;CAN2 DBC 含 12 条报文、49 个信号;仅 CAN1 包含 0x301 心跳,其余报文布局相同。CAN 工具必须按接入端口设置速率,导入 DBC 不一定自动改硬件速率。实际接法:SDC 500 kbit/s 接 CAN1,BMS 250 kbit/s 接 CAN2。 FDCAN 时钟 64 MHz,时钟分频为 1;NominalPrescaler 为 CAN1=8、CAN2=16,两路均使用 Sync=1、TimeSeg1=13、TimeSeg2=2、SJW=1。速率 = 64 MHz / Prescaler / (1+13+2);采样点 = (1+13)/16 = 87.5%。 -本 DBC 包含 AMI 唯一发送的 `0x300` 任务请求,以及 AMI 当前识别的 SDC / BMS 和自定义显示输入。SDC `0x6A3` DAC 控制、`0x6A5` ASSI 控制、BMS 其他电芯/故障字段不属于此接口子集。`0x182` 新增扭矩千分、电机温度和电机控制器 MCU 温度的仪表显示输入;发送者负责转换实际电机控制器协议。`0x183` 为新增 VCU 状态反馈,需 VCU 按此自定义接口发送;未定义标定后的车速或 AMI 周期心跳。旧 `0x180 / 0x181 / 0x280` 输入已停用。 +本 DBC 包含 AMI 发送的 `0x300` 任务请求和 `0x301` 周期心跳,以及 AMI 当前识别的 SDC / BMS 和自定义显示输入。SDC `0x6A3` DAC 控制、`0x6A5` ASSI 控制、BMS 其他电芯/故障字段不属于此接口子集。`0x182` 新增扭矩千分、电机温度和电机控制器 MCU 温度的仪表显示输入;发送者负责转换实际电机控制器协议。`0x183` 为新增 VCU 状态反馈,需 VCU 按此自定义接口发送;未定义标定后的车速。旧 `0x180 / 0x181 / 0x280` 输入已停用。 SDC 字段依据 `SDC_ACQ_DAC.dbc` VERSION 1.1,保持其信号名、位布局、缩放和单位;仅将输入接收节点设为 AMI。BMS 字段依据 [BmsMonitor-CANTest](https://git.acetaffy.ltd/acetaffy/BmsMonitor-CANTest) 提交 `e65c95203d1689df05343775982d7e85bd782646` 的 `BmsProtocolParser.cs`。 DBC 为 ASCII 编码,注释和枚举使用英文,便于导入 CAN 工具;本文为 UTF-8 中文。物理值 = 原始值 × Factor + Offset;`0x182` 的三个数值为有符号 int16,其他数值按表定义。下表范围为接口允许范围,不表示车辆正常工作范围。 +## AMI 周期心跳 0x301 + +2026-10-04 新增:标准 ID `0x301`、Classic CAN 数据帧、DLC 8。仅 CAN1(500 kbit/s)每 **100 ms** 尝试发送,CAN2 不发送心跳,不依赖接收活动或屏幕连接。首帧在启动约 100 ms 后发送。 + +| 字节 | 含义 | +| --- | --- | +| 0 | 协议版本,固定 1 | +| 1 | 保留,固定 0 | +| 2..3 | uint16 小端心跳序号,首帧 0,每个调度周期加 1,65535 后回到 0 | +| 4..7 | uint32 小端 `HAL_GetTick()` 运行时间,单位 ms,自然回绕 | + +例如运行 100 ms 的首帧:`01 00 00 00 64 00 00 00`。任务请求先处理,心跳仅在发送 FIFO 至少有两个空位时入队,为任务保留一个空位;忙或入队失败时跳过本周期,不在软件中积压或补发。硬件自动重传仍启用,已入硬件 FIFO 的帧可能延迟到总线恢复后发出。100 ms 为主循环调度周期,实际总线时刻受仲裁/错误重传影响。序号按调度递增,因此丢帧时可以跳号。 + +仅表示 AMI 主循环运行,不表示屏幕、VCU 或车辆状态正常。2026-10-04 已烧录并全量回读一致;CAN1 抓取 121 帧,间隔 99.952~100.180 ms,序号连续,详见 [心跳测试报告](AMI心跳测试报告.md)。CAN2 未接线抓帧。 + + ## 报文总览 | CAN ID | 类型 | DLC | 报文名 | 方向和作用 | 周期 / 触发 | @@ -28,6 +44,7 @@ DBC 为 ASCII 编码,注释和枚举使用英文,便于导入 CAN 工具; | `0x182` | 标准 | 8 | `AMI_DrivetrainDisplay` | VCU / 测试器 -> AMI:扭矩千分、电机温度、MCU 温度 | 100 ms | | `0x183` | 标准 | 8 | `AMI_VCUStatus` | VCU -> AMI:实际当前任务、锁定状态、EBS 状态 | 100 ms | | `0x300` | 标准 | 8 | `AMI_TaskRequest` | AMI -> VCU:用户确认后的任务选择请求 | 确认任务触发 | +| `0x301` | 标准 | 8 | `AMI_Heartbeat` | AMI -> VCU(仅 CAN1):版本、序号、运行时间 | 100 ms | | `0x6A0` | 标准 | 8 | `SDC_Heartbeat` | SDC -> AMI:板标识、版本、序号、上电时间 | 100 ms | | `0x6A1` | 标准 | 2 | `SDC_ADC_InputVoltage` | SDC -> AMI:低压电池电压,精确 DLC=2 | 500 ms | | `0x6A2` | 标准 | 8 | `SDC_InputFrequencies` | SDC -> AMI:PA0 / PA2 / PA6 / PB14 原始频率 | 20 ms | @@ -40,7 +57,7 @@ DBC 为 ASCII 编码,注释和枚举使用英文,便于导入 CAN 工具; 扩展帧在 DBC 的 `BO_` 十进制 ID 中设置 bit31:`0x186040F3 -> 2556444915`,`0x186140F3 -> 2556510451`。CAN 工具中使用实际 29 位仲裁 ID 并选择扩展帧;bit31 不是总线上发送的仲裁 ID。 -`GenMsgCycleTime` 填写已确认的 SDC 周期 100 / 500 / 20 ms,以及自定义 `0x182` 的约定周期 100 ms。其余帧未填写周期,默认 0 表示未指定,不据此推断 BMS 周期。 +`GenMsgCycleTime` 填写已确认的 SDC 周期 100 / 500 / 20 ms,以及 `0x182`、`0x183` 和 `0x301` 的约定周期 100 ms。其余帧未填写周期,默认 0 表示未指定,不据此推断 BMS 周期。 ## 信号布局 @@ -88,6 +105,15 @@ Start 为 DBC 起始位,位号从 0 开始。Intel `@1` 从最低有效位起 `Protocol_Version`:1 = Version_1;`Task_ID`:1 = Skidpad,2 = Acceleration,3 = Autocross,4 = Inspection_Test,5 = EBS_Test,6 = Manual_Driving;`Request_Source`:1 = AMI_HMI。 +### 0x301 - AMI_Heartbeat + +| 信号 | Start | 位数 | 字节序 | Factor | Offset | 单位 | 编码范围 | +| --- | --- | --- | --- | --- | --- | --- | --- | +| `Protocol_Version` | 0 | 8 | Intel | 1 | 0 | - | 1..1 | +| `Reserved` | 8 | 8 | Intel | 1 | 0 | - | 0(固定) | +| `Heartbeat_Sequence` | 16 | 16 | Intel | 1 | 0 | - | 0..65535 | +| `MCU_Uptime` | 32 | 32 | Intel | 1 | 0 | ms | 0..4.29497e+09 | + ### 0x6A0 - SDC_Heartbeat | 信号 | Start | 位数 | 字节序 | Factor | Offset | 单位 | 编码范围 | @@ -296,7 +322,7 @@ python scripts/export_dbc_docs.py --check python scripts/verify_dbc.py --sdc-dbc ../SDC_ACQ_DAC/SDC_ACQ_DAC.dbc ``` -校验覆盖严格 DBC 解析(长度、信号越界与重叠)、12 个 ID 与固件宏对应、标准/扩展格式、49 个信号、发送/接收节点、SDC / 自定义帧周期、已知报文解码、六个任务号与计数边界编码、大端偏置电流、无效温度枚举、全负温度和截短 DLC。已安装并验证 cantools 44.1.0,接口参考 [cantools 官方文档](https://cantools.readthedocs.io/en/latest/)。 +校验覆盖严格 DBC 解析(长度、信号越界与重叠)、13 个 ID 与固件宏对应、标准/扩展格式、53 个信号、发送/接收节点、SDC / 自定义帧周期、已知报文解码、六个任务号与计数边界编码、大端偏置电流、无效温度枚举、全负温度和截短 DLC。已安装并验证 cantools 44.1.0,接口参考 [cantools 官方文档](https://cantools.readthedocs.io/en/latest/)。 上述是静态及软件编解码验证,另校验两份 DBC 的速率、相同信号布局及源码 / CubeMX 位时序一致。v2.2 的烧录回读、新帧 CAN2 测试及串口显示核验状态见 [显示 CAN 测试报告](AMI自定义显示CAN测试报告.md)。v2.1 已完成烧录、完整 Flash 回读比对、CAN1 500K 与 CAN2 250K 到官方 HMI 调试器的实物测试,详见 [双 CAN 测试报告](CAN1_CAN2_v2.1测试报告.md)。之前 v2.0 的 CAN 盒 -> 实物 AMI CAN1 / MCU -> USART2 -> COM4 -> 官方 HMI 调试器的实际更新和六个任务回传见 [联调报告](SDC_BMS联调报告.md)。物理串口屏、真实 SDC/BMS 节点、两路同时接入和车辆执行动作尚未实测;文档生成和 DBC 解析不替代这些测试。 diff --git a/docs/AMI心跳测试报告.md b/docs/AMI心跳测试报告.md new file mode 100644 index 0000000..b4a63b8 --- /dev/null +++ b/docs/AMI心跳测试报告.md @@ -0,0 +1,16 @@ +# AMI CAN1 心跳烧录与实测 + +2026-10-04。仅 CAN1 500 kbit/s 发送标准 0x301 / DLC 8 心跳,周期 100 ms。 + +- ST-Link:37FF71064E573436188C1543;MCU ID 0x467,128 KB Flash,电压 3.27 V。 +- Release 编译通过:Flash 16528 字节,RAM 2648 字节。 +- 烧录校验成功并复位;全量回读 16528 字节与 BIN 逐字节一致。 +- 固件 SHA256:`e97ec2fb3384e4bad0980017c65360f7d615dc9e716038af4445da43892f2b6e`。 +- PCAN-USB 以 500 kbit/s 抓取 CAN1 12 秒,收到 121 帧 0x301。 +- 总线间隔:最小 99.952 ms,平均 100.094 ms,最大 100.180 ms。 +- 标准数据帧、DLC 8、版本 1、保留字节 0 校验通过;uint16 序号连续,uint32 运行时间每帧递增 100 ms;PCAN 状态 0,无总线错误。 +- CAN2 不发送心跳已经源码核对;本次没有对 CAN2 接线抓帧,也未测试屏幕或车辆动作。 + +[测试结果](evidence/2026-10-04/heartbeat/results.json) · [原始帧](evidence/2026-10-04/heartbeat/capture.json) · [烧录日志](evidence/2026-10-04/heartbeat/flash.log) · [回读日志](evidence/2026-10-04/heartbeat/readback.log) + +烧录前已备份完整 128 KB Flash 至同目录 before-flash.bin;readback.bin 为本次固件回读。第一次脚本在烧录成功后因终端编码打印失败退出;确认原始日志包含 Download verified successfully 后,使用 --capture-only 继续回读和抓帧,没有重复烧录。CAN 时间戳采用适配器相对时间,间隔统计不依赖 UTC 时钟。 diff --git a/docs/SDC_BMS协议.md b/docs/SDC_BMS协议.md index e62e802..1c0044f 100644 --- a/docs/SDC_BMS协议.md +++ b/docs/SDC_BMS协议.md @@ -1,5 +1,7 @@ # AMI 接入 SDC / BMS 协议 +2026-10-04:新增 AMI `0x301` 标准心跳帧(DLC 8),仅 CAN1(500 kbit/s)100 ms 一次,CAN2 不发送心跳,包含版本、uint16 序号和 uint32 运行毫秒值,小端。源码和 DBC 已更新,已烧录并全量回读一致;CAN1 实测 121 帧,间隔 99.952~100.180 ms。完整定义见 [DBC 说明](AMI_CAN_DBC说明.md)。 + 版本 2.4,2026-10-03。CAN1 为 500 kbit/s,CAN2 为 250 kbit/s;两路均为 Classic CAN、87.5% 采样点,接收 ID、解码和任务发送功能相同,不转发原始帧。CAN1 使用 [AMI.dbc](../AMI.dbc),CAN2 使用 [AMI_CAN2_250k.dbc](../AMI_CAN2_250k.dbc)。当前固件不再接收旧 `0x180 / 0x181 / 0x280` 数据接口。 VCU 实际当前任务、锁定和 EBS 汇总显示由新增标准 `0x183 / DLC 8` 输入,独立超时 500 ms。任务按钮仅发送 0x300 请求,不更新实际任务;完整布局和颜色见 [VCU 反馈协议](AMI_CAN_DBC说明.md#vcu-状态反馈-0x183),验证边界见 [反馈报告](VCU状态反馈测试报告.md)。本页 SDC / BMS 采样与该 VCU 反馈独立。 diff --git a/docs/evidence/2026-10-04/heartbeat/before-flash.bin b/docs/evidence/2026-10-04/heartbeat/before-flash.bin new file mode 100644 index 0000000..14c6ed9 Binary files /dev/null and b/docs/evidence/2026-10-04/heartbeat/before-flash.bin differ diff --git a/docs/evidence/2026-10-04/heartbeat/capture.json b/docs/evidence/2026-10-04/heartbeat/capture.json new file mode 100644 index 0000000..5b6dda0 --- /dev/null +++ b/docs/evidence/2026-10-04/heartbeat/capture.json @@ -0,0 +1,1091 @@ +[ + { + "timestamp": 852216.866583, + "id": 769, + "data": "01 00 72 00 ec 2c 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852216.966678, + "id": 769, + "data": "01 00 73 00 50 2d 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.06673, + "id": 769, + "data": "01 00 74 00 b4 2d 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.166781, + "id": 769, + "data": "01 00 75 00 18 2e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.266833, + "id": 769, + "data": "01 00 76 00 7c 2e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.366828, + "id": 769, + "data": "01 00 77 00 e0 2e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.466879, + "id": 769, + "data": "01 00 78 00 44 2f 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.567016, + "id": 769, + "data": "01 00 79 00 a8 2f 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.667111, + "id": 769, + "data": "01 00 7a 00 0c 30 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.767205, + "id": 769, + "data": "01 00 7b 00 70 30 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.867342, + "id": 769, + "data": "01 00 7c 00 d4 30 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852217.967437, + "id": 769, + "data": "01 00 7d 00 38 31 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.067531, + "id": 769, + "data": "01 00 7e 00 9c 31 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.167668, + "id": 769, + "data": "01 00 7f 00 00 32 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.26772, + "id": 769, + "data": "01 00 80 00 64 32 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.367715, + "id": 769, + "data": "01 00 81 00 c8 32 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.467766, + "id": 769, + "data": "01 00 82 00 2c 33 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.567861, + "id": 769, + "data": "01 00 83 00 90 33 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.667955, + "id": 769, + "data": "01 00 84 00 f4 33 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.76805, + "id": 769, + "data": "01 00 85 00 58 34 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.868144, + "id": 769, + "data": "01 00 86 00 bc 34 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852218.968196, + "id": 769, + "data": "01 00 87 00 20 35 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.06829, + "id": 769, + "data": "01 00 88 00 84 35 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.168385, + "id": 769, + "data": "01 00 89 00 e8 35 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.268479, + "id": 769, + "data": "01 00 8a 00 4c 36 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.368474, + "id": 769, + "data": "01 00 8b 00 b0 36 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.468568, + "id": 769, + "data": "01 00 8c 00 14 37 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.568662, + "id": 769, + "data": "01 00 8d 00 78 37 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.668714, + "id": 769, + "data": "01 00 8e 00 dc 37 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.768894, + "id": 769, + "data": "01 00 8f 00 40 38 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.868988, + "id": 769, + "data": "01 00 90 00 a4 38 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852219.969126, + "id": 769, + "data": "01 00 91 00 08 39 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.069263, + "id": 769, + "data": "01 00 92 00 6c 39 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.169357, + "id": 769, + "data": "01 00 93 00 d0 39 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.269494, + "id": 769, + "data": "01 00 94 00 34 3a 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.369489, + "id": 769, + "data": "01 00 95 00 98 3a 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.469583, + "id": 769, + "data": "01 00 96 00 fc 3a 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.569677, + "id": 769, + "data": "01 00 97 00 60 3b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.669772, + "id": 769, + "data": "01 00 98 00 c4 3b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.769866, + "id": 769, + "data": "01 00 99 00 28 3c 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.869961, + "id": 769, + "data": "01 00 9a 00 8c 3c 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852220.970098, + "id": 769, + "data": "01 00 9b 00 f0 3c 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.070235, + "id": 769, + "data": "01 00 9c 00 54 3d 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.170329, + "id": 769, + "data": "01 00 9d 00 b8 3d 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.270467, + "id": 769, + "data": "01 00 9e 00 1c 3e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.370504, + "id": 769, + "data": "01 00 9f 00 80 3e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.470641, + "id": 769, + "data": "01 00 a0 00 e4 3e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.570778, + "id": 769, + "data": "01 00 a1 00 48 3f 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.67083, + "id": 769, + "data": "01 00 a2 00 ac 3f 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.770967, + "id": 769, + "data": "01 00 a3 00 10 40 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.871061, + "id": 769, + "data": "01 00 a4 00 74 40 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852221.971113, + "id": 769, + "data": "01 00 a5 00 d8 40 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.071207, + "id": 769, + "data": "01 00 a6 00 3c 41 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.171302, + "id": 769, + "data": "01 00 a7 00 a0 41 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.271396, + "id": 769, + "data": "01 00 a8 00 04 42 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.371348, + "id": 769, + "data": "01 00 a9 00 68 42 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.471485, + "id": 769, + "data": "01 00 aa 00 cc 42 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.57158, + "id": 769, + "data": "01 00 ab 00 30 43 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.671674, + "id": 769, + "data": "01 00 ac 00 94 43 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.771768, + "id": 769, + "data": "01 00 ad 00 f8 43 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.871863, + "id": 769, + "data": "01 00 ae 00 5c 44 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852222.972, + "id": 769, + "data": "01 00 af 00 c0 44 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.072137, + "id": 769, + "data": "01 00 b0 00 24 45 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.172274, + "id": 769, + "data": "01 00 b1 00 88 45 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.272411, + "id": 769, + "data": "01 00 b2 00 ec 45 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.372448, + "id": 769, + "data": "01 00 b3 00 50 46 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.472585, + "id": 769, + "data": "01 00 b4 00 b4 46 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.572723, + "id": 769, + "data": "01 00 b5 00 18 47 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.67286, + "id": 769, + "data": "01 00 b6 00 7c 47 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.772997, + "id": 769, + "data": "01 00 b7 00 e0 47 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.873134, + "id": 769, + "data": "01 00 b8 00 44 48 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852223.973271, + "id": 769, + "data": "01 00 b9 00 a8 48 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.073365, + "id": 769, + "data": "01 00 ba 00 0c 49 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.173502, + "id": 769, + "data": "01 00 bb 00 70 49 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.27354, + "id": 769, + "data": "01 00 bc 00 d4 49 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.373677, + "id": 769, + "data": "01 00 bd 00 38 4a 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.473771, + "id": 769, + "data": "01 00 be 00 9c 4a 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.573866, + "id": 769, + "data": "01 00 bf 00 00 4b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.67396, + "id": 769, + "data": "01 00 c0 00 64 4b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.774054, + "id": 769, + "data": "01 00 c1 00 c8 4b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.874192, + "id": 769, + "data": "01 00 c2 00 2c 4c 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852224.974286, + "id": 769, + "data": "01 00 c3 00 90 4c 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.07438, + "id": 769, + "data": "01 00 c4 00 f4 4c 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.174475, + "id": 769, + "data": "01 00 c5 00 58 4d 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.274469, + "id": 769, + "data": "01 00 c6 00 bc 4d 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.374606, + "id": 769, + "data": "01 00 c7 00 20 4e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.474701, + "id": 769, + "data": "01 00 c8 00 84 4e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.574795, + "id": 769, + "data": "01 00 c9 00 e8 4e 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.67489, + "id": 769, + "data": "01 00 ca 00 4c 4f 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.774984, + "id": 769, + "data": "01 00 cb 00 b0 4f 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.875079, + "id": 769, + "data": "01 00 cc 00 14 50 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852225.975173, + "id": 769, + "data": "01 00 cd 00 78 50 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.07531, + "id": 769, + "data": "01 00 ce 00 dc 50 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.175405, + "id": 769, + "data": "01 00 cf 00 40 51 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.275442, + "id": 769, + "data": "01 00 d0 00 a4 51 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.375536, + "id": 769, + "data": "01 00 d1 00 08 52 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.475673, + "id": 769, + "data": "01 00 d2 00 6c 52 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.575768, + "id": 769, + "data": "01 00 d3 00 d0 52 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.675905, + "id": 769, + "data": "01 00 d4 00 34 53 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.775999, + "id": 769, + "data": "01 00 d5 00 98 53 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.876094, + "id": 769, + "data": "01 00 d6 00 fc 53 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852226.976231, + "id": 769, + "data": "01 00 d7 00 60 54 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.076325, + "id": 769, + "data": "01 00 d8 00 c4 54 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.176462, + "id": 769, + "data": "01 00 d9 00 28 55 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.276457, + "id": 769, + "data": "01 00 da 00 8c 55 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.376551, + "id": 769, + "data": "01 00 db 00 f0 55 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.476646, + "id": 769, + "data": "01 00 dc 00 54 56 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.57674, + "id": 769, + "data": "01 00 dd 00 b8 56 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.676834, + "id": 769, + "data": "01 00 de 00 1c 57 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.776929, + "id": 769, + "data": "01 00 df 00 80 57 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.877066, + "id": 769, + "data": "01 00 e0 00 e4 57 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852227.97716, + "id": 769, + "data": "01 00 e1 00 48 58 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.077297, + "id": 769, + "data": "01 00 e2 00 ac 58 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.177392, + "id": 769, + "data": "01 00 e3 00 10 59 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.277386, + "id": 769, + "data": "01 00 e4 00 74 59 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.377481, + "id": 769, + "data": "01 00 e5 00 d8 59 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.477575, + "id": 769, + "data": "01 00 e6 00 3c 5a 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.57767, + "id": 769, + "data": "01 00 e7 00 a0 5a 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.677721, + "id": 769, + "data": "01 00 e8 00 04 5b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.777816, + "id": 769, + "data": "01 00 e9 00 68 5b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + }, + { + "timestamp": 852228.87791, + "id": 769, + "data": "01 00 ea 00 cc 5b 00 00", + "dlc": 8, + "extended": false, + "remote": false, + "error": false + } +] \ No newline at end of file diff --git a/docs/evidence/2026-10-04/heartbeat/dbc-verification.json b/docs/evidence/2026-10-04/heartbeat/dbc-verification.json new file mode 100644 index 0000000..f9c1514 --- /dev/null +++ b/docs/evidence/2026-10-04/heartbeat/dbc-verification.json @@ -0,0 +1,18 @@ +{ + "result": "passed", + "messages": 13, + "signals": 53, + "known_payload_checks": 84, + "all_task_ids_and_counter_edges": true, + "ports_bitrate": { + "CAN1": 500000, + "CAN2": 250000 + }, + "shared_dbc_layouts_and_payloads_match": true, + "heartbeat_can1_only": true, + "firmware_and_ioc_bit_timing_match": true, + "firmware_ids_match": true, + "sdc_source_layout_match": true, + "display_sender_known_bytes_and_argument_rejection": true, + "cantools_version": "44.1.0" +} diff --git a/docs/evidence/2026-10-04/heartbeat/flash.log b/docs/evidence/2026-10-04/heartbeat/flash.log new file mode 100644 index 0000000..5ca867e --- /dev/null +++ b/docs/evidence/2026-10-04/heartbeat/flash.log @@ -0,0 +1,56 @@ + ------------------------------------------------------------------- + STM32CubeProgrammer v2.20.0 + ------------------------------------------------------------------- + +ST-LINK SN : 37FF71064E573436188C1543 +ST-LINK FW : V2J47S7 +Board : -- +Voltage : 3.27V +SWD freq : 950 KHz +Connect mode: Under Reset +Reset mode : Hardware reset +Device ID : 0x467 +Revision ID : Rev Z +Device name : STM32G0B0xx/B1xx/C1xx +Flash size : 128 KBytes +Device type : MCU +Device CPU : Cortex-M0+ +BL Version : 0x92 + + + +Opening and parsing file: AMI_Controller.bin + + +Memory Programming ... + File : AMI_Controller.bin + Size : 16.14 KB + Address : 0x08000000 + + +Erasing memory corresponding to segment 0: +Erasing internal memory sectors [0 8] +Download in Progress: +±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± 0% ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ 100% + +File download complete +Time elapsed during download operation: 00:00:00.799 + + + +Verifying... + + +Read progress: +±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± 50% ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ 100% + +Time elapsed during verifying operation: 00:00:00.263 + + +Download verified successfully + + + +MCU Reset + +Software reset is performed diff --git a/docs/evidence/2026-10-04/heartbeat/flash_test.py b/docs/evidence/2026-10-04/heartbeat/flash_test.py new file mode 100644 index 0000000..5b230e4 --- /dev/null +++ b/docs/evidence/2026-10-04/heartbeat/flash_test.py @@ -0,0 +1,34 @@ +import os, json, time, subprocess, hashlib, statistics, sys +from pathlib import Path +root=Path.cwd(); out=root/'docs/evidence/2026-10-04/heartbeat' +dll=root/'tmp/can1-test-20261002/pcan-basic/x64' +os.environ['PATH']=str(dll)+os.pathsep+os.environ['PATH']; handle=os.add_dll_directory(str(dll)) +import can +cli=r'D:\STM32CubeCLT_1.19.0\STM32CubeProgrammer\bin\STM32_Programmer_CLI.exe' +firmware=root/'firmware/build/Release/AMI_Controller.bin' +def run(name,args): + p=subprocess.run([cli]+args,capture_output=True,timeout=40) + (out/(name+'.log')).write_bytes(p.stdout+p.stderr) + print(name, p.returncode, p.stdout.decode(errors='replace')[-750:],flush=True) + assert p.returncode==0,name + return p +with can.Bus(interface='pcan',channel='PCAN_USBBUS1',bitrate=500000) as bus: + assert bus.reset() + if '--capture-only' not in sys.argv: run('flash',['-c','port=SWD','mode=UR','freq=1000','-d',str(firmware),'0x08000000','-v','-rst']) + readback=out/'readback.bin' + run('readback',['-c','port=SWD','mode=HOTPLUG','freq=1000','-u','0x08000000',str(firmware.stat().st_size),str(readback)]) + assert firmware.read_bytes()==readback.read_bytes() + while bus.recv(0): pass + frames=[];end=time.monotonic()+12 + while time.monotonic()=100,'bus_ok':status==0,'format':all(f['dlc']==8 and not f['extended'] and not f['remote'] and bytes.fromhex(f['data'])[:2]==b'\x01\x00' for f in h),'sequence_contiguous':all((b-a)%65536==1 for a,b in zip(seq,seq[1:])),'uptime_100ms':all((b-a)%2**32==100 for a,b in zip(ticks,ticks[1:])),'wire_period_95_to_105ms':bool(intervals) and all(95<=v<=105 for v in intervals)} +result={'firmware_bytes':firmware.stat().st_size,'sha256':hashlib.sha256(firmware.read_bytes()).hexdigest(),'flash_readback_identical':True,'bus':'CAN1 500 kbit/s PCAN_USBBUS1','duration_s':12,'heartbeat_count':len(h),'bus_status':status,'interval_ms':{'min':min(intervals),'mean':statistics.mean(intervals),'max':max(intervals)} if intervals else None,'checks':checks,'passed':all(checks.values()),'CAN2_wire_verified':False} +(out/'results.json').write_text(json.dumps(result,indent=2));print(json.dumps(result,indent=2)) diff --git a/docs/evidence/2026-10-04/heartbeat/readback.bin b/docs/evidence/2026-10-04/heartbeat/readback.bin new file mode 100644 index 0000000..9eb76ba Binary files /dev/null and b/docs/evidence/2026-10-04/heartbeat/readback.bin differ diff --git a/docs/evidence/2026-10-04/heartbeat/readback.log b/docs/evidence/2026-10-04/heartbeat/readback.log new file mode 100644 index 0000000..b378189 --- /dev/null +++ b/docs/evidence/2026-10-04/heartbeat/readback.log @@ -0,0 +1,29 @@ + ------------------------------------------------------------------- + STM32CubeProgrammer v2.20.0 + ------------------------------------------------------------------- + +ST-LINK SN : 37FF71064E573436188C1543 +ST-LINK FW : V2J47S7 +Board : -- +Voltage : 3.27V +SWD freq : 950 KHz +Connect mode: Hot Plug +Reset mode : Software reset +Device ID : 0x467 +Revision ID : Rev Z +Device name : STM32G0B0xx/B1xx/C1xx +Flash size : 128 KBytes +Device type : MCU +Device CPU : Cortex-M0+ +BL Version : 0x92 + + +UPLOADING ... + File : D:\YMR\AMI\docs\evidence\2026-10-04\heartbeat\readback.bin + Size : 16528 Bytes + Address: : 0x8000000 +Read progress: +±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± 0% ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ 100% + +Data read successfully +Time elapsed during read operation is: 00:00:00.262 diff --git a/docs/evidence/2026-10-04/heartbeat/results.json b/docs/evidence/2026-10-04/heartbeat/results.json new file mode 100644 index 0000000..eb55144 --- /dev/null +++ b/docs/evidence/2026-10-04/heartbeat/results.json @@ -0,0 +1,24 @@ +{ + "firmware_bytes": 16528, + "sha256": "e97ec2fb3384e4bad0980017c65360f7d615dc9e716038af4445da43892f2b6e", + "flash_readback_identical": true, + "bus": "CAN1 500 kbit/s PCAN_USBBUS1", + "duration_s": 12, + "heartbeat_count": 121, + "bus_status": 0, + "interval_ms": { + "min": 99.95199996046722, + "mean": 100.09439166654677, + "max": 100.17999995034188 + }, + "checks": { + "enough_frames": true, + "bus_ok": true, + "format": true, + "sequence_contiguous": true, + "uptime_100ms": true, + "wire_period_95_to_105ms": true + }, + "passed": true, + "CAN2_wire_verified": false +} \ No newline at end of file diff --git a/firmware/Core/Inc/ami_protocol.h b/firmware/Core/Inc/ami_protocol.h index 219d542..c5719c4 100644 --- a/firmware/Core/Inc/ami_protocol.h +++ b/firmware/Core/Inc/ami_protocol.h @@ -15,6 +15,8 @@ #define AMI_CAN_ID_BMS_EXTREMES_EXT 0x186140F3UL /* AMI task requests are not ASSI commands; no SDC mapping is defined. */ #define AMI_CAN_ID_TASK_REQUEST 0x300U +#define AMI_CAN_ID_HEARTBEAT 0x301U +#define AMI_HEARTBEAT_PERIOD_MS 100U #define AMI_CAN_DATA_TIMEOUT_MS 500U #define AMI_ADC_TIMEOUT_MS 1500U diff --git a/firmware/Core/Src/ami_app.c b/firmware/Core/Src/ami_app.c index 75b0d52..d102478 100644 --- a/firmware/Core/Src/ami_app.c +++ b/firmware/Core/Src/ami_app.c @@ -537,6 +537,47 @@ static void SendPendingTask(void) } } +static void SendHeartbeat(void) +{ + static uint32_t last_tx_ms; + static uint16_t sequence; + uint32_t now = HAL_GetTick(); + FDCAN_TxHeaderTypeDef header = {0}; + uint8_t data[8]; + + if ((uint32_t)(now - last_tx_ms) < AMI_HEARTBEAT_PERIOD_MS) + { + return; + } + /* Skip missed periods instead of generating a catch-up burst. */ + last_tx_ms = now; + data[0] = 1U; /* Protocol version. */ + data[1] = 0U; /* Reserved. */ + data[2] = (uint8_t)sequence; + data[3] = (uint8_t)(sequence >> 8); + data[4] = (uint8_t)now; + data[5] = (uint8_t)(now >> 8); + data[6] = (uint8_t)(now >> 16); + data[7] = (uint8_t)(now >> 24); + ++sequence; + + header.Identifier = AMI_CAN_ID_HEARTBEAT; + header.IdType = FDCAN_STANDARD_ID; + header.TxFrameType = FDCAN_DATA_FRAME; + header.DataLength = FDCAN_DLC_BYTES_8; + header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + header.BitRateSwitch = FDCAN_BRS_OFF; + header.FDFormat = FDCAN_CLASSIC_CAN; + header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; + + /* CAN1 (500 kbit/s) only; reserve one FIFO slot for task requests. + A busy port skips this period; no software backlog or blocking retry. */ + if (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) > 1U) + { + (void)HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &header, data); + } +} + static void UpdateTimeoutsAndLeds(void) { static uint32_t last_heartbeat_ms; @@ -720,6 +761,7 @@ void AMI_App_Service(void) uint32_t now = HAL_GetTick(); SendPendingTask(); + SendHeartbeat(); UpdateTimeoutsAndLeds(); /* The HMI may reboot/reconnect after the MCU has already sent its state. */ if ((now - last_screen_sync_ms) >= AMI_SCREEN_RESYNC_MS) diff --git a/firmware/README.md b/firmware/README.md index 8a5f8a9..235af7e 100644 --- a/firmware/README.md +++ b/firmware/README.md @@ -1,5 +1,7 @@ # AMI 主控固件 +2026-10-04:新增 AMI `0x301` 标准心跳帧(DLC 8),仅 CAN1(500 kbit/s)100 ms 一次,CAN2 不发送心跳,包含版本、uint16 序号和 uint32 运行毫秒值,小端。源码和 DBC 已更新,已烧录并全量回读一致;CAN1 实测 121 帧,间隔 99.952~100.180 ms。完整定义见 [DBC 说明](../docs/AMI_CAN_DBC说明.md)。 + 这是 `AMI.HMI` 配套的 STM32 HAL 固件。目标器件按 **STM32G0B1CBT6(LQFP48,128 KB Flash)** 生成;ST 的 G0B1 产品线没有 `STM32G0B1C8T6`,如果实物丝印为 `STM32G0B1CCT6` 或 `STM32G0B1CET6`,引脚及应用代码兼容,只需在 CubeMX 中切换具体料号后重新生成。 ## 引脚与外设 diff --git a/output/pdf/AMI_CAN报文说明.pdf b/output/pdf/AMI_CAN报文说明.pdf index 26969ed..ebf7b39 100644 Binary files a/output/pdf/AMI_CAN报文说明.pdf and b/output/pdf/AMI_CAN报文说明.pdf differ diff --git a/scripts/export_can_pdf.py b/scripts/export_can_pdf.py index cd057c1..6fc1458 100644 --- a/scripts/export_can_pdf.py +++ b/scripts/export_can_pdf.py @@ -127,7 +127,7 @@ def export(font_path): canvas.line(40, 31, page_width-40, 31) canvas.setFont('AMIChinese', 8) canvas.setFillColor(colors.HexColor('#506775')) - canvas.drawString(40, 19, 'AMI-2.4 | 2026-10-03 | CAN1 500K / CAN2 250K') + canvas.drawString(40, 19, 'AMI-2.5 | 2026-10-04 | CAN1 500K / CAN2 250K') canvas.drawRightString(page_width-40, 19, f'{doc.page}') canvas.restoreState() @@ -136,7 +136,7 @@ def export(font_path): leftMargin=40, rightMargin=40, topMargin=36, bottomMargin=44, title='AMI CAN 报文说明', author='AMI / YMR', - subject='AMI CAN DBC v2.4: CAN1 500K / CAN2 250K') + subject='AMI CAN DBC v2.5: CAN1 500K / CAN2 250K') document.build(story, onFirstPage=footer, onLaterPages=footer) print(OUTPUT) diff --git a/scripts/export_dbc_docs.py b/scripts/export_dbc_docs.py index d9a81e9..740bc97 100644 --- a/scripts/export_dbc_docs.py +++ b/scripts/export_dbc_docs.py @@ -1,5 +1,6 @@ """Generate the Chinese handoff document directly from AMI.dbc.""" import argparse +import re from pathlib import Path import cantools @@ -20,9 +21,15 @@ def can2_dbc_text(): ]: assert old in text, old text = text.replace(old, new) - return text + text = re.sub(r'BO_ 769 AMI_Heartbeat:.*?(?=BO_)', '', text, flags=re.S) + text = '\n'.join(line for line in text.splitlines() + if not line.startswith(('CM_ BO_ 769 ', 'BA_ "GenMsgCycleTime" BO_ 769 '))) + text = text.replace('AMI heartbeat is standard 0x301 every 100 ms on CAN1 only.', + 'AMI heartbeat 0x301 is CAN1 only and is not included in this CAN2 file.') + return text.rstrip() + '\n' PURPOSE = { + 0x301: 'AMI -> VCU(仅 CAN1):版本、序号、运行时间', 0x183: 'VCU -> AMI:实际当前任务、锁定状态、EBS 状态', 0x182: 'VCU / 测试器 -> AMI:扭矩千分、电机温度、MCU 温度', 0x300: 'AMI -> VCU:用户确认后的任务选择请求', @@ -51,16 +58,16 @@ def render(): '| --- | --- | --- | --- |', '| CAN1 | 500 kbit/s | PA11 / PA12 | [AMI.dbc](../AMI.dbc) |', '| CAN2 | 250 kbit/s | PB0 / PB1 | [AMI_CAN2_250k.dbc](../AMI_CAN2_250k.dbc) |', '', - 'DBC 的 `Baudrate` / `AMIPort` 分别标注所属总线。每份 DBC 均含 12 条报文、49 个信号;' - '同一份报文表适用于两路。CAN 工具必须按接入端口设置速率,导入 DBC 不一定自动改硬件速率。' + 'DBC 的 `Baudrate` / `AMIPort` 分别标注所属总线。CAN1 DBC 含 13 条报文、53 个信号;CAN2 DBC 含 12 条报文、49 个信号;' + '仅 CAN1 包含 0x301 心跳,其余报文布局相同。CAN 工具必须按接入端口设置速率,导入 DBC 不一定自动改硬件速率。' '实际接法:SDC 500 kbit/s 接 CAN1,BMS 250 kbit/s 接 CAN2。', '', 'FDCAN 时钟 64 MHz,时钟分频为 1;NominalPrescaler 为 CAN1=8、CAN2=16,' '两路均使用 Sync=1、TimeSeg1=13、TimeSeg2=2、SJW=1。' '速率 = 64 MHz / Prescaler / (1+13+2);采样点 = (1+13)/16 = 87.5%。', '', - '本 DBC 包含 AMI 唯一发送的 `0x300` 任务请求,以及 AMI 当前识别的 SDC / BMS 和自定义显示输入。' + '本 DBC 包含 AMI 发送的 `0x300` 任务请求和 `0x301` 周期心跳,以及 AMI 当前识别的 SDC / BMS 和自定义显示输入。' 'SDC `0x6A3` DAC 控制、`0x6A5` ASSI 控制、BMS 其他电芯/故障字段不属于此接口子集。' '`0x182` 新增扭矩千分、电机温度和电机控制器 MCU 温度的仪表显示输入;' - '发送者负责转换实际电机控制器协议。`0x183` 为新增 VCU 状态反馈,需 VCU 按此自定义接口发送;未定义标定后的车速或 AMI 周期心跳。' + '发送者负责转换实际电机控制器协议。`0x183` 为新增 VCU 状态反馈,需 VCU 按此自定义接口发送;未定义标定后的车速。' '旧 `0x180 / 0x181 / 0x280` 输入已停用。', '', 'SDC 字段依据 `SDC_ACQ_DAC.dbc` VERSION 1.1,保持其信号名、位布局、缩放和单位;' '仅将输入接收节点设为 AMI。BMS 字段依据 ' @@ -69,6 +76,7 @@ def render(): 'DBC 为 ASCII 编码,注释和枚举使用英文,便于导入 CAN 工具;本文为 UTF-8 中文。' '物理值 = 原始值 × Factor + Offset;`0x182` 的三个数值为有符号 int16,其他数值按表定义。' '下表范围为接口允许范围,不表示车辆正常工作范围。', '', + '## AMI 周期心跳 0x301\n\n2026-10-04 新增:标准 ID `0x301`、Classic CAN 数据帧、DLC 8。仅 CAN1(500 kbit/s)每 **100 ms** 尝试发送,CAN2 不发送心跳,不依赖接收活动或屏幕连接。首帧在启动约 100 ms 后发送。\n\n| 字节 | 含义 |\n| --- | --- |\n| 0 | 协议版本,固定 1 |\n| 1 | 保留,固定 0 |\n| 2..3 | uint16 小端心跳序号,首帧 0,每个调度周期加 1,65535 后回到 0 |\n| 4..7 | uint32 小端 `HAL_GetTick()` 运行时间,单位 ms,自然回绕 |\n\n例如运行 100 ms 的首帧:`01 00 00 00 64 00 00 00`。任务请求先处理,心跳仅在发送 FIFO 至少有两个空位时入队,为任务保留一个空位;忙或入队失败时跳过本周期,不在软件中积压或补发。硬件自动重传仍启用,已入硬件 FIFO 的帧可能延迟到总线恢复后发出。100 ms 为主循环调度周期,实际总线时刻受仲裁/错误重传影响。序号按调度递增,因此丢帧时可以跳号。\n\n仅表示 AMI 主循环运行,不表示屏幕、VCU 或车辆状态正常。2026-10-04 已烧录并全量回读一致;CAN1 抓取 121 帧,间隔 99.952~100.180 ms,序号连续,详见 [心跳测试报告](AMI心跳测试报告.md)。CAN2 未接线抓帧。\n\n', '## 报文总览', '', '| CAN ID | 类型 | DLC | 报文名 | 方向和作用 | 周期 / 触发 |', '| --- | --- | --- | --- | --- | --- |', @@ -82,7 +90,7 @@ def render(): '', '扩展帧在 DBC 的 `BO_` 十进制 ID 中设置 bit31:' '`0x186040F3 -> 2556444915`,`0x186140F3 -> 2556510451`。' 'CAN 工具中使用实际 29 位仲裁 ID 并选择扩展帧;bit31 不是总线上发送的仲裁 ID。', '', - '`GenMsgCycleTime` 填写已确认的 SDC 周期 100 / 500 / 20 ms,以及自定义 `0x182` 的约定周期 100 ms。' + '`GenMsgCycleTime` 填写已确认的 SDC 周期 100 / 500 / 20 ms,以及 `0x182`、`0x183` 和 `0x301` 的约定周期 100 ms。' '其余帧未填写周期,默认 0 表示未指定,不据此推断 BMS 周期。', '', '## 信号布局', '', 'Start 为 DBC 起始位,位号从 0 开始。Intel `@1` 从最低有效位起算;' @@ -220,8 +228,8 @@ def render(): '# 若同时检出 SDC 仓库,可额外比较五条输入帧的原始布局:', 'python scripts/verify_dbc.py --sdc-dbc ../SDC_ACQ_DAC/SDC_ACQ_DAC.dbc', '```', '', - '校验覆盖严格 DBC 解析(长度、信号越界与重叠)、12 个 ID 与固件宏对应、' - '标准/扩展格式、49 个信号、发送/接收节点、SDC / 自定义帧周期、已知报文解码、' + '校验覆盖严格 DBC 解析(长度、信号越界与重叠)、13 个 ID 与固件宏对应、' + '标准/扩展格式、53 个信号、发送/接收节点、SDC / 自定义帧周期、已知报文解码、' '六个任务号与计数边界编码、大端偏置电流、无效温度枚举、全负温度和截短 DLC。' '已安装并验证 cantools 44.1.0,接口参考 [cantools 官方文档](https://cantools.readthedocs.io/en/latest/)。', '', '上述是静态及软件编解码验证,另校验两份 DBC 的速率、相同信号布局及源码 / CubeMX 位时序一致。' diff --git a/scripts/verify_dbc.py b/scripts/verify_dbc.py index 46effc3..10170bd 100644 --- a/scripts/verify_dbc.py +++ b/scripts/verify_dbc.py @@ -73,28 +73,37 @@ def main(): header = (ROOT / 'firmware/Core/Inc/ami_protocol.h').read_text(encoding='utf-8') identifiers = {int(value, 16) for value in re.findall( r'^#define\s+AMI_CAN_ID_\w+\s+(0x[\dA-Fa-f]+)', header, re.MULTILINE)} - expected = {0x182:(False,8), 0x183:(False,8), 0x300:(False,8), 0x6A0:(False,8), 0x6A1:(False,2), + expected = {0x182:(False,8), 0x183:(False,8), 0x300:(False,8), 0x301:(False,8), 0x6A0:(False,8), 0x6A1:(False,2), 0x6A2:(False,8), 0x6A4:(False,4), 0x6A6:(False,8), 0x140:(False,8), 0x156:(False,8), 0x186040F3:(True,8), 0x186140F3:(True,8)} actual = {m.frame_id:(m.is_extended_frame,m.length) for m in db.messages} assert actual == expected, actual assert set(actual) == identifiers, (actual, identifiers) - assert len(db.messages) == 12 - assert sum(len(m.signals) for m in db.messages) == 49 + assert len(db.messages) == 13 + assert sum(len(m.signals) for m in db.messages) == 53 for m in db.messages: - if m.frame_id == 0x300: + if m.frame_id in (0x300, 0x301): assert m.senders == ['AMI'] and m.receivers == {'VCU'} else: assert m.receivers == {'AMI'} assert m.senders == (['VCU'] if m.frame_id in (0x182,0x183) else ['SDC_ACQ_DAC'] if 0x6A0 <= m.frame_id <= 0x6A6 else ['BMS']) assert db.dbc.attributes['Baudrate'].value == 500000 - for ident, cycle in [(0x182,100), (0x183,100), (0x6A0,100), (0x6A1,500), (0x6A2,20)]: + for ident, cycle in [(0x301,100), (0x182,100), (0x183,100), (0x6A0,100), (0x6A1,500), (0x6A2,20)]: assert db.get_message_by_frame_id(ident).cycle_time == cycle for ident in [0x300,0x6A4,0x6A6,0x140,0x156,0x186040F3,0x186140F3]: assert db.get_message_by_frame_id(ident).cycle_time in (None,0) + assert len(db2.messages) == 12 + assert all(m.frame_id != 0x301 for m in db2.messages) + heartbeat = db.get_message_by_frame_id(0x301) + for sequence, uptime in ((0,100), (65535,4294967295), (0,0)): + values = dict(Protocol_Version=1, Reserved=0, + Heartbeat_Sequence=sequence, MCU_Uptime=uptime) + raw = bytes([1,0]) + sequence.to_bytes(2,'little') + uptime.to_bytes(4,'little') + assert heartbeat.encode(values) == raw + assert heartbeat.decode(raw) == values checks = [] def decode(ident, data): checks.append({'id':hex(ident),'data':data}) @@ -239,7 +248,7 @@ def main(): db2.decode_message(ident, payload, decode_choices=decode_choices) print(json.dumps({'result':'passed','messages':len(db.messages),'signals':sum(len(m.signals) for m in db.messages), 'known_payload_checks':len(checks),'all_task_ids_and_counter_edges':True, - 'ports_bitrate':bitrates,'both_dbc_layouts_and_payloads_match':True, + 'ports_bitrate':bitrates,'shared_dbc_layouts_and_payloads_match':True, 'heartbeat_can1_only':True, 'firmware_and_ioc_bit_timing_match':True, 'firmware_ids_match':True,'sdc_source_layout_match':source_check, 'display_sender_known_bytes_and_argument_rejection':True,