Summary of spidev usage of embedded linux general spi driver

Because of interest, I played with the imax6ul development board in my spare time. The Linux kernel integrates the spidev driver and provides a user space API for SPI devices. Supports read and write access interfaces for half-duplex communication and ioctl interfaces for full-duplex communication and I/O configuration. When in use, just add the compatible attribute value of the SPI slave device to the spidev dt ids[] array of the spidev zone, and the SPI slave device can be created as a spidev device. If you don't want to write a separate spi device driver, it is enough to use the general spidev device driver provided by the linux kernel, which provides a unified character device operation, so you only need to read, write and control it at the application layer.

Introduction to spidev driver

spidev is a Linux kernel driver for communicating with SPI (Serial Peripheral Interface) devices. SPI is a full-duplex, synchronous serial communication protocol commonly used to interface microcontrollers and external devices. The spidev driver allows userspace programs to communicate with SPI devices through the Linux device file interface. Users can send and receive SPI data by opening and reading and writing device files. The spidev driver provides a set of ioctl commands to control IO ports and SPI parameters.

At the same time, the Linux kernel also integrates the SPI test tool spidev test, which is used to test and verify the spidev dynamic function in user mode.

The spidev device driver source code location is: linux-imx-4.1.15\drivers\spi\spidev.c

Driver frame diagram:

In addition to using the spidev driver, of course you can also write your own SPI driver.

Using the existing spidev driver can simplify the development process, because it provides a set of user space interfaces, which can directly use standard file operation functions (such as open, read, write and ioctl) in the application to operate the SPI device. This method is suitable for most application scenarios, especially for simple SPI device operations, which can realize functions quickly.

If you use the SPI driver written by yourself, it is not too troublesome. You need to implement the SPI subsystem in the kernel, including the SPI controller driver and the SPI device driver, and finally implement a character-type device driver operation interface for upper-layer applications. Just use it.

Application layer usage steps

The steps for using the spidev driver in the user application layer are as follows:

1. Open the SPI device file: users can access the SPI device by opening the /dev/spidevX.Y file, where X is the number of the SPI controller and Y is the number of the SPI device.

2. Configure SPI parameters: users can use ioctl commands SPI_IOC_WR_MODE, SPI_IOC_WR_BITS_PER_WORD and SPI_IOC_WR_MAX_SPEED_HZ to set parameters such as SPI mode, data bits and clock speed.

3. Send and receive data: users can use read and write system calls to send and receive SPI data. Data written will be transferred to the SPI device, while data read from the device will be stored in a user-supplied buffer.

4. Close the SPI device file: When it is no longer necessary to communicate with the SPI device, the user should close the SPI device file.

To sum up, the spidev driver provides a simple and flexible way to communicate with SPI devices, allowing users to easily develop and control SPI devices on Linux systems.

kernel configuration

Enable spidev user mode driver

In the generated config file, you can see that the following configurations have taken effect. Mine is in the linux kernel configuration file of imx_v7_defconfig of the imx6ul development board.

CONFIG_SPI=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_IMX=y
CONFIG_SPI_SPIDEV=y

Write device tree

&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>;
    };
};

Note above: If there are multiple slave devices mounted under the spi interface, you need to set fsl, spi-num-chipselects = <2>; the default value is 1. Another thing to note is that the cs-gpios chip select signal needs to be configured with the corresponding number. The above is to configure two chip selection GPIO pins, the first one is default, and the second one is specified. If there is only one slave device, you can configure cs-gpio. Pay attention to the difference between cs-gpio and cs-gpios, there can be multiple identifiers with s.

If the CS pin count configuration is ignored, the following error will occur:

Need to set fsl,spi-num-chipselects = <2>; 

Pay attention to the compatible attribute above, in the new version of the linux kernel, you can write any string, it is best not to write "spidev", the old version should be written as "spidev". The reason given is: spidev should never be referenced in DT without a specif ic  compatible string, it is a Linux implementation thing rather than a description of the hardware.

In addition, there are some additional configurations, the following are custom attributes, which are used to specify the working timing method and other function settings. If CPOL needs to be set to 1, you only need to add the "spi-cpol" attribute in the spi device node; if CPOL is set to 0, you can not write the "spi-cpol" attribute.

buswidth = <8>; /* 传输以8位为单位 */
mode = <0>; /* 使用第几种工作时序(CPOL, CPHA) */
/*但在现用的内核源码里发现, spi设备的工作时序并不是用mode属性值来指定的*/
/* 如CPOL需要设1, 则只需在spi设备节点里加上"spi-cpol"属性即可; CPOL设0,则不写"spi-cpol"属性即可 */
/* CPHA设1时,则在设备节点里加上"spi-cpha"属性即可 */ 

pinctrl configuration

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*/
                    >;
            };

Compile the kernel and device tree

#加载环境
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

Modify the spidev driver

The default spidev.c does not match the device you added, so you need to modify the spidev.c code to add compatible matching.

/* 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

After the kernel is successfully compiled, update the kernel and device tree files. After starting the device, you can confirm how many spi devices spidev has enumerated under /sys/class/spidev.

Device tree view

Check if there are newly added nodes in the device tree:

After updating the device tree to the board, check whether the spi device node is generated:

Open Source Testing Tools

The spidev driver has ready-made testing tools. One of the commonly used test tools is spi_test, which is a test tool that comes with the spidev driver and can be used to test and debug SPI devices. spi_test can set various parameters of SPI devices through command line parameters, such as device files, transmission rate, byte order, etc. Use spi_test to send and receive SPI data to verify the functionality and performance of the spidev driver.

In the source code linux-imx-4.1.15-2.1.0-v2.7\Documentation\spi path, there are two source code files of test tools, spidev_fdx.c and spidev_test.c files. It can be directly cross-compiled into executable files. These tools are all implemented based on the spidev general device driver and the corresponding ioctl commands, which can be conveniently used to test the spi general driver.

compile method

#加载环境
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

loopback test

First, short the MISO and MOSI interfaces of the spi interface.

Second, compile the test code:

Documentation/spi/spidev_test.c

For example, send the "string_to_send" string on /dev/spidev2.0, and display the sent and received data:

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

If you want to send 32-bit/16-bit data, you need to generate a binary file first, such as generating 32-byte random data:

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

Use hexdump to view this binary file:

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

send:

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

  

Finally, the output is correct if it is the same as the input.

epilogue

In such an era of fast food, insist on being yourself, slow down, ponder with great concentration, be in awe, and comprehend knowledge, only then can you get down to the roots, pierce the sky upward, and move forward with the world on your back!

other resources

The use of spidev (SPI user mode API)

Using spidev to drive OLED based on Linux - Embedded Technology - Electronic Paper

The 0.96-inch OLED screen is transplanted to the Linux system equipped with mx6ull_AURORA1997's Blog-CSDN Blog

Embedded Linux driver development - solve the problem that there is no corresponding spi device file under /sys/bus/spi/devices - Programmer Sought

Embedded Linux driver development - solve the problem that there is no corresponding spi device file under /sys/bus/spi/  devices spidev0_blog_xu's Blog - CSDN Blog

Write SPI device driver_How to program spi program_Hilbert(*^*)'s Blog-CSDN Blog

154 spidev: SPI "universal" driver_Your board is smoking Blog-CSDN Blog

i.MX6ULL driver development | 14 - Read ICM-20608 sensor based on Linux SPI driver framework_MCUlover666's technical blog_51CTO blog

Device tree learning (9) SPI device registration process_spi_lsb_first_kunkliu's Blog-CSDN Blog

https://www.cnblogs.com/lknlfy/p/3265019.html

The spi device in the device tree and the processing flow of the kernel to the spi node

Two SPI driver methods for embedded Linux_linux spidev_iot-lorawan's Blog-CSDN Blog

Guess you like

Origin blog.csdn.net/qq8864/article/details/131918983