基于zynq的CAN接口移植
博客专区 > sspg 的博客 > 博客详情
基于zynq的CAN接口移植
sspg 发表于3个月前
基于zynq的CAN接口移植
  • 发表于 3个月前
  • 阅读 1
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   

主机:Ubuntu 16.04

目标板:zynq + Linux内核4.4

一 硬件设计

    采用zynq的CAN接口,外面用物理芯片SN65HVD23x,挂载到CAN总线。开始感觉不用物理芯片也可以向串口一样进行回环测试,发现是不可能,查看CAN的协议可以发现原因。

    vivado生成相关文件,不在累述。

二 向内核中添加xilinx的can的驱动模块
[*] Networking support --->
    <*> CAN bus subsystem support --->
            CAN Device Drivers --->
                <*> Xilinx CAN
三 修改设备树文件
zynq-7000.dtsi文件中,已经包含CAN的设备树文件,只是status设置为了disabled
    can0: can@e0008000 {
        compatible = "xlnx,zynq-can-1.0";
        status = "disabled";
        clocks = <&clkc 19>, <&clkc 36>;
        clock-names = "can_clk", "pclk";
        reg = <0xe0008000 0x1000>;
        interrupts = <0 28 4>;
        interrupt-parent = <&intc>;
        tx-fifo-depth = <0x40>;
        rx-fifo-depth = <0x40>;
    };

    can1: can@e0009000 {
        compatible = "xlnx,zynq-can-1.0";
        status = "disabled";
        clocks = <&clkc 20>, <&clkc 37>;
        clock-names = "can_clk", "pclk";
        reg = <0xe0009000 0x1000>;
        interrupts = <0 51 4>;
        interrupt-parent = <&intc>;
        tx-fifo-depth = <0x40>;
        rx-fifo-depth = <0x40>;
    };
为了保持一致性,在system.dts文件中修改can的状态设置
    &can0 {
        status = "okay";
    };
    &can1 {
        status = "okay";
    };
三 通过cantest.c程序测试
可以通过ipconfig -a查看can接口状态
配置can0和can1

ip link set can0 down                                                           
ip link set can1 down                                                           
ip link set can0 type can bitrate 500000                                        
ip link set can1 type can bitrate 500000                                                           
ip link set can0 up                                                             
ip link set can1 up

can0和can1都挂载在can总线上
 

./cantest -r can0
./cantest -s can1

附cantest.c代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>


int main(int argc, char *argv[])
{
	int s, nbytes;
    int i;
	char *array[2] = {"-r", "-s"};
	struct sockaddr_can addr;
	struct ifreq ifr;
	struct can_frame frame;
	struct can_filter rfilter[1];


	/* handle (optional) flags first */
	if(argc != 3) {
		fprintf(stderr, "Usage:  %s <-r> <can interface name> for receiving\nor <-s> <can interface name> for sending\n", argv[0]);
		exit(1);
	}
    /* create socket */
	if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
	{
	    perror("Create socket failed");
	    exit(-1);
	}

	/* set up can interface */
	strcpy(ifr.ifr_name, argv[2]);
	printf("can port is %s\n",ifr.ifr_name);
	/* assign can device */
	ioctl(s, SIOCGIFINDEX, &ifr);
    addr.can_family = AF_CAN;
	addr.can_ifindex = ifr.ifr_ifindex;
    /* bind can device */
	if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		perror("Bind can device failed\n");
		close(s);
		exit(-2);
	}

	/* configure receiving */
	if(!strcmp(argv[1],array[0]))
	{
	    /* set filter for only receiving packet with can id 0x1F */
	    rfilter[0].can_id = 0x1F;
	    rfilter[0].can_mask = CAN_SFF_MASK;
	    if(setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter)) < 0)
	    {
	    	perror("set receiving filter error\n");
	    	close(s);
	    	exit(-3);
	    }
	    /* keep reading */
	    while(1){
	        nbytes = read(s, &frame, sizeof(frame));
	        if(nbytes > 0)
	        {
	        	printf("%s ID=%#x data length=%d\n", ifr.ifr_name, frame.can_id, frame.can_dlc);
	        	for (i=0; i < frame.can_dlc; i++)
	        		printf("%#x ", frame.data[i]);
	        	printf("\n");
	        }
	    }
	}
	/* configure sending */
	else if(!strcmp(argv[1],array[1]))
	{
        /* configure can_id and can data length */
		frame.can_id = 0x1F;
        frame.can_dlc = 8;
        printf("%s ID=%#x data length=%d\n", ifr.ifr_name, frame.can_id, frame.can_dlc);
        /* prepare data for sending: 0x11,0x22...0x88 */
        for (i=0; i<8; i++)
        {
        	frame.data[i] = ((i+1)<<4) | (i+1);
        	printf("%#x ", frame.data[i]);
        }
        printf("Sent out\n");
        /* Sending data */
        if(write(s, &frame, sizeof(frame)) < 0)
		{
            perror("Send failed");
            close(s);
            exit(-4);
		}
    }
	/* wrong parameter input situation */
	else
	{
	    printf("wrong parameter input\n");
	}

	close(s);
    return 0;
}

 

共有 人打赏支持
粉丝 0
博文 1
码字总数 641
×
sspg
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: