如何编写测试用例验证Linux下SPI驱动?求示例及命令验证方法
Hey there! Let's break down how to tackle SPI driver testing on Linux—both with quick command-line checks and writing your own test cases. I’ve messed around with this a fair bit, so here’s what I’ve picked up that should help you get started:
Before diving into test cases, let’s confirm the driver is properly recognized and can handle basic operations:
Check if SPI devices are detected
First, verify the kernel has enumerated your SPI bus and device by checking the sysfs nodes:ls /sys/bus/spi/devices/You should see entries like
spi0.0(where0is the bus number and0is the chip-select index). If you’re using device tree, you can also inspect the relevant tree nodes with:cat /proc/device-tree/spi@*Use
spidev_testfor basic read/write tests
This tool comes with the Linux tools package—install it first (Debian/Ubuntu example):sudo apt install linux-tools-common linux-tools-$(uname -r)Then run these tests:
- Send a string to the SPI device:
sudo spidev_test -D /dev/spidev0.0 -p "Hello SPI" - Perform a bidirectional transfer (send test bytes and read responses):
sudo spidev_test -D /dev/spidev0.0 -r - Adjust parameters like baud rate or SPI mode:
SPI modes 0-3 are supported, so test each if your device requires it.# Test with 1Mbps baud rate and SPI mode 0 (CPOL=0, CPHA=0) sudo spidev_test -D /dev/spidev0.0 -s 1000000 -m 0
- Send a string to the SPI device:
Directly interact with the
/dev/spidevdevice file
For quick one-off transfers, use standard Unix commands:- Write data with
dd:echo -n "test data" | sudo dd of=/dev/spidev0.0 bs=1 count=8 - Read data (note: some devices require a command byte first before returning data):
sudo cat /dev/spidev0.0
- Write data with
Test cases should cover basic functionality, edge cases, and stability. Here’s how to approach it:
1. User-Space Test Case (C Language Example)
This uses the spidev user-space API to directly control the SPI device—great for validating end-to-end functionality:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/spi/spidev.h> #define SPI_DEVICE "/dev/spidev0.0" #define SPI_MODE SPI_MODE_0 #define SPI_BAUD_RATE 1000000 // 1Mbps #define TRANSFER_LEN 3 int main() { int fd; unsigned char tx_buf[TRANSFER_LEN] = {0x01, 0x02, 0x03}; unsigned char rx_buf[TRANSFER_LEN] = {0}; struct spi_ioc_transfer spi_xfer = { .tx_buf = (unsigned long)tx_buf, .rx_buf = (unsigned long)rx_buf, .len = TRANSFER_LEN, .speed_hz = SPI_BAUD_RATE, .delay_usecs = 0, .bits_per_word = 8, .cs_change = 0, }; // Open SPI device fd = open(SPI_DEVICE, O_RDWR); if (fd < 0) { perror("Failed to open SPI device"); return -1; } // Configure SPI mode if (ioctl(fd, SPI_IOC_WR_MODE, &SPI_MODE) < 0) { perror("Failed to set SPI mode"); close(fd); return -1; } // Configure baud rate if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &SPI_BAUD_RATE) < 0) { perror("Failed to set baud rate"); close(fd); return -1; } // Execute transfer if (ioctl(fd, SPI_IOC_MESSAGE(1), &spi_xfer) < 0) { perror("SPI transfer failed"); close(fd); return -1; } // Print results printf("Transmitted: 0x%02X 0x%02X 0x%02X\n", tx_buf[0], tx_buf[1], tx_buf[2]); printf("Received: 0x%02X 0x%02X 0x%02X\n", rx_buf[0], rx_buf[1], rx_buf[2]); close(fd); return 0; }
Compile and run it with:
gcc spi_test.c -o spi_test sudo ./spi_test
2. Kernel-Space Test Module (For Driver Core Validation)
If you need to test the kernel-side SPI driver logic (like bus handling or low-level transfers), write a simple kernel module:
#include <linux/module.h> #include <linux/spi/spi.h> static struct spi_device *test_spi_dev; static int spi_test_transfer(void) { unsigned char tx[] = {0x01, 0x04}; unsigned char rx[] = {0, 0}; struct spi_message msg; struct spi_transfer tr = { .tx_buf = tx, .rx_buf = rx, .len = sizeof(tx), .speed_hz = 1000000, }; spi_message_init(&msg); spi_message_add_tail(&tr, &msg); return spi_sync(test_spi_dev, &msg); } static int spi_test_probe(struct spi_device *spi) { int ret; test_spi_dev = spi; ret = spi_test_transfer(); if (ret < 0) { dev_err(&spi->dev, "SPI transfer failed\n"); return ret; } dev_info(&spi->dev, "SPI test passed! Rx: 0x%02X 0x%02X\n", rx[0], rx[1]); return 0; } static const struct spi_device_id spi_test_id[] = { {"spi-test-device", 0}, {} }; MODULE_DEVICE_TABLE(spi, spi_test_id); static struct spi_driver spi_test_driver = { .driver = { .name = "spi-test-driver", .owner = THIS_MODULE, }, .probe = spi_test_probe, }; module_spi_driver(spi_test_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SPI Driver Kernel Test Module");
You’ll need to bind this module to your SPI device (via device tree or user-space binding tools) to run it.
3. Key Test Scenarios to Cover
- Parameter Validation: Test all supported baud rates, SPI modes (0-3), and bit widths (8/16 bits) to ensure the driver handles them correctly.
- Edge Cases: Test invalid baud rates, non-existent SPI devices, zero-length transfers, and timeout conditions.
- Concurrency: Spawn multiple threads to read/write the same SPI device—verify the driver uses proper locking to avoid race conditions.
- Stability: Run continuous transfers (e.g., 10,000+ cycles) to check for memory leaks, data corruption, or crashes.
- Enable SPI debug logs to see low-level transfer details:
echo 1 > /sys/module/spidev/parameters/debug dmesg -w - Use a logic analyzer to capture SPI bus waveforms—this is critical for verifying hardware-level data integrity.
- Check driver statistics (if available): Some drivers expose stats in sysfs (e.g.,
/sys/bus/spi/devices/spi0.0/statistics/) to track transfer counts and errors.
内容的提问来源于stack exchange,提问作者Lokesh Kumar

