SPI 通用接口層
- SPI 通用接口層把具體的 SPI 設(shè)備的協(xié)議驅(qū)動(dòng)和 SPI 控制器驅(qū)動(dòng)連接在一起。
- 負(fù)責(zé) SPI 系統(tǒng)與 Linux 設(shè)備模型相關(guān)的初始化工作。
- 為協(xié)議驅(qū)動(dòng)和控制器驅(qū)動(dòng)提供一系列的標(biāo)準(zhǔn)接口 API 及其數(shù)據(jù)結(jié)構(gòu)。
- SPI 設(shè)備、SPI 協(xié)議驅(qū)動(dòng)、SPI 控制器的數(shù)據(jù)抽象
- 協(xié)助數(shù)據(jù)傳輸而定義的數(shù)據(jù)結(jié)構(gòu)
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;
}
// 創(chuàng)建 /sys/bus/spi 節(jié)點(diǎn)
status = bus_register(&spi_bus_type);
if (status < 0)
goto err1;
//創(chuàng)建 /sys/class/spi_master 節(jié)點(diǎn)
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;
}
......
}
在這里創(chuàng)建了 SPI 總線,創(chuàng)建 /sys/bus/spi 節(jié)點(diǎn)和 /sys/class/spi_master 節(jié)點(diǎn)。
重要數(shù)據(jù)結(jié)構(gòu):
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
接下來(lái)詳細(xì)解析結(jié)構(gòu)體和API,只講解重點(diǎn)部分,完整解析請(qǐng)參考官方文檔
https://www.kernel.org/doc/html/v4.14//driver-api/spi.html
只有熟悉每個(gè)結(jié)構(gòu)體存儲(chǔ)的是什么東西,才能真正搞懂 SPI 模塊。
spi_master/spi_controller:描述一個(gè) spi 主機(jī)設(shè)備
struct spi_master {
//Linux 驅(qū)動(dòng)模型中的設(shè)備
struct device dev;
//此 spi_master 設(shè)備在全局 spi_master 鏈表中的節(jié)點(diǎn)
struct list_head list;
//此 spi_master 編號(hào)
s16 bus_num;
//此 spi_master 支持的片選信號(hào)數(shù)量
u16 num_chipselect;
//dma 地址對(duì)齊
u16 dma_alignment;
//此 spi_master 支持傳輸?shù)?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 狀態(tài)
bool bus_lock_flag;
//準(zhǔn)備傳輸,設(shè)置傳輸?shù)膮?shù)
int (*setup)(struct spi_device *spi);
//傳輸數(shù)據(jù)
int (*transfer)(struct spi_device *spi,
struct spi_message *mesg);
// 設(shè)備 release 時(shí)的清除工作
void (*cleanup)(struct spi_device *spi);
bool (*can_dma)(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer);
bool queued;//是否采用系統(tǒng)的序列化傳輸
struct kthread_worker kworker;//序列化傳輸時(shí)的線程 worker
struct task_struct *kworker_task;//序列化傳輸?shù)木€程
struct kthread_work pump_messages;//序列化傳輸時(shí)的處理函數(shù)
spinlock_t queue_lock;//序列化傳輸時(shí)的queue_lock
struct list_head queue;//序列化傳輸時(shí)的 msg 隊(duì)列頭
struct spi_message *cur_msg;//序列化傳輸時(shí)當(dāng)前的 msg
bool idling;
bool busy;//序列化傳輸時(shí)線程是否處于busy狀態(tài)
bool running;//序列化傳輸時(shí)線程是否在運(yùn)行
bool rt;//是否實(shí)時(shí)傳輸
......
int (*prepare_transfer_hardware)(struct spi_master *master);
//一個(gè) msg 的傳輸實(shí)現(xiàn)
int (*transfer_one_message)(struct spi_master *master,
struct spi_message *mesg);
......
/* gpio chip select */
int *cs_gpios;
......
};
spi_device:描述一個(gè) spi 從機(jī)設(shè)備
struct spi_device {
//Linux驅(qū)動(dòng)模型中的設(shè)備
struct device dev;
struct spi_master *master;//設(shè)備所連接的 spi 主機(jī)設(shè)備
u32 max_speed_hz;//該設(shè)備最大傳輸速率
u8 chip_select;//CS片選信號(hào)編號(hào)
u8 bits_per_word;//每次傳輸長(zhǎng)度
u16 mode;//傳輸模式
......
int irq;//軟件中斷號(hào)
void *controller_state;//控制器狀態(tài)
void *controller_data;//控制參數(shù)
char modalias[SPI_NAME_SIZE];//設(shè)備名稱
//CS 片選信號(hào)對(duì)應(yīng)的 GPIO number
int cs_gpio; /* chip select gpio */
/* the statistics */
struct spi_statistics statistics;
};
spi_driver:描述一個(gè) spi 設(shè)備驅(qū)動(dòng)
struct spi_driver {
//此driver所支持的 spi 設(shè)備 list
const struct spi_device_id *id_table;
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
//系統(tǒng) shutdown 時(shí)的回調(diào)函數(shù)
void (*shutdown)(struct spi_device *spi);
struct device_driver driver;
};
spi_board_info:描述一個(gè) spi 從機(jī)設(shè)備板級(jí)信息,無(wú)設(shè)備樹(shù)時(shí)使用
struct spi_board_info {
//設(shè)備名稱
char modalias[SPI_NAME_SIZE];
const void *platform_data;//設(shè)備的平臺(tái)數(shù)據(jù)
void *controller_data;//設(shè)備的控制器數(shù)據(jù)
int irq;//設(shè)備的中斷號(hào)
u32 max_speed_hz;//設(shè)備支持的最大速率
u16 bus_num;//設(shè)備連接的 spi 總線編號(hào)
u16 chip_select;//設(shè)備連接的 CS 信號(hào)編號(hào)
u16 mode;//設(shè)備使用的傳輸 mode
};
spi_transfer:描述 spi 傳輸?shù)木唧w數(shù)據(jù)
struct spi_transfer {
const void *tx_buf;//spi_transfer 的發(fā)送 buf
void *rx_buf;//spi_transfer 的接收 buf
unsigned len;//spi_transfer 發(fā)送和接收的長(zhǎng)度
dma_addr_t tx_dma;//tx_buf 對(duì)應(yīng)的 dma 地址
dma_addr_t rx_dma;//rx_buf 對(duì)應(yīng)的 dma 地址
struct sg_table tx_sg;
struct sg_table rx_sg;
//spi_transfer傳輸完成后是否要改變 CS 片選信號(hào)
unsigned cs_change:1;
unsigned tx_nbits:3;
unsigned rx_nbits:3;
......
u8 bits_per_word;//spi_transfer 中一個(gè) word 占的bits
u16 delay_usecs;//兩個(gè) spi_transfer 直接的等待延遲
u32 speed_hz;//spi_transfer 的傳輸速率
struct list_head transfer_list;//spi_transfer掛載到的 message 節(jié)點(diǎn)
};
spi_message:描述一次 spi 傳輸?shù)男畔?/p>
struct spi_message {
//掛載在此 msg 上的 transfer 鏈表頭
struct list_head transfers;
//此 msg 需要通信的 spi 從機(jī)設(shè)備
struct spi_device *spi;
//所使用的地址是否是 dma 地址
unsigned is_dma_mapped:1;
//msg 發(fā)送完成后的處理函數(shù)
void (*complete)(void *context);
void *context;//complete函數(shù)的參數(shù)
unsigned frame_length;
unsigned actual_length;//此 msg 實(shí)際成功發(fā)送的字節(jié)數(shù)
int status;//此 msg 的發(fā)送狀態(tài),0:成功,負(fù)數(shù),失敗
struct list_head queue;//此 msg 在所有 msg 中的鏈表節(jié)點(diǎn)
void *state;//此 msg 的私有數(shù)據(jù)
};
-
SPI
+關(guān)注
關(guān)注
17文章
1742瀏覽量
93814 -
接口層
+關(guān)注
關(guān)注
0文章
2瀏覽量
1023
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
SPI接口硬件設(shè)計(jì)介紹

SPI協(xié)議層及固件庫(kù)
基于PC/104 總線與CPLD 的SPI 接口設(shè)計(jì)
SPI接口的工作原理

SPI接口總線介紹

一種通用SPI接口的FPGA設(shè)計(jì)與實(shí)現(xiàn)

Firefly-RK328-SPI接口介紹

Firefly-RK3128--SPI接口介紹

STM32CubeMX-HAL庫(kù)的SPI接口使用

SPI接口簡(jiǎn)介

SPI控制器驅(qū)動(dòng)層功能介紹

SPI接口的相關(guān)介紹

評(píng)論