目的:在imx6q上添加第二路CAN的驱动支持,并实现第二路CAN的通信功能。
CPU:imx6q
Linux:imx linux3.10.53
一、添加二路CAN的驱动支持
这个过程很简单,就是添加第二路CAN的设备树,驱动系统已经帮我们做好。
在内核源码中搜索can,可以在imx6q-sabresd.dts中发现如下信息:
这是原本已经添加的一路CAN的设备树(一部分代码),仿照此段添加另一路CAN的设备树即可。如下:
其中第4行的trx-stby-gpio是使能can芯片,低电平使能,如果原理图中已将此引脚拉低,可不写。
修改完成后重新编译,然后将设备树和内核烧入开发板启动,如果一切正确,ifconfig -a后可看到can0和can1。
二、两路CAN通信的Linux应用程序编写
两路can通信使用两条can总线,因此建立两个socket即可:
void can_init( void )
{
int socked, socked_can1;
struct sockaddr_can can_addr;
struct ifreq ifr;
int b_on=1;
if((socked = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
printf("if((socked = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) \n");
return;
}
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, DEV_CAN);
if (RET_SUCCESS != ioctl(socked, SIOCGIFINDEX, &ifr))
{
close(socked);
return;
}
printf("ioctl has been set \n");
t_RetData = ioctl (socked, FIONBIO, &b_on); //b_on=1,设置为非阻塞模式
memset(&can_addr, 0, sizeof(can_addr));
can_addr.can_family = AF_CAN;
can_addr.can_ifindex = 2;
if(bind(socked, (struct sockaddr *)&can_addr, sizeof(can_addr)) < 0)
{
close(socked);
return;
}
printf("CAN initialed");
s_Can0Socket = socked;
printf("InitCAN1 \n");
if((socked_can1 = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
printf("if((socked = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) \n");
return;
}
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, DEV_CAN1);
if (RET_SUCCESS != ioctl(socked_can1, SIOCGIFINDEX, &ifr))
{
printf("if (RET_SUCCESS != ioctl(socked, SIOCGIFINDEX, &ifr))\n");
close(socked_can1);
return;
}
printf("ioctl has been set \n");
b_on = 0;
t_RetData = ioctl(socked_can1, FIONBIO, &b_on);
printf("t_RetData:%d",t_RetData);
memset(&can_addr, 0, sizeof(can_addr));
can_addr.can_family = AF_CAN;
can_addr.can_ifindex = 3; // 这里ifindex不能和第一个的相同,不然会有问题。可以在系统中查看此值
if(bind(socked_can1, (struct sockaddr *)&can_addr, sizeof(can_addr)) < 0)
{
close(socked_can1);
return;
}
printf("CAN initialed ");
s_Can1Socket = socked_can1;
return;
}