记一次位域赋值错误导致的LIN休眠问题

背景:最近在调试一个新的HFA电机,此电机支持自寻址且LDF调度表协议由1.3升级到2.1。在CCM切到某个continue的table后,大约500ms后Lin休眠。
9dfcf4b8fed8e6cbca988c08d0aaa54d

调试过程:
1.抓取休眠前的正常报文和异常报文
整体情况:
027247c0b1b6917f4d4bc81930197131

正常报文:报头 + PID + DATA(因为从节点未响应所以数据未填充)
4bf71879d7ddf7ebf856b2a8461781fe

异常报文:报头 + 无PID......
d309056a63b28c54773c185df0dd5377

明显看出最后一帧PID未填充且总线处于显性电平后被拉低进入到休眠状态。

2.为什么调度表会被异常打断
①检查物理层 LINTRCV
物理层设置IO,比如使能PIN。IO设置后示波器测量是高电平,符合预期。
②检查LINIF层
LINIF层可以查看到调度表的信息,调度表的信息未被修改。
③检查LINSM层
LINSM负责休眠逻辑的管理,在davinci中取消休眠后无效果。
④检查Comm层
APP调用Comm中的模式请求设置休眠唤醒,无效果。
⑤检查BswM层/应用层
此项目中BswM中会调用ModeRequest请求切表,先屏蔽应用层再屏蔽BswM层后一帧报文都没有。
⑥检查所有应用层代码
屏蔽过程中发现定时更新IO的函数会导致报文消失。

3.为什么定时更新IO的函数会导致报文消失
函数作用:我们的架构文档中明确要求对于不使用的pin脚需要定时更新方向和模式,此函数就是此功能的体现。
函数细节:我们使用位域的方式设置模式和方向两个属性,每个分别占4个bit。
错误原因:我们在赋值的时候直接赋值单个值。 比如array[2]={1,2},array中的元素是结构体,结构体中使用位域,此时这种赋值就是错误的,这种赋值默认会把1或者给到低4位的位域,高四位的默认填充0. 因此正确的赋值是array[2]={{1,2},{2,3}}

结论:
正常报文发送的过程中周期任务将串口改成了GPIO,报文的高低电平无法被正确发送,导致触发休眠逻辑。

posted @ 2026-04-27 22:50  日暮_途远  阅读(15)  评论(0)    收藏  举报