linux spi驅動分析 基於STM32

2021-06-22 11:46:18 字數 4201 閱讀 1572

linux kernel 版本2.6.30, spi驅動基於platform_device, platform_driver驅動模型來編寫.

spi分為主從裝置,乙個主裝置下可心掛接多個從裝置,linux驅動中使用struct spi_master結構來表示乙個主裝置,

使用struct spi_device表示乙個從裝置.從裝置通過spi_device->master指標來表示掛接到哪個主裝置下.

乙個cpu中一般都會有多個spi主裝置,spi不同的主裝置通過spi_master->bus_num來區分.

一般在定義platform_device的時候,通過platform_device->id來指定spi主裝置的bus_num號(在probe函式中,

spi_master->bus_num = platform_device->id).

總的來說,linux下的spi驅動可以分為兩部分,

乙個是spi主控器的驅動(主裝置),這部分的驅動主要負責將資料乙個位元組乙個位元組的從spi匯流排上傳出去,或從spi匯流排上

乙個位元組乙個位元組的讀回來,它不用去理解幾個位元組組合起來是什麼意思.

另一部分驅動是從裝置的驅動,因為從裝置不同,驅動也不一樣,主裝置的驅動可以只有乙個,但是如果從裝置有好幾個,那麼

從裝置的驅動也可能有好幾個.如乙個spi主裝置下掛有乙個1m的spi flash,乙個spi的時鐘晶元.對spi flash來說,往0xfffff位址

寫資料,協議可能是這樣:

位元組0 位元組1 位元組2 位元組3 位元組4

位址0 位址1 位址2 位址3 資料

而往spi時鐘晶元寫資料,協議可能是這樣:

位元組0        位元組1

暫存器位址   暫存器值

所以從裝置驅動就必須理解幾個位元組組合起來時,表示什麼意思.如拿上面的spi flash來舉例,從裝置寫5個資料,那前4個位元組表示

spi flash的位址,最後乙個位元組表示往這個位址寫的資料.從裝置驅動寫這5個位元組時,最後會通過主裝置驅動寫到spi匯流排上的(主

從驅動通過struct spi_message傳輸資料),spi主裝置驅動並不知道5個位元組是什麼意思,它只需要將從裝置驅動傳給它的這5個字

節寫到spi匯流排上就可以了.

platform_device驅動:

static struct platform_device spi_stm32_dev1 = ;

static struct platform_device spi_stm32_dev2 = ;

platform_device->id區別不同的spi主裝置.

platform_device_register(&spi_stm32_dev1); // 註冊platform_device

// 以下的資訊是從裝置驅動的資訊

// spi flash分割槽資訊

static struct mtd_partition

|---------> spi_stm32_flash_partitions__stm32f4_som = ,

|  ,

| };

| // 分割槽資訊和從裝置驅動名稱, 會有乙個對應的從裝置驅動(.name也="m25p32")

| static struct flash_platform_data

|  spi_stm32_flash_data__stm32f4_som = ;          |

|static struct spi_stm32_slv       |

|-------> spi_stm32_flash_slv__stm32f4_som  = ;          |

| static struct spi_board_info       |

|  spi_stm32_flash_info__stm32f4_som = ;

//註冊從裝置資訊, 只將spi_board_info掛到全域性鍊錶board_list

//struct spi_board_info 結構包含了從裝置的所有資訊

spi_register_board_info(&spi_stm32_flash_info__stm32f4_som,

sizeof(spi_stm32_flash_info__stm32f4_som) /

sizeof(struct spi_board_info));

platform_driver驅動:

static int __devinit spi_stm32_probe(struct platform_device *dev)

spi_register_master呼叫scan_boardinfo函式,將spi裝置與spi_master關聯

void scan_boardinfo(struct spi_master *master)}}

spi_new_device呼叫spi_alloc_device分配乙個struct spi_device, 將spi_device->master指向scan_boardinfo引數master,

這樣spi_device與spi_master就關聯起來了,spi_alloc_device還將spi_board_info資訊copy過來.

下面來看一下從裝置驅動

從裝置驅動在/driver/mtd/devices/m25p80.c中

static struct spi_driver m25p80_driver =

m25p_ids中有"m25p32",當核心初始化時檢查到與spi_board_info->modalias相等時,呼叫m25p_probe函式,

該函式中主要工作:

1.  註冊spi_device的操作函式

flash->mtd.erase = m25p80_erase;

flash->mtd.read = m25p80_read;

flash->mtd.write = m25p80_write;

2.     呼叫add_mtd_partitions註冊分割槽資訊

該函式中有乙個結構struct m25p, 該結構中有:

struct spi_device *spi;

struct mtd_info mtd;

這樣spi_device和mtd裝置就可以關聯起來了.

拿m25p80_write來舉例:

......

struct m25p *flash = mtd_to_m25p(mtd);

struct spi_transfer t[2];

struct spi_message m; // 從裝置驅動與主裝置驅動以struct spi_message結構來互動資料

// t[0]傳輸的是write命令和位址

t[0].tx_buf = flash->command;

t[0].len = m25p_cmdsz(flash);

spi_message_add_tail(&t[0], &m);

// t[1]傳輸的是要寫進去的資料

t[1].tx_buf = buf; // 傳進來的資料緩衝區和長度

t[1].len    = len;

spi_message_add_tail(&t[1], &m);

flash->command[0] = opcode_pp; // program命令

m25p_addr2cmd(flash, to, flash->command);  //位址存到flash->command[1], flash->command[2], flash->command[3], to為要寫到spi flash中的位址

//設定好命令和資料之後,呼叫spi_sync傳輸資料

spi_sync(flash->spi, &m);

spi_sync呼叫spi_async, spi_async呼叫spi_master->transfer來將資料傳給主裝置驅動.

spi_master->transfer=spi_stm32_transfer:

//該函式只是簡單的將struct spi_message結掛到c->queue佇列上,然後呼叫queue_work函式

list_add_tail(&msg->queue, &c->queue);

queue_work(c->workqueue, &c->work);

呼叫queue_work之後,核心會在某一時候呼叫spi_stm32_handle,這部分屬於核心工作佇列的內容,可以找相關資料看一下.

spi_stm32_handle最終會呼叫spi_stm32_hw_txfifo_put函式,將資料寫到spi匯流排上.

linux spi驅動分析

關於spi的學習,我覺得最好的方法還是看linux的源 主要是driver spi spi.c h spidev.c h spi dev的示例可以看看at25.c,spi匯流排的示例可以看omap uwire或者spi s3c24xx.c和spi s3c24xx gpio.c。在看這些 之前,需要對...

LINUX SPI驅動筆記

spi匯流排由miso 序列資料輸入 mosi 序列資料輸出 sck 序列移位時鐘 cs 使能訊號 4個訊號線組成 linux下spi驅動開發 首先明確spi驅動層次,如下圖 我們以上面的這個圖為思路 spi bus spi匯流排對應的匯流排型別為spi bus type,在核心的drivers s...

嵌入式Linux SPI驅動

1.1 spi主機驅動 linux使用spi master結構體表示spi主機驅動,定義在 drivers linux spi spi.h transfer 資料傳輸函式 transfer one message spi傳送護具函式,傳送乙個spi message資料 1.2 spi裝置驅動 lin...