版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、Linux下的SPI總線驅(qū)動(一)2013-04-12 15:08:46分類:LINUX版權(quán)所有,轉(zhuǎn)載請說明轉(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è) 備產(chǎn)生)、CS (從設(shè)備使能信號,由主設(shè)備控制)。由于 SPI總線有專用的數(shù)據(jù) 線用于數(shù)據(jù)的發(fā)送和接收,因此可以工作于全雙工,當(dāng)前市面上可以找到的SPI
2、外圍設(shè)備包括RF芯片、智能卡接口、 E2PROM、RTC、觸摸屏傳感器、ADC。SCLK信號線只由主設(shè)備控制,從設(shè)備不能控制信號線。同樣,在一個基于SPI的設(shè)備中,至少有一個主控設(shè)備。 這樣傳輸?shù)奶攸c(diǎn):這樣的傳輸方式有一個優(yōu)點(diǎn),與普通的串行通訊不同,普通的串行通訊一次連續(xù)傳送至少8位數(shù)據(jù),而SPI允許數(shù)據(jù)一位一位的傳送, 甚至允許暫停,因?yàn)镾CLK時鐘線由主控設(shè)備控制, 當(dāng)沒有時鐘跳變時, 從設(shè)備不采集或傳送數(shù)據(jù)。 也就是說,主設(shè)備通過對 SCLK時鐘線的控制可以完成對通訊的控制。SPI還是一個數(shù)據(jù)交換協(xié)議:因?yàn)镾PI的數(shù)據(jù)輸入和輸出線獨(dú)立,所以允許同時完成數(shù)據(jù)的輸入和輸出。不同的SPI設(shè)備的
3、實(shí)現(xiàn)方式不盡相同,主要是數(shù)據(jù)改變和采集的時間不同,在時鐘信號上沿或下沿 采集有不同定義,具體請參考相關(guān)器件的文檔。在點(diǎn)對點(diǎn)的通信中,SPI接口不需要進(jìn)行尋址操作,且為全雙工通信,顯得簡單高效。在多個從設(shè)備的系統(tǒng)中,每個從設(shè)備需要獨(dú)立的 使能信號,硬件上比I2C系統(tǒng)要稍微復(fù)雜一些。二. SPI驅(qū)動移植我們下面將的驅(qū)動的移植是針對Mini2440的SPI驅(qū)動的移植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è)備的名稱用來和驅(qū)動進(jìn)行匹配.bus_num = 0,總線的編號,實(shí)際指對應(yīng)的SPI寄存器.chip_select = 0, 反映了這個芯片是不是被連接到SPI上.irq = IRQ_EINT9,/設(shè)備的中斷號.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,/所有的片選信號.bus_num = 0,/SPI多對應(yīng)的總線編號.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平臺數(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)入開發(fā)板,并且編譯測試程序 運(yùn)行即可。好了,我們的SPI驅(qū)動移植就做好了,我們可以編寫SPI測試代碼進(jìn)行測試。三.SPI設(shè)備和驅(qū)動的注冊在SPI子系統(tǒng)中,包含兩類設(shè)備驅(qū)動。一類稱之為.SPI主控設(shè)備驅(qū)動,用于驅(qū)動SPI主控設(shè)備,以和SPI總線交互,讀寫通信數(shù)據(jù)。另一類稱之為SPI接口設(shè)備驅(qū)動,用于解析SPI主控設(shè)備驅(qū)動讀取的數(shù)據(jù),形成有意義的協(xié)議數(shù)據(jù)。下面我們就看看SPI主控設(shè)備的
11、注冊、SPI 主控設(shè)備驅(qū)動的注冊、SPI接口設(shè)備的添加、SPI接口設(shè)備的注冊、SPI接口設(shè)備驅(qū)動的注冊五個過程。3.1SPI主控設(shè)備的注冊我們在移植的 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);這樣就能理解移植時添加 s3c_device_spi0.dev.platform_data= &s3c2410_spi0_platdata 代碼, 其實(shí)是把s3c2410_spi0_platdata作為平臺設(shè)備的私有數(shù)據(jù)。 在s3c_device_spi0 中就包含了 設(shè)備的寄存器地址,設(shè)備名稱,設(shè)備所產(chǎn)生的總線號,總線掛載的數(shù)目,及各種配置函數(shù)。然后由函數(shù) platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_de
15、vices);統(tǒng) 一把2440所有設(shè)備進(jìn)行注冊。然后看下這個 platform_add_devices注冊函數(shù)主要干了什么事情。在linux/drivers/base/platform.c中105行定義了這個函數(shù)。函數(shù)調(diào)用platform_device_register ()來進(jìn)行注冊。然后在 platform_device_regisrer 中調(diào)用 device_initialize ( pdev->dev)platform_device_add (pdev) 這倆個函數(shù),從函數(shù)名稱上我們推斷一個是初始化設(shè)備信息中的dev結(jié)構(gòu)體,另一個是把這個設(shè)備增加到什么地方去。首先看初始化dev結(jié)
16、構(gòu)體。初看下初始化了kobj相關(guān)東西,初始化鏈表,同步鎖,還有相關(guān)標(biāo)志。然后看 platform_device_add里面內(nèi)容。把其中一個 pdev->dev.bus=& platform_bus_type (全局變量)至此我們基本可以確定了,這個設(shè)備屬于 platform_bus_type。所以這個設(shè)備的總線信息就知道了,但是總線還不知道這個設(shè)備,不過 放心,在接下來的初始化過程中有一個函數(shù)bus_add_device,會讓總線知道這個函數(shù)。這樣至此我們就把一個設(shè)備注冊完畢,初始化了一些我們能初始化的東西。結(jié)果之一是設(shè)備在總線上可以找到。3.2 SPI接口設(shè)備的添加在移植的St
17、epl中,曾經(jīng)添加了如下代碼static struct spi_board_ info s3c2410_spi0_board=0 = .modalias = "spidev",/設(shè)備的名稱用來和驅(qū)動進(jìn)行匹配.bus_num = 0,總線的編號,實(shí)際指對應(yīng)的SPI寄存器.chip_select = 0, 反映了這個芯片是不是被連接到SPI上irq = IRQ_EINT9, /設(shè)備的中斷號.max_speed_hz = 500 * 1000, /SPI 的最大速率;上面結(jié)構(gòu)體來填充 SPI接口的設(shè)備信息,然后通過函數(shù)spi_register_boardn fo(s3c2410_
18、spi0_board,ARRAY_SIZE(s3c2410_spi0_board); 注冊。下面 來跟蹤下這個函數(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;在這個函數(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;這里使用編程技巧定義個元素為0的數(shù)組,目的是接收s3c2410_spi0_borad里面的不確定元素,因?yàn)槭孪炔恢涝氐亩嗌佟H缓笤谙到y(tǒng)編譯的時候會把 boardnfo的內(nèi)存默認(rèn)為0,所以賦值的時候還要自動申請內(nèi)存。memcpy(bi->boardnfo, info, n * sizeof *info);然后定義了同步鎖,創(chuàng)建了鏈表。 list_add_tail(&bi->list, &board_list);這部分好像就到這個地方了,系統(tǒng)把信息保存 到一塊內(nèi)存中,我們可以通過全局變量board_list找到這塊地方。3.
21、3 SPI主控設(shè)備驅(qū)動的注冊在 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 中會調(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)]?這個和SPI主控設(shè)備的注冊過程中的最終掛接的總線類型是一致的。這樣SPI主控設(shè)備
23、和SPI主控驅(qū)動都要注冊到同一個總線上,總線再根據(jù)名稱一樣來進(jìn)行匹配。3.4 SPI接口設(shè)備的注冊我們繼續(xù)看 在spi_s3c24xx.c文件在 s3c24xx_spi_probe 里面我們調(diào)用 spi_bitbang_start(&hw->bitbang);這就是 SPI 接口驅(qū)動的 注冊。跟蹤 spi_bitbang_start 函數(shù),我們看至U它調(diào)用了 spi_register_master(bitbang->master); 在函數(shù)spi_register_master()里面有一函數(shù)調(diào)用 scan_boardinfo(master);用來掃描設(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) /通過 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;這說明該設(shè)備就掛在全局 變量spi_bus_type 總線上了。然后在 spi_new_device中調(diào)用
26、spi_add_device函數(shù),目的我 們已經(jīng)看到,最終 SPI接口的設(shè)備注冊到了 spi_bus_type 上了,如果把 SPI接口設(shè)備的驅(qū) 動也注冊到這個總線上,然后根據(jù)名稱進(jìn)行匹配則device和driver就配對成功。3.5 SPI接口設(shè)備驅(qū)動的注冊我們以spidev.c的驅(qū)動為例,來追蹤該驅(qū)動的注冊|static int _in it spidev_ in it(void)int status;注冊字符設(shè)備BUILD_BUG_ON(N_SPI_MINORS > 256);status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); /if (status <
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 貴州大學(xué)《機(jī)械制圖(二)》2023-2024學(xué)年第一學(xué)期期末試卷
- 貴陽學(xué)院《自動控制原理C》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025黑龍江省安全員-B證考試題庫附答案
- 2025年上海建筑安全員考試題庫附答案
- 硅湖職業(yè)技術(shù)學(xué)院《廣播電視深度報道實(shí)務(wù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025湖南建筑安全員B證考試題庫附答案
- 2025重慶市建筑安全員-B證(項(xiàng)目經(jīng)理)考試題庫
- 廣州幼兒師范高等??茖W(xué)?!督ㄖ⒔Y(jié)構(gòu)識圖》2023-2024學(xué)年第一學(xué)期期末試卷
- 廣州新華學(xué)院《數(shù)字化模具設(shè)計(jì)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025重慶市安全員考試題庫
- 非急救轉(zhuǎn)運(yùn)管理制度
- 第18課《天下第一樓(節(jié)選)》 統(tǒng)編版語文九年級下冊
- 活動策劃部培訓(xùn)課件
- 江蘇省鹽城市2022-2023學(xué)年八年級上學(xué)期期末歷史試題
- 稻草購銷合同模板
- 執(zhí)法中隊(duì)競聘演講稿
- 國有企業(yè)員工守則
- CSR社會責(zé)任管理手冊模板
- 毛澤東軍事思想概述(新)
- 錨桿框格梁施工技術(shù)交底
- 商戶清場協(xié)議書
評論
0/150
提交評論