海思SDK驅動部分_第1頁
海思SDK驅動部分_第2頁
海思SDK驅動部分_第3頁
海思SDK驅動部分_第4頁
海思SDK驅動部分_第5頁
已閱讀5頁,還剩5頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、1,linux驅動程序介紹1.1 linux驅動程序在系統中的角色Linux分為用戶態(tài)和內核態(tài),一般應用程序是在用戶態(tài)執(zhí)行,他們通過一系列的系統調用同內核態(tài)進行交互。驅動程序是內核與硬件的接口,它把系統調用映射到具體設備對于實際硬件的特定操作上,關系如下圖所通過這種方法,應用程序就可以像操作普通文件一樣操作硬件設備,用戶程序只需要關心這個抽象出來的文件,而一切同硬件打交道的工作都交給了驅動程序。1.2 linux驅動的類型linux系統將設備分為3類:字符設備、塊設備、網絡設備,攝像機常用的外圍設備(如I2C,串口,SPI,GPIO,PWM等)均屬于字符設備,tf卡驅動屬于塊設備,網卡相關驅動

2、屬于網絡設備。字符設備與塊設備的區(qū)別:1、字符設備是面向流的,最小訪問單位是字節(jié);而塊設備是面向塊的,最小訪問單位是512字節(jié)或2的更高次冪。2、字符設備只能順序按字節(jié)訪問,而塊設備可隨機訪問。3、塊設備上可容納文件系統,訪問形式上,字符設備通過設備節(jié)點訪問,而塊設備雖然也可通過設備節(jié)點訪問,但一般是通過文件系統來訪問數據的。而網絡設備沒有設備節(jié)點,是因為網絡設備是面向報文的,很難實現相關read、write等文件讀寫函數。所以驅動的實現也與字符設備和塊設備不同。1.3 linux驅動的一些重要概念設備號Linux把所有設備都當作文件,為了管理這些設備,系統為它們各自都編了號,而每個設備號又分

3、為主設備號和次設備號。主設備號用來區(qū)分不同類型的設備,而次設備號用來區(qū)分同一類型內的多個設備(及其設備分區(qū))。 在建立字符驅動時需要做的第一件事是獲取設備號。設備號的分配方式一般有2種,靜態(tài)分配和動態(tài)分配,靜態(tài)分配設備號,就是驅動程序開發(fā)者,靜態(tài)地指定一個設備號。對于一部分常用的設備,linux內核開發(fā)者已經為其分配了設備號。這些設備號可以在內核源碼documentation/devices.txt文件中找到。如果只有開發(fā)者自己使用這些設備驅動程序,那么其可以選擇一個尚未使用的設備號。當添加新硬件時,很可能造成設備號沖突,影響設備的使用。為了解決手動分配設備號存在沖突的問題,內核開發(fā)者提出動態(tài)

4、分配設備號的方法。使用該方法驅動程序在加載的時候,通過linux內核提供的專門的函數動態(tài)獲取設備號。int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name)設備節(jié)點linux系統中對所有設備的訪問都是基于文件的形式。對于每一種設備,在加載驅動程序的時候都會在/dev目錄下創(chuàng)建一個文件,這個文件就是設備節(jié)點。對于每一個設備節(jié)點,在實際運行時, linux系統通過VFS(虛擬文件系統)來完成將文件的各種系統調用與具體的驅動程序函數之間的映射。 設備節(jié)點可以通過mknod命令在系統啟動

5、的時候手動創(chuàng)建,也可以通過udev自動創(chuàng)建。在驅動用加入對udev的支持主要做的就是:在驅動初始化的代碼里調用內核提供的API向內核注冊驅動信息class_create       :    創(chuàng)建class     class_device_create    :    創(chuàng)建device驅動加載時會在/sys/class目錄下生成與該模塊相關的信息,同時用戶空間中的udev會自

6、動響應 device_create()函數,去/sysfs下尋找對應的類從而創(chuàng)建設備節(jié)點。驅動初始化時,需要完成以下工作:  1,通過alloc_chrdev_region()及相關函數分配主/次設備號。  2,使用device_create()創(chuàng)建/dev和/sys節(jié)點。  3,使用cdev_init()和cdev_add()將自身注冊為字符驅動程序?;祀s設備考慮到有的系統包含很多簡單字符設備驅動,單獨為這些設備分配設備號比較浪費資源,同時工作量也很大,linux系統針對這些情況推出了一種叫混雜設備模型的驅動框架(miscellaneous)。混雜設備主要有2個

7、特征:1)所有的misc設備被分配同一個主設備號MISC_MAJOR(10),但是可以選擇一個單獨的次設備號。如果一個字符設備驅動要驅動多個設備,那么它就不應該用misc設備來實現;2)混雜設備驅動初始化時,只需要執(zhí)行簡單的一個注冊函數,即可自動完成設備號分配,設備節(jié)點創(chuàng)建,向內核注冊等工作,極大的簡化了驅動初始化流程。硬件IO操作IO端口與IO內存x86體系和ARM體系的尋址方式是有差別的:在x86下,為了能夠滿足CPU高速地運行,內存與CPU之間通過北橋相連并通過地址方式訪問,而外設通過南橋與CPU相連并通過端口訪問。因為這兩種訪問方式的不同,linux分出了兩種不同的訪問操作:以地址方式

8、訪問硬件使用IO內存操作。以端口方式訪問硬件使用IO端口操作。在ARM下也實現了類似的操作,通過兩條不同的總線(AHB BUS和APB BUS)來連接不同訪問速度的外設。但是它與x86不同,無論是內存還是外設,ARM都是通過地址訪問。在ARM下,訪問寄存器就像訪問內存一樣從指定的寄存器地址獲取數據,修改。所以,ARM下一般是使用IO內存的操作。但這并不是說IO端口的操作在ARM下不能用,它們的代碼差不多,只是沒有使用的必要,下面也將介紹IO內存操作。如何使用IO內存獲得硬件的地址我們不能在linux使用實際的物理地址,要對指定的物理地址進行操作,必須要先將物理地址與虛擬地址對應,通過虛擬地址訪

9、問。于是有了以下的物理地址映射函數:#includevoid *ioremap(unsigned long phys_addr, unsigned long size);函數傳入兩個參數,需要訪問的物理內存(寄存器)的首地址phys_addr和這段內存區(qū)域的大小size,返回與該段物理地址對應的虛擬地址。這段地址可以多次被映射,當然,每次映射的虛擬地址也不一樣。phys = 0x200f0000; /1、指定物理地址virt = (unsigned long)ioremap(phys, 0x0c); /2、通過ioremap獲得對應的虛擬地址/0x0c表示只要12字節(jié)的大小 GPECON =

10、(unsigned long *)(virt + 0x40); /3、指定需要操作的寄存器的地址*GPECON &= (3 << 24); /配置GPE12為輸出端口為了實現更好的移植性,上面的程序就有缺陷了。內核建議,盡量使用內核提供的內存訪問接口:#include/從內存讀取數據,返回值是指定內存地址中的值unsigned int ioread8(void *addr)unsigned int ioread16(void *addr)unsigned int ioread32(void *addr)/往指定內存地址寫入數據void iowrite8(u8 value,

11、void *addr)void iowrite16(u16 value, void *addr)void iowrite32(u32 value, void *addr)參照硬件說明,通過對寄存器的控制實現操作硬件硬件說明文檔驅動的調試Linux設備模型linux系統作為開源的下系統,支持世界上大部分的硬件,導致Linux內核看上去非常臃腫、雜亂、不易維護。為了優(yōu)化,linux系統從2.6版本開始提出了全新的設備模型(也稱作Driver Model)概念。設備模型將硬件設備歸納、分類,然后抽象出一套標準的數據結構和接口。驅動的開發(fā),就簡化為對內核所規(guī)定的數據結構的填充和實現。1)Linux設備

12、模型中包含四個重要概念:Bus、Class、Device、 Device Driver。Bus(總線):Bus(總線)是一類特殊的設備,它是連接處理器和其它設備之間的通道(channel)。在設備模型中,所有的設備都通過總線相連,甚至是那些內部的虛擬平臺總線(platform bus).Class(類):在Linux設備模型中,Class的概念非常類似面向對象程序設計中的Class(類),它主要是集合具有相似功能或屬性的設備,這樣就可以抽象出一套可以在多個設備之間共用的數據結構和接口函數。因而從屬于相同Class的設備的驅動程序,就不再需要重復定義這些公共資源,直接從Class中繼承即可。De

13、vice(設備):抽象系統中所有的硬件設備,描述它的名字、屬性、從屬的Bus、從屬的Class等信息。Device Driver(驅動):Linux設備模型用Driver抽象硬件設備的驅動程序,它包含設備初始化、電源管理相關的接口實現。而Linux內核中的驅動開發(fā),基本都圍繞該抽象進行(實現所規(guī)定的接口函數)。2)Linux設備模型的運行機制配對(Match):當總線上添加了新設備或者新驅動函數的時候,內核會調用一次或者多次這個函數。舉例,如果我現在添加了一個新的驅動函數,內核就會調用所屬總線的match函數,配對總線上所有的設備,如果驅動能夠處理其中一個設備,函數返回0,告訴內核配對成功。探

14、測(probe) 當配對(match)成功后,內核就會執(zhí)行device_driver中的probe回調函數,而該函數就是所有driver的入口,可以執(zhí)行諸如硬件設備初始化、字符設備注冊、設備文件操作ops注冊等動作。所以說,真正的驅動函數入口是在probe函數中。卸載(remove) 當該驅動函數或者驅動函數正在操作的設備被移除時,內核會調用驅動函數中的remove函數調用,進行一些設備卸載相應的操作。platform設備針對一些可以通過CPU直接尋址的設備(比如集成在嵌入式SOC芯片上的控制器,CPU可以直接訪問其寄存器),linux內核在設備模型的基礎上(device和device_dri

15、ver),對這些設備進行了更進一步的封裝,抽象出paltform bus、platform device和platform driver,以便驅動開發(fā)人員可以方便的開發(fā)這類設備的驅動。paltform設備對嵌入式Linux驅動開發(fā)是非常重要的,因為我們編寫的大多數設備驅動,都是為了驅動plaftom設備。由圖片可知,Platform設備在內核中的實現主要包括三個部分:Platform Bus,基于底層bus模塊,抽象出一個虛擬的Platform bus,用于掛載Platform設備; Platform Device,基于底層device模塊,抽象出Platform Device,用于

16、表示Platform設備; Platform Driver,基于底層device_driver模塊,抽象出Platform Driver,用于驅動Platform設備。Linux platform_driver機制和傳統的device_driver 機制(通過driver_register函數進行注冊)相比,最大的區(qū)別在于platform機制將設備本身的資源注冊進內核,由內核統一管理,在驅動程序中使用這些資源時通過platform_device提供的標準接口進行申請并使用。這樣提高了驅動和資源管理的獨立性,并且擁有較好的可移植性和安全性(這些標準接口是安全的)。platform機制的

17、本身使用并不復雜,由兩部分組成:platform_device和platfrom_driver。通過platform機制開發(fā)底層設備驅動的大致流程如圖所示定義并注冊 platform device定義platform device時需要填充linux定義的結構體:struct platform_device該結構體主要包含設備相關的參數,比如設備名稱,id,還有設備將要用到的資源的描述,在Linux中,系統資源包括I/O、Memory、Register、IRQ、DMA、Bus等多種類型。這些資源大多具有獨占性,不允許多個設備同時使用,因此Linux內核提供了一些API,用于分配、管理這些資源。

18、當某個設備需要使用某些資源時,只需利用struct resource組織這些資源(如名稱、類型、起始、結束地址等),并保存在該設備的resource指針中即可。然后在設備probe時,設備需求會調用資源管理接口,分配、使用這些資源。struct platform_device 3: const char *name; 4: int id; 5: bool id_auto; 6: struct device dev; 7: u32 num_resources; 8: struct resource *resource; 9:  10: const struct platform_dev

19、ice_id *id_entry; 11: 12: /* MFD cell pointer */ 13: struct mfd_cell *mfd_cell; 14:  15: /* arch specific additions */ 16: struct pdev_archdata archdata; 17: ;struct resource            resource_size_tstart;   /定義資源

20、的起始地址         resource_size_tend;     /定義資源的結束地址         constchar *name;        /定義資源的名稱        

21、60;unsignedlong flags;     /定義資源的類型,比如MEM,IO,IRQ,DMA類型         structresource *parent, *sibling, *child;   /資源鏈表指針;  然后 通過調用函數platform_add_devices()向系統中添加該設備了,該函數內部調用platform_device_reg

22、ister( )進行設備注冊。定義和注冊platform driver用于抽象Platform設備驅動的數據結構如下 1: /* include/linux/platform_device.h, line 173 */ 2: struct platform_driver 3: int (*probe)(struct platform_device *); 4: int (*remove)(struct platform_device *); 5: void (*shutdown)(struct platform_device *); 6: int (*suspend)(struct platf

23、orm_device *, pm_message_t state); 7: int (*resume)(struct platform_device *); 8: struct device_driver driver; 9: const struct platform_device_id *id_table; 10: ;初始化時需要將對應的函數指針賦值給該結構體,并調用linux提供的API向內核注冊。另外還有兩個變量:name和owner。那么的作用主要是為了和相關的platform_device關聯起來,owner的作用是說明模塊的所有者,驅動程序中一般初始化為THIS_MODULE。p

24、robe、remove,這兩個接口函數用于實現driver邏輯的開始和結束。Driver是一段軟件code,因此會有開始和結束兩個代碼邏輯,就像PC程序,會有一個main函數,main函數的開始就是開始,return的地方就是結束。而內核driver卻有其特殊性:在設備模型的結構下,只有driver和device同時存在時,才需要開始執(zhí)行driver的代碼邏輯。這也是probe和remove兩個接口名稱的由來:檢測到了設備和移除了設備(就是為熱拔插起的!)。shutdown、suspend、resume、pm與linux定義的電源管理模型相關的接口,probe函數的原型為  

25、;  int xxx_probe(struct platform_device *pdev)    即它的返回類型為int,接收一個platform_device類型的指針作為參數。返回類型就是我們熟悉的錯誤代碼了,而接收的這個參數呢,我們上面已經說過,驅動程序為設備服務,就需要知道設備的信息。而這個參數,就包含了與設備相關的信息。    probe函數接收到plarform_device這個參數后,就需要從中提取出需要的信息。它一般會通過調用內核提供的platform_get_resource

26、和platform_get_irq等函數來獲得相關信息。如通過platform_get_resource獲得設備的起始地址后,可以對其進行request_mem_region和ioremap等操作,以便應用程序對其進行操作。通過platform_get_irq得到設備的中斷號以后,就可以調用request_irq函數來向系統申請中斷。這些操作在設備驅動程序中一般都要完成。將設備節(jié)點和對應驅動關聯。用戶態(tài)調用open的時候,VFS新建建一個文件句柄,并將之與驅動程序初始化時定義的struct file_operations結構體對象關聯, file_operation就是把系統調用和驅動程序關聯起來的關鍵數據結構。注冊的所有回調函數與之關聯,并一起傳遞給那個驅動(register_chrdev的那個驅動),那個驅動本身有所有調用的回調,也可以給filp建立另一套回調,無所謂,之后其他調用

溫馨提示

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

評論

0/150

提交評論