激情综合丁香-激情综合六月-激情综合婷婷亚洲图片-激情综合图区-激情综合网五月

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; 
        }

主站蜘蛛池模板: 亚洲欧美日韩中文字幕在线一| 日韩欧美亚洲国产一区二区三区| 国产高清在线视频| 成人国产精品免费视频| 美女被免费网站在线视频九色| 亚洲一区欧洲一区| 一级片在线观看| 日韩亚洲人成在线| 成人区视频| 免费能看的黄色网址| 国产成人影院| 国产精品第一区在线观看| 91国内视频| 国产精品视频网| 六月丁香激情综合成人| 亚洲tv成人天堂在线播放| 91在线一区二区三区| 久久中文字幕视频| 日韩中文字幕精品免费一区| 在线观看嗯啊成人动作片| 免费看日韩| 欧美国产日本| 国产大战女模特在线视频| 国产精品毛片无码| 美国免费黄色片| 萝l在线精品社区资源| 91久久网| 成人亚洲欧美日韩在线观看| 国产日韩一区| 久久9966e这里只有精品| 欧美久久久久久久一区二区三区| 亚洲va久久久久| 亚洲国产成人久久77| 在线亚州| 一区二区日韩欧美| 91看片淫黄大片欧美看国产片| 人成xxxwww免费视频| 三个黑人强一个女人视频| 久热香蕉视频| 久久亚洲黄色| 久久yy|