socketcan如何获取发送失败状态?

问题描述 投票:0回答:1

大家都知道,在CAN总线通信协议中,发送方知道数据是否发送成功。我发送socketcan数据的过程如下。

ret = write (socket, frame, sizeof (struct can_frame));

但是,即使CAN通信电缆断开,ret的返回值仍然是16(=sizeof(struct can_frame)).我查询资料,发现问题出在socketcan使用的网络栈的tx_queue上。当多次调用write时,缓冲区已满,ret的返回值为-1。但这并不是我所期望的行为,我希望每发送一帧数据都能立即得到成功或失败的状态。

echo 0> / sys / class / net / can0 / tx_queue_len

我想取消tx_queue,但是没有成功。我想问的是,有没有办法取消socketcan的tx_queue,或者通过API(如libsocketcan)来获取每个发送帧关于控制器的状态。 谢谢。

linux-device-driver embedded-linux can-bus zynq socketcan
1个回答
0
投票

你不能使用 write() 本身来发现CAN帧是否被成功地放在总线上,因为它所做的只是将帧写入内核的socket缓冲区。然后内核将帧移动到SocketCAN网络接口的发送队列中,接着驱动将其移动到CAN控制器的发送缓冲区,最后将帧放在总线上。你想要的是绕过所有这些缓冲区的直接写入,但这在SocketCAN中是不可能的,即使你把发送队列的长度设置为0。

不过,还有一种方法可以得到确认。如果您启用了 CAN_RAW_RECV_OWN_MSGS 插座选项(见第4.1.4节和第4.1.7节)。SocketCAN文档),您将收到成功发送的帧。您需要使用 recvmsg() 所以你得到的消息标志。msg_flags 将有 MSG_CONFIRM 位设置的帧被成功发送的同一个套接字接收。你不会被告知失败,但你可以通过使用超时确认来检测它们。

这不是一个理想的解决方案,因为它混合了你的应用程序中的读和写逻辑。避免这种情况的一种方法是使用两个套接字。一个用于写和读 MSG_CONFIRM 帧,另一个用于读取所有其他帧。然后你可以创建一个(阻塞)写函数,做一个 write() 随后多次致电 recvmsg() 适当的超时。

最后,启用错误帧是很有用的(通过 CAN_RAW_ERR_FILTER socket选项)。) 如果你在一个断开电缆的插座上发送一个帧,通常会导致总线关闭状态,这将在一个错误帧中报告。

© www.soinside.com 2019 - 2024. All rights reserved.