寫在前面

  在文章“嵌入式Linux的CAN匯流排配置——基於迅為iTOP-4412開發板”中我給4412開發板配置了SPI轉CAN模組,使用的是不帶裝置樹的核心。在本篇文章中,要使用支援裝置樹的核心,給iMX6UL開發板配置MCP2515。

  開啟iMX6UL開發板的串列埠終端,輸入命令ifconfig -a,可以看到CAN0和CAN1兩個裝置,這是iMX6UL晶片自帶的兩路FlexCAN。

  在完成配置MCP2515模組之後,輸入命令ifconfig -a,可以看到三路CAN,其中CAN1和CAN2是iMX6UL晶片自帶的兩路FlexCAN,而CAN0便是通過MCP2515實現的SPI轉CAN。

硬體連線

  將SPI轉CAN模組插到iMX6UL開發板的GPIO插槽上。

  需要注意的是,該GPIO插槽中的PIN腳沒有支援ECSPI的,所以我們在這裡用的SPI是把相應的PIN腳用軟體模擬出的SPI。

  通過檢視GPIO插槽和SPI轉CAN的原理圖,可以知道MCP2515和GPIO插槽上PIN腳的對應關係。共需要五個PIN腳,分別是SPI_SCK,SPI_CS,SPI_MOSI,SPI_MISO,以及中斷引腳MCP2515_INT。

  再檢視核心板的文件,可以獲得MCP2515的這五個腳和iMX6UL晶片PIN腳的對應關係,如下表所示。

MCP2515 iMX6UL
SPI_SCK GPIO5_IO11
SPI_CS GPIO1_IO09
SPI_MOSI GPIO5_IO10
SPI_MISO GPIO3_IO07
MCP2515_INT GPIO1_IO31

# 修改裝置樹
  進入核心目錄,使用命令`vim Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt`開啟關於MCP2515的裝置樹幫助文件。

  可以根據該幫助文件的提示資訊來仿寫一個CAN節點。

  再開一個終端,進入核心目錄,使用命令vim arch/arm/boot/dts/imx6ul-14x14-evk_emmc.dts開啟開發板對應的裝置樹檔案(裝置樹檔案可能會因開發板型號的不同而不同,請開啟你的開發板對應的裝置樹檔案)。在裝置樹的根節點下,可以看到一個名為“spi4”的裝置節點,這個節點對應的就是模擬SPI。

  ①首先在“spi4”節點前增加一個時鐘節點,如下圖所示。

   clocks {

                mcp2515_clock: mcp2515_clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <8000000>; //對應模組上晶振的頻率,我的是8MHz的
}; };

  ②然後對“spi4”節點做修改,並刪除它的子節點“gpio_spi”,然後根據幫助文件自己寫一個“can0”節點作為“spi4”節點的子節點,如下圖所示(註釋部分為所做的修改或新增)。

   spi4 {
compatible = "spi-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi4>;
//pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;//這個引腳用不到
status = "okay";
gpio-sck = <&gpio5 11 0>;
gpio-mosi = <&gpio5 10 0>;
gpio-miso = <&gpio3 7 0>; //增加SPI_MISO引腳
//cs-gpios = <&gpio5 7 0>;
cs-gpios = <&gpio1 9 0>; //修改SPI_CS對應的引腳
num-chipselects = <1>;
#address-cells = <1>;
#size-cells = <0>; can0: can0@1 {
compatible = "microchip,mcp2515";
reg = <0>; //地址從0開始
clocks = <&mcp2515_clock>; //使用剛剛自己寫的時鐘
interrupt-parent = <&gpio1>; //中斷引腳配置,中斷引腳是GPIO1_IO31
interrupts = <31 0x2>; //中斷引腳配置,中斷引腳是GPIO1_IO31,引數0x2表示觸發方式
vdd-supply = <&reg_can_3v3>; //使用3.3V供電
xceiver-supply = <&reg_can_3v3>; //使用3.3V供電 spi-max-frequency = <1000000>; //最後增加spi最大頻率設定,設定為1MHz
};
};

  ③找到節點“pinctrl_spi4”,在該節點中新增SPI_CS和SPI_MISO相關的引腳,如下圖所示(有註釋的部分為所做的新增)。

pinctrl_spi4: spi4grp {
fsl,pins = <
MX6UL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1
MX6UL_PAD_BOOT_MODE1__GPIO5_IO11 0x70a1
MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1
MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x80000000
MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x80000000 /*SPI_CS*/
MX6UL_PAD_LCD_DATA02__GPIO3_IO07 0x70a1 /*SPI_MISO*/
>;
};

  ④搜尋“gpio1 9”和“GPIO1_IO09”,註釋掉裝置樹檔案自帶的和GPIO1_IO09引腳相關的內容(因為這個腳被我們用做SPI_CS了),如下圖所示。

  ⑤搜尋“I2C2_SCL”、“LCD_DATA00”、“LCD_DATA02”,註釋掉裝置樹原有的相關語句,如下圖所示。

  ⑥搜尋“spi_gpio”,把所有和“spi_gpio”相關的語句全部註釋掉,否則會編譯出錯(因為節點“spi_gpio”已經被刪除了),如下圖所示。



  ⑦然後分別進入裝置樹檔案“arch/arm/boot/dts/topeet_emmc_4_3.dts”、“arch/arm/boot/dts/topeet_emmc_5_0.dts”、“arch/arm/boot/dts/topeet_emmc_7_0.dts”、“arch/arm/boot/dts/topeet_emmc_9_7.dts”、“arch/arm/boot/dts/topeet_emmc_10_1.dts”、“arch/arm/boot/dts/topeet_emmc_1024x600.dts”這六個裝置樹檔案,刪除“gpio_spi”相關的語句,如下圖所示。

裁剪核心

  進入核心根目錄下,使用命令export ARCH=arm,指定架構。然後使用命令make menuconfig進入核心裁剪介面。

  ①進入“Device Drivers--->SPI support--->”,選中“GPIO-based bitbanging SPI Master”和“Freescale i.MX SPI controllers ”

  ②然後進入“Networking support--->CAN bus subsystem support--->CAN Device Drivers--->CAN SPI interfaces--->”,選中“Microchip MCP251x SPI CAN controllers”。

  儲存,並退出。

編譯和燒寫

  編譯核心和裝置樹,並將編譯出來的核心和裝置樹檔案燒寫到開發板中。重啟裝置,MCP2515裝置便可以使用了。

目前存在的問題

  每次裝置重啟後,第一次使用命令ifconfig can0 up啟動MCP2515會提示沒有該裝置,再啟動一次就能正常啟動了。

  裝置樹原始碼在這裡,下載下來後覆蓋掉“arch/arm/boot/dts/”路徑下相應的dts檔案即可。