<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • EM9287 Linux Socket CAN驅動簡介

     2013-9-9              

    一、簡述

     

            EM9287工控主板CPU為Freescale 的iMX287,主頻454MHz,以具有豐富的通訊接口為特色,可同時支持雙網口、7路串口、32路GPIO、SPI、I2C以及CAN通訊等接口。CAN是一種在世界范圍內廣泛用于自動控制、嵌入式設備和汽車領域的網絡技術,EM9287 的CAN通訊接口是通過FlexCAN模塊來實現控制局域網絡協議(CAN)通信的,FlexCAN模塊同時支持CAN協議規范2.0,包括協議所規定的標準幀和擴展幀。

     

            Linux下最早使用CAN的方法是基于字符設備來實現的,在EM9287上移植的Linux-3.9.7內核中FlexCAN模塊驅動實現的是Socket CAN方式,Scoket CAN使用了socket接口和Linux網絡協議棧,這種方法使得CAN設備驅動可以通過網絡接口函數來調用,這樣大大地方便了熟悉Linux網絡編程的程序員,由于調用的都是標準的socket 函數,也使得應用程序便于移植,而不會因為硬件的調整而修改應用程序,這樣加強了應用程序的可維護性。關于Socket CAN在Linux內核文檔中有更為詳細的介紹(/Linux-3.9.7/Documentation/networtking/can.txt)。

     

            本文將簡要介紹EM9287在Linux-3.9.7內核上如何實現CAN驅動以及如何在應用程序中使用Socket CAN。

     

    二、Linux內核配置

     

            內核配置中增加以下選項(make menuconfig):

     

            Networking support --->
            <*> CAN bus subsystem support --->
            <*> Raw CAN Protocol (raw access with CAN-ID filtering) 
            <*> Broadcast Manger CAN Protocol (with content filtering)
            <*> CAN Gateway/Router (with netlink configuration)
                CAN Device Drivers --->
            <*> Platform CAN drivers with Netlink support
            [*] CAN bit-timing calculation 
            <*> Support for Freescale FLEXCAN based chips

     

            EM9287移植的是Linux-3.9.7版本,對于硬件的描述和配置都是通過device tree相關文件進行傳遞,除了內核的配置外,還需要在相應的dst文件中增加can0節點。如:

     

            can0: can@80032000 {
                    compatible = 'fsl,imx28-flexcan', 'fsl,p1010-flexcan';
                    reg = <0x80032000 0x2000>;
                    interrupts = <8>;
                    clocks = <&clks 58>, <&clks 58>;
                    clock-names = 'ipg', 'per'; 
                    pinctrl-names = 'default';
                    pinctrl-0 = <&can0_pins_a>;
            };

     

            內核編譯成功后,板卡啟動顯示即表示flexcan驅動加載成功。

            [ 2.022398] CAN device driver interface 
            [ 2.031257] flexcan 80032000.can: device registered (reg_base=f5032000, irq=190)

     

    三、Socket CAN的測試

     

            Socket CAN 的使用會用到ip命令工具,由于busybox中的ip沒有支持 socket can,所以需要重新移植ip工具,iproute2中的ip可以支持socket can。

     

    1、移植iproute2
            從iproute2官方網站上下載源碼,我們這里用到的是iproute2-3.10.0.
            1) tar jxvf iproute2-3.10.0
            2) 修改Makefie
            CC=arm-none-linux-gnueabi-gcc
            由于只用到ip工具,所以將別編譯目錄屏蔽:
            #SUBDIRS=lib ip tc bridge misc netem genl man
            SUBDIRS=lib ip
            3) make編譯成功后生成 “ip”
            4) 將ip復制到EM9287的文件系統中,替換原來busybox中的ip

     

            這樣ip命令工具就算是移植好了。

     

    2、使用ip命令配置can0接口。
            // 關閉can0接口,以便進行配置
            ifconfig can0 down
            // 方法一:配置can0的波特率為250Kbps
            ip link set can0 type can bitrate 250000
            // 方法二:配置can0的波特率為250Kbps
            ip link set can0 type can tp 250 prog-seg 5 phase-seg1 8 phase-seg2 2 sjw 2
            // 啟動can0接口
            ifconfig can0 up

     

            EM9287的FLEXCAN時鐘選用的是24MHz的外部晶體振蕩時鐘。為了適應各種不同的采樣率,我們采用方法二來對can的波特率進行設置,以CiA推薦的采樣點在bit的87.5%處,作為基準來計算:

     


    波特率PRESDIV
    -> fTq
    TSEG1TSEG2TQ采樣點
    PROPSEG+PSEG1+2PSEG2+1
    10001 -> 12MHz(0 + 7 + 2)= 9(1+1)= 21283.3%
    8001 -> 12MHz(3 + 7 + 2)= 12(1+1)= 21586.6%
    5002 -> 8MHz(4 + 7 + 2)= 13(1+1)= 21687.5%
    2505 -> 4MHz(4 + 7 + 2)= 13(1+1)= 21687.5%
    12511 -> 2MHz(4 + 7 + 2)= 13(1+1)= 21687.5%
    10014 -> 1.6MHz(4 + 7 + 2)= 13(1+1)= 21687.5%
    6024 -> 960KHz(4 + 7 + 2)= 13(1+1)= 21687.5%
    5029 -> 800KHz(4 + 7 + 2)= 13(1+1)= 21687.5%
    2074 -> 320KHz(4 + 7 + 2)= 13(1+1)= 21687.5%
    10149 -> 160KHz(4 + 7 + 2)= 13(1+1)= 21687.5%


     

    3、Scoket CAN測試代碼

     

            就像TCP/IP協議一樣,在使用CAN網絡之前首先需要打開一個套接字。CAN的套接字使用到了一個新的協議族PF_CAN,所以在調用socket( )這個系統函數的時候需要將PF_CAN作為第一個參數。當前有兩個CAN的協議可以選擇,一個是原始套接字協議( raw socket protocol),另一個是廣播管理協議BCM(broadcast manager)。作為一般的工業應用我們選用原始套接字協議:

            s = socket(PF_CAN, SOCK_RAW, CAN_RAW);

     

            在成功創建一個套接字之后,通常需要使用bind( )函數將套接字綁定在某個CAN接口上。在綁定 (CAN_RAW)套接字之后,就可以在套接字上使用read( )/write( )進行數據收發的操作。

     

            基本的CAN幀結構體和套接字地址結構體定義在include/linux/can.h

     

            /*
             * 擴展格式識別符由 29 位組成。其格式包含兩個部分:11 位基本 ID、18 位擴展 ID。
             * Controller Area Network Identifier structure
             *
             * bit 0-28 : CAN識別符 (11/29 bit)
             * bit 29 : 錯誤幀標志 (0 = data frame, 1 = error frame)
             * bit 30 : 遠程發送請求標志 (1 = rtr frame)
             * bit 31 :幀格式標志 (0 = standard 11 bit, 1 = extended 29 bit)
            */
            typedef __u32 canid_t;
            struct can_frame {
                    canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ 
                    __u8 can_dlc; /* 數據長度: 0 .. 8 */ 
                    __u8 data[8] __attribute__((aligned(8)));
            };

     

            以下為相關的測試代碼:

     

            int main( int argc,char* argv[] )
            {
                    int i1, ret; 
                    int nbytes, baudrate; 
                    int s;
                    struct sockaddr_can addr;
                    struct ifreq ifr;
                    struct can_frame frame;

                    printf( 'SocketCAN Test V1.0\n' );
                    // 解析命令行參數, CAN波特率
                    if( argc > 1 )
                    {
                            baudrate = atoi( argv[1] );
                    }
                    else
                    {
                            baudrate = 250000;
                    }
                    printf( 'bitrate is %d\n', baudrate );
                    set_can_bittiming( baudrate );

                    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
                    printf( 'SOCK_RAW can sockfd:%d\n', s );
                    if( s < 0 )
                    {
                            return -1; 
                    }

                    int loopback = 0; /* 0 = disabled, 1 = enabled (default) */
                    setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

                    strcpy(ifr.ifr_name, 'can0' );
                    ret = ioctl(s, SIOCGIFINDEX, &ifr);
                    if( ret < 0 )
                    {
                            return -1;
                    }

                    addr.can_family = AF_CAN;
                    addr.can_ifindex = ifr.ifr_ifindex;
                    bind(s, (struct sockaddr *)&addr, sizeof(addr));

                    for( i1=0; i1<10; i1++ )
                    {
                            nbytes = read(s, &frame, sizeof(struct can_frame));
                            if (nbytes < 0) {
                                    perror('can raw socket read');
                                    return 1;
                            }
                            if( nbytes < (int)sizeof(struct can_frame))
                            {
                                    perror('read: incomplete CAN frame\n'); 
                                    return 1;
                            }
                            /* do something with the received CAN frame: send back */
                            nbytes = write(s, &frame, sizeof(struct can_frame));
                            printf( '%d sendbytes: %d\n', i1+1, nbytes );
                    }
                    close( s );
                    return 0; 
            }

    一本久久a久久精品综合夜夜| 国产91成人精品亚洲精品| 久久国产精品免费一区二区三区| 玩弄人妻少妇精品视频| 北岛玲在线精品视频| 91精品福利一区二区三区野战| 日韩精品一区二区三区中文3d| 2022国产成人精品视频人| 国产精品亚洲天堂| 蜜芽国内精品视频在线观看| 国产精品无码无卡无需播放器 | 国产精品亚洲а∨无码播放麻豆| 亚洲精品国产啊女成拍色拍| 久久se精品一区精品二区| 久久精品国产亚洲av天美18| 精品国产污污免费网站| 国产精品99久久久久久宅男| 91精品国产91久久久久| 久久国产精品范冰啊| 亚洲精品tv久久久久久久久| 国产内地精品毛片视频| 四虎永久在线精品免费影视| 最新国语自产精品视频在| 亚洲色偷精品一区二区三区 | 亚洲精品综合久久| 亚洲乱码日产精品BD在线观看| 久久久精品午夜免费不卡| 日韩精品国产一区| 久久无码av亚洲精品色午夜| 精品国产一二三区在线影院| 亚洲宅男精品一区在线观看| 久久99国产综合精品免费| 久久久久九国产精品| 国产精品美女网站在线观看| 香蕉99久久国产综合精品宅男自 | 久久亚洲精品视频| 久久精品国产影库免费看| 亚洲精品成人网站在线观看| 人人妻久久人人澡人人爽人人精品| 久久久精品人妻无码专区不卡| 国产精品青草视频免费播放|