Ubuntu16.04+Xenomai内核重启CAN电机后PCAN报I/O错误如何解决
问题根源
- 电机断电时CAN总线状态异常,PCAN适配器受Xenomai实时内核的IO栈调度限制,默认没有开启总线状态自动重置逻辑,内核驱动持有的硬件状态与实际硬件状态不一致,导致重新初始化进入正常工作模式时报I/O错误。
- 你的代码中打开端口时没有添加硬件状态重置逻辑,直接尝试进入工作模式,硬件卡在Bus Off/离线状态时就会初始化失败。
- 整机重启后硬件和驱动都会重新初始化,状态同步后就会恢复正常。
解决方案
1. 临时验证方案(无需修改代码)
出现错误后,直接卸载再重新加载pcan内核模块即可恢复,不需要重启整机:
sudo rmmod pcan sudo modprobe pcan
如果执行后代码运行正常,即可确认是驱动与硬件状态不一致导致的问题。
2. 代码层面修复方案
在打开端口前添加硬件复位逻辑,同时开启驱动的Bus Off自动管理能力,修改main.cpp代码如下:
#include <sys/time.h> #include <lcm/lcm_coretypes.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <inttypes.h> #include <unistd.h> #include <fcntl.h> #include <signal.h> #include <pthread.h> #include <errno.h> #include <sys/syscall.h> #include <pcanfd.h> #include <libpcanfd.h> #include <cmath> #include <iostream> int main(int argc, char *argv[]){ int fd; // 先尝试复位设备,清除之前的异常状态 int reset_ret = pcanfd_reset("/dev/pcan0", 0); if (reset_ret < 0) { printf("Reset device returned %d, ignore and continue open\n", reset_ret); } sleep(1); // 给硬件留足够的复位时间 // 打开参数新增PCANFD_INIT_BUS_OFF_MANAGED,让驱动自动处理Bus Off状态 fd = pcanfd_open("/dev/pcan0", OFD_BITRATE | PCANFD_INIT_STD_MSG_ONLY | OFD_NONBLOCKING | PCANFD_INIT_BUS_OFF_MANAGED, 1000000); if (fd < 0) { printf("First open failed with err %d, retry after full reset\n", fd); // 首次打开失败时执行完整复位后重试一次 reset_ret = pcanfd_reset("/dev/pcan0", 1); sleep(1); fd = pcanfd_open("/dev/pcan0", OFD_BITRATE | PCANFD_INIT_STD_MSG_ONLY | OFD_NONBLOCKING | PCANFD_INIT_BUS_OFF_MANAGED, 1000000); if (fd < 0) { printf("Retry open still failed: %d\n", fd); exit(1); } } printf("Open succeeded with return value %d on port no. %s\n",fd, "/dev/pcan0"); }
3. 驱动层面永久配置方案
修改pcan内核模块加载参数,开启总线异常自动复位能力,无需修改代码即可自动处理断电异常:
- 新建/编辑
/etc/modprobe.d/pcan.conf文件,添加如下配置:
options pcan fd=1 auto_restart_ms=1000
参数说明:auto_restart_ms=1000表示总线进入Bus Off状态后1秒自动执行复位操作,可根据实际需求调整时长。
2. 执行以下命令让配置开机生效:
sudo update-initramfs -u
额外优化建议
你的项目根目录CMakeLists.txt存在冗余配置,已经直接通过add_executable(io_error_debug src/main.cpp)指定了源文件,无需再调用add_subdirectory(src),src目录下的CMakeLists.txt没有实际作用可以删除,不影响当前功能但能避免后续构建出现潜在问题。
内容的提问来源于stack exchange,提问作者echo_sg
相关产品推荐
相关产品推荐

