S32K144调试记录(二)
最近在调试一个新板子,我负责板子上通讯模块程序的编写和调试,调试的时候断断续续遇到不少问题,在这里记录下。
调试CAN收发过程中遇到的问题
1 现象
接上篇CAN/LIN的收发程序调通了之后,紧接着整体的路由功能也都实现了,本以为皆大欢喜,后面用板子试了上下电,再进行测试发现,CANoe只能接收几次由CAN2在接收中断里执行的发送任务里发出的报文,而不是稳定的报文。接下来就开启了漫长的调试过程。
2 调试
这路CAN的功能其实很简单,有两个任务,任务一:接收到其他节点发过来的标准CAN报文,触发中断调用Callback函数,在Callback函数里把接收到的报文原封不动的传回去、任务二:每隔100ms就周期性的发几帧报文。以前的项目里这两个功能其实已经实现过了,所以觉得很奇怪为什么板子冷启动之后突然就不行了。
从现象来看,CANoe是可以通过CAN2发出报文,这说明CAN模块是可以正常接收报文,因为如果板子没法接收报文,CANoe会报Not Acknowledge,同时,在CANoe端也可以读到通过CAN2发出的报文,说明板子的CAN模块是可以正常工作的,所以分析直接原因是板子的冷启动导致了CAN2在上电后只能几次进入中断,再往后就无法进入中断调用Callback函数。
开始怀疑是把两路CAN的接收函数放在同一个while(1)里导致的,尝试了把两个接收函数放到了两个任务里,结果仍然进不去中断。
然后怀疑其他模块的任务占用了我的CAN的资源,然后把其他任务注释掉,发现还是不行。
这时候同事提醒我可能不是CAN没有进中断,而是压根CAN没收到报文。那为什么CANoe显示发送成功了呢?因为Transiver或者MCU接收到报文后在硬件层面回复了ACK,但是实际上并没有把收到的报文放到邮箱里,也就不会触发中断调用Callback函数。那么到这里,立马验证到底是没有进中断还是没有进Receive()函数。
这里用到一个小技巧,可以用示波器读MCU输出引脚电平状态的方法,不需要MCU在DEBUG模式下,就可以观测到函数有没有运行到设定的地方。
由于没有直接使用中断函数,而是调用的Callback函数,所以在Callback函数里加入了电平翻转的功能,只要Callback函数被调用了,目标引脚的电平就会不停翻转。代码如下。代码下载进去,上下电后测试PTE3引脚的电平状态,短暂变化几次后保持不变。
void CAN1_TX_RX_Callback(uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, flexcan_state_t *flexcanState)
{if(instance == 1){PINS_DRV_SetPinDirection(PTE, 3, 1);PINS_DRV_TogglePins(PTE, 1<<3);}else if(instance == 0){//if(Msg_CanRxbuffer.msgId || Msg_CanRxbuffer.data[0]){PINS_DRV_SetPinDirection(PTE, 9, 1);PINS_DRV_TogglePins(PTE, 1<<9);}}if(eventType == FLEXCAN_EVENT_RX_COMPLETE) //receive completed{//CAN1_HandleRequest();}
}
再往上查,FLEXCAN_IRQHandlerRxMB这个函数里调用了Callback函数,把电平翻转的代码插到这个函数里。
if(instance == 1){PINS_DRV_SetPinDirection(PTE, 3, 1);PINS_DRV_TogglePins(PTE, 1<<3);}else if(instance == 0){//if(Msg_CanRxbuffer.msgId || Msg_CanRxbuffer.data[0]){PINS_DRV_SetPinDirection(PTE, 9, 1);PINS_DRV_TogglePins(PTE, 1<<9);}}/* Invoke callback */if (state->callback != NULL){state->callback(instance, FLEXCAN_EVENT_RX_COMPLETE, mb_idx, state);}
再次测试,现象与刚才的一致。再往上查,发现FLEXCAN_IRQHandler这个函数调用了FLEXCAN_IRQHandlerRxMB这个函数,于是插入调试代码。
/* Check mailbox completed reception */if (state->mbs[mb_idx].state == FLEXCAN_MB_RX_BUSY){if(instance == 1){PINS_DRV_SetPinDirection(PTE, 3, 1);PINS_DRV_TogglePins(PTE, 1<<3);}else if(instance == 0){//if(Msg_CanRxbuffer.msgId || Msg_CanRxbuffer.data[0]){PINS_DRV_SetPinDirection(PTE, 9, 1);PINS_DRV_TogglePins(PTE, 1<<9);}}FLEXCAN_IRQHandlerRxMB(instance, mb_idx);}
再次测试,现象与刚才的一致。于是把测试代码拿出这个if语句,判断是否与邮箱的状态有关。
if(instance == 1){PINS_DRV_SetPinDirection(PTE, 3, 1);PINS_DRV_TogglePins(PTE, 1<<3);}else if(instance == 0){//if(Msg_CanRxbuffer.msgId || Msg_CanRxbuffer.data[0]){PINS_DRV_SetPinDirection(PTE, 9, 1);PINS_DRV_TogglePins(PTE, 1<<9);}}/* Check mailbox completed reception */if (state->mbs[mb_idx].state == FLEXCAN_MB_RX_BUSY){FLEXCAN_IRQHandlerRxMB(instance, mb_idx);}
经过测试,终于发现了异常。当把测试代码放到判断邮箱状态上一行后,此时PTE9引脚的输出电平会一直变化。也就是说每次代码执行到这里时邮箱都是FLEXCAN_MB_RX_IDLE的状态,然后通过查看CAN模块的FLEXCAN_DRV_Receive函数
/* Start receiving mailbox */if(state->mbs[mb_idx].state != FLEXCAN_MB_IDLE){return STATUS_BUSY;}state->mbs[mb_idx].state = FLEXCAN_MB_RX_BUSY;state->mbs[mb_idx].mb_message = data;state->mbs[mb_idx].isBlocking = isBlocking;/* Enable MB interrupt*/result = FLEXCAN_SetMsgBuffIntCmd(base, mb_idx, true);if (result != STATUS_SUCCESS){state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;}
只有当程序判断当前邮箱是FLEXCAN_MB_IDLE的状态,才会开启邮箱的接收过程,同时更改邮箱状态为FLEXCAN_MB_RX_BUSY。
这说明,之前所有的测试例子中,由于某种原因,邮箱是FLEXCAN_MB_RX_BUSY的状态,导致无法将data里的数据放入到邮箱中,邮箱无法启动接收过程。但是由于上一次接收成功的过程中已经打开了中断使能,所以后面无论接收过程是否被启动,只要MCU的硬件完成了接收过程,就会触发中断进入到中断服务程序。
定位到问题后,再用CAN0_ReceiveData函数验证一下是否正确。
status_t CAN0_ReceiveData(void)
{status_t result;result = FLEXCAN_DRV_Receive(INST_CANCOM1, RX_MB_64BYTES, &Msg_CanRxbuffer);if(result == STATUS_SUCCESS){PINS_DRV_SetPinDirection(PTE, 3, 1);PINS_DRV_TogglePins(PTE, 1<<3);}return result;
}
经过测试,发现PTE3输出电平不会翻转,验证了判断是正确的。
到这一步,问题排查就很清晰了。用测试代码一层一层往上测试,发现负责通讯的任务都挂掉了。再测试其他任务,发现都是挂掉的状态。
经过与硬件工程师讨论,板子上负责芯片供电的VDD本来有一颗电解电容用于稳压的,由于时间原因没有焊上去,导致输出电压不稳定,也间接让程序里多个用软件计时的任务挂掉了。而用硬件计时的定时器任务完好无损,这也是为什么定时器中断函数能够稳定的执行,并稳定的输出100ms的CAN报文。
VDD输出波形见下图。
S32K144调试记录(二)相关推荐
- S32K144调试记录(一)
最近在开发S32K144的CAN/LIN模块,调试的时候断断续续遇到不少问题,在这里记录下. 调试CAN/LIN收发过程中出现的问题 1 现象 1.1 CAN CANoe一直报Tx stuff err ...
- S32DS使用Jlink下载S32K144程序记录
一,S32DS配置. 参考文章 在S32DS中使用J-Link调试S32K144开发板_大橙员的博客-CSDN博客 新建工程 以自带例程"S32K144_Project_ADC"为 ...
- ROS上同时预览depth,IR,RGB 调试记录
ROS上同时预览depth,IR,RGB 调试记录 用rviz同时显示RGB,IR,DEPTH(验证设备:astraprosm,canglong2,deeyea) 1.编译libuvc库 cd lib ...
- 松下MINAS-A6伺服电机调试记录
松下MINAS-A6伺服电机调试记录 因项目需求,进行松下MINAS-A6伺服电机调试 文章目录 松下MINAS-A6伺服电机调试记录 概述 一.手册数据 二.设备使用 1.驱动器及电机连接 2.设备 ...
- AML8726调试记录
一:源代码下载: 1:Installing Repo # mkdir ~/bin # PATH=~/bin:$PATH # curl https://dl-ssl.google.com/dl/goog ...
- 海思NNIE开发(一):海思Hi3559AV100/Hi3519AV100 NNIE深度学习模块开发与调试记录
海思NNIE开发系列文章: 海思NNIE开发(一):海思Hi3559AV100/Hi3519AV100 NNIE深度学习模块开发与调试记录 海思NNIE开发(二):FasterRCNN在海思NNIE平 ...
- 煤炭超临界水气化与超临界燃烧传热耦合Fluent模拟(调试记录)
煤炭超临界水气化与超临界燃烧传热耦合Fluent模拟(调试记录) 这是一篇fluent数值计算的调试记录(自分用) ------------------------------------------ ...
- RK3568开发笔记-EDP显示屏接口调试记录
目录 文章目录 前言 一.edp显示接口介绍 二.edp接口部分原理图 三.edp接口显示屏参数介绍 四.RK3568设备树参数配置 五.完整DTS edp参数 六.RK3568多屏显示vop选择 七 ...
- 2020-02-24 RK3288 Android7.1 5.1 增加AP6256 WI-FI Bluetooth调试记录
RK3288 Android7.1 5.1 增加AP6256 WI-FI Bluetooth调试记录 一.硬件连接图,AP6335.AP6255.AP6256 Pin对Pin,可以直接替换. 二.原本 ...
最新文章
- 快速提高你的UI设计水平的一些小技巧
- 【scala】 scala 条件控制 和异常处理(二)
- 原始套接字SOCK_RAW
- 树莓派进阶之路 (037) - 设置树莓派3 B+的静态IP
- Linux中的文件描述符与打开文件之间的关系
- 库存管理-历史库存和收发存系列-俄罗斯库存报表J3RFLVMOBVED1
- spring boot基础教程:入门程序Hello World的编写
- 推荐21个顶级的Vue UI库! – TalkingData‘s Blog
- [置顶] 删除:大数据取舍之道读书笔记
- 性能测试——loadrunner_添加多个主机发送请求
- 使用强类型DataSet增加数据并获取自动增长的ID
- Atitit 编程语言原理与概论attilax总结
- 武汉CMMI3-CMMI5三年到期后复审指南
- 微信小程序实现物流步骤条
- 【黑灰产犯罪研究】恶意点击
- 高压均质机原理、使用方法及维护注意事项
- 首次登录Navicat连接数据库遇到的问题
- 2022-XTU程设练习1
- 蓝宇数码冲刺深交所:年营收2.72亿 郭振荣控制45%股权
- cesium颜色值赋值