"); //-->
因为兴趣,业余时间把玩下手边的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
驱动框架框图:
除了使用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设备。
内核配置
在生成的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驱动
/* 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设备。
开源测试工具
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回环测试
如,在/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
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。