应用程序和驱动中使用SPI设备的流程
编写SPI设备驱动有两种方法。一种是利用系统给我们提供的spidev.c来实现一个spi适配器的设备文件。然后通过在应用层操作spi适配器来控制spi设备。另一种是为spi设备,独立编写一个设备驱动。注意:在后一种情况下,是不需要使用spidev.c的。
前一种方法也就是说只要系统实现了spi适配器的驱动并生成了设备文件, 那么挂在其上面的spi设备也可以在应用层直接通过操作这个设备文件来间接控制这个spi设备, 这样就省去了专门为这个设备编写驱动的麻烦。本文将详细描述在应用层和驱动层分别控制spi设备的流程。
关于在应用层如何使用spidev驱动的问题, 可以参考源码的documenation/spi目录下的文档, 其中spidev_test.c就是一个测试程序,可以参考。
下面将结合本人工作中实现的一个例子来介绍应用层使用spidev的流程。实际上流程比较简单:打开设备文件 -> 配置设备 -> 读写设备 -> 关闭设备文件。
1. 打开设备文件:
#defineICCARD_DEVICE_FILE ("/dev/spidev0.0") /*spi controller device file*/
/*1.open lcd device*/
fd_iccard= open(ICCARD_DEVICE_FILE, O_WRONLY);
if(fd_iccard< 0) {
LOGE("can'topen ICCARD device file");
return0;
}
跟打开普通的文件没有什么区别。
2. 配置设备:
static uint8_ticcard_spi_mode = SPI_MODE_3; /*spi operation mode*/
/*2.initialize SPI controller*/
/*
* spi mode
*/
ret= ioctl(fd_iccard, SPI_IOC_WR_MODE, &iccard_spi_mode);
if (ret< 0) {
LOGE("can'tset spi mode");
gotoinit_failed;
}
ret =ioctl(fd_iccard, SPI_IOC_RD_MODE, &iccard_spi_mode);
if (ret< 0) {
LOGE("can'tget spi mode");
gotoinit_failed;
}
/*
* bits per word
*/
ret =ioctl(fd_iccard, SPI_IOC_WR_BITS_PER_WORD, &iccard_spi_bits);
if (ret< 0) {
LOGE("can'tset bits per word");
gotoinit_failed;
}
ret =ioctl(fd_iccard, SPI_IOC_RD_BITS_PER_WORD, &iccard_spi_bits);
if (ret< 0) {
LOGE("can'tget bits per word");
gotoinit_failed;
}
/*
* max speed hz
*/
ret =ioctl(fd_iccard, SPI_IOC_WR_MAX_SPEED_HZ, &iccard_spi_speed);
if (ret< 0) {
LOGE("can'tset max speed hz");
gotoinit_failed;
}
ret =ioctl(fd_iccard, SPI_IOC_RD_MAX_SPEED_HZ, &iccard_spi_speed);
if (ret< 0) {
LOGE("can'tget max speed hz");
gotoinit_failed;
}
通过ioctl系统调用设置spi的工作模式(4种模式之一, 参考SPI协议),每个传输单元的位数,最大工作频率等。
3. 读写设备:
static structspi_ioc_transfer iccard_spi_msg = { /*spi message for transfer*/
.speed_hz = 2000000,
.bits_per_word = 8,
.delay_usecs = 0,
}; /*每个传输必须封装成这种格式*/
iccard_spi_msg.tx_buf= (unsigned long) NULL; /*我们的设备只需要读, 所以没有tx_buf*/
while(index< ICCARD_DATA_LEN)
{
iccard_spi_msg.rx_buf = (unsignedlong)&ic_data_ptr[index]; /*读到的数据缓存*/
iccard_spi_msg.len= 1; /*每次读1个字节*/
ret= ioctl(fd_iccard, SPI_IOC_MESSAGE(1), &iccard_spi_msg);
if(ret < 0)
{
LOGE("[AARON]read iccard failed");
return0;
}
index++;
}
同样的,通过ioctl系统调用,发送SPI_IOC_MESSAGE命令给设备,来读取或写入数据。
4. 关闭设备:
close(fd_iccard);
如上描述, spidev给开发人员提供了一种比较简单的操作SPI设备的方式, 开发人员可以不用会编写spi驱动就能使用spi设备。
参考: