Linux下SPI驅(qū)動(dòng)測(cè)試程序_第1頁(yè)
Linux下SPI驅(qū)動(dòng)測(cè)試程序_第2頁(yè)
Linux下SPI驅(qū)動(dòng)測(cè)試程序_第3頁(yè)
Linux下SPI驅(qū)動(dòng)測(cè)試程序_第4頁(yè)
Linux下SPI驅(qū)動(dòng)測(cè)試程序_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Linux下的SPI總線驅(qū)動(dòng)(一)2013-04-12 15:08:46分類:LINUX版權(quán)所有,轉(zhuǎn)載請(qǐng)說(shuō)明轉(zhuǎn)自http:/my.csd n.n et/weiqi ng1981127一. spi理論介紹SPI總線全名,串行外圍設(shè)備接口,是一種串行的主從接口,集成于很多微控制 器內(nèi)部。和I2C使用2根線相比,SPI總線使用4根線:MOSI (SPI總線主機(jī)輸 出/從機(jī)輸入)、MISO (SPI總線主機(jī)輸入/從機(jī)輸出)、SCLK(時(shí)鐘信號(hào),由主設(shè) 備產(chǎn)生)、CS (從設(shè)備使能信號(hào),由主設(shè)備控制)。由于 SPI總線有專用的數(shù)據(jù) 線用于數(shù)據(jù)的發(fā)送和接收,因此可以工作于全雙工,當(dāng)前市面上可以找到的SPI

2、外圍設(shè)備包括RF芯片、智能卡接口、 E2PROM、RTC、觸摸屏傳感器、ADC。SCLK信號(hào)線只由主設(shè)備控制,從設(shè)備不能控制信號(hào)線。同樣,在一個(gè)基于SPI的設(shè)備中,至少有一個(gè)主控設(shè)備。 這樣傳輸?shù)奶攸c(diǎn):這樣的傳輸方式有一個(gè)優(yōu)點(diǎn),與普通的串行通訊不同,普通的串行通訊一次連續(xù)傳送至少8位數(shù)據(jù),而SPI允許數(shù)據(jù)一位一位的傳送, 甚至允許暫停,因?yàn)镾CLK時(shí)鐘線由主控設(shè)備控制, 當(dāng)沒(méi)有時(shí)鐘跳變時(shí), 從設(shè)備不采集或傳送數(shù)據(jù)。 也就是說(shuō),主設(shè)備通過(guò)對(duì) SCLK時(shí)鐘線的控制可以完成對(duì)通訊的控制。SPI還是一個(gè)數(shù)據(jù)交換協(xié)議:因?yàn)镾PI的數(shù)據(jù)輸入和輸出線獨(dú)立,所以允許同時(shí)完成數(shù)據(jù)的輸入和輸出。不同的SPI設(shè)備的

3、實(shí)現(xiàn)方式不盡相同,主要是數(shù)據(jù)改變和采集的時(shí)間不同,在時(shí)鐘信號(hào)上沿或下沿 采集有不同定義,具體請(qǐng)參考相關(guān)器件的文檔。在點(diǎn)對(duì)點(diǎn)的通信中,SPI接口不需要進(jìn)行尋址操作,且為全雙工通信,顯得簡(jiǎn)單高效。在多個(gè)從設(shè)備的系統(tǒng)中,每個(gè)從設(shè)備需要獨(dú)立的 使能信號(hào),硬件上比I2C系統(tǒng)要稍微復(fù)雜一些。二. SPI驅(qū)動(dòng)移植我們下面將的驅(qū)動(dòng)的移植是針對(duì)Mini2440的SPI驅(qū)動(dòng)的移植Step1 :在 Linux Source Code中修改 arch/arm/mach-s3c2440/mach-mini2440.文件,加入頭文件:#in clude <li nu x/spi/spi.h>#in clude

4、 <./mach-s3c2410/i nclude/mach/spi.h>然后加入如下代碼:static struct spi_board_ info s3c2410_spi0_board=0 = .modalias = "spidev",/設(shè)備的名稱用來(lái)和驅(qū)動(dòng)進(jìn)行匹配.bus_num = 0,總線的編號(hào),實(shí)際指對(duì)應(yīng)的SPI寄存器.chip_select = 0, 反映了這個(gè)芯片是不是被連接到SPI上.irq = IRQ_EINT9,/設(shè)備的中斷號(hào).max_speed_hz = 500 * 1000, /SPI 的最大速率;static struct s3c24

5、10_spi_i nfo s3c2410_spi0_platdata = .pin_cs = S3C2410_GPG(2),.n um_cs = 1,/所有的片選信號(hào).bus_num = 0,/SPI多對(duì)應(yīng)的總線編號(hào).gpio_setup = s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,/ 引腳設(shè)置函數(shù);static struct spi_board_ info s3c2410_spi1_board=0 = .modalias = "spidev",.bus_ num = 1,.chip_select = 0,.irq = IRQ_EINT2,

6、.max_speed_hz = 500 * 1000,;static struct s3c2410_spi_info s3c2410_spi1_platdata = .pin_cs = S3C2410_GPG(3),.num_cs = 1,.bus_ num = 1,.gpio_setup = s3c24xx_spi_gpiocfg_bus1_gpg5_6_7,;Step2:在mini2440_devices平臺(tái)數(shù)組中添加如下代碼:&s3c_device_spi0,&s3c_device_spi1,Step3:最后在mini2440_machine_init函數(shù)中加入如下代碼:

7、s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata;spi_register_boardn fo(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board); s3c_device_spi1.dev.platform_data= &s3c2410_spi1_platdata;spi_register_boardn fo(s3c2410_spi1_board, ARRAY_SIZE(s3c2410_spi1_board);Step4:最后需要修改 arch/arm/plat-

8、s3c24xx/KConfig 文件找到config S3C24XX SPI BUS0 GPE11 GPE12 GPE13boolhelpSPI GPIO con figurati on code for BUS0 whe n conn ected toGPE11, GPE12 and GPE13.config S3C24XX SPI BUS1 GPG5 GPG6 GPG7boolhelpSPI GPIO con figuratio n code for BUS 1 whe n conn ected toGPG5, GPG6 and GPG7.修改為config S3C24XX SPI BUS

9、0 GPE11 GPE12 GPE13bool "S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13"helpSPI GPIO con figurati on code for BUS0 whe n conn ected toGPE11, GPE12 and GPE13.config S3C24XX SPI BUS1 GPG5 GPG6 GPG7bool "S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7"helpSPI GPIO configuration code for BUS 1 when connected to

10、GPG5, GPG6 and GPG7.Step5:最后 make menuconfig配置,選中 System Type和 SPI support相應(yīng)文件Step6 :執(zhí)行make生成zlnage,將編譯好的內(nèi)核導(dǎo)入開(kāi)發(fā)板,并且編譯測(cè)試程序 運(yùn)行即可。好了,我們的SPI驅(qū)動(dòng)移植就做好了,我們可以編寫(xiě)SPI測(cè)試代碼進(jìn)行測(cè)試。三.SPI設(shè)備和驅(qū)動(dòng)的注冊(cè)在SPI子系統(tǒng)中,包含兩類設(shè)備驅(qū)動(dòng)。一類稱之為.SPI主控設(shè)備驅(qū)動(dòng),用于驅(qū)動(dòng)SPI主控設(shè)備,以和SPI總線交互,讀寫(xiě)通信數(shù)據(jù)。另一類稱之為SPI接口設(shè)備驅(qū)動(dòng),用于解析SPI主控設(shè)備驅(qū)動(dòng)讀取的數(shù)據(jù),形成有意義的協(xié)議數(shù)據(jù)。下面我們就看看SPI主控設(shè)備的

11、注冊(cè)、SPI 主控設(shè)備驅(qū)動(dòng)的注冊(cè)、SPI接口設(shè)備的添加、SPI接口設(shè)備的注冊(cè)、SPI接口設(shè)備驅(qū)動(dòng)的注冊(cè)五個(gè)過(guò)程。3.1SPI主控設(shè)備的注冊(cè)我們?cè)谝浦驳?Step3:最后在mini2440_machine_init函數(shù)中加入如下代碼:s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata;spi_register_boardn fo(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board);s3c_device_spi1.dev.platform_data= &s3c2410_

12、spi1_platdata;spi_register_boardnfo(s3c2410_spi1_board, ARRAY_SIZE(s3c2410_spi1_board);這里面的 s3c_device_spi0 其實(shí)定義在 archarmplat-s3c24xxdevs.c 中,跟蹤下static struct resource s3c_spi0_resource = 0 = .start = S3C24XX_PA_SPI,.end = S3C24XX_PA_SPI + 0x1f,.flags = IORESOURCE_MEM,1 = .start = IRQ_SPI0,.end = IR

13、Q_SPI0,.flags = IORESOURCE_IRQ,; static u64 s3c_device_spi0_dmamask = OxffffffffUL;struct platform_device s3c_device_spi0 = .n ame= "s3c2410-spi",.id= 0,.num .resources= ARRAY_SIZE(s3c_spiO_resource),.resource = s3c_spi0_resource,.dev= .dma_mask = & s3c_device_spi0_dmamask,.cohere nt_d

14、ma_mask = OxffffffffUL;EXPORT_SYMBOL(s3c_device_spiO);這樣就能理解移植時(shí)添加 s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata 代碼, 其實(shí)是把s3c2410_spi0_platdata作為平臺(tái)設(shè)備的私有數(shù)據(jù)。 在s3c_device_spi0 中就包含了 設(shè)備的寄存器地址,設(shè)備名稱,設(shè)備所產(chǎn)生的總線號(hào),總線掛載的數(shù)目,及各種配置函數(shù)。然后由函數(shù) platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_de

15、vices);統(tǒng) 一把2440所有設(shè)備進(jìn)行注冊(cè)。然后看下這個(gè) platform_add_devices注冊(cè)函數(shù)主要干了什么事情。在linux/drivers/base/platform.c中105行定義了這個(gè)函數(shù)。函數(shù)調(diào)用platform_device_register ()來(lái)進(jìn)行注冊(cè)。然后在 platform_device_regisrer 中調(diào)用 device_initialize ( pdev->dev)platform_device_add (pdev) 這倆個(gè)函數(shù),從函數(shù)名稱上我們推斷一個(gè)是初始化設(shè)備信息中的dev結(jié)構(gòu)體,另一個(gè)是把這個(gè)設(shè)備增加到什么地方去。首先看初始化dev結(jié)

16、構(gòu)體。初看下初始化了kobj相關(guān)東西,初始化鏈表,同步鎖,還有相關(guān)標(biāo)志。然后看 platform_device_add里面內(nèi)容。把其中一個(gè) pdev->dev.bus=& platform_bus_type (全局變量)至此我們基本可以確定了,這個(gè)設(shè)備屬于 platform_bus_type。所以這個(gè)設(shè)備的總線信息就知道了,但是總線還不知道這個(gè)設(shè)備,不過(guò) 放心,在接下來(lái)的初始化過(guò)程中有一個(gè)函數(shù)bus_add_device,會(huì)讓總線知道這個(gè)函數(shù)。這樣至此我們就把一個(gè)設(shè)備注冊(cè)完畢,初始化了一些我們能初始化的東西。結(jié)果之一是設(shè)備在總線上可以找到。3.2 SPI接口設(shè)備的添加在移植的St

17、epl中,曾經(jīng)添加了如下代碼static struct spi_board_ info s3c2410_spi0_board=0 = .modalias = "spidev",/設(shè)備的名稱用來(lái)和驅(qū)動(dòng)進(jìn)行匹配.bus_num = 0,總線的編號(hào),實(shí)際指對(duì)應(yīng)的SPI寄存器.chip_select = 0, 反映了這個(gè)芯片是不是被連接到SPI上irq = IRQ_EINT9, /設(shè)備的中斷號(hào).max_speed_hz = 500 * 1000, /SPI 的最大速率;上面結(jié)構(gòu)體來(lái)填充 SPI接口的設(shè)備信息,然后通過(guò)函數(shù)spi_register_boardn fo(s3c2410_

18、spi0_board,ARRAY_SIZE(s3c2410_spi0_board); 注冊(cè)。下面 來(lái)跟蹤下這個(gè)函數(shù)干了些什么事情。int _init spi_register_board_ in fo(struct spi_board_ info const *info, un sig ned n)struct board info*bi;bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);if (!bi)return -ENOMEM;bi->n _board_ info = n;/把s3c2410_spi0_board的信息

19、都拷貝到結(jié)構(gòu)體memcpy(bi->board_ info, info, n * sizeof *in fo);mutex_lock (&board_lock);list_add_tail(&bi->list, &boardl_list);mutex_ uni ock (&board_lock);return 0;在這個(gè)函數(shù)里面,是把s3c2410_spi0_board的信息都拷貝到結(jié)構(gòu)體 struct board info struct list_head list;un sig ned n _board_ info;struct spi_boar

20、d_ info board_i nfo0;這里使用編程技巧定義個(gè)元素為0的數(shù)組,目的是接收s3c2410_spi0_borad里面的不確定元素,因?yàn)槭孪炔恢涝氐亩嗌佟H缓笤谙到y(tǒng)編譯的時(shí)候會(huì)把 boardnfo的內(nèi)存默認(rèn)為0,所以賦值的時(shí)候還要自動(dòng)申請(qǐng)內(nèi)存。memcpy(bi->boardnfo, info, n * sizeof *info);然后定義了同步鎖,創(chuàng)建了鏈表。 list_add_tail(&bi->list, &board_list);這部分好像就到這個(gè)地方了,系統(tǒng)把信息保存 到一塊內(nèi)存中,我們可以通過(guò)全局變量board_list找到這塊地方。3.

21、3 SPI主控設(shè)備驅(qū)動(dòng)的注冊(cè)在 spi_s3c24xx.c 文件中static int _in it s3c24xx_spi_ in it(void)retur n platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);在 platform_driver_probe 中會(huì)調(diào)用 platform_driver_register(drv);繼續(xù)跟蹤int platform_driver_register(struct platform_driver *drv)drv->driver.bus = &platf

22、orm_bus_type;總線類型if (drv->probe)drv->be = platform_drv_probe;if (drv->remove)drv->driver.remove = platform_drv_remove;if (drv->shutdow n)drv->driver.shutdow n = platform_drv_shutdow n;return driver_register(&drv->driver);看到?jīng)]?這個(gè)和SPI主控設(shè)備的注冊(cè)過(guò)程中的最終掛接的總線類型是一致的。這樣SPI主控設(shè)備

23、和SPI主控驅(qū)動(dòng)都要注冊(cè)到同一個(gè)總線上,總線再根據(jù)名稱一樣來(lái)進(jìn)行匹配。3.4 SPI接口設(shè)備的注冊(cè)我們繼續(xù)看 在spi_s3c24xx.c文件在 s3c24xx_spi_probe 里面我們調(diào)用 spi_bitbang_start(&hw->bitbang);這就是 SPI 接口驅(qū)動(dòng)的 注冊(cè)。跟蹤 spi_bitbang_start 函數(shù),我們看至U它調(diào)用了 spi_register_master(bitbang->master); 在函數(shù)spi_register_master()里面有一函數(shù)調(diào)用 scan_boardinfo(master);用來(lái)掃描設(shè)備。static v

24、oid sca n_board in fo(struct spi_master *master)struct board info *bi;mutex_lock(&boardo ck);list_for_each_entry(bi, &board_list, list) /通過(guò) boardist遍歷鏈表,取得設(shè)備信息struct spi_board_i nfo *chip = bi->board_i nfo;un sig nedn;for (n = bi->n _board_i nfo; n > 0; n-, chip+) if (chip->bus_

25、num != master->bus_ num)con ti nue;(void) spi_ new_device(master, chip);mutex_ un lock(&boardo ck);我們跟蹤 scan_boardinfo 中的 spi_new_device 函數(shù)發(fā)現(xiàn),spi_new_device 調(diào)用 spi_alloc_device , 而在spi_alloc_device函數(shù)中有一句 spi->dev.bus = &spi_bus_type;這說(shuō)明該設(shè)備就掛在全局 變量spi_bus_type 總線上了。然后在 spi_new_device中調(diào)用

26、spi_add_device函數(shù),目的我 們已經(jīng)看到,最終 SPI接口的設(shè)備注冊(cè)到了 spi_bus_type 上了,如果把 SPI接口設(shè)備的驅(qū) 動(dòng)也注冊(cè)到這個(gè)總線上,然后根據(jù)名稱進(jìn)行匹配則device和driver就配對(duì)成功。3.5 SPI接口設(shè)備驅(qū)動(dòng)的注冊(cè)我們以spidev.c的驅(qū)動(dòng)為例,來(lái)追蹤該驅(qū)動(dòng)的注冊(cè)|static int _in it spidev_ in it(void)int status;注冊(cè)字符設(shè)備BUILD_BUG_ON(N_SPI_MINORS > 256);status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); /if (status <

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論