1. 程式人生 > >i.MX6Q -- Linux系統下FlexCAN總線的使用記錄

i.MX6Q -- Linux系統下FlexCAN總線的使用記錄

開發 static 結構 str sk_buff fat tar.bz2 prev cto

開發板平臺:珠海鼎芯D338 – 基於i.MX6Q
系統平臺:Linux3.0.35 + Busybox1.22

1、 需要的工具
FlexCAN工具包:
libsocketcan-0.0.10.tar.bz2
canutils-4.0.6.tar.bz2
交叉編譯器:
fsl-linaro-toolchain.tar.bz2

2、編譯過程:
交叉編譯器:
環境變量配置命令:
exportPATH=<YourCompilerPath>/fsl?linaro?toolchain/bin/:PATH

   libsocketcan-0.0.10:
  • 1
  • 2

使用tar命令解壓libsocketcan-0.0.10.tar.bz2後,使用如下命令交叉編譯並安裝。
./configureprefix=/flexcan/installhost=arm?none?linux?gnueabi

make && make install

   canutils-4.0.6:
  • 1
  • 2

同樣,交叉編譯並安裝命令如下。
./configureprefix=/flexcan/installhost=arm?none?linux?gnueabiCC=arm?none?linux?gnueabi?gcclibsocketcanCFLAGS=?I//flexcan/install/includelibsocketcanLIBS=?lsocketcanLDFLAGS=?L//flexcan/install/libenable?staticmake && make install

   移植拷貝安裝目錄下(<YourInstallPath>/flexcan/install)的所有文件到D338開發板/usr/目錄下即可;
  • 1
  • 2

至此,FlexCAN工具的移植就完成了,直接將文件系統打包為rootfs.tar.bz2,然後拷貝到dchip_MFGTools_Linux3.0.35_MX6Q_UPDATER工具下進行燒寫啟動就可以使用了,接下來,主要是FlexCAN總線的使用方法及詳細說明。

3、錯誤與解決:
錯誤1:
編譯canutils錯誤
canconfig.c:34:26: fatal error: libsocketcan.h: No such fileor directory
解決1:
將libsocketcan已編譯安裝目錄(/flexcan/install)下的include/can_netlink.h和libsocketcan.h文件,拷貝到canutils4.0.6/include目錄下

4、測試過程:
準備:兩個板子CAN總線進行相應管腳對接;

   開發板命令:
  • 1
  • 2

設置比特率: iplinksetcan0uptypecanbitrate125000使can0 ifconfig can0 up
查看can0信息: $ ifconfig can0

發送數據到0x123地址:
$ cansend can0 -i 0x123 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88

接收0x123地址數據:
canechocan0?v candump can0 –filter 0x123:/未設置ID濾波 /
或$ candump can0 –filter 0x123: 0x7FF/設置使用ID濾波 /

說明:
接收時,未使用ID濾波,可以接收總線上的所有數據,無論ID是否正確;
接收時,使用ID濾波,就只有符合要求的ID的數據,才做接收,其他ID的數據均丟棄不管。

使用以上測試方法測試時,發現filter id最大可用值為0x7FF;
ID = 0x7FF = 1111111 1111 = 11bit地址,說明當前使用的是標準格式;
如果想使用更多地址,需要設置為擴展幀格式。

如何設置CAN總線數據幀為擴展幀格式呢?

經過查看CAN驅動源碼發現:
在d-chip-linux3.0.35/drivers/net/can/flexcan.c中,有如下開始傳輸函數:
static int flexcan_start_xmit(struct sk_buff* skb,struct net_device *dev)
{
if (cf->can_id & CAN_EFF_FLAG) {
can_id = cf->can_id & CAN_EFF_MASK;
ctrl |= FLEXCAN_MB_CNT_IDE | FLEXCAN_MB_CNT_SRR;
} else {
can_id = (cf->can_id & CAN_SFF_MASK) << 18;
}

if (cf->can_id & CAN_RTR_FLAG)
ctrl |= FLEXCAN_MB_CNT_RTR;

if (cf->can_dlc > 0) {
u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
writel(data,&regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
}
if (cf->can_dlc > 3) {
u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
writel(data,&regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
}
}
查看以上源碼發現:
由cf->can_id & CAN_EFF_FLAG 按位’與’的運算結果來判斷當前是否是擴展幀格式,cf->can_id 是命令行設置的Filter ID, CAN_EFF_FLAG宏定義為0x80000000;因此,當命令行下設置ID時,使其最高位( id[31] )為1,即表示選擇為擴展幀格式;0表示選擇為標準幀格式。
而cf->can_id & CAN_RTR_FLAG用來判斷是否設置遠程幀請求;

以下是源碼中的結構說明:
/*
*Controller Area Network Identifier structure
*
*bit 0-28 : CAN identifier (11/29 bit)
*bit 29 : error frame flag (0 = dataframe, 1 = error frame)
*bit 30 : remote transmission requestflag (1 = rtr frame)
*bit 31 : frame format flag (0 =standard 11 bit, 1 = extended 29 bit)
*/
/**
*struct can_frame - basic CAN frame structure
*@can_id: the CAN ID of the frame andCAN_*_FLAG flags, see above.
*@can_dlc: the data length field of the CAN frame
*@data: the CAN frame payload.
*/
struct can_frame {
canid_t can_id; /* 32bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* datalength code: 0 .. 8 */
u8 data[8] __attribute((aligned(8))); /* 設定為8字節對齊 */
};

根據以上研究表明,想使用擴展幀格式,可按如下方法使用:
ifconfigcan0down/?CANCAN?/ ip link set can0 up type can bitrate 125000 /* 配置比特率並打開 */
ifconfigcan0/?CAN?/ cansend can0 -i 0x81234567 0x11 0x22 0x33 0x440x55 0x66 0x77 0x88 /* 發送8bytes數據到ID=0x1234567 */

canechocan0?v candump can0 –filter 0x81234567: 或
$ candump can0 –filter 0x81234567:0x1FFFFFFF
最大ID地址為0x1FFFFFFF ,即:–filter 0x9FFFFFFF:

i.MX6Q -- Linux系統下FlexCAN總線的使用記錄