轉自http://blog.csdn.net/yaolanshu_june/article/details/52152790
本文主要驗證kernel/Documentation/spi目錄下spidev_test.c的測試例程,能否正??刂芐PI接口。
一、驅動配置1.修改設備樹找到內核源碼的linux-imx_share/arch/arm/boot/dts目錄下的imx6qdl-sabresd.dtsi,找到ecspi1的代碼
將spidev這段注釋去掉,開啟這段代碼。
2.修改內核配置輸入:make ARCH=arm menuconfig進行內核配置,進入配置界面,依次選擇Device Drivers->SPI support,使User mode SPI device driver support選項起作用,選擇Y,并save。
選擇這個的目的是使spidev.c參與編譯,原因可以參考linux-imx_share/drivers/spi目錄下的Kconfig和Makefile。
配置好之后,運行./build.sh,編譯生成zImage,zImage-imx6dl-sabresd-emmc.dtb燒寫進板子。檢查新燒進去的系統里,dev目錄下有無spidev32766.0。如有,表示spidev的設備驅動燒寫成功。
二、測試1.找到ECSPI的引腳,連接MISO和MOSI,進行自回環測試。
2.編寫makefile生成自測代碼spidev_test.c對應的可執行程序。
使用rz命令,將spidev_test上載至板子
接收的數據正確,自回環測試成功。------------------------------------------------------------------------------------------------------------------------------------疑問:生成的設備節點為什么是spidev32766.0?
在spidev.c中的函數spidev_PRobe里,找到設備節點的賦值。[objc] view plain copy print?spidev->devt = MKDEV(SPIDEV_MAJOR, minor); //計算出設備號 //創建設備/dev/spidev%d.%d(spidev總線號.片選號) dev = device_create(spidev_class, &spi->dev, spidev->devt, spidev, "spidev%d.%d", spi->master->bus_num, spi->chip_select); 下面看下spi->master->bus_num和spi->chip_select的值。
在drivers/spi目錄下的spi.c文件中,spi_alloc_master函數中,給master->bus_num = -1進行了初始化。[objc] view plain copy print?struct spi_master *spi_alloc_master(struct device *dev, unsigned size) { struct spi_master *master; if (!dev) return NULL; master = kzalloc(size + sizeof(*master), GFP_KERNEL); if (!master) return NULL; device_initialize(&master->dev); <span style="color:#3333ff;">master->bus_num = -1; //初始化 <span style="color:#3333ff;">master->num_chipselect = 1; master->dev.class = &spi_master_class; master->dev.parent = get_device(dev); spi_master_set_devdata(master, &master[1]); return master; } 在spi_register_master函數中,對bus_num進行了處理[objc] view plain copy print?/* convention: dynamically assigned bus IDs count down from the max */ if (master->bus_num < 0) <span style="font-family: Arial, Helvetica, sans-serif;">{</span> [objc] view plain copy print?/* FIXME switch to an IDR based scheme, something like * I2C now uses, so we can't run out of "dynamic" IDs */ master->bus_num = atomic_dec_return(&dyn_bus_id); dynamic = 1;
其中dyn_bus_id計算結果是32767[objc] view plain copy print?static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); [objc] view plain copy print?#define atomic_dec_return(v) (atomic_sub_return(1, v)) [objc] view plain copy print?static inline int atomic_sub_return(int i, atomic_t *v) { unsigned long flags; int val; raw_local_irq_save(flags); val = v->counter; v->counter = val -= i; raw_local_irq_restore(flags); return val; } 如此計算出master->bus_num=32766。of_register_spi_devices函數里chip_select的獲得是通過value賦值的,而value是通過設備樹里的reg后面的值取得的[objc] view plain copy print?/* Device address */ rc = of_property_read_u32(nc, "reg", &value); if (rc) { dev_err(&master->dev, "%s has no valid 'reg' property (%d)/n", nc->full_name, rc); spi_dev_put(spi); continue; } spi->chip_select = value; [objc] view plain copy print?spidev: spidev@0 { spi-max-frequency = <24000000>; reg = <0>; compatible = "rohm,dh2228fv"; }; 所以生成的設備節點號是spidev32766.0。
如果在imx6qdl-sabresd.dtsi設備樹里,改成下面這樣,則生成的設備節點號是spidev32766.1。[plain] view plain copy print?&ecspi1 { fsl,spi-num-chipselects = <2>; //改成2 cs-gpios = <&gpio2 30 0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi1_1>; status = "okay"; Flash: m25p32@0 { #address-cells = <1>; #size-cells = <1>; compatible = "winbond,w25q32"; spi-max-frequency = <20000000>; reg = <0>; }; spidev: spidev@1 { spi-max-frequency = <24000000>; reg = <1>; compatible = "rohm,dh2228fv"; }; };
新聞熱點
疑難解答