深入淺出spi驅動之資料結構(一)
阿新 • • 發佈:2019-02-04
Allein.Cao原創作品,轉載請註明出處:
核心版本:2.6.32.2
硬體:S3C2440
SPI匯流排是一種比較通用的資料傳輸匯流排,遵從主從模式,由主裝置發起通訊請求,通常工作於全雙工模式,由4條資料時鐘線組成,下面這段話摘自s3c2440資料手冊:
There are 4 I/O pin signals associated with SPItransfers: SCK (SPICLK0,1), MISO (SPIMISO0,1) data line, MOSI (SPIMOSI0,1) dataline and active low /SS (nSS0,1) pin (input).
- 確定驅動檔案
SPI作為Linux裡面比較小的一個子系統,其驅動程式位於/drivers/spi/*目錄,首先,我們可以通過Makefile及Kconfig來確定我們需要看的原始檔:
Makefile:
- <prename="code"class="csharp">#
- # Makefile for kernel SPI drivers.
- #
- ……………………………………………….
- # small core, mostly translating board-specific
-
# config declarations into driver model code
- obj-$(CONFIG_SPI_MASTER) += spi.o
- # SPI master controller drivers (bus)
- …………………………………………………
- obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
- …………………………………………………
- obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
-
obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
- …………………………………………………
- # ... add above this line ...
- # SPI protocol drivers (device/link on bus)
- obj-$(CONFIG_SPI_SPIDEV) += spidev.o
- …………………………………………………
- # ... add above this line ...</pre>
- <pre></pre>
- <p></p>
- <p>通過以上分析我們知道,spi驅動由三部分組成,分別是core(spi.c),master controller driver (spi_s3c24xx.c or spi_s3c24xx_gpio.)以及SPIprotocol drivers (spidev.c),這裡spi_s3c24xx_gpio.c檔案是用普通的io口來模擬spi時序,具體見Kconfig描述:</p>
- <prename="code"class="csharp">config SPI_S3C24XX_GPIO
- tristate "Samsung S3C24XX series SPI by GPIO"
- depends on ARCH_S3C2410 && EXPERIMENTAL
- select SPI_BITBANG
- help
- SPI driver for Samsung S3C24XX series ARM SoCs using
- GPIO lines to provide the SPI bus. This can be used where
- the inbuilt hardware cannot provide the transfer mode, or
- where the board is using non hardware connected pins.
- </pre>
- <p>在此,我們以spi控制器方式進行分析。</p>
- <p></p>
- <ul>
- <li>資料結構</li></ul>
- <p></p>
- <p>Spi驅動涉及的<ahref="http://lib.csdn.net/base/datastructure"class="replace_word"title="演算法與資料結構知識庫"target="_blank"style="color:#df3434; font-weight:bold;">資料結構</a>主要位於/include/<ahref="http://lib.csdn.net/base/linux"class="replace_word"title="Linux知識庫"target="_blank"style="color:#df3434; font-weight:bold;">linux</a>/spi.h,對各個結構有比較詳細的解釋,限於篇幅,簡單介紹如下:</p>
- <p>1、Spi_device代表一個外圍spi裝置,由master controller driver註冊完成後掃描BSP中註冊裝置產生的裝置連結串列並向spi_bus註冊產生。</p>
- <p></p>
- <prename="code"class="csharp">struct spi_device {
- struct device dev; //裝置模型使用
- struct spi_master *master; //裝置使用的master結構
- u32 max_speed_hz; //通訊時鐘
- u8 chip_select; //片選號,每個master支援多個spi_device
- u8 mode; //裝置支援的模式,如片選是高or低?
- #define SPI_CPHA 0x01 /* clock phase */
- #define SPI_CPOL 0x02 /* clock polarity */
- #define SPI_MODE_0 (0|0) /* (original MicroWire) */
- #define SPI_MODE_1 (0|SPI_CPHA)
- #define SPI_MODE_2 (SPI_CPOL|0)
- #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
- #define SPI_CS_HIGH 0x04 /* chipselect active high? */
- #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
- #define SPI_3WIRE 0x10 /* SI/SO signals shared */
- #define SPI_LOOP 0x20 /* loopback mode */
- #define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
- #define SPI_READY 0x80 /* slave pulls low to pause */
- u8 bits_per_word; //每個字長的位元數
- int irq; //中斷號
- void *controller_state; //控制器暫存器狀態
- void *controller_data;
- char modalias[SPI_NAME_SIZE]; //裝置名稱
- };
- </pre>
- <p>2、 spi_driver代表一個SPI protocol drivers,即外設驅動。</p>
- <p></p>
- <prename="code"class="csharp">struct spi_driver {
- const struct spi_device_id *id_table; //支援的spi_device裝置表
- int (*probe)(struct spi_device *spi); //probe函式
- int (*remove)(struct spi_device *spi);
- void (*shutdown)(struct spi_device *spi);
- int (*suspend)(struct spi_device *spi, pm_message_t mesg);
- int (*resume)(struct spi_device *spi);
- struct device_driver driver; //裝置模型使用
- };
- </pre>
- <p>3、spi_master代表一個主機控制器,此處即S3C2440中的SPI控制器</p>
- <p></p>
- <prename="code"class="csharp">struct spi_master {
- struct device dev; //裝置模型使用
- s16 bus_num; //master編號,s3c2440有2個spi控制器,編號為0 1
- u16 num_chipselect; //支援的片選的數量,從裝置的片選