一、问题概述
环境是两块stm32H743单板级联进行利用CAN协议栈进行通信,CAN的报文帧一次只能传输8字节,其中还有一部分是CAN帧头的部分,实际传输的用户数据还达不到8字节,所以当想传输的数据超过8字节时就需要进行多帧传输了,CAN的协议栈就是解决了这一问题,多帧通信的大致流程如图所示,目前我这边进行多帧通信时会出现接收方进程挂死,根据zephyr的报错信息显示是cpu0堆栈溢出,报错信息也放在下图。
二、问题定位
看到堆栈溢出就大致猜测是某个进程申请的栈空间不够,于是在代码里面直接加大接收线程和主线程的栈空间(主线程栈空间大小在配置文件CONFIG_MAIN_STACK_SIZE,接收线程是在代码K_THREAD_STACK_DEFINE(rx_0_5_thread_stack, RX_THREAD_STACK_SIZE)定义),重试了一下多帧通信,发现问题依旧存在,排除了这俩线程的栈空间问题,瞬间没了方向,因为目前能感知的进程就这俩,不是这俩进程溢出感觉没其他方向。
之后就开始头脑风暴了,试了下是不是硬件的接收缓冲区不够导致的溢出,虽然硬件问题应该跟软件栈溢出没关系,但是瞎摸就多方向尝试了,于是降低了下报文字节,多帧下一CAN帧只会携带6个字节用户数据,于是我试着发7个字节发文,结果问题依旧存在。之后怀疑是硬件不支持协议栈那么高的发包速率,于是在单帧通信下每帧间隔一毫秒发送发现没问题,现在基本是排除了硬件层面支持的问题。
软件问题还是要回归代码,于是开始走读整个接收流程,过程中发现多帧的接收处理流程进行了大量日志的记录,于是猜想有没可能是日子记录太多导致,阅读了下zephyr官方关于日志这块的表述,zephyr的日志是先放进缓冲区,在系统空闲在讲数据输出到后端设备,猜想有可能是缓冲区溢出或者记录日志文件超出范围。尝试了下减少接收流程的两条日志记录,溢出问题立马解决,这下子算是找到根因了。
三、问题解决
既然是日志记录的问题,那就就只需要考虑zephyr日志记录涉及的两个关键因素一个是缓冲区大小,这个关系到大量日志记录时候缓冲区不够会出现日志丢失的情况;还有一个是日志进程栈空间大小,也是本次问题的触发点,加大栈空间后运行正常。详细可以看看zephyr对于日志模块的介绍:https://docs.zephyrproject.org/latest/services/logging/index.html#controlling-the-logging
(发送数据给对端成功并成功接收到对端传来的数据:Z-10111111111111)