SPI 通用接口層
- SPI 通用接口層把具體的 SPI 設備的協議驅動和 SPI 控制器驅動連接在一起。
- 負責 SPI 系統與 Linux 設備模型相關的初始化工作。
- 為協議驅動和控制器驅動提供一系列的標準接口 API 及其數據結構。
- SPI 設備、SPI 協議驅動、SPI 控制器的數據抽象
- 協助數據傳輸而定義的數據結構
kernel-4.14/drivers/spi/spi.c
static int __init spi_init(void)
{
int status;
buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
if (!buf) {
status = -ENOMEM;
goto err0;
}
// 創建 /sys/bus/spi 節點
status = bus_register(&spi_bus_type);
if (status < 0)
goto err1;
//創建 /sys/class/spi_master 節點
status = class_register(&spi_master_class);
if (status < 0)
goto err2;
if (IS_ENABLED(CONFIG_SPI_SLAVE)) {
status = class_register(&spi_slave_class);
if (status < 0)
goto err3;
}
......
}
在這里創建了 SPI 總線,創建 /sys/bus/spi 節點和 /sys/class/spi_master 節點。
重要數據結構:
spi_device
spi_driver
spi_board_info
spi_controller/spi_master
spi_transfer
spi_message
重要 API
spi_message_init
spi_message_add_tail
spi_sync
spi_async
spi_write
spi_read
接下來詳細解析結構體和API,只講解重點部分,完整解析請參考官方文檔
https://www.kernel.org/doc/html/v4.14//driver-api/spi.html
只有熟悉每個結構體存儲的是什么東西,才能真正搞懂 SPI 模塊。
spi_master/spi_controller:描述一個 spi 主機設備
struct spi_master {
//Linux 驅動模型中的設備
struct device dev;
//此 spi_master 設備在全局 spi_master 鏈表中的節點
struct list_head list;
//此 spi_master 編號
s16 bus_num;
//此 spi_master 支持的片選信號數量
u16 num_chipselect;
//dma 地址對齊
u16 dma_alignment;
//此 spi_master 支持傳輸的 mode
u16 mode_bits;
u32 bits_per_word_mask;
/* limits on transfer speed */
u32 min_speed_hz;
u32 max_speed_hz;
/* other constraints relevant to this driver */
u16 flags;
/* lock and mutex for SPI bus locking */
spinlock_t bus_lock_spinlock;//總線自旋鎖
struct mutex bus_lock_mutex;//總線互斥鎖
//總線是否處于 lock 狀態
bool bus_lock_flag;
//準備傳輸,設置傳輸的參數
int (*setup)(struct spi_device *spi);
//傳輸數據
int (*transfer)(struct spi_device *spi,
struct spi_message *mesg);
// 設備 release 時的清除工作
void (*cleanup)(struct spi_device *spi);
bool (*can_dma)(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer);
bool queued;//是否采用系統的序列化傳輸
struct kthread_worker kworker;//序列化傳輸時的線程 worker
struct task_struct *kworker_task;//序列化傳輸的線程
struct kthread_work pump_messages;//序列化傳輸時的處理函數
spinlock_t queue_lock;//序列化傳輸時的queue_lock
struct list_head queue;//序列化傳輸時的 msg 隊列頭
struct spi_message *cur_msg;//序列化傳輸時當前的 msg
bool idling;
bool busy;//序列化傳輸時線程是否處于busy狀態
bool running;//序列化傳輸時線程是否在運行
bool rt;//是否實時傳輸
......
int (*prepare_transfer_hardware)(struct spi_master *master);
//一個 msg 的傳輸實現
int (*transfer_one_message)(struct spi_master *master,
struct spi_message *mesg);
......
/* gpio chip select */
int *cs_gpios;
......
};
spi_device:描述一個 spi 從機設備
struct spi_device {
//Linux驅動模型中的設備
struct device dev;
struct spi_master *master;//設備所連接的 spi 主機設備
u32 max_speed_hz;//該設備最大傳輸速率
u8 chip_select;//CS片選信號編號
u8 bits_per_word;//每次傳輸長度
u16 mode;//傳輸模式
......
int irq;//軟件中斷號
void *controller_state;//控制器狀態
void *controller_data;//控制參數
char modalias[SPI_NAME_SIZE];//設備名稱
//CS 片選信號對應的 GPIO number
int cs_gpio; /* chip select gpio */
/* the statistics */
struct spi_statistics statistics;
};
spi_driver:描述一個 spi 設備驅動
struct spi_driver {
//此driver所支持的 spi 設備 list
const struct spi_device_id *id_table;
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
//系統 shutdown 時的回調函數
void (*shutdown)(struct spi_device *spi);
struct device_driver driver;
};
spi_board_info:描述一個 spi 從機設備板級信息,無設備樹時使用
struct spi_board_info {
//設備名稱
char modalias[SPI_NAME_SIZE];
const void *platform_data;//設備的平臺數據
void *controller_data;//設備的控制器數據
int irq;//設備的中斷號
u32 max_speed_hz;//設備支持的最大速率
u16 bus_num;//設備連接的 spi 總線編號
u16 chip_select;//設備連接的 CS 信號編號
u16 mode;//設備使用的傳輸 mode
};
spi_transfer:描述 spi 傳輸的具體數據
struct spi_transfer {
const void *tx_buf;//spi_transfer 的發送 buf
void *rx_buf;//spi_transfer 的接收 buf
unsigned len;//spi_transfer 發送和接收的長度
dma_addr_t tx_dma;//tx_buf 對應的 dma 地址
dma_addr_t rx_dma;//rx_buf 對應的 dma 地址
struct sg_table tx_sg;
struct sg_table rx_sg;
//spi_transfer傳輸完成后是否要改變 CS 片選信號
unsigned cs_change:1;
unsigned tx_nbits:3;
unsigned rx_nbits:3;
......
u8 bits_per_word;//spi_transfer 中一個 word 占的bits
u16 delay_usecs;//兩個 spi_transfer 直接的等待延遲
u32 speed_hz;//spi_transfer 的傳輸速率
struct list_head transfer_list;//spi_transfer掛載到的 message 節點
};
spi_message:描述一次 spi 傳輸的信息
struct spi_message {
//掛載在此 msg 上的 transfer 鏈表頭
struct list_head transfers;
//此 msg 需要通信的 spi 從機設備
struct spi_device *spi;
//所使用的地址是否是 dma 地址
unsigned is_dma_mapped:1;
//msg 發送完成后的處理函數
void (*complete)(void *context);
void *context;//complete函數的參數
unsigned frame_length;
unsigned actual_length;//此 msg 實際成功發送的字節數
int status;//此 msg 的發送狀態,0:成功,負數,失敗
struct list_head queue;//此 msg 在所有 msg 中的鏈表節點
void *state;//此 msg 的私有數據
};
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
SPI
+關注
關注
17文章
1700瀏覽量
91319 -
接口層
+關注
關注
0文章
2瀏覽量
991
發布評論請先 登錄
相關推薦
SPI接口硬件設計介紹
SPI(Serial Peripheral interface)串行外圍設備接口。是微控制器和外圍IC(如傳感器、 ADC、 DAC、移位寄存器、 SRAM等)之間使用最廣泛的接口之一。SPI
發表于 09-15 15:45
?1233次閱讀
SPI協議層及固件庫
》[正點原子]STM32F4開發指南-庫函數版本_V1.2[ST]《STM32F4xx中文參考手冊》SPI協議及總線協議介紹W25Q128產品數據手冊SPI協議介紹
發表于 08-20 08:00
基于PC/104 總線與CPLD 的SPI 接口設計
本文根據SPI 同步串行接口的通信協議,介紹了在CPLD 中利用VHDL 語言實現PC/104
總線擴展SPI 接口的設計原理和編程思想。
發表于 05-30 09:28
?41次下載
SPI接口的工作原理
MAX7456隨屏顯示(OSD)發生器具有SPI™兼容接口,本應用筆記介紹了SPI接口的工作原理,文中還包含在微控制器內逐位模擬
發表于 07-27 23:24
?1.5w次閱讀
SPI接口總線介紹
SPI接口總線介紹
SPI 可以作為主、從器件工作,并可在同一總線上支持多個主、從器件。SPI 主要使用3 個信號。(1)主輸出、從
發表于 11-24 08:41
?4841次閱讀
一種通用SPI接口的FPGA設計與實現
SPI 串行總線是一種常用的標準接口,其使用簡單方便而且占用系統資源少,應用相當廣泛。本文將介紹一種新的通用的SPI 總線的FPGA 實現方
發表于 09-09 11:58
?67次下載
SPI接口的相關介紹
SPI和IIC接口一樣是非常常見的開發板接口,但與IIC相比,SPI設計了一種二進制流的交互方式,擁有更快的傳輸速度,它可以在任何兩個嵌入式設備之間交換消息,ELF1開發板也是通過
評論