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

下載本文檔

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

文檔簡介

Linux下SPI驅(qū)動測試程序Linux下SPI驅(qū)動測試程序Linux下SPI驅(qū)動測試程序Linux下SPI驅(qū)動測試程序編制僅供參考審核批準(zhǔn)生效日期地址:電話:傳真:郵編:

Linux下的SPI總線驅(qū)動(一)?2013-04-1215:08:46分類:

LINUX版權(quán)所有,轉(zhuǎn)載請說明轉(zhuǎn)自

一.SPI理論介紹SPI總線全名,串行外圍設(shè)備接口,是一種串行的主從接口,集成于很多微控制器內(nèi)部。和I2C使用2根線相比,SPI總線使用4根線:MOSI(SPI總線主機輸出/從機輸入)、

MISO(SPI總線主機輸入/從機輸出)、SCLK(時鐘信號,由主設(shè)備產(chǎn)生)、CS(從設(shè)備使能信號,由主設(shè)備控制)。由于SPI總線有專用的數(shù)據(jù)線用于數(shù)據(jù)的發(fā)送和接收,因此可以工作于全雙工,當(dāng)前市面上可以找到的SPI外圍設(shè)備包括RF芯片、智能卡接口、E2PROM、RTC、觸摸屏傳感器、ADC。SCLK信號線只由主設(shè)備控制,從設(shè)備不能控制信號線。同樣,在一個基于SPI的設(shè)備中,至少有一個主控設(shè)備。這樣傳輸?shù)奶攸c:這樣的傳輸方式有一個優(yōu)點,與普通的串行通訊不同,普通的串行通訊一次連續(xù)傳送至少8位數(shù)據(jù),而SPI允許數(shù)據(jù)一位一位的傳送,甚至允許暫停,因為SCLK時鐘線由主控設(shè)備控制,當(dāng)沒有時鐘跳變時,從設(shè)備不采集或傳送數(shù)據(jù)。也就是說,主設(shè)備通過對SCLK時鐘線的控制可以完成對通訊的控制。SPI還是一個數(shù)據(jù)交換協(xié)議:因為SPI的數(shù)據(jù)輸入和輸出線獨立,所以允許同時完成數(shù)據(jù)的輸入和輸出。不同的SPI設(shè)備的實現(xiàn)方式不盡相同,主要是數(shù)據(jù)改變和采集的時間不同,在時鐘信號上沿或下沿采集有不同定義,具體請參考相關(guān)器件的文檔。在點對點的通信中,SPI接口不需要進行尋址操作,且為全雙工通信,顯得簡單高效。在多個從設(shè)備的系統(tǒng)中,每個從設(shè)備需要獨立的使能信號,硬件上比I2C系統(tǒng)要稍微復(fù)雜一些。二.SPI驅(qū)動移植我們下面將的驅(qū)動的移植是針對Mini2440的SPI驅(qū)動的移植Step1

:在LinuxSourceCode中修改arch/arm/mach-s3c2440/文件,加入頭文件:#include<linux/spi/>

#include<../mach-s3c2410/include/mach/>然后加入如下代碼:staticstructspi_board_infos3c2410_spi0_board[]=

{

[0]={

.modalias="spidev",

us_num=0,

hip_select=0,

rq=IRQ_EINT9,

ax_speed_hz=500*1000,

in_cs=S3C2410_GPG(2),

.num_cs=1,

us_num=0,

pio_setup=s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,

odalias="spidev",

.bus_num=1,

.chip_select=0,

.irq=IRQ_EINT2,

.max_speed_hz=500*1000,

}

};

staticstructs3c2410_spi_infos3c2410_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ù)中加入如下代碼:&s3c2410_spi0_platdata;

spi_register_board_info(s3c2410_spi0_board,ARRAY_SIZE(s3c2410_spi0_board));

&s3c2410_spi1_platdata;

spi_register_board_info(s3c2410_spi1_board,ARRAY_SIZE(s3c2410_spi1_board));Step4:最后需要修改arch/arm/plat-s3c24xx/KConfig文件找到configS3C24XX_SPI_BUS0_GPE11_GPE12_GPE13

bool

help

SPIGPIOconfigurationcodeforBUS0whenconnectedto

GPE11,GPE12andGPE13.

configS3C24XX_SPI_BUS1_GPG5_GPG6_GPG7

bool

help

SPIGPIOconfigurationcodeforBUS1whenconnectedto

GPG5,GPG6andGPG7.修改為configS3C24XX_SPI_BUS0_GPE11_GPE12_GPE13

bool"S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13"

help

SPIGPIOconfigurationcodeforBUS0whenconnectedto

GPE11,GPE12andGPE13.

configS3C24XX_SPI_BUS1_GPG5_GPG6_GPG7

bool"S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7"

help

SPIGPIOconfigurationcodeforBUS1whenconnectedto

GPG5,GPG6andGPG7.Step5:最后makemenuconfig配置,選中SystemType和SPIsupport相應(yīng)文件Step6:執(zhí)行make生成zInage,將編譯好的內(nèi)核導(dǎo)入開發(fā)板,并且編譯測試程序運行即可。好了,我們的SPI驅(qū)動移植就做好了,我們可以編寫SPI測試代碼進行測試。三.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è)備的注冊、SPI主控設(shè)備驅(qū)動的注冊、SPI接口設(shè)備的添加、SPI接口設(shè)備的注冊、SPI接口設(shè)備驅(qū)動的注冊五個過程。主控設(shè)備的注冊我們在移植的Step3:最后在mini2440_machine_init函數(shù)中加入如下代碼:&s3c2410_spi0_platdata;

spi_register_board_info(s3c2410_spi0_board,ARRAY_SIZE(s3c2410_spi0_board));

&s3c2410_spi1_platdata;

spi_register_board_info(s3c2410_spi1_board,ARRAY_SIZE(s3c2410_spi1_board));這里面的s3c_device_spi0其實定義在\arch\arm\plat-s3c24xx\中,跟蹤下staticstructresources3c_spi0_resource[]={

[0]={

.start=S3C24XX_PA_SPI,

.end

=S3C24XX_PA_SPI+0x1f,

.flags=IORESOURCE_MEM,

},

[1]={

.start=IRQ_SPI0,

.end

=IRQ_SPI0,

.flags=IORESOURCE_IRQ,

}};staticu64s3c_device_spi0_dmamask=0xffffffffUL;structplatform_devices3c_device_spi0={

.name

="s3c2410-spi",

.id

=0,

.num_resources

=ARRAY_SIZE(s3c_spi0_resource),

.resource

=s3c_spi0_resource,

.dev

={

.dma_mask=&s3c_device_spi0_dmamask,

.coherent_dma_mask=0xffffffffUL

}};EXPORT_SYMBOL(s3c_device_spi0);這樣就能理解移植時添加&s3c2410_spi0_platdata代碼,其實是把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_devices));統(tǒng)一把2440所有設(shè)備進行注冊。然后看下這個platform_add_devices注冊函數(shù)主要干了什么事情。在linux/drivers/base/中105行定義了這個函數(shù)。函數(shù)調(diào)用platform_device_register()來進行注冊。然后在platform_device_regisrer中調(diào)用device_initialize(pdev->dev)platform_device_add(pdev)這倆個函數(shù),從函數(shù)名稱上我們推斷一個是初始化設(shè)備信息中的dev結(jié)構(gòu)體,另一個是把這個設(shè)備增加到什么地方去。首先看初始化dev結(jié)構(gòu)體。初看下初始化了kobj相關(guān)東西,初始化鏈表,同步鎖,還有相關(guān)標(biāo)志。然后看platform_device_add里面內(nèi)容。把其中一個pdev->=&platform_bus_type(全局變量)至此我們基本可以確定了,這個設(shè)備屬于platform_bus_type。所以這個設(shè)備的總線信息就知道了,但是總線還不知道這個設(shè)備,不過放心,在接下來的初始化過程中有一個函數(shù)bus_add_device,會讓總線知道這個函數(shù)。這樣至此我們就把一個設(shè)備注冊完畢,初始化了一些我們能初始化的東西。結(jié)果之一是設(shè)備在總線上可以找到。

SPI接口設(shè)備的添加在移植的Step1中,曾經(jīng)添加了如下代碼staticstructspi_board_infos3c2410_spi0_board[]=

{

[0]={

.modalias="spidev",

us_num=0,

hip_select=0,

rq=IRQ_EINT9,

ax_speed_hz=500*1000,

//SPI的最大速率

}

};

上面結(jié)構(gòu)體來填充SPI接口的設(shè)備信息,然后通過函數(shù)spi_register_board_info(s3c2410_spi0_board,ARRAY_SIZE(s3c2410_spi0_board));注冊。下面來跟蹤下這個函數(shù)干了些什么事情。int__init

spi_register_board_info(structspi_board_infoconst*info,unsignedn){

structboardinfo

*bi;

bi=kmalloc(sizeof(*bi)+n*sizeof*info,GFP_KERNEL);

if(!bi)

return-ENOMEM;

bi->n_board_info=n;//把s3c2410_spi0_board的信息都拷貝到結(jié)構(gòu)體

memcpy(bi->board_info,info,n*sizeof*info);

mutex_lock(&board_lock);

list_add_tail(&bi->list,&board_list);

mutex_unlock(&board_lock);

return0;}在這個函數(shù)里面,是把s3c2410_spi0_board的信息都拷貝到結(jié)構(gòu)體structboardinfo{

structlist_head

list;

unsigned

n_board_info;

structspi_board_info

board_info[0];};這里使用編程技巧定義個元素為0的數(shù)組,目的是接收s3c2410_spi0_borad里面的不確定元素,因為事先不知道元素的多少。然后在系統(tǒng)編譯的時候會把board_info的內(nèi)存默認(rèn)為0,所以賦值的時候還要自動申請內(nèi)存。memcpy(bi->board_info,info,n*sizeof*info);然后定義了同步鎖,創(chuàng)建了鏈表。list_add_tail(&bi->list,&board_list);這部分好像就到這個地方了,系統(tǒng)把信息保存到一塊內(nèi)存中,我們可以通過全局變量board_list找到這塊地方。SPI主控設(shè)備驅(qū)動的注冊在文件中staticint__inits3c24xx_spi_init(void){

returnplatform_driver_probe(&s3c24xx_spi_driver,s3c24xx_spi_probe);}在platform_driver_probe中會調(diào)用platform_driver_register(drv);繼續(xù)跟蹤intplatform_driver_register(structplatform_driver*drv){

drv->=&platform_bus_type;

//總線類型

if(drv->probe)

drv->=platform_drv_probe;

if(drv->remove)

drv->=platform_drv_remove;

if(drv->shutdown)

drv->=platform_drv_shutdown;

returndriver_register(&drv->driver);}看到?jīng)]這個和SPI主控設(shè)備的注冊過程中的最終掛接的總線類型是一致的。這樣SPI主控設(shè)備和SPI主控驅(qū)動都要注冊到同一個總線上,總線再根據(jù)名稱一樣來進行匹配。SPI接口設(shè)備的注冊我們繼續(xù)看在文件在s3c24xx_spi_probe里面我們調(diào)用spi_bitbang_start(&hw->bitbang);這就是SPI接口驅(qū)動的注冊。跟蹤spi_bitbang_start函數(shù),我們看到它調(diào)用了spi_register_master(bitbang->master);在函數(shù)spi_register_master()里面有一函數(shù)調(diào)用scan_boardinfo(master);用來掃描設(shè)備。staticvoidscan_boardinfo(structspi_master*master){

structboardinfo

*bi;

mutex_lock(&board_lock);

list_for_each_entry(bi,&board_list,list){//通過board_list遍歷鏈表,取得設(shè)備信息

structspi_board_info

*chip=bi->board_info;

unsigned

n;

for(n=bi->n_board_info;n>0;n--,chip++){

if(chip->bus_num!=master->bus_num)

continue;

(void)spi_new_device(master,chip);

}

}

mutex_unlock(&board_lock);}我們跟蹤scan_boardinfo中的spi_new_device函數(shù)發(fā)現(xiàn),spi_new_device調(diào)用spi_alloc_device,而在spi_alloc_device函數(shù)中有一句spi->=&spi_bus_type;這說明該設(shè)備就掛在全局變量spi_bus_type總線上了。然后在spi_new_device中調(diào)用spi_add_device函數(shù),目的我們已經(jīng)看到,最終SPI接口的設(shè)備注冊到了spi_bus_type上了,如果把SPI接口設(shè)備的驅(qū)動也注冊到這個總線上,然后根據(jù)名稱進行匹配則device和driver就配對成功。SPI接口設(shè)備驅(qū)動的注冊我們以的驅(qū)動為例,來追蹤該驅(qū)動的注冊staticint__initspidev_init(void){

intstatus;

BUILD_BUG_ON(N_SPI_MINORS>256);

status=register_chrdev(SPIDEV_MAJOR,"spi",&spidev

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論