• zynq+linux+ramdisk can调试


    由于采用ramdisk文件系统,自带的ip工具版本太旧无法配置can,需要自行编译ip,具体参见参考文献2

    1.vivado配置ps

    2.设备树增加can0,一般开发板均已提供此配置

    can@e0008000 {
    			compatible = "xlnx,zynq-can-1.0";
    			status = "okay";
    			clocks = <0x1 0x13 0x1 0x24>;
    			clock-names = "can_clk", "pclk";
    			reg = <0xe0008000 0x1000>;
    			interrupts = <0x0 0x1c 0x4>;
    			interrupt-parent = <0x3>;
    			tx-fifo-depth = <0x40>;
    			rx-fifo-depth = <0x40>;
    		};

    3.kernel配置,一般已配好,具体参见参考文献1

    4.测试

    # ifconfig -a
    can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
              NOARP  MTU:16  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:10
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
              Interrupt:22
    
    eth0      Link encap:Ethernet  HWaddr 00:0A:35:00:01:22
              inet addr:192.168.0.120  Bcast:192.168.0.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:397 errors:0 dropped:0 overruns:0 frame:0
              TX packets:242 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:476490 (465.3 KiB)  TX bytes:18536 (18.1 KiB)
              Interrupt:148 Base address:0xb000
    
    lo        Link encap:Local Loopback
              LOOPBACK  MTU:65536  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

    设置can0的波特率,这里设置的是100k, ip程序一般需要自己编译生成,参见2
    #./ip link set can0 up type can bitrate 100000
    显示can0状态信息
    #./ip -d -s link show can0

    Z-turn# ./ip link set can0 type can bitrate 100000
    xilinx_can e0008000.can can0: bitrate error 0.0%
    Z-turn#./ip link set can0 up
    Z-turn#./ip -d -s link show can0
    2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
        link/can  promiscuity 0
        can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
              bitrate 99999 sample-point 0.750
              tq 2500 prop-seg 1 phase-seg1 1 phase-seg2 1 sjw 1
              xilinx_can: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..256 brp-inc 1
              clock 99999999
              re-started bus-errors arbit-lost error-warn error-pass bus-off
              0          0          0          0          0          0         numtxqueues 1 numrxqueues 1
        RX: bytes  packets  errors  dropped overrun mcast
        0          0        0       0       0       0
        TX: bytes  packets  errors  dropped carrier collsns
        0          0        0       0       0       0

    5.下面程序为收发测试,也可参见参考文献3

    /*****************************************************************************
     * Copyright (c) 2014-2017 MYIR Tech Ltd.
     *        File: can-test.c
     *        Date: 2014/11/3
     *      Author: Kevin Su
     * Description: A demo program to show how to transmit/receive data with
     *              socket can interface on CAN bus.
     *                Please note that, this demo needs two boards to run as
     *                transmitter and receiver.
     *                Before run "can-test", we need to config the bitrate with
     *              "ip" command:
     *              # ip link set can0 up type can bitrate 100000
     */
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <net/if.h>
    #include <linux/can.h>
    #include <linux/can/raw.h>
    
    #define DEBUG    1
    
    #define ERR_MSG(fmt, args...)    fprintf(stderr, fmt, ##args)
    #ifdef DEBUG
        #define DBG_MSG(fmt, args...)    fprintf(stdout, fmt, ##args)
    #else
        #define DBG_MSG(fmt, args...)
    #endif
    
    #ifndef PF_CAN
        #define PF_CAN 29
    #endif
    
    #ifndef AF_CAN
        #define AF_CAN PF_CAN
    #endif
    
    int main(int argc, char *argv[])
    {
        int fd, ret, flag, len;
        char senddata[32] = "test";
        struct sockaddr_can addr;
        struct ifreq ifr;
        struct can_frame frame;
        socklen_t socket_len = sizeof(struct sockaddr_can);
    
        /* Create a socket with PF_CAN family, SOCK_RAW and CAN_RAW protocol */
        fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); 
        if (fd < 0) {
            ERR_MSG("Open socket failed!
    ");
            return fd;
        }
    
        /* Use can0 */
        strcpy((char *)(ifr.ifr_name), "can0");
        
        /* Get information */
        ret = ioctl(fd, SIOCGIFINDEX, &ifr);
        if (ret != 0) {
            ERR_MSG("SIOCGIFINDEX failed! ret:%d
    ", ret);
            close(fd);
            return ret;
        }
        DBG_MSG("can0 can_ifindex = %x
    ",ifr.ifr_ifindex);
    
        /* Disable loopback */
        flag = 0;
        ret = setsockopt(fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &flag, sizeof(flag));
        if (ret != 0) {
            ERR_MSG("Set loopback disable failed! ret:%d
    ", ret);
            close(fd);
            return ret;
        }
        DBG_MSG("Set can0 loopback disable
    ");
    
        /* Disable receiving own message */
        flag = 0;
        ret = setsockopt(fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, 
                   &flag, sizeof(flag));
        if (ret != 0) {
            ERR_MSG("Disable receiving own message failed! ret:%d
    ", ret);
            close(fd);
            return ret;
        }
        DBG_MSG("Disable receiving own message
    ");
    
        /* Use AF_CAN protocol family */
        addr.can_family = AF_CAN;
        addr.can_ifindex = ifr.ifr_ifindex;
        
        /* Binding socket */
        ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
        if (ret != 0) {
            ERR_MSG("Bind socket failed! ret:%d
    ", ret);
            close(fd);
            return ret;
        }
        DBG_MSG("Bind can0 socket
    ");
    
        frame.can_id = 0x123;
        len = strlen(senddata);
        
        while (1) {
            strncpy((char *)frame.data, senddata, len);
            frame.can_dlc = len;
            ret = sendto(fd, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr, sizeof(addr));
            if (ret > 0) {
                DBG_MSG("Send success: [%s], ret=%d
    ", senddata, ret);
                ret = recvfrom(fd, &frame, sizeof(struct can_frame), 0, (struct sockaddr *)&addr, &socket_len);
                if (ret > 0) {
                    DBG_MSG("Recv message: [%s], ret=%d
    ", frame.data, ret);
                }
            }
            usleep(500000);
        }
    
        return 0;
    }

     超时设置(参考文献4):

    struct timeval timeout = {1,0}; //1.0s
     //设置发送超时
    setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
    //设置接收超时
    setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));

     对于offline节点处理:

     如果该控制器没有连接到can网络上,调用send会返回成功,但只是发送至kernel的缓冲区,并非发送至can网络。kernel会一直尝试重发,即使关闭socket或结束进程都不会取消重  发操作,此时如果将控制器连接到can网络上则会一次性将缓冲区内所有内容发出,有时这并非所要结果。如果想要清空发送和接收缓冲区,只能重启can接口

    ifconfig can0 down
    ifconfig can0 up

     在程序中可使用system调用。

    有两点注意就是
    1)recv ()的第四个参数需为MSG_WAITALL,在阻塞模式下不等到指定数目的数据不会返回,除非超时时间到。

        2)即使等待超时时间值未到,但对方已经关闭了socket, 则此时recv()会立即返回,并收到多少数据返回多少数据。

    参考文献:

    1.http://xilinx.eetrend.com/blog/12062

    2.http://www.cnblogs.com/hujianhua/p/8446291.html

    3.https://wenku.baidu.com/view/65baea51bb68a98271fefaa7.html

    4.https://blog.csdn.net/newger/article/details/2459113

  • 相关阅读:
    L208
    L207
    L206
    L205 EE
    L204
    监控glusterfs
    监控elssticSearch健康状态
    防火墙
    创建逻辑卷
    编译安装nginx,并使用systemd管理nginx
  • 原文地址:https://www.cnblogs.com/hujianhua/p/8446344.html
Copyright © 2020-2023  润新知