應用程序和驅動中使用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設備。
參考: