标签: panda safety

  • Nissan panda safety:总线变体锁定、转角与取消载荷

    结论:Nissan safety 的核心是「变体先见即锁定」:get_addr_check_index() 在健康检查组内第一次看到某地址/总线/长度变体后就锁定其下标,之后只匹配该变体。对 Altima,如果错误接线或额外转发让 0x285 总线 0 先于所需的总线 1 到达,该组会锁到总线 0,而车型 RX 钩子只处理总线 1,后续车速不再被识别。另一条关键边界是:不在当前锁定变体内的帧,rx_msg_safety_check() 返回 true,但 safety_rx_hook() 的 whitelisted 为假,所以「返回有效不等于已消费」。TX 侧 0x169 受共享角度限制,而 0x280 Leaf 取消帧与 HUD 帧没有逐位载荷门。

    初始化与总线变体锁定

    nissan_init() 的 ALT_EPS_BUS 参数位只切换 RX 钩子预期的车速、踏板和巡航总线,构建同一 TX 白名单。get_addr_check_index() 在组内首次匹配时设置 msg_seen 与 status.index,之后只匹配该变体;safety_rx_hook() 要求变体有效且当前仍匹配才调用车型 RX 钩子。

    nissan_rx_hook() 采样 0x185 转角、0x285 后轮速度、0x15C/0x239 油门、0x454/0x239 制动和 0x30F 原车巡航。在 ALT_EPS_BUS=1 时它从总线 1 读取 0x285、0x15C、0x454、0x30F;常规模式从总线 0 读取前三类、总线 2 读取巡航;0x185 转角始终要求总线 0。

    RX:五组健康检查与「有效不等于被消费」

    nissan_rx_checks 有五个健康检查组,各项均显式忽略校验和、计数器、质量位,仅以地址、长度、总线与名义频率/存活约束健康。

    检查组 地址 允许总线
    转角 0x185 0
    后轮速度 0x285 0/1
    巡航 0x30F 2/1
    油门 0x15C 或 Leaf 0x239 0/1 或 0
    制动/状态 0x454 或 0x1CC 0/1 或 0

    源文档强调,这不是对每个 CAN 字段做完整性认证。Leaf 0x239 总线 0 的同一帧可更新油门与制动;它被放在油门健康检查组,制动组另有 0x1CC 变体,后者未被车型 RX 钩子直接解析为 brake_pressed。因此「健康表监视的消息」与「车型钩子消费的信号」不是完全一对一。

    转角以 -0.01 度/位及偏置 1310 度解码到每度 100 单位;后轮双速取平均更新速度,任一原始后轮速度非零便视为在移动。原车巡航接合由 0x30F 输入巡航检查,其上升沿可使能、断开时退出。源文档提醒,新硬件不能将 Altima 总线、Leaf 踏板和 X-Trail 踏板归一成没有来源的旧值。

    TX:转角、按钮与 Leaf 取消载荷

    nissan_tx_hook() 对 0x169 从 CAN 位域解码目标角与 LKA_ACTIVE,用共享的转角命令检查:600 度绝对界限、随车速变化的起/退转角速率、测量角度及未使能中性状态。源文档强调这里是每度 100 原始单位,不是通用扭矩接口。对 0x20B 的附加判据只有 (data[1] & 0x3D) == 0:它禁止掩码内非取消按钮位,但不会逐位检查整帧或要求取消位必须为 1。

    TX 帧 检查强度 备注
    0x169 解码目标角与 LKA_ACTIVE,运行共享角度限制 每度 100 原始单位,不是通用扭矩接口
    0x20B 仅检查 (data[1] & 0x3D) == 0 可在总线 2 或 Altima 总线 1 发送;check_relay=false
    0x2B1、0x4CC HUD 无逐字段检查 总线 0
    0x280 Leaf 取消 无逐字段检查 总线 2;探针中非零任意测试载荷仍通过 safety TX

    软件 create_acc_cancel_cmd() 会复制原车字段并覆盖按钮;Leaf create_cancel_msg() 会把 CANCEL_SEATBELT 置位,利用原车安全带告警退出巡航。源文档指出后者是驾驶员可感知的安全/HMI 行为,不能包装成普通、静默的取消插件。软件构帧约定也不能替代 MCU 逐位门:隔离探针中 0x280 的非零任意测试载荷仍通过 safety TX。

    验证证据与插件边界

    已有测试覆盖常规与 Altima 的转角/按钮基础行为,但源文档指出 Leaf 的按钮测试被明确跳过,不能证明 0x280 的 CANCEL_SEATBELT 载荷被硬件安全规则约束。本机新增探针以严格编译和 UBSan 通过按钮掩码、0x280 无载荷门及 Altima 错误总线先到锁定序列;未运行完整车型测试、目标编译器、实板或车辆 ECU 行为。

    插件化时必须把 Nissan 平台、ALT_EPS_BUS、DBC、总线拓扑与取消方式绑定;0x280 及 HUD 原始帧应列为高权限输出,不能由任意插件直接构造。Nissan 未定义专属转发钩子,共享转发按当前 TX 表中 check_relay=true 的地址/目标总线阻断主机自身控制帧;0x20B 设置 check_relay=false,不应把它的白名单资格混同于静态阻断或原车报文真实性。

    常见问题

    为什么 Altima 的车速有时候识别不到?

    因为健康检查组先见即锁定。源文档指出,若错误接线或额外转发让 0x285 总线 0 先于 Altima 所需的总线 1 到达,该组会锁到总线 0,而车型 RX 钩子仅处理总线 1,后续总线 1 车速不会被该组识别;本机隔离探针复现了这一序列。

    健康检查通过是否说明车型已经消费了该信号?

    不说明。源文档明确:不在当前锁定变体内的帧会让 rx_msg_safety_check() 返回 true,但 safety_rx_hook() 的 whitelisted 为假,车型状态不更新,因此「返回有效不等于已消费」。

    0x280 Leaf 取消帧有逐位载荷校验吗?

    没有。源码的 TX 白名单允许总线 2 的 0x280,但 nissan_tx_hook() 对它没有逐字段检查;源文档的隔离探针显示非零任意测试载荷仍通过 safety TX,因此它应列为高权限输出。

    0x20B 的 check_relay=false 是否等于原车报文可信?

    不等于。0x20B 设置 check_relay=false,源文档提示不应把它的白名单资格混同于静态转发阻断或原车报文真实性;共享转发只按 check_relay=true 的地址与目标总线阻断主机自身控制帧。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/NISSAN_PANDA_SAFETY_MODE_DEEP_DIVE.md(取用了 RX 五组健康检查表、变体锁定语义、TX 帧检查强度表、Leaf 取消载荷与探针结果)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Chrysler panda safety:CUSW 双位按钮与两套模式矩阵

    结论:Chrysler panda safety 有两套互不通用的安全模式:常规模式按参数位选 Pacifica/Jeep、Ram DT 或调试构建中的 Ram HD,CUSW 是独立且仅调试注册的另一套钩子。最需要记住的边界是按钮载荷:常规模式以 data[0]==1 判取消、data[0]==0x10 判恢复,两个值不能同时匹配;而 CUSW 用两个独立位,表达式 is_cancel || (is_resume && controls_allowed) 使 0x11 同时置位在控制未许可时仍会通过。

    本文基于固定源码快照,分析常规 Chrysler 与独立 CUSW safety 模式,并用本机隔离探针核对若干分支。ALLOW_DEBUG 是编译条件,不等于目标 panda 固件已经启用;探针不代表刷写、台架或实车验证。

    模式入口与函数索引

    chrysler_init() 按参数位选择 RX/TX 表,Ram DT 分支优先于 Ram HD;非调试构建忽略 Ram HD 位,落入 Pacifica/Jeep 配置。CUSW 的安全模式注册受 ALLOW_DEBUG 限制,属于独立钩子。

    函数 作用与关键差异
    chrysler_init() 按参数位选 Pacifica/Jeep、Ram DT 或调试构建中的 Ram HD;Ram DT 优先于 Ram HD,非调试构建忽略 Ram HD 位
    chrysler_rx_hook() 按平台地址与总线更新 EPS 电机扭矩、ACC 接合、停车状态、油门及制动
    chrysler_tx_hook() 解码目标转向扭矩及请求位,调用共享限幅;按钮仅允许取消,或在 controls_allowed 时恢复
    chrysler_cusw_init() 建立独立的五组 RX 与三组 TX 白名单;安全模式注册受 ALLOW_DEBUG 限制
    chrysler_cusw_tx_hook() 扭矩限制为 250 原始单位;取消与恢复按钮分别取 bit 0、bit 4
    chrysler_compute_checksum() 对除末字节外的载荷按多项式 0x1D 做 CRC8,初始值 0xFF,末尾按位取反;末字节为接收校验值

    平台与信号矩阵

    四种模式的电机扭矩误差项均为 80。表内上限是 safety 内部原始单位,不是物理方向盘扭矩,也不是可直接移植的标定值。常规模式的 EPS 测量来自载荷字节 4/5,CUSW 来自字节 3/4;常规模式以 0x1F4/0x99 的 bit 21 判断 ACC,CUSW 以 0x2EC 的 bit 7。

    模式 关键 RX 来源 TX 地址、总线、长度 扭矩上限 / 每帧升降 / 实时变化
    Pacifica/Jeep EPS 0x220/bus 0;ACC 0x1F4/bus 0;车速 0x202/bus 0;油门 0x22F、制动 0x140/bus 0 按钮 0x23B/0/3;转向 0x292/0/6;HUD 0x2A6/0/8 261 / 3、3 / 112
    Ram DT EPS 0x31/bus 0;ACC 0x99/bus 2;车速 0x79/bus 0;油门 0x9D、制动 0x83/bus 0 按钮 0xB1/2/3;转向 0xA6/0/8;HUD 0xFA/0/8 350 / 6、6 / 112
    Ram HD,仅 ALLOW_DEBUG EPS 0x220/bus 0;ACC 0x1F4/bus 2;车速 0x11C/bus 0;油门 0x22F、制动 0x140/bus 0 按钮 0x23A/2/3;转向 0x276/0/8;HUD 0x275/0/8 361 / 14、14 / 182
    CUSW,仅 ALLOW_DEBUG 电机扭矩 0x1EC;ACC 0x2EC;车速 0x1E4;油门 0x1FE;制动 0x1E8,均 bus 0 按钮 0x2FA/0/3;转向 0x1F6/0/4;HUD 0x5DC/0/4 250 / 4、4 / 150

    移动判断也按平台分:Pacifica/Jeep 用左右轮速 0x202,Ram 用 ESP_8 双字节非零,CUSW 用 0x1E4 车速字段非零。健康检查方面,常规 RX 表监视五组;Pacifica/Jeep 的 0x202 特别忽略校验和与计数器,其余四组检查 CRC/计数器但忽略质量位;常规计数器为字节 6 高半字节,CUSW 计数器为倒数第二字节低半字节。CRC/计数健康不等于报文来源认证,总线身份、线束和原车 ECU 时序仍需单独验证。

    按钮载荷与转发边界

    常规按钮帧以 data[0] == 1 判断取消,以 data[0] == 0x10 判断恢复,因此两值不能同时匹配,但其它字节没有车型专属检查。CUSW 以两个独立位判断,表达式 is_cancel || (is_resume && controls_allowed) 使 0x11 同时置位在控制未许可时仍通过。

    项目 常规模式 CUSW
    取消判定 data[0] == 1 bit 0
    恢复判定 data[0] == 0x10 bit 4
    双位组合 两值互斥,组合无法同时匹配 0x11 在控制未许可时仍通过
    测试覆盖 明确测试组合被拒 测了中性、单独取消/恢复,未断言双位组合

    各模式的 HUD 地址在 TX 白名单,但两套车型 TX 钩子都没有 HUD 载荷检查。转向与 HUD 的 check_relay=true 会参与共享继电器故障检查和来自 bus 2 的静态转发阻断;按钮的 check_relay=false 不具备这两项效果。

    转发边界的判定要分三步:safety_tx_hook() 先做通用地址/总线/长度白名单与继电器故障门,再由车型钩子做载荷判定,而来自另一总线的静态转发阻断由 safety_fwd_hook() 处理。因此「能不能发」与「会不会阻断原车转发」是两个独立问题,不能只看白名单。

    两套测试的口径也不同:现有 test_chrysler_cusw.py 测了中性、单独取消或恢复,但没有断言双位组合;常规 test_chrysler.py 则明确测试组合被拒。这一差异是现有钩子行为,不应当视作车辆接受或设计允许组合键。

    软件层与固件层不是同一件事

    软件 CarInterface._get_params() 把 Ram HD 与 CUSW 标为 dashcamOnly,CUSW 另选 chryslerCusw 模式;其 CarControllerParams 还设置软件侧限幅与周期。尤其 Ram DT 软件上限为 261,而板端限值为 350,说明软件策略和固件许可不是同一层。

    自制硬件插件不能把 dashcamOnly、软件限幅或模式参数当作板端已经正确配置的回执。插件化时应把平台指纹、DBC、总线映射、safety 模式/参数、编译能力与线束版本作为不可分割的准入清单。HUD 与按钮原始帧均须列为受控输出,普通 UI/诊断插件不能绕过 card 和板端安全层直接发送。

    本机隔离探针在 release/debug 两种 ALLOW_DEBUG 编译条件下均以 -Wall -Wextra -Werror 与 UBSan 通过,覆盖平台按钮总线、Ram HD 非调试回退、CUSW 非调试不可注册、CUSW 双位组合、HUD 无逐字段门及静态转发阻断。它没有输入有效 RX 序列、验证 CRC 错误/计数回绕或执行完整车型测试;更不代表目标固件、台架或实车。

    常见问题

    CUSW 模式和常规 Chrysler 模式能混用吗?

    不能。CUSW 是独立钩子,拥有自己的五组 RX 与三组 TX 白名单、独立的扭矩编码与限值,且安全模式注册受 ALLOW_DEBUG 限制;常规模式的地址、总线、长度与按钮位都不能按品牌名复用。

    Ram HD 在普通构建里会怎样?

    非调试构建会忽略 Ram HD 位,落入 Pacifica/Jeep 配置;而且 Ram DT 分支优先于 Ram HD。所以不是「选了 Ram HD 位就一定按 Ram HD 配置」,还要看构建条件与优先级。

    为什么 CUSW 的 0x11 组合键仍能通过?

    因为 CUSW 用两个独立位判断,表达式为 is_cancel || (is_resume && controls_allowed),只要有取消位就通过,所以 0x11 在控制未许可时仍会通过。常规模式则因两值互斥无法同时匹配,且测试明确覆盖组合被拒。这是现有钩子行为,不应视作车辆接受或设计允许组合键。

    HUD 地址在白名单里,是不是就有逐字段校验?

    不是。各模式的 HUD 地址在 TX 白名单,但两套车型 TX 钩子都没有 HUD 载荷检查。白名单控制的是地址、总线、长度,并受继电器故障门约束,不等于载荷逐字段校验。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/CHRYSLER_PANDA_SAFETY_MODE_DEEP_DIVE.md(取用了常规与 CUSW 两套模式矩阵、按钮载荷差异、平台信号表与隔离探针结论)。
    • 项目 02 —— openpilot-research/ACTUATION_GATE_CHAIN_DEEP_DIVE.md(仅用于确认执行链分层语义,未取用其未公开内容)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • GM panda safety:三个参数位切换拓扑,白名单不等于字段认证

    结论:GM panda safety 按 HW_CAM、HW_CAM_LONG、EV 三个参数位切换硬件拓扑与 TX 表,三者的使能与转发策略互不相同:ASCM 分支 disable_forwarding=true 完全禁转发、由按钮沿使能;相机原车纵向跟随 PCM;相机自控纵向仅在调试构建且 HW_CAM_LONG 置位时才把 gm_pcm_cruise 改为假。白名单只控制 CAN 地址、总线、长度,不代表所有字段都经安全认证。

    本文基于固定源码快照逐函数静态解析 opendbc/safety/modes/gm.h,结合通用 safety 分发与本机原版 GM 测试。未编译目标固件或接入车辆;这里的总线号、编码和阈值仅适用于该源码快照及匹配车型,不能直接当作新硬件配置。

    RX:来源、使能与完整性缺口

    GM_COMMON_RX_CHECKS 监视总线 0 的 0x184 驾驶员扭矩、0x34A 后轮速度、0x1E1 按钮、0xBE 踏板、0x1C4 油门/巡航和 0xC9 制动状态;0xBE 允许三种长度以适配不同车型。各项暂以 10 Hz 标称检查,且显式忽略校验和、计数器、质量位——源码 TODO 指出这不是完整报文完整性校验。EV 参数位另把 0xBD 再生制动消息纳入 RX 表,频率配置为 40 Hz。

    报文 用途 完整性处理
    0x184 驾驶员扭矩(11 位有符号,进共享采样窗口) 忽略校验和/计数器/质量位
    0x34A 后轮双速;两轮原始速度均不超过 10 判静止 停车判据,不是完整车速估计
    0x1E1 按钮沿使能(ASCM 用 SET 松开沿或 RESUME 按下沿) 忽略完整性字段
    0xBE ASCM 刹车(字节阈值);允许三种长度 与相机刹车帧 0xC9 不是同义来源
    0x1C4 相机原车纵向读取巡航接合状态 走 pcm_cruise_check()
    0xC9 相机刹车(bit 40) 与 0xBE 不能互换
    0xBD EV 再生制动,仅 EV 参数位置位时入 RX 表 配置为 40 Hz

    safety_rx_hook() 只在检查通过、命中表后调用 gm_rx_hook(),因此再生制动分支并非在非 EV 模式下无条件接收。ASCM 以 0x1E1 的 SET 松开沿或 RESUME 按下沿使能,CANCEL 按下退出;相机原车纵向则从 0x1C4 读取巡航接合状态。

    TX 与模式矩阵

    GM 自控纵向时 gm_pcm_cruise=false;相机原车纵向时为 true。相机自控纵向仅在调试构建且 HW_CAM_LONG 位置位时把它改为假。这决定使能来自按钮沿还是 PCM,影响告警与执行权限,不只是 TX 白名单的变化。

    模式 纵向 TX 转发与使能
    ASCM,HW_CAM=0 0x2CB 位于总线 0,0x315 位于总线 2;另有观测/keepalive 帧 disable_forwarding=true,由按钮沿使能
    相机,默认或 release 无 0x2CB/0x315;0x1E1 总线 2 仅允许取消 跟随 PCM 巡航接合,仍可发横向 0x180
    相机,ALLOW_DEBUG 且 HW_CAM_LONG=1 0x2CB/0x315 总线 0 改用按钮沿,禁原车 0x1E1 TX
    上述模式叠加 EV 不改变所选 TX 表 仅增加 0xBD 再生制动 RX

    gm_tx_hook() 对 0x180 调用共享扭矩安全检查,含 300 原始单位上限、变化率、驾驶员扭矩与实时增量限制。0x315 的 12 位原始编码先反转为非负制动量,再用 longitudinal_brake_checks() 限制到 max_brake=400 且未使能时必须为零。0x2CB 将油门/再生制动信号偏移到整数域后分别按 ASCM/相机限值检查,apply 位在 controls_allowed=false 时禁止。相机原车纵向的 0x1E1 只有原车巡航已接合且按钮编码为 CANCEL 时放行。

    白名单不等于字段认证

    并非所有 GM 白名单帧都有逐信号检查:例如 ASCM 的 keepalive/观测帧和相机的 0x184 状态帧,在 gm_tx_hook() 中没有对应载荷分支。白名单控制的是 CAN 地址、总线、长度。

    转发层面同样分层:相机模式中 0x184 总线 2 的 check_relay=true 会使共享转发逻辑阻断来自总线 0、目标为总线 2 的同地址帧;ASCM 则完全禁转发。应把「是否允许发」「是否阻断原车转发」「是否检测原车 ECU」分别建模。

    验证范围与插件边界

    test_gm.py 有 ASCM、相机、EV、相机自控纵向测试类,包含按钮、踏板、扭矩/纵向限值和点火用例。本机运行原版 GM 模块测试为 Ran 192 tests、OK (skipped=19),即 173 项执行且通过,19 项未执行。跳过项来自无 _user_regen_msg 的通用再生制动用例、无第二车速消息的通用检查,以及四个抽象基类的 setUpClass,不能计入通过。

    测试调用 libsafety_py._build_libsafety() 默认加 ALLOW_DEBUG,因此相机自控纵向用例不能证明 release 固件接受 HW_CAM_LONG。本机另用严格警告把测试库 safety.c 分别编译为不含/含 ALLOW_DEBUG 的目标文件,只在后者找到 GM_CAM_LONG_TX_MSGS——这核对的是本机编译分支,不是 STM32 固件或运行时许可。实板转发、实际 CAN 来源和目标 ECU 响应仍未测试。

    • 自制硬件的 GM 插件契约应固定车型/DBC、ASCM 或相机接线、EV 位、总线号、固件构建类型和 safetyParam。
    • 只读采集和回放先验证 0xBE 长度变体、0xC9 刹车、0xBD 再生制动、按钮沿、PCM 巡航及 0x184 驾驶员扭矩。
    • 台架再做丢帧、重放、错总线、故障继电器和 release/debug 差异。
    • 普通插件只产生候选控制,不能设置安全钩子或绕过板端 TX/转发判定。

    常见问题

    GM 白名单里的帧都经过字段级安全检查吗?

    不是。白名单只控制 CAN 地址、总线、长度;ASCM 的 keepalive/观测帧和相机的 0x184 状态帧在 gm_tx_hook() 中没有对应载荷分支,不能据此声称所有字段都经过安全认证。

    相机自控纵向在 release 固件里能用吗?

    测试不能证明。相机自控纵向仅在调试构建且 HW_CAM_LONG 位置位时把 gm_pcm_cruise 改为假;而测试默认加 ALLOW_DEBUG,本机只在含该宏的目标文件里找到 GM_CAM_LONG_TX_MSGS,这核对的是编译分支而非运行时许可。

    ASCM 和相机的刹车帧可以互换吗?

    不能。ASCM 的刹车取 0xBE 字节阈值,相机刹车取 0xC9 的 bit 40,切换拓扑时不能把两种刹车帧视为同义来源;0xBE 还允许三种长度以适配不同车型。

    GM 的 RX 完整性与校验和有关系吗?

    没有做完整校验。各项暂以 10 Hz 标称检查,且显式忽略校验和、计数器、质量位;源码 TODO 指出这不是完整报文完整性校验。所以「命中 RX 表」不等于「报文完整可信」。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/GM_PANDA_SAFETY_MODE_DEEP_DIVE.md(取用了 GM 三参数位模式矩阵、RX/TX 与转发边界、白名单不等于字段认证,以及本机测试计数)。
    • 项目 02 —— openpilot-research/ACTUATION_GATE_CHAIN_DEEP_DIVE.md(仅用于确认执行链分层语义,未取用其未公开内容)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Subaru Global safety:0x221 只允许取消,纵向不放行

    结论:Subaru Global safety 的 TX 权限极窄:转向帧 0x122 受扭矩与请求位门约束,而 0x221 ES_Distance 只允许取消——任何非 inactive_gas=1818 的 Cruise_Throttle 或未设置 Cruise_Cancel 都被拒,主动油门、制动或巡航 RPM 命令一律不放行。该快照下 alphaLongitudinalAvailable=False,不能因限值结构存在就向插件授予纵向执行权限。

    本文依据固定源码快照的 subaru.h、车型接口和相邻安全测试做静态分析,不证明目标固件、线束、ECU 或实车安全。本文覆盖 Global 模式;它与 Preglobal 是不同安全钩子,能力不能互相继承。

    模式与总线矩阵:Gen2 只搬了三组 RX

    Global 选择 subaru 安全模式,Gen2 额外设置 GEN2 参数。subaru_init() 按 Gen2 标志选择两组 RX/TX 总线表,没有纵向 TX 表分支。一个常见误解是「Gen2 把全部 RX 移到 bus 1」——实际只有轮速、制动、巡航三组从 bus 0 改到 bus 1,油门与驾驶员扭矩仍留在 bus 0。

    报文职责 Gen1 Gen2 钩子使用
    0x40 油门、0x119 驾驶员扭矩 RX bus 0 bus 0 两代相同
    0x13A 轮速、0x13C 制动、0x240 巡航 RX bus 0 bus 1 Gen2 的 alt bus 影响这三组,不能把全部 RX 一起移到 bus 1
    0x122 ES_LKAS TX bus 0 / 8 字节 bus 0 / 8 字节 两代均检查扭矩与请求位
    0x221 ES_Distance TX bus 0 / 8 字节 bus 1 / 8 字节 均只允许取消,Cruise_Throttle=1818
    0x321/0x322/0x323 HUD TX bus 0 / 8 字节 bus 0 / 8 字节 白名单与继电器检查;无本模式逐字段校验

    五组 RX 均要求 8 字节、8 位累加校验、四位计数器和存活检查;声明频率依次为油门 100 Hz、扭矩 50 Hz、轮速 50 Hz、制动 50 Hz、巡航 20 Hz。这些频率用于健康检查,不等于每帧独立实时截止时间。subaru_get_checksum()、subaru_get_counter()、subaru_compute_checksum() 定下字节 0 存校验和、字节 1 低四位为计数器;校验值为地址两字节加字节 1 起的数据之和并截断为 8 位。

    校验与计数器:一个已知的盲点

    一个值得写进契约盲点的现象来自离线探针:把已打包 0x221 帧的字节 4 异或 0xFF、保持原校验字节不变,两代仍能通过 TX 钩子。这说明该数据字节及由此产生的校验和失配不在本模式的 TX 专属检查内。需要强调边界:这不意味着 ECU 会接受畸形帧,只是固件这一层没有拦。

    项目 规则 边界
    校验和 字节 0 存校验和;地址两字节加字节 1 起数据求和截断为 8 位 8 位累加,非通用 CRC
    计数器 字节 1 低四位 四位回绕,配合存活检查
    TX 校验盲点 改字节 4 保持原校验字节仍可通过 TX 钩子 不在本模式 TX 专属检查内,不代表 ECU 接受

    转向、纵向与转发边界

    subaru_tx_hook() 对 0x122 解码 13 位有符号转向扭矩并反转符号,检查请求位。Gen1 最大扭矩 2047、上升/下降分别 50/70;Gen2 为 1000、40/40。两代共用实时差 940、驾驶员余量 60、倍数 50,以及至少 7 帧有效请求、最多 1 帧无效请求和 144 ms 最小间隔的容忍配置。这些是固件限值,不等于主机控制器一定按相同步长构帧。

    纵向一侧,源码定义了较多 SUBARU_LONG_LIMITS 字段,但当前 TX 钩子只在 0x221 读取其 inactive_gas=1818,没有放行主动油门、制动或巡航 RPM 命令。与之对应,接口显式关闭自控纵向能力。

    同时,两代的 0x122 与 HUD TX 均标 check_relay=true,若本机发送总线出现同地址原车帧,可触发共享继电器故障;0x221 为 check_relay=false。该模式无专属 fwd 钩子,通用转发只在 bus 0 与 bus 2 之间;Gen2 的 bus 1 不是该转发对。不能只看上层相机/网关接线位置就假定 0x221 已被正确转发或替代。

    状态侧,subaru_rx_hook() 对 0x119 读取 11 位驾驶员扭矩并反转符号;轮速解析四轮 13 位原始值,只要任一非零即认为移动,并以均值形成速度。通用 RX 门继续处理踏板退出。

    验证与插件准入

    三项原钩子离线探针用真实 DBC 打包 0x221 取消帧并调用编译版 safety_tx_hook():Gen1 仅 bus 0、Gen2 仅 bus 1 可通过;取消位缺失或油门从 1818 变为 1819 都被拒。相邻 test_subaru.py 覆盖 Gen1/Gen2 扭矩、请求位及取消帧;本机运行该模块 64 项,12 项跳过,其余通过。

    • 身份插件需证明 Global Gen1/Gen2、DBC 和物理总线布局;Preglobal、Hybrid、角度 LKAS 的能力不能继承本模式推断。
    • 车辆输入插件保留五组 RX 的来源与时间戳;Gen2 特别区分 bus 0 的油门/扭矩与 bus 1 的轮速/制动/巡航。
    • 控制插件只提交转向意图和受限取消请求;安全模式读回、CRC/计数、继电器、失联降级仍由独立 MCU/网关裁决。
    • 验证需覆盖错总线、校验/计数故障、巡航边沿、驾驶员反扭矩、请求位切断、0x221 非活动油门和 HUD 载荷,再进入台架与受控场地。

    HUD 三帧仅做通用地址/总线/长度白名单及继电器检查,未在本模式限制载荷字段。自制硬件应把这些帧的构造权留给可信任网关,限制模板与发送节拍,避免普通插件直接写原始 CAN。当前无目标板或实车验证。

    常见问题

    Subaru Global 支持自控纵向吗?

    不支持。该快照下 alphaLongitudinalAvailable=False,普通参数路径不会启用自控纵向;subaru_init() 也没有纵向 TX 表分支。当前 TX 钩子只在 0x221 读取 inactive_gas=1818,任何非该值的 Cruise_Throttle 或未设置 Cruise_Cancel 都被拒。

    Gen2 是把所有 RX 都移到 bus 1 吗?

    不是。Gen2 只把轮速、制动、巡航三组从 bus 0 改到 bus 1,油门与驾驶员扭矩仍留在 bus 0。不能把全部 RX 一起移到 bus 1,否则会读错来源。

    改了 0x221 的数据字节还能通过 TX 钩子,是不是说明固件有漏洞?

    该数据字节及由此产生的校验和失配不在本模式的 TX 专属检查内,所以按探针做法仍能通过 TX 钩子;但这不等于 ECU 会接受畸形帧。这里应把它写成契约盲点,而不是定性为整车级缺陷。

    为什么不能只按接线位置判断 0x221 是否被转发?

    因为该模式没有专属 fwd 钩子,通用转发只在 bus 0 与 bus 2 之间,Gen2 的 bus 1 不是该转发对;而 0x221 的 check_relay=false。只看上层相机/网关接线位置,无法推断 0x221 已被正确转发或替代。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/SUBARU_GLOBAL_PANDA_SAFETY_DEEP_DIVE.md(取用了 Global Gen1/Gen2 总线矩阵、TX 取消帧约束、转向限值与三项离线探针结论)。
    • 项目 02 —— openpilot-research/SUBARU_PREGLOBAL_PANDA_SAFETY_DEEP_DIVE.md(仅用于确认 Preglobal 是不同安全钩子、能力不可继承)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Tesla panda 安全模式:Autopark 优先与选择性转发矩阵

    结论:Tesla panda 安全模式的优先级不是「谁能发」而是「谁优先」:启动时先假定 Autopark/Summon 活跃并拒绝所有主机 Tesla 候选帧;原车 LKAS 锁存时把 0x488 从主机 TX 切回原车透传;原车 AEB 活跃时恢复 0x2B9 透传并拒绝主机取消帧。因此「白名单里有某地址」不等于该地址的每个字段都经过逐信号安全校验。

    RX 完整性:9 类监视帧与校验

    tesla_model3_y_rx_checks 含 9 类帧:相机总线 2 的 0x2B9/0x488,主总线 0 的 DI 速度、ESP 第二车速、EPAS 状态、油门、刹车、DI 巡航/Autopark 和 UI 警告。各自配置地址、长度、名义频率及计数上限;仅 ESP 轮速和刹车未忽略质量位。UI 警告进入通用 RX 健康监控,但 tesla_rx_hook() 并无对应的状态提取分支。

    共享 safety_rx_hook() 先验证校验/计数/质量位,再对命中且有效的帧运行车型钩子;坏 RX 帧不可当作有效的原车 AEB/LKAS 状态更新。校验按地址选择校验字节,计算地址两字节与其它载荷字节的 8 位和。

    函数 责任
    tesla_get_counter() 按地址从不同字节/位域取得 3 或 4 位计数器。
    tesla_get_checksum_byte()、tesla_get_checksum()、tesla_compute_checksum() 按地址选择校验字节,计算地址两字节与其它载荷字节的 8 位和。
    tesla_get_quality_flag_valid() 0x155 ESP 轮速质量位必须为 1;0x145 制动状态不能为未初始化或故障编码。
    tesla_rx_hook() 更新角度/接管、DI/ESP 双车速、踏板、巡航、Autopark、原车 AEB/LKAS 锁存。
    tesla_init() 选择默认或调试纵向 TX 表,重置原车辅助状态,并在启动时先假定 Autopark/Summon 活跃。

    原车状态锁存:Autopark、LKAS 与 AEB 的上升沿

    tesla_rx_hook() 的 DI 主车速与 0x155 ESP 第二车速按不同原始编码解码;后者经 speed_mismatch_check() 比较,差超过 2 m/s 时撤销控制许可。0x370 EPAS 角度进入采样窗口;高等级手握或特定高角速度故障置 steering_disengage,由共享接管逻辑消费。两速度帧及 EPAS 帧异步到达,静态代码不保证共时。

    0x286 的 Autopark 活跃编码包括 3、4、9;只有在原车巡航未接合的上升沿才锁存 tesla_autopark,状态退出时清除。随后的原车巡航状态须再与 !tesla_autopark 合取后送 pcm_cruise_check()。0x488 相机报文仅在自身 LKAS 状态上升沿且 controls_allowed=false 时锁存原车 LKAS;状态消失时清除。0x2B9 相机报文的 AEB 活动位则直接更新 tesla_stock_aeb。插件必须保留三种原车状态的来源、有效性和时间信息,不可只发布合并后的「辅助驾驶占用」布尔量。

    TX 与转发优先级矩阵

    条件 主机 TX 相机总线 2 到主总线 0
    初始化后尚未收到解除 Autopark 的 0x286,或锁存的 Autopark 活跃 tesla_tx_hook() 拒绝所有 Tesla 候选帧 车型动态钩子不阻断 0x488/0x27D/0x2B9,允许原车路径继续。
    普通非 Autopark、原车 LKAS 未锁存 0x488 可在角度/控制类型许可下发送 0x488 与 0x27D 被 tesla_fwd_hook() 阻断。
    原车 LKAS 已锁存 0x488 被车型 TX 钩子拒绝 0x488 透传给主总线。
    默认原车纵向 0x2B9 仅允许无执行量的 ACC_CANCEL_GENERIC_SILENT,且不得宣称 AEB 事件 0x2B9 一直透传;原车 AEB 活跃时主机取消帧也被拒绝。
    ALLOW_DEBUG 且纵向参数位置位 0x2B9 可按加速度限值发送,仍禁止主机 AEB 事件 无原车 AEB 时阻断原车 0x2B9;原车 AEB 活跃时恢复透传并拒绝主机 0x2B9。

    tesla_tx_hook() 对 0x488 只接受控制类型 NONE 或 ANGLE_CONTROL,并用车辆模型参数限制 0.1 度转角及横向动力学;原车 LKAS 锁存时即使数值合规仍拒绝。0x2B9 禁止主机设置任何 AEB 事件;默认模式仅可送加速度上下限均为中性 375 的取消编码。调试纵向模式的原始加速度范围为 288–425,中性为 375;两端都低于中性时额外拒绝,以防静止后倒车风险。

    白名单不等于逐信号校验:0x27D 的边界

    tesla_init() 的两个 TX 表都含 0x488、0x2B9、0x27D/总线 0。0x488 与 0x27D 保留 check_relay=true,但设 disable_static_blocking=true,因此共享 safety_fwd_hook() 不会先把它们恒定阻断,留给 Tesla 的动态钩子选择透传。默认模式的 0x2B9 check_relay=false;纵向模式则为 true 但仍关闭静态阻断。

    关键在于 0x27D 没有 Tesla TX 载荷分支:非 Autopark 时,它只经过通用地址/总线/长度、继电器状态和车型总阻断门,不能据此认定各字段经过逐信号安全校验。

    证据与新硬件边界

    test_tesla.py 包含校验/计数、速度失配、制动质量位、驾驶员接管、Autopark、原车 LKAS/AEB 透传、转角和倒车限制用例;其测试库默认加 ALLOW_DEBUG。新增的本机转发矩阵探针在严格编译和 UBSan 下分别运行 release/debug 变体,两者均通过:核对启动 Autopark 阻断、普通/原车 LKAS 转向透传,以及调试纵向和原车 AEB 的 0x2B9 转发切换。但它只设置隔离状态并检查通用 safety 函数,没有覆盖真实 RX 报文时序、目标编译器、板级继电器或 ECU 接受。

    自制硬件与插件化重构应把固件构建类型、Tesla 平台/转向控制字段代际、CAN 来源、车辆模型参数和安全参数版本绑定。感知/控制插件只能提供候选角度或加速度;Autopark、原车 LKAS/AEB 优先权、双车速、质量位与故障降级仍须由独立受信任安全层执行。

    常见问题

    为什么启动时会拒绝所有主机 Tesla 候选帧?

    因为 tesla_init() 在启动时先假定 Autopark/Summon 活跃,在收到解除 Autopark 的 0x286 之前,tesla_tx_hook() 会拒绝所有 Tesla 候选帧;Autopark 锁存活跃时同样如此。

    原车 LKAS 锁存后,0x488 还能由主机发送吗?

    不能。原车 LKAS 已锁存时 0x488 被车型 TX 钩子拒绝,主总线方向则改为把 0x488 透传给主总线。普通非 Autopark 且原车 LKAS 未锁存时,0x488 才可在角度/控制类型许可下发送。

    0x27D 在白名单里是否代表它经过逐信号校验?

    不代表。0x27D 没有 Tesla TX 载荷分支;非 Autopark 时它只经过通用地址/总线/长度、继电器状态和车型总阻断门,不能据此认定各字段经过逐信号安全校验。

    原车 AEB 活跃时 0x2B9 会怎样处理?

    原车 AEB 活跃时恢复 0x2B9 透传并拒绝主机 0x2B9;默认原车纵向模式下,主机侧 0x2B9 仅允许无执行量的 ACC_CANCEL_GENERIC_SILENT,且不得宣称 AEB 事件。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TESLA_PANDA_SAFETY_MODE_DEEP_DIVE.md(取用了 RX 监视帧、原车状态锁存、TX 与转发优先级矩阵及证据边界)。
    • 项目 02 —— openpilot-research/FORD_PANDA_SAFETY_MODE_DEEP_DIVE.md(仅用于对照品牌安全模式的通用分发结构)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Chrysler 四套构帧:0x292 与 0xa6 为什么不能互换

    结论:Chrysler 的构帧不是一套模板,而是四套并存的布局:Pacifica/常规 Jeep、Ram DT、Ram HD 与 Cherokee CUSW,三帧消息的地址、字节长度和所在总线都不同,不能互相套用。几个最容易踩的点是:Ram 的按钮帧走 bus 2 而其他走 bus 0;Ram HD 与 CUSW 的 TX/RX 只在 ALLOW_DEBUG 构建中注册且参数层标 dashcamOnly;Pacifica、Ram DT、Ram HD 的转向扭矩上限分别是 261、261、361,CUSW 为 250。字段名相同并不代表可共用原始载荷。以下为固定快照 c8fb906 的静态分析,未向车辆发送 CAN。

    四套发帧布局

    主机侧三类输出分别是 LKAS 转向命令、DAS_6 图标/车系码/警示,以及巡航按钮。CANPacker.pack() 会在未显式提供时按地址递增 COUNTER,并调用 DBC 对应的 CHECKSUM 函数;chrysler_ 系列 DBC 使用 chrysler_checksum(),即最后一字节之外的 CRC-8 J1850,初值与尾异或都是 0xff。

    平台族 LKAS / DAS_6 / 按钮(地址/长度) 主机 bus panda 限制
    Pacifica / 常规 Jeep 0x292/6 B、0x2a6/8 B、0x23b/3 B 三种都在 bus 0 扭矩最大值 261,速率上/下限每次 3。
    Ram DT 0xa6/8 B、0xfa/8 B、0xb1/3 B LKAS/HUD bus 0,按钮 bus 2 主机扭矩上限 261,固件白名单 350,实际受主机更紧约束。
    Ram HD 0x276/8 B、0x275/8 B、0x23a/3 B LKAS/HUD bus 0,按钮 bus 2 主机/固件扭矩上限均 361,速率 14;TX/RX 仅 ALLOW_DEBUG 注册。
    Cherokee CUSW 0x1f6/4 B、0x5dc/4 B、0x2fa/3 B 三种都在 bus 0 独立 safety model,扭矩 250,速率 4;参数层标 dashcamOnly。

    控制周期与按钮时序

    CarController.update() 以 DT_CTRL = 0.01 s 的帧计数运行。按钮只在距上次发送严格超过 0.05 s 时生成,优先取消、其次恢复;计数用 CS.button_counter + 1,再由 create_cruise_buttons() 截成 4 位。这里有一个平台差异:CUSW 的 update_cusw() 没有像常规分支那样刷新 button_counter,若生成按钮帧会反复使用初始化值加一,是否触发原车计数拒收仍需台架确认。

    DAS_6 的字段由 create_lkas_hud() 生成:它把激活态、车系码和告警转成图标与车道线字段;Ram 额外带原车自动远光状态,而 CUSW 的告警字段固定为零。也就是说,同一个「车道保持已激活」在四套布局里落在不同字段上,跨平台复用图标语义需要分别核对。

    HUD 每 25 帧尝试一次,且只有 CS.lkas_car_model != -1 才发送。hud_count 小于 4 的启动告警只覆盖最初四个实际发送的 HUD 帧,源码注释里的「first 3 seconds」不能当作精确时长。转向周期由 CarControllerParams 设为普通/Ram 50 Hz、CUSW 100 Hz;控制位则依 minSteerSpeed、平台迟滞和最近下降沿约 200 个控制帧的等待决定。由于 lkas_active 在本次控制位更新前读取上一状态,控制位首次置位的周期不会产生非零扭矩。

    时序项 取值 备注
    控制步长 DT_CTRL = 0.01 s 按钮与 HUD 都按帧计数节流。
    按钮最小间隔 严格大于 0.05 s 优先取消,其次恢复。
    HUD 周期 每 25 帧 仅当 lkas_car_model != -1。
    转向速率 普通/Ram 50 Hz、CUSW 100 Hz 由 CarControllerParams 决定。
    控制位迟滞 约 200 个控制帧 自最近下降沿起等待。

    控制字段与原始载荷不能共用

    create_lkas_command() 对 Ram 的控制字段编码为 2,其他为 1。这对应固件里的不同检查:常规固件在 Pacifica 上检查 bit 4、在 Ram 上检查字段值 2,而 CUSW 独立检查 bit 12。字段名相同并不代表可以共用原始载荷,这也是四套布局必须分别验证的原因之一。

    panda 是最后一道独立门

    主机发出的三类帧仍要经过 panda 安全钩子。常规模式仅允许表中的地址、总线与长度;转向再做扭矩与请求位检查;按钮只接受纯取消,或在 controls_allowed 下的纯恢复,CUSW 的取消/恢复位解析则不同。这套白名单与按钮限制应被视为独立于应用插件的最后一道门。生成式 Ram DBC 的地址映射(DAS_6 与按钮来自 Stellantis 共用 DBC 的地址替换)也应纳入构建一致性检查。

    硬件与插件验收边界

    把 DBC、总线、帧长、安全模式与固件构建作为同一车型插件的版本化契约;Ram 的按钮 bus 2 与普通平台的 bus 0 不可互换。台架应分别验证编码后的计数、CRC、控制位与 panda TX 的接受/拒绝矩阵,尤其覆盖 Pacifica、Ram DT、Ram HD、CUSW 四套布局——软件里有构帧函数,并不意味 HD/CUSW 的 release 固件允许发送。

    实车验证前应先只读记录原车的 DAS_6、按钮计数与测得 EPS 扭矩以及 LKAS 故障时序,确认线束与转发路径。本文没有 DBC 动态编码回放、目标板或车辆响应证据,不构成上路控制许可。

    常见问题

    四套 Chrysler 布局能共用同一套构帧代码吗?

    不能。Pacifica/常规 Jeep、Ram DT、Ram HD、Cherokee CUSW 的地址、长度和总线都不同:例如 Ram 的按钮帧走 bus 2,其他走 bus 0;Ram HD 与 CUSW 的 TX/RX 还只在 ALLOW_DEBUG 构建中注册。

    为什么控制字段取值在 Ram 和其他平台上不同?

    create_lkas_command() 对 Ram 的控制字段编码为 2、其他为 1,对应固件的不同检查:常规固件在 Pacifica 检查 bit 4、在 Ram 检查字段值 2,CUSW 则独立检查 bit 12。字段名相同不等于原始载荷可共用。

    按钮计数在 CUSW 上有什么特殊之处?

    CUSW 的 update_cusw() 没有像常规分支那样刷新 button_counter,若生成按钮帧会反复使用初始化值加一;这是否触发原车计数拒收仍需台架确认。

    软件里有构帧函数就说明 HD/CUSW 可发送吗?

    不能这样推断。Ram HD 与 CUSW 的参数层标 dashcamOnly,HD 的 TX/RX 只在 ALLOW_DEBUG 构建中注册;台架应分别验证四套布局的 panda 接受/拒绝矩阵,构帧函数存在不代表 release 固件允许发送。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/CHRYSLER_CAN_FRAME_CONTROL_CONTRACT_DEEP_DIVE.md(取用了四平台发帧矩阵、控制周期与按钮/HUD 时序、控制字段编码差异与 panda 安全门边界)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Toyota SecOC 边界缺口:密钥在内存、同步不匹配只记日志、计数先于确认

    结论:Toyota 的 SecOC 链路在源码里是三段彼此独立的机制:密钥装载、同步计数器校验与 panda 安全钩子。它们各自都有明确的边界缺口——密钥只以 16 字节形式留在内存中,Params 的 DONT_LOG 标记并不等于加密;同步 MAC 不匹配时源码只写一条 carlog.error(),不停止组帧;三个消息计数在调用 add_mac() 后、返回候选帧前就递增,不等待 sendcan、SPI、panda TX 或 ECU 的接受回执。发布版对这类车型设 dashcamOnly,MCU 侧也不持有车辆认证密钥。以下为固定快照的静态阅读,未获取车辆密钥、未连接 ECU、未发送 CAN。

    能力门与密钥生命周期

    Toyota SecOC 平台把认证要求写进 CarParams,并把安全参数传给 panda。ToyotaSecOCPlatformConfig.init() 设置 TSS2/NO_DSU/SECOC 标志和专用 DBC;CarInterface._get_params() 置 secOcRequired 与 Toyota safety 参数,发布版把这类车型设成 dashcamOnly。Car.__init__() 从缓存文件或 Params 读取键,做长度与十六进制解析后交给 CarState/CarController;其中的 secOcKeyAvailable 仅是本地装载标志。

    具体地,card 可以从设备本地缓存文件中的 SecOCKey 导入 32 个字符到 Params,再用 bytes.fromhex() 解成 16 字节。正确长度只能证明数据格式,secOcKeyAvailable=True 并不证明它匹配车辆;若 Params 里是非十六进制文本,bytes.fromhex() 在该分支没有局部异常处理,初始化可能直接失败。密钥在 Params 里注册为 DONT_LOG,这只约束常规日志取值,不是存储加密、进程隔离或密钥来源认证。

    层 载体 能证明什么 / 不能证明什么
    能力门 CarParams.secOcRequired + dashcamOnly 声明该车型需要 SecOC;发布版因此进入被动模式,安全配置被改为 NO_OUTPUT。
    密钥装载 设备本地缓存文件中的 SecOCKey → Params → 16 字节内存 长度与格式可校验;不证明匹配车辆,也不是加密存储。
    日志标记 SecOCKey 注册为 DONT_LOG 只约束常规日志取值,不等于进程隔离或来源认证。

    同步与认证:MAC 不匹配只记日志

    SECOC_SYNCHRONIZATION 在 DBC 中是 8 字节消息,含 Trip/Reset 计数和 Authenticator。CarState 每轮复制解析器缓存的当前值,未在此处对同步 MAC 或样本年龄作校验。控制器看到 Reset 与上次不同时,把 LKA、LTA2、ACC2 三个计数清零,再计算期望的同步 MAC。

    关键边界在于:不匹配时只有 carlog.error(),没有在该分支停止组帧或撤销控制资格。另有一个初始化细节——首次本地 Reset 初值为零,若同步消息也为零,本轮不会触发这次校验。解析器总线健康属于另一层,控制器在这里没有逐同步帧的年龄门。

    签名输出:计数先于链路确认递增

    add_mac() 用地址、控制载荷前四字节以及 Trip/Reset/消息计数构造 CMAC 输入,截断后与两组低位标记一起放进 8 字节 CAN 数据;不同命令流各有递增计数。CarController.update() 在 Reset 变化时归零三种本地计数,并分别签 LKA、LTA2、ACC2。

    递增时机是核心问题:计数在调用 add_mac() 之后、返回候选 CAN 帧之前增加,不等待 sendcan、SPI、panda TX hook 或 ECU 的接受回执。因此应用层的计数是「本地尝试序号」,不是「车辆已执行序号」;断流、重启、Reset 切换及报文丢失时的同步策略需要另行验证。

    环节 源码可见做法 缺口
    同步帧解析 CarState.update() 复制解析器缓存 未在此处校验 MAC 或样本年龄。
    同步 MAC 校验 Reset 变化时清零三计数并算期望值 不匹配只 carlog.error(),不停组帧。
    Reset 初值 首次本地 Reset 为 0 同步消息也为 0 时不触发本轮校验。
    命令计数 add_mac() 后立即递增 不等待 sendcan/SPI/panda/ECU 回执。

    panda safety 与覆盖范围

    Toyota safety 的 SecOC TX 白名单包含相应的 LKA/LTA2/ACC2 报文,继续约束消息地址、总线、长度、力矩/角度及纵向输出;例如 SecOC LTA2 的非零执行字段在当前钩子中被禁止。toyota_secoc 参数只有在 ALLOW_DEBUG 编译时才从安全参数开启,不能假定所有固件构建都允许相同模式。

    更重要的是责任边界:MCU 侧没有车辆 SecOC 密钥,也不在此代码中校验 AES-CMAC;认证通过与否由车辆 ECU 决定,安全钩子只负责本地发送约束。相邻测试里,通用车型 TX 回放会跳过 SecOC(需要真实键),panda safety 单测会检查 SecOC 地址与限幅,但不验证 ECU 的密码学接受——白名单与限幅通过并不证明车辆会接受签名帧。

    自制硬件与插件重构

    把车辆认证能力放在受信任、受限的签名服务中,而不是通用车型插件或日志进程:签名服务只对已授权的车型、命令与当前有效同步状态处理候选帧,记录键版本而不泄露键值;CAN 执行仍需独立的 ECU 安全限幅网关。输入契约至少应包含同步帧来源、解析器有效位、接收时间、Trip/Reset 代号和认证结果;MAC 失败、缺帧、过期或密钥不匹配都应进入明确的不可执行状态,不能只写日志。

    离线验收要覆盖:未配置键、非法十六进制键、错误键、同步 MAC 不匹配、Reset 为零或跳变、丢帧、重复或过期同步,以及三条命令流计数的重启行为;再在无车台架验证安全钩子与总线发送结果。在没有车辆密钥或 ECU 反馈时,只能确认本地编码与限幅,不应宣称 SecOC 车型已受支持或已可安全上路。

    常见问题

    SecOCKey 注册为 DONT_LOG 就等于密钥被加密了吗?

    不是。DONT_LOG 只约束常规日志取值,它不代表存储加密、进程隔离或密钥来源认证。密钥最终以 16 字节形式留在 CarState/CarController 内存中,正确长度也只证明数据格式,不证明匹配车辆。

    同步 MAC 不匹配会阻止发送控制帧吗?

    不会。源码在不匹配分支里只有一条 carlog.error(),没有停止组帧或撤销控制资格。此外首次本地 Reset 初值为零,若同步消息也为零,本轮根本不会触发这次校验。

    LKA/LTA2/ACC2 的计数是「车辆已执行」的序号吗?

    不是。计数在调用 add_mac() 后、返回候选 CAN 帧前就递增,不等待 sendcan、SPI、panda TX hook 或 ECU 回执,因此它只是本地尝试序号,不是车辆已执行的序号。

    panda safety 通过就能说明 SecOC 车型可用吗?

    不能。panda 只约束消息地址、总线、长度与力矩/角度/纵向限幅;MCU 不持有车辆密钥、也不校验 AES-CMAC。车型回放测试因无密钥会跳过 SecOC TX 用例,白名单与限幅通过并不证明车辆会接受签名帧。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_SECOC_KEY_FRESHNESS_SAFETY_BOUNDARY_DEEP_DIVE.md(取用了能力门与密钥生命周期、同步与认证边界、add_mac() 计数时机、panda safety 覆盖范围与插件重构建议)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • body、BYD、MG、PSA 与 mock:五种平台的执行语义与资格标记

    结论:在固定快照 c8fb906 中,body、BYD、MG、PSA 与 mock 这五个平台各有完全不同的执行语义:body 是双轮开发平台而非乘用车,只做左右轮速度与差速;BYD 与 PSA 走转角链,MG 走扭矩链;mock 返回空状态与空发送,只在无法识别车型时回退。BYD、MG、PSA 在快照中均被标记 dashcamOnly,其 panda 安全模式仅在 ALLOW_DEBUG 注册,因此不能把代码路径解读为发布固件可用功能。本文为静态代码分析,未运行测试、未做实车验证。

    平台资格:notCar、dashcamOnly 与调试注册

    同一套接口在不同平台上可能只是「能加载」而不是「允许执行」。body 通过 CarInterface._get_params() 设置 notCar=True,它并不是乘用车;BYD、MG、PSA 与 mock 都设置了 dashcamOnly=True,且它们的安全模式只出现在调试注册表里。插件清单必须把这几类资格分开标注。

    平台 控制语义 资格标记
    body 双轮差速、速度控制 notCar=True,非乘用车
    BYD 角度转向、原车纵向 dashcamOnly=True,调试注册
    MG 扭矩转向、原车巡航 dashcamOnly=True,调试注册
    PSA 角度转向、EPS 重使能 dashcamOnly=True,调试注册
    mock 空状态、空发送 dashcamOnly=True,未知车型回退

    body:开发用双轮平台

    CarState.update() 从电机数据读取左右电机速度并估算速度,电机错误会形成永久转向故障,同时读取充电与电量,且巡航状态被设为可用且已启用。CarController.update() 与构帧函数把 actuators.accel 与 torque 转成期望前进速度与左右差速,使用两个 PID,经过死区、变化率及幅度限制,最终编码双轮扭矩;代码明确注明加速度字段并非真实加速度语义。

    body_rx_hook() 在 RX 有效后允许控制,body_tx_hook() 只开放指定 TX 地址与长度并关闭转发。需要注意两处例外:未允许控制时仍可发送 0x1,且 0x250 的特定魔数刷写帧也被放行。固件没有乘用车式的双轮扭矩逐字段限制,因此它的安全策略不能移植到车辆。

    层 关键函数 实现事实
    参数 _get_params() notCar=True、body 安全模式、纵向开启、角度控制类型
    输入 CarState.update() 左右电机速度估算速度;电机错误形成永久转向故障
    输出 CarController.update() / create_control() accel 与 torque 转差速,经死区与限幅编码双轮扭矩
    固件 body_rx_hook() / body_tx_hook() 仅白名单与长度;未允许时仍可发 0x1,0x250 刷写帧为例外

    BYD 与 MG:转角链与扭矩链

    BYD 走角度转向:CarController.update() 用车辆模型限制目标转角,每两帧发转角与 HUD,取消时每十帧发按钮候选帧;byd_tx_hook() 检查转角与速率,按钮只接受取消或释放,且取消需有先前巡航接合状态。其部分 RX 项显式忽略校验和与计数器,不能泛称全链路完整性校验。驾驶员 EPS 扭矩分别用于软覆盖与硬退出。

    MG 走扭矩转向:CarController.update() 每两帧按驾驶员施力与变化率对期望扭矩限幅,未激活时置零,只构造 LKAS 转向帧;mg_tx_hook() 的 TX 白名单仅一条转向帧,固件再次检查最大扭矩、速率、实时变化与驾驶员扭矩。其安全注册只在调试编译中。

    平台 输入来源 输出与固件门
    BYD 动力总线取速度、转角、扭矩、踏板、车门;相机总线取 ACC 与原 LKAS HUD 车辆模型限幅转角;TX 检查转角与速率,按钮只接受取消/释放
    MG 状态来自 PT 与相机两路,含巡航故障与临时转向故障 每两帧限幅扭矩、未激活置零;TX 仅一条转向帧并复检扭矩/速率

    PSA 与 mock:EPS 重使能与未知车型回退

    PSA 设转角控制与 dashcamOnly=True,主、ADAS、相机三总线共同提供速度、驾驶员与 EPS 状态、巡航、制动与安全带。CarController.update() 每五帧做转角限幅并发 LKAS;在 EPS 覆盖后按 READY 到 AUTHORIZED 再到 ACTIVE 的状态序列尝试重使能,实际策略必须在目标平台验证。psa_tx_hook() 的白名单只含 LKAS 转角帧,并限制目标角度与速度相关变化率;部分 RX 项忽略校验与计数。

    mock 是明确的隔离边界:_get_params() 设 dashcamOnly=True,CarState.update() 返回空状态,CarController.update() 返回空 CAN 列表。get_car() 在无法识别车型时回退到它,被动路径还会把安全配置设为 noOutput。因此 mock 可用于只读、仿真与未知车型隔离,不能用来推定车辆控制可用。

    对硬件与插件化的含义

    插件清单必须区分 notCar、dashcamOnly、发布与调试固件注册状态、控制语义和总线拓扑;加载实现并不等于允许执行。车型控制插件只能产出候选帧,独立安全 MCU 仍需按车型验证 RX 有效性、TX 白名单与转角或扭矩限制。body 的刷写例外不能进入乘用车固件。

    BYD 的相机 HUD 保留、PSA 的 EPS 重使能状态机及各平台的巡航接合语义,都应放入明确的能力与风险契约,不能抽成无条件的通用按钮或转向插件。相关测试入口包括 body、BYD、MG、PSA 的专项测试与通用车型接口测试,本次只确认文件存在,未运行也未验证实车行为。

    常见问题

    body 是乘用车平台吗?

    不是。body 是开发平台,其接口设置 notCar=True,执行方式是双轮差速与速度控制,代码还明确注明加速度字段并非真实加速度语义。它的固件安全策略不能移植到乘用车。

    dashcamOnly 与调试注册意味着什么?

    意味着这些路径在固定快照中不作为发布可用功能。BYD、MG、PSA 都设了 dashcamOnly=True,其 panda 安全模式只在 ALLOW_DEBUG 下注册,因此不能把代码路径解读为发布固件可用功能。

    mock 会不会真的发控制帧?

    不会。mock 的 CarState.update() 返回空状态,CarController.update() 返回空 CAN 列表,被动路径还把安全配置设为 noOutput。它用于只读、仿真与未知车型隔离,不能用来推定车辆控制可用。

    插件加载了某平台实现就代表可以执行控制吗?

    不代表。插件清单要区分 notCar、dashcamOnly、发布或调试固件注册状态与控制语义;加载实现不等于允许执行,最终 TX 仍由独立安全 MCU 按车型校验。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/OTHER_PLATFORMS_DEEP_DIVE.md(取用了 body/BYD/MG/PSA/mock 五平台的参数、输入、输出与固件事实,以及插件化含义)。
    • 项目 02 —— openpilot-research/BYD_PANDA_SAFETY_MODE_DEEP_DIVE.md(关联的 BYD Atto 3 safety 专题,用于补充转角链与按钮门细节,本文未展开其探针)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • panda safety 测试链:libsafety、回放与变异的证据边界

    结论:panda safety 的测试链要分四层证据看——本机逻辑库、离线回放、板级验证、车辆验证,它们不能互相替代。源文档反复强调:默认启用的 ALLOW_DEBUG 测试库、test.sh 要求的 100% 行覆盖率、以及回放返回的布尔通过,都不等于目标固件、线束或实车安全认证。make_CANPacket() 得到的只是 DBC 构帧后的 CFFI CANPacket_t,不是 panda USB/SPI、FDCAN 或 ECU 真实发送回执。

    一、本机库与通用断言

    入口 作用与限制
    _build_libsafety()、__getattr__() 首次取 libsafety 时将测试 C 翻译单元编译为临时共享库;默认启用 ALLOW_DEBUG,release=True 才不加该宏。正常模式加 UBSan,覆盖率模式改用 gcov flags。
    make_CANPacket()、CANPackerSafety.make_can_msg_safety() DBC 构帧后转成 CFFI CANPacket_t,保留地址、bus、长度码与数据;不是 panda USB/SPI、FDCAN 或 ECU 真实发送回执。
    init_tests() 测试库可人工改时钟、使能和测量窗口,并设置 safety_mode_cnt=2 等测试专用状态,并不模拟真实 MCU 启动。
    test_spam_can_buses()、test_fwd_hook() 对已列扫描地址、总线及测试用长度检查 TX/转发;不是 29 位地址和 0~64 字节载荷的全穷举。
    test_safety_tick()、test_relay_malfunction() 分别验证缺失关键 RX 时退出与继电器故障否决;仍是本机状态模拟。

    库编译使用 -Wall -Wextra -Werror -nostdlib -fno-builtin;common.py 用继承式 mixin 组合地址扫描、踏板/巡航、转向扭矩、角度、曲率、纵向和转发断言。SCANNED_ADDRS 扫全 11 位地址,但仅取少量 29 位诊断区间,且基础 spam 测试固定构造 8 字节零载荷。test_tx_hook_on_wrong_safety_mode() 读取其他测试类声明的 TX 列表并有多组车型/地址重叠例外,它是跨模式回归检查,不是形式化证明。另一个关键点:独立 test_release_build.py 只确认两种测试库能编译,没有对 release 版本逐车型跑相同 TX/RX 行为矩阵。

    还要注意测试库与真实固件的差异:libsafety/safety.c 内嵌仓库的 can.h、safety.h、ignition.h,以全局 timer_cnt 替代 MCU 微秒计时器,并暴露测试专用 getter/setter。模式切换仍走真实 safety 头文件,但总线驱动、线束继电器、电源/心跳和芯片时钟不在测试库内;init_tests() 在 set_safety_hooks() 之后另改测试状态,例如跳过初期继电器忽略窗口,故它是逻辑钩子验证而不是板级启动验证。

    二、覆盖率与变异测试的解释边界

    机制 给出的结论 不能被读成什么
    test.sh + UBSan 先跑 UBSan 单测,再在 SAFETY_COVERAGE=1 下重跑。 行覆盖率(排除 libsafety 包装器后 100%)不等于分支、状态序列、真实总线或发布固件覆盖。
    MISRA(test_misra.sh) 用 cppcheck 执行静态检查。 不能与动态 safety 断言合并为同一种证据。
    enumerate_sites()、build_priority_tests()、eval_mutant() 对预处理后的 safety C 生成变异点,按车型文件或共享核心测试选用例,统计杀死、存活或基础设施错误。 modes/ 下默认只取同名 test_<mode>.py;共享模式头文件若无同名测试,所选列表可能为空,不能据「该文件变异全部存活」直接断言无测试能覆盖它。

    变异统计里还有两个陷阱:worker 异常或进程池崩溃在结果汇总中被记为 killed,而另一路 Python 异常记为 infra_error——查看变异得分时必须把崩溃原因从有效测试断言失败中分离;脚本还有三条已知存活变异例外,不能把返回码零解释为零存活点。

    三、回放的证据边界

    replay_drive() 从日志 carParams.safetyConfigs[-1] 默认取最后一个模式,可覆盖参数;package_can_msg() 将 src % 4 映射为本地 bus。它按 logMonoTime 排序,给安全库设置软件时钟;在离片段首尾各超过 1 秒的区间,对每条 CAN 消息调用 safety_tick(),而板端该函数按 1 Hz 调用。回放成功条件是「控制允许时无 TX 被拒、无 RX 无效、没有区间内的 RX 健康失败」;控制未允许时被拒的 TX 仍计数但不使返回值失败。没有 can/sendcan 消息时会在首尾索引处失败,不是空路段的安全通过证明。

    init_segment() 用首个识别到的转向 sendcan 帧人工设 controls_allowed、上轮目标及测量值,然后断言该帧 TX 可过。这样可降低片段开头状态缺失导致的误报,但也意味着回放不完整验证实际巡航使能沿和最初几帧的真实状态。测试前应记录路段是否从设备启动/控制开始,不能只看最终布尔结果。

    四、自制硬件的验收证据链

    1. 本机逻辑:按目标安全模式分别运行 development/release 构建和关键 RX/TX 单测,保存精确源提交、编译宏、测试选择及失败列表。
    2. 离线时序:用目标车型路段回放,记录首帧预置、源 bus 映射、RX 健康与「控制未允许时拒帧」;回放不能替代无车故障注入。
    3. 板级验证:确认 MCU 固件签名/模式参数读回、实际 FDCAN 发送回执、继电器方向、心跳失联和异常报文抑制,不用 CFFI 测试库结果替代。
    4. 车辆验证:在合法合规的受控条件下单独确认 ECU 接受、原车 AEB/制动保留、驾驶员覆盖与恢复;插件系统不得把测试报告布尔值当作实时控制许可。

    本轮未运行完整安全测试,也没有目标硬件/车辆证据;上述内容是测试框架能力与缺口的源码索引。

    常见问题

    默认测试通过能否当作发布固件权限证明?

    不能。测试库默认启用 ALLOW_DEBUG,日常单测可覆盖仅调试注册的模式和纵向参数;test_release_build.py 只确认两种测试库能编译,没有对 release 版本逐车型跑相同 TX/RX 行为矩阵。

    100% 行覆盖率说明什么?

    只说明在 SAFETY_COVERAGE=1、排除 libsafety 包装器后行覆盖达到 100%,不等于分支、状态序列、真实总线或发布固件覆盖。MISRA 的 cppcheck 检查是另一种证据,不能与之合并。

    回放成功是否等于通过了安全验证?

    不等于。回放要求「控制允许时无 TX 被拒、无 RX 无效、无区间 RX 健康失败」,但控制未允许时被拒的 TX 仍计数而不使返回值失败;init_segment() 还人工预置首个转向帧状态,故不完整验证实际使能沿与最初几帧。

    变异评分零存活就代表没有缺口吗?

    不代表。共享模式头文件若无同名测试文件,所选用例列表可能为空;worker 异常或进程池崩溃会被汇总记为 killed,脚本还有三条已知存活变异例外,因此不能把返回码零解释为零存活点。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/SAFETY_TEST_HARNESS_REPLAY_EVIDENCE_DEEP_DIVE.md(取用了本机库与通用断言、覆盖率与变异边界、回放证据边界、硬件验收证据链)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Toyota panda safety:LKA/LTA 与纵向模式矩阵

    结论:Toyota panda safety 是MCU 本地规则,不验证 SecOC CMAC、雷达静默的正响应或车辆 ECU 是否接受命令。同一套 safety 代码按「原车 / 自控纵向 × 非 SecOC / SecOC × LKA / LTA」组合出不同模式,各模式允许的 TX 帧、长度与字段门都不同,不能把两个标志当成可随意组合。SecOC 相关位只在 ALLOW_DEBUG 构建下生效,上层即便能构帧也不能绕开普通固件或发布版 dashcamOnly 的能力边界。固定快照基线为 c8fb906,没有目标固件、车辆密钥、ECU 或实车验证。

    关键函数与调用顺序

    CarInterface._get_params() 配置 Toyota safety 参数、LTA / 替代制动 / SecOC、原车或自控纵向——注意上层参数和目标 ECU 已接受控制不是同一事实。toyota_init() 从 safetyParam 低八位读取 EPS 扭矩比例,高位选择替代制动、原车纵向、LTA;SecOC 位只在 ALLOW_DEBUG 下生效。

    toyota_rx_hook() 更新 EPS / 驾驶员扭矩、测量角、巡航 / 油门 / 制动和轮速;toyota_tx_hook() 分别检查 ACC、LKA 扭矩、LTA 角度 / 请求位、SecOC LTA2、AEB 和诊断保活。更外层,safety_tx_hook() 与 safety_fwd_hook() 先做地址 / 总线 / 长度白名单,继电器状态与静态转发阻断是独立的最终门。

    模式矩阵

    维度 选择与实际影响
    原车纵向 STOCK_LONGITUDINAL 非 SecOC 的 TX 仅含基础 LKA / LTA / HUD 与 0x343 取消;0x343 必须置 CANCEL_REQ 且加速度为零。
    自控纵向,非 SecOC 在基础 TX 上增加 DSU bus 0/1、PCS_HUD、0x750、0x283;0x343 可携带受限加速度,并另以 check_relay=true 登记。
    SecOC + 原车纵向 0x2E4 长度由 5 改 8,增加 0x131;0x343 仍只准零加速度取消;没有 0x183。
    SecOC + 自控纵向 0x2E4 长度 8,增加 0x131 和 0x183;0x343 只许零加速度,实际加速度走 0x183;没有非 SecOC DSU / 雷达诊断扩展表。
    LTA 标志 0x191 是否可执行受限角度由 LTA 位决定,即使同时设置 SecOC 位也如此;0x2E4 必须零扭矩 / 无请求。LKA 模式相反,0x191 必须无角度执行。SecOC 的 0x131 LTA2 在当前钩子中始终不准执行。
    替代制动 仅非 SecOC、非 LTA 的 RX 分支选择 0x224;普通分支用 0x226。LTA 分支固定普通 RX 表,SecOC 固定 0x101。

    自控纵向表里 0x343 同时经基础宏以 check_relay=false、扩展项以 check_relay=true 列出;通用继电器和转发代码遍历整个表,所以后者仍会触发对应故障 / 静态阻断,不能只看第一条白名单记录。

    RX 信号与健康

    所有 safety RX 均在总线 0。0x0AA 轮速 83 Hz,忽略 checksum / counter,但四个轮速故障位必须为零;0x260 转向传感器 50 Hz 检查 Toyota 累加校验,非 SecOC 的 LTA RX 表还要求 STEER_ANGLE_INITIALIZING=0。SecOC 初始化优先选择 TOYOTA_SECOC_RX_CHECKS,即使 LTA 位同时设置,该质量位也不作为 RX 有效性门。忽略某一完整性字段不等于不要求报文存活。

    报文 频率与门
    0x0AA 轮速 83 Hz,忽略 checksum / counter,四路故障位必须为零
    0x260 转向传感器 50 Hz,检查累加校验;非 SecOC LTA 表要求转角初始化位为 0
    0x1D2 巡航 / 油门 普通车 33 Hz,检查校验
    0x226 / 0x224 制动 40 Hz,忽略校验 / 计数;替代制动改用 0x224
    SecOC 路径 使用 0x176 巡航、0x116 油门和 0x101 制动

    toyota_rx_hook() 从 0x260 读取 16 位 EPS 扭矩,乘 safetyParam 低八位比例后采样,并把窗口最小值减 1、最大值加 1 以覆盖整数取整;驾驶员扭矩和测量角分别取独立字段。测量角仅在初始化位关闭时更新,不能把上一样本当成当前有效角。0x0AA 四轮原始值各减 6767 后求和,和不为零即视为移动。

    TX 权限与未覆盖载荷

    1. 扭矩 LKA:非 LTA 时 0x2E4 检查最大 1500、每帧上升 15 / 下降 25、相对 EPS 实测误差 350、实时差 450 与请求位切断节拍;LTA 模式仅允许零扭矩且请求位为零。SecOC 的 0x2E4 长度为 8,普通车为 5。
    2. 角度 LTA:非 LTA 时 0x191 的两个请求位、角度、TORQUE_WIND_DOWN 都必须不执行;LTA 时角度受速度相关变化率、最大 1657 原始单位及测量角邻域约束,两个请求位必须一致,wind-down 只可为 0 / 100,且驾驶员 / EPS 扭矩过高时禁止 100。SecOC 的 0x131 只允许请求位和角度字段均为零——这不是车辆认证成功的证明。
    3. 纵向:0x343 或 SecOC 0x183 的有符号加速度活动范围 -3.5 至 2.0 m/s²,未激活码为 0;共享门还要求允许控制且未踩油门。
    4. AEB 与诊断:仅非 SecOC 自控纵向白名单包含 0x283,前六字节必须全零,避免主机执行 AEB;0x750 仅允许固定载荷 0F 02 3E 00 00 00 00 00,用于雷达 tester-present。

    自制硬件与插件化契约

    车型插件提交 DBC / 平台、LKA / LTA、SecOC、制动地址及 EPS 比例的证据;未知 / 矛盾组合保持 noOutput。受信任网关独占 SecOC 密钥与签名、UDS 雷达静默、DSU / HUD 模板及节拍;普通插件只提交高层转向 / 加速度 / 取消意图,MCU safety 保留独立限幅。验证分层覆盖模式参数组合、错误 CRC / 质量位、双请求位不一致、wind-down、油门覆盖、非零 AEB、诊断错误载荷、签名失败与失联降级;随后是无负载台架和受控场地。当前没有这些目标车证据。

    常见问题

    LKA 和 LTA 模式能随便组合吗?

    不能。0x191 是否可执行受限角度由 LTA 位决定,即使同时设置 SecOC 位也如此;LKA 模式相反,0x191 必须无角度执行。0x2E4 在 LTA 模式必须零扭矩 / 无请求。未知或矛盾组合应保持 noOutput。

    「四个轮速故障位为零」是不是意味着数据都可信?

    不等于。0x0AA 忽略 checksum / counter,只用四个故障位做门;0x260 才检查 Toyota 累加校验并要求转角初始化位为 0。忽略某一完整性字段不等于不要求报文存活,健康判定要按报文明细区分。

    AEB 帧在 safety 里怎么处理?

    仅非 SecOC 自控纵向白名单包含 0x283,且前六字节必须全零,以避免主机执行 AEB。其它 DSU、PCS_HUD、0x1D2 / 0x412 等白名单帧没有同等级的逐字段门。

    panda safety 通过就等于车辆 ECU 接受命令了吗?

    不等于。这些只是 MCU 本地规则,不验证 SecOC CMAC、雷达静默的正响应或车辆 ECU 是否接受命令。SecOC 相关位只在 ALLOW_DEBUG 构建下生效,也不能绕开 dashcamOnly 等能力边界。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_PANDA_SAFETY_MODE_DEEP_DIVE.md(取用了模式矩阵、RX 健康门、TX 权限与插件化契约分析)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11