




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中秋劃拳活動方案
- 中秋商場活動方案
- 中秋國慶長期活動方案
- 中秋小預(yù)算公司活動方案
- 中秋托管活動方案
- 中秋晚宴活動方案
- 中秋活動大型活動方案
- 中秋清倉活動方案
- 中秋續(xù)費活動方案
- 中秋節(jié)藥店活動活動方案
- 2024年重新寫撫養(yǎng)協(xié)議書模板
- 專題6.6射影定理專項提升訓(xùn)練(重難點培優(yōu))-2022-2023學(xué)年九年級數(shù)學(xué)下冊尖子生培優(yōu)題典(原卷版)
- 中華詩詞之美學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 蚊蠅蟲鼠害防治管理制度
- DL∕T 1811-2018 電力變壓器用天然酯絕緣油選用導(dǎo)則
- 水泵檢修工(高級)技能鑒定考試題庫(含答案)
- AQ/T 9009-2015 生產(chǎn)安全事故應(yīng)急演練評估規(guī)范(正式版)
- 瀘州老窖“濃香文釀杯”企業(yè)文化知識競賽考試題庫大全-下(多選、填空題)
- 酒店運營管理 智慧樹知到期末考試答案章節(jié)答案2024年山東青年政治學(xué)院
- 幼兒園課程故事開展培訓(xùn)
- 佐藤大用設(shè)計解決問題
評論
0/150
提交評論