CanNm 从休眠唤醒后重复消息报文的周期与数量分析

CanNm 从休眠唤醒后重复消息报文的周期与数量分析

现象

调试 CAN 网络管理状态机时,观察到两种唤醒方式进入重复消息模式后的 NM 报文表现不同:

唤醒方式 观察到的报文 周期
休眠后由 CAN 网络管理报文唤醒 4 帧 约 500 ms
KL15 唤醒 5 帧 约 20 ms

抓包使用周立功设备,且只连接了这一条 CAN 总线。因此分析仪显示的 Rx 是分析仪接收到总线报文的方向;这些帧可按 ECU 发到总线上的报文进行分析。

原始抓包截图:

两种唤醒路径的区别

CAN 网络报文唤醒:按普通 NM 周期发送

CAN 网络报文唤醒属于网络侧唤醒。ECU 从休眠相关状态被唤醒后进入重复消息状态,NM 报文按普通消息周期发送。

若普通周期配置为 500 ms,重复消息状态持续约 1.6 s,那么在这个时间窗口内看到约 4 帧是合理的:首帧及后续周期帧受状态切换时刻、定时器调度和抓包窗口边界影响,实际帧数不一定简单等于 1.6 s / 0.5 s 的整数结果。

KL15 唤醒:启动快速发送

KL15 唤醒是本节点主动唤醒网络。项目启用了 CanNm 的快速 NM 发送功能,配置的快速发送次数为 5、周期为 20 ms,因此抓到 5 帧、间隔约 20 ms,与这组参数相符。

在 CanNm 实现中,进入重复消息状态时会检查节点是否主动请求网络;满足条件时设置快速发送计数并启动发送。后续每次成功发送都会递减计数,计数结束后恢复普通消息周期。因此,快速发送次数和重复消息状态的持续时间是两个不同概念:前者控制唤醒后的快速帧数,后者控制重复消息状态持续多久。

原理示意图

#mermaid-svg-BrV5Nm4xibcABqBK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BrV5Nm4xibcABqBK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BrV5Nm4xibcABqBK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BrV5Nm4xibcABqBK .error-icon{fill:#552222;}#mermaid-svg-BrV5Nm4xibcABqBK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BrV5Nm4xibcABqBK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BrV5Nm4xibcABqBK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BrV5Nm4xibcABqBK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BrV5Nm4xibcABqBK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BrV5Nm4xibcABqBK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BrV5Nm4xibcABqBK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BrV5Nm4xibcABqBK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BrV5Nm4xibcABqBK .marker.cross{stroke:#333333;}#mermaid-svg-BrV5Nm4xibcABqBK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BrV5Nm4xibcABqBK p{margin:0;}#mermaid-svg-BrV5Nm4xibcABqBK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BrV5Nm4xibcABqBK .cluster-label text{fill:#333;}#mermaid-svg-BrV5Nm4xibcABqBK .cluster-label span{color:#333;}#mermaid-svg-BrV5Nm4xibcABqBK .cluster-label span p{background-color:transparent;}#mermaid-svg-BrV5Nm4xibcABqBK .label text,#mermaid-svg-BrV5Nm4xibcABqBK span{fill:#333;color:#333;}#mermaid-svg-BrV5Nm4xibcABqBK .node rect,#mermaid-svg-BrV5Nm4xibcABqBK .node circle,#mermaid-svg-BrV5Nm4xibcABqBK .node ellipse,#mermaid-svg-BrV5Nm4xibcABqBK .node polygon,#mermaid-svg-BrV5Nm4xibcABqBK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BrV5Nm4xibcABqBK .rough-node .label text,#mermaid-svg-BrV5Nm4xibcABqBK .node .label text,#mermaid-svg-BrV5Nm4xibcABqBK .image-shape .label,#mermaid-svg-BrV5Nm4xibcABqBK .icon-shape .label{text-anchor:middle;}#mermaid-svg-BrV5Nm4xibcABqBK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BrV5Nm4xibcABqBK .rough-node .label,#mermaid-svg-BrV5Nm4xibcABqBK .node .label,#mermaid-svg-BrV5Nm4xibcABqBK .image-shape .label,#mermaid-svg-BrV5Nm4xibcABqBK .icon-shape .label{text-align:center;}#mermaid-svg-BrV5Nm4xibcABqBK .node.clickable{cursor:pointer;}#mermaid-svg-BrV5Nm4xibcABqBK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BrV5Nm4xibcABqBK .arrowheadPath{fill:#333333;}#mermaid-svg-BrV5Nm4xibcABqBK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BrV5Nm4xibcABqBK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BrV5Nm4xibcABqBK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BrV5Nm4xibcABqBK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BrV5Nm4xibcABqBK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BrV5Nm4xibcABqBK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BrV5Nm4xibcABqBK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BrV5Nm4xibcABqBK .cluster text{fill:#333;}#mermaid-svg-BrV5Nm4xibcABqBK .cluster span{color:#333;}#mermaid-svg-BrV5Nm4xibcABqBK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BrV5Nm4xibcABqBK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BrV5Nm4xibcABqBK rect.text{fill:none;stroke-width:0;}#mermaid-svg-BrV5Nm4xibcABqBK .icon-shape,#mermaid-svg-BrV5Nm4xibcABqBK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BrV5Nm4xibcABqBK .icon-shape p,#mermaid-svg-BrV5Nm4xibcABqBK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BrV5Nm4xibcABqBK .icon-shape .label rect,#mermaid-svg-BrV5Nm4xibcABqBK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BrV5Nm4xibcABqBK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BrV5Nm4xibcABqBK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BrV5Nm4xibcABqBK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 收到 CAN NM 报文
KL15 置位
否:被动网络唤醒
是:KL15 主动唤醒
否
是
休眠相关状态
唤醒来源
网络报文唤醒
本节点主动请求网络
进入 Repeat Message
是否为主动网络请求
按普通 MsgCycleTime 发送
RepeatMessageTime 到期
装载快速发送计数 5
按 ImmediateNmCycleTime 发送
快速发送计数归零?
恢复普通 MsgCycleTime

text 复制代码
网络报文唤醒:  NM ──500 ms── NM ──500 ms── NM ──500 ms── NM ...
                  普通 MsgCycleTime;Repeat Message 状态到期后退出

KL15 唤醒:      NM ─20 ms─ NM ─20 ms─ NM ─20 ms─ NM ─20 ms─ NM
                  快速发送 5 帧;快速计数结束后恢复普通周期

上图表达的是发送机制。抓包帧数还会受首帧触发时刻、定时器调度和测量窗口边界影响;排查时应结合 ECU 实际加载的配置和完整抓包窗口判断。

在代码中的对应逻辑

项目 CanNm 实现位于:

  • Proj_Code/_01_BSW/Src/CanNm/CanNm.c
  • CanNm_TransitionToRepeatMessage():进入重复消息状态时启动 Repeat Message 定时器;若节点主动请求网络且快速发送功能启用,则设置快速发送计数并启动发送。
  • 消息定时器处理逻辑:快速发送计数大于零时,按快速周期发送;快速计数结束后切换到普通 MsgCycleTime。

KL15 唤醒来源标记和 NM 用户数据更新位于 Proj_Code/_02_CDD/NmCdd/NmCdd.c。状态切换回调会根据 KL15 标记区分唤醒来源,并更新 NM 用户数据中的唤醒原因和重复消息标志。

排查时发现:ECUC 与生成代码参数不一致

对比 ECUC 配置和当前生成代码,发现参数值存在差异:

参数 ECUC 配置 TC27x_CanNm_ecuc.arxml 当前生成代码 CanNm_Cfg.c
CanNmMsgCycleTime 普通 NM 周期 500 ms 100 ms
CanNmImmediateNmCycleTime 快速发送周期 20 ms 4 ms
CanNmRepeatMessageTime 重复消息状态时间 1.6 s 320 ms
CanNmImmediateNmTransmissions 快速发送次数 5 5

因此,虽然抓包中的 500 ms 和 20 ms 与 ECUC 配置吻合,但当前仓库的生成文件仍是另一组旧参数。可能原因包括:生成代码未重新生成、编译时使用了不同的生成目录,或烧录固件并非由当前这份生成代码构建。

建议的核对步骤

  1. 确认实际构建使用的 GENDATA_DIR,以及编译输入的 CanNm_Cfg.c 路径。
  2. 从当前 ECUC 配置重新生成 CanNm 配置代码,确认生成文件中的普通周期、快速周期和重复消息时间分别为 500 ms、20 ms 和 1.6 s。
  3. 完整编译并烧录后重新抓包,核对两种唤醒路径的报文周期和数量。
  4. 记录固件版本或构建产物,确保抓包结果能对应到实际烧录的配置。

结论

两种唤醒方式进入重复消息模式后,报文表现不同,主要是因为它们触发了不同的发送节奏:网络报文唤醒走普通 NM 周期;KL15 主动唤醒触发配置的快速发送序列。当前应优先解决 ECUC 与 CanNm 生成代码参数不一致的问题,并确认实际编译和烧录使用的配置。

相关推荐
事圆则缓1 小时前
Kotlin 变量与函数:把页面状态和行为写成清楚的契约
android·开发语言·kotlin
silvamux_1 小时前
豆包 API 调用教程:Python 接入可跑通示例
开发语言·python
李纲明1 小时前
WordPress 安全加固基线:更新策略、文件权限、登录面收缩和备份验证(含回滚注意)
运维·安全·php·wordpress
wdfk_prog2 小时前
LWIP教程 15:IPv4 与 IPv6——从网络层工作原理到嵌入式工程取舍
运维·开发语言·网络·笔记·学习·智能路由器·ip
Novproxy_Z2 小时前
IPv4 与 IPv6 代理在跨境自动化场景下的选型与风险
运维·自动化·php
棉猴2 小时前
玩游戏学Python10-算术运算符应用2
开发语言·python·玩游戏·游戏编程
tachibana22 小时前
Go 语言的 Map 是否是并发安全的?
开发语言·数据结构·后端·golang·go·语言
后除2 小时前
Go 实战: 使用 Wails v2.15 构建轻量级的桌面应用 - 仿微信登录界面
开发语言·微信·golang
坤坤子吖2 小时前
Linux 进程信号入门——从 Ctrl+C 到 kill
linux·开发语言·c++·笔记·学习