博客專欄

        EEPW首頁 > 博客 > 嵌入式linux之iMX6ULL驅動開發 | 通用spi驅動之spidev使用總結

        嵌入式linux之iMX6ULL驅動開發 | 通用spi驅動之spidev使用總結

        發布人:電子禪石 時間:2024-02-03 來源:工程師 發布文章

        因為興趣,業余時間把玩下手邊的imax6ul開發板。Linux內核集成了spidev驅動,

        提供了SPI設備的用戶空間API。支持用于半雙工通信的read和write訪問接口以及用于

        全雙工通信和I/O配置的ioctl接口。使用時,只需將SPI從設備的compatible屬性值添加

        到spidev區動的spidev dt ids[]數組中,即可將該SPI從設備創建為spidev設備。

        如果不想編寫單獨的spi設備驅動,那么使用linux內核提供的通用spidev設備驅動就夠了,

        它提供統一的字符設備操作,那么只需要在應用層讀寫和控制即可。

        spidev驅動

        spidev是一個Linux內核驅動,用于與SPI(串行外設接口)設備進行通信。SPI是一種全雙工、

        同步的串行通信協議,常用于連接微控制器和外部設備。spidev驅動允許用戶空間程序通過

        Linux的設備文件接口與SPI設備進行通信。用戶可以通過打開和讀寫設備文件來發送和

        接收SPI數據。spidev驅動提供了一組控制IO口和SPI參數的ioctl命令。


        同時Linux內核也集成了SPI測試工具spidev test,用于在用戶態對spidev動功能進行測試

        和驗證。


        spidev設備驅動源碼位置在:linux-imx-4.1.15driversspispidev.c

        驅動框架框圖:

        1706957541784792.png

           

        除了使用spidev驅動外,當然也可以自己編寫SPI驅動。


        使用現有的spidev驅動可以簡化開發過程,因為它提供了一組用戶空間接口,

        可以直接在應用程序中使用標準的文件操作函數(如open、read、write和ioctl)

        來操作SPI設備。這種方式適用于大多數應用場景,特別是對于簡單的SPI設備操作,

        可以快速實現功能。


        如果使用自己編寫的SPI驅動也可以,也不算麻煩,需要在內核中實現SPI子系統,

        包括SPI控制器驅動和SPI設備驅動,最后根據需要實現個如字符型設備驅動操作接口,

        供上層應用使用即可。

        應用層使用步驟

        用戶應用層使用spidev驅動的步驟如下:


        1. 打開SPI設備文件:用戶可以通過打開/dev/spidevX.Y文件來訪問SPI設備,

        其中X是SPI控制器的編號,Y是SPI設備的編號。


        2. 配置SPI參數:用戶可以使用ioctl命令SPI_IOC_WR_MODE、

        SPI_IOC_WR_BITS_PER_WORD和SPI_IOC_WR_MAX_SPEED_HZ來設置SPI模式

        、數據位數和時鐘速度等參數。


        3. 發送和接收數據:用戶可以使用read和write系統調用來發送和接收SPI數據。

        寫入的數據將被傳輸到SPI設備,而從設備讀取的數據將被存儲在用戶提供的緩沖區中。


        4. 關閉SPI設備文件:當不再需要與SPI設備通信時,用戶應該關閉SPI設備文件。


        總結起來,spidev驅動提供了一種簡單而靈活的方式來與SPI設備進行通信,

        使得用戶可以輕松地在Linux系統上開發和控制SPI設備。

        內核配置

        使能spidev用戶態驅動

        1706957938689736.png在生成的config文件中可以看到以下配置生效了。我的是在imx6ul開發板的imx_v7_defconfig的linux內核配置文件中。

        CONFIG_SPI=y
        CONFIG_SPI_GPIO=y
        CONFIG_SPI_IMX=y
        CONFIG_SPI_SPIDEV=y
        編寫設備樹

        &ecspi3 {
                fsl,spi-num-chipselects = <2>;/*cs管腳數配置*/
                cs-gpios = <0>,<&gpio1 20 GPIO_ACTIVE_LOW>;/*cs管腳配置*/
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_ecspi3>;
                status = "okay";/* status屬性值為"okay" 表示該節點使能*/
         
        	spidev: icm20608@0 {
        	compatible = "alientek,icm20608";
                spi-max-frequency = <8000000>;
                reg = <0>;/*spi設備是沒有設備地址的, 這里是指使用spi控制器的cs-gpios里的第幾個片選io */
            };
         
        	oled: oledsh1106@1 {
        	compatible = "yang,oledsh1106";/*重要,會匹配spidev.c中指定的compatible*/
        	spi-cpol;/*配置spi信號模式*/
        	spi-cpha;
        	spi-max-frequency = < 8000000 >;/* 指定spi設備的最大工作時鐘 */
            reg = <1>;
            };
        };

        以上需要注意的是:如果該spi接口下掛載有多個從設備,

        需要設置fsl,spi-num-chipselects = <2>;默認該值為1。還有需要注意的地方是,

        cs-gpios 片選信號需要配置對應的個數。以上的為配置了兩路片選GPIO管腳,

        第一個默認的,第二個是指定的。如果僅有一個從設備,可以配置cs-gpio就行了。

        注意cs-gpio和cs-gpios的區別,帶s的標識可以有多個。

        如果忽略cs管腳數配置,則會出現以下錯誤:

        需要設置fsl,spi-num-chipselects = <2>; 


        注意上面的compatible 屬性,在新版linux內核,可以寫任意的字符串,

        最好不再寫”spidev”,老版的是要寫成”spidev”。

        給出的理由是: spidev should never be referenced in DT without a specific

         compatible string, it is a Linux implementation thing rather than a description 

        of the hardware。


        此外還有一些額外配置,以下為自定義屬性,用于指定工作時序方式及其它功能設置等。

        如CPOL需要設1, 則只需在spi設備節點里加上"spi-cpol"屬性即可; CPOL設0,

        則不寫"spi-cpol"屬性即可 。

        • buswidth = <8>; /* 傳輸以8位為單位 */
          mode = <0>; /* 使用第幾種工作時序(CPOL, CPHA) */
          /*但在現用的內核源碼里發現, spi設備的工作時序并不是用mode屬性值來指定的*/
          /* 如CPOL需要設1, 則只需在spi設備節點里加上"spi-cpol"屬性即可;
        • CPOL設0,則不寫"spi-cpol"屬性即可 */
          /* CPHA設1時,則在設備節點里加上"spi-cpha"屬性即可 */

        pinctrl的配置

        pinctrl_ecspi3: ecspi3grp {
                        fsl,pins = <
                                MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO        0x100b1  /* MISO*/
                                MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI        0x100b1  /* MOSI*/
                                MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK      0x100b1  /* CLK*/
                                MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20       0x100b0  /* CS*/
                            >;
                    };
        編譯內核和設備樹
        #加載環境
        source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
        #編譯內核
        make zImage -j16
        #編譯指定的設備樹
        make imx6ull-14x14-nand-4.3-480x272-c.dtb
        修改spidev驅動

        默認的spidev.c中,是沒有匹配你添加的設備的,因此需要修改spidev.c代碼,增加compatible匹配。

        /* The main reason to have this class is to make mdev/udev create the
         * /dev/spidevB.C character device nodes exposing our userspace API.
         * It also simplifies memory management.
         */
         
        static struct class *spidev_class;
         
        //#ifdef CONFIG_OF
        static const struct of_device_id spidev_dt_ids[] = {
        	{ .compatible = "rohm,dh2228fv" },
          { .compatible = "yang,oledsh1106" },
        	{},
        };
        MODULE_DEVICE_TABLE(of, spidev_dt_ids);
        //#endif

        內核編譯成功后,更新內核和設備樹文件。啟動設備后,在/sys/class/spidev下可以確認spidev枚舉出了多少個spi設備。


        設備樹查看

        查看設備樹是否有新添加的節點:


        更新設備樹到板子上后查看下是否有生成spi設備節點:

                                


        開源測試工具

        spidev驅動有現成的測試工具。其中一個常用的測試工具是spi_test,

        它是spidev驅動自帶的測試工具,可以用于測試和調試SPI設備。

        spi_test可以通過命令行參數設置SPI設備的各種參數,如設備文件、

        傳輸速率、字節順序等。使用spi_test可以發送和接收SPI數據,

        以驗證spidev驅動的功能和性能。


        在源碼linux-imx-4.1.15-2.1.0-v2.7\Documentation\spi路徑下,

        有兩個測試工具的源碼文件,spidev_fdx.c和spidev_test.c文件。

        可以直接交叉編譯為可執行文件使用。

        這些工具都基于spidev通用設備驅動以及對應的ioctl命令實現,

        可以方便的用來對spi的通用型驅動來進行測試。


        編譯方法

        #加載環境
        source /opt/fsl-imx-x11/4.1.15-2.1.0/
        environment-setup-cortexa7hf-neon-poky-linux-gnueabi
        #編譯
        $(CC) spidev_fdx.c -o spidev_fdx
        $(CC) spidev_test.c -o spidev_test
        回環測試

        首先,將spi接口的MISO和MOSI接口短接。

        其次,編譯測試代碼:

        Documentation/spi/spidev_test.c


        如,在/dev/spidev2.0上發送"string_to_send"字符串,顯示發送和接收的數據:

         ./spidev_test -D /dev/spidev2.0 -v -p string_to_send

        如果要發送32位/16位的數據,則需要先生成二進制文件,如生成32字節的隨機數據:

        dd if=/dev/urandom of=test_data bs=16 count=2

        用hexdump來查看這個二進制文件:

        hexdump -v test_data -C


        00000000 74 6a 59 3e 1e 81 73 fb 5a 3f 94 c7 d8 20 ca e9 |tjY>..s.Z?... ..|


        00000010 24 2e a5 68 75 ab f7 12 af e6 c1 3d e2 d8 9a ba |$..hu......=....|


        00000020


        發送:

        ./spidev_test -D /dev/spidev2.0 -b 32 -v -i test_data————————————————

        最后,輸出結果與輸入相同即為正確。

         

        結語

        在這樣一個速食的時代,堅持做自己,慢下來,潛心琢磨,心懷敬畏,領悟知識,

        才能向下扎到根,向上捅破天,背著世界往前行!

        原文鏈接:https://blog.csdn.net/yyz_1987/article/details/131918983

                                



                                



                 

                            

                                


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: spi

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 壤塘县| 武山县| 大英县| 沭阳县| 莱芜市| 灵宝市| 卓尼县| 临江市| 邻水| 阜康市| 淮北市| 汝阳县| 平谷区| 翼城县| 合江县| 岑巩县| 海晏县| 泸西县| 大化| 资中县| 剑川县| 巴东县| 海盐县| 丽水市| 沿河| 资兴市| 肇州县| 阜平县| 石渠县| 东至县| 定州市| 钟山县| 香港 | 马尔康县| 万州区| 黄梅县| 河西区| 衡阳市| 曲麻莱县| 深泽县| 铜山县|