寫在前面
在文章“嵌入式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 = <®_can_3v3>; //使用3.3V供電
xceiver-supply = <®_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文件即可。