版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
Linux驅(qū)動程序設計主要內(nèi)容設備驅(qū)動的基本原理設備驅(qū)動的編寫方法2.6內(nèi)核設備模型框架設備驅(qū)動中的中斷處理方法串口讀寫程序?qū)嵗鼵havezWang@G2嵌入式系統(tǒng)研究室設備驅(qū)動的基本原理-1嵌入式系統(tǒng)研究室3ChavezWang@GUSERAPPVFSDEVICEopfuncDEV_REGISTERHARDWARE用戶空間內(nèi)核空間設備驅(qū)動設備文件與設備文件系統(tǒng)Linux中,字符設備和塊設備都是通過文件節(jié)點進行訪問。每個設備對應一個文件名,操作時對應各自的驅(qū)動程序。設備文件與設備文件系統(tǒng)Linux系統(tǒng)靠主次設備號來聯(lián)系驅(qū)動程序和設備文件節(jié)點,依靠主設備號標志不同的驅(qū)動程序注冊Linux設備號的方法為避免不同的驅(qū)動程序具有相同的設備號,需要提供一種分配設備號的機制每個驅(qū)動程序分配一個主設備號:不可行,Linux最多支持255個主設備根據(jù)/proc/devices中的對應關系,用腳本動態(tài)的創(chuàng)建設備文件:太麻煩,程序員不愿意設備文件系統(tǒng)自動管理注冊Linux設備號的方法系統(tǒng)啟動時,會把設備驅(qū)動程序掛載在/dev/目錄下,Linux設備文件的創(chuàng)建和刪除、目錄層次都都由各個設備驅(qū)動程序管理/dev/下面每個文件都動態(tài)對應了一個系統(tǒng)上存在的設備驅(qū)動程序。新添加(或者刪除)一個設備,比如u盤,系統(tǒng)就會自動在/dev目錄中創(chuàng)建(或者刪除)對應的設備節(jié)點。注冊Linux設備號的方法在設備文件系統(tǒng)中,由于分的比較細致,一些驅(qū)動程序的對應目標跟以前比一樣,如:Linux2.4之前:/dev/fb0/dev/ttyS0Linux2.6之后:/dev/fb/0/dev/tts/0可以用符號鏈接進行更改,以便與之前的相匹配:ln-s/dev/fb/0/dev/fb0ls-s/dev/tts/0/dev/ttyS0設備驅(qū)動的基本原理-2設備分類字符設備:存取時沒有緩存、只能順序讀/寫的設備??赏ㄟ^設備文件節(jié)點被訪問與普通文件的區(qū)別:普通文件的訪問可以前后移動訪問指針,而大多數(shù)字符設備不支持該操作。典型的字符設備鼠標鍵盤串口嵌入式系統(tǒng)研究室4ChavezWang@G設備驅(qū)動的基本原理-3設備分類塊設備:一般塊設備都有緩存支持,并且支持隨機存取創(chuàng)建的塊設備硬盤軟盤ramdisk嵌入式系統(tǒng)研究室5ChavezWang@G設備驅(qū)動的基本原理-4設備分類網(wǎng)絡設備:從BSDUNIX網(wǎng)絡組件移植而來。網(wǎng)絡設備沒有對應地映射到文件系統(tǒng)的設備節(jié)點。在Linux中,網(wǎng)絡設備的訪問采用Socket機制實現(xiàn)嵌入式系統(tǒng)研究室6ChavezWang@G設備驅(qū)動的基本原理-5設備號:Linux采用主設備號和次設備號來標志一個具體設備。主設備號用來標志設備類型次設備號用來區(qū)分不同的具體設備系統(tǒng)創(chuàng)建一個設備驅(qū)動程序時,設備驅(qū)動需要使用一個主設備號向內(nèi)核注冊此驅(qū)動。創(chuàng)建一個設備節(jié)點的方法:mknod設備名設備類型主設備號次設備號例:mknodttyS0c644嵌入式系統(tǒng)研究室7ChavezWang@G設備驅(qū)動的基本原理-6-內(nèi)核模塊內(nèi)核模塊的概念:內(nèi)核模塊是一些可以讓操作系統(tǒng)內(nèi)核在需要時載入和執(zhí)行的代碼,不需要時可以從操作系統(tǒng)中卸載內(nèi)核模塊是Linux內(nèi)核運行時動態(tài)擴展的一種技術(shù),可以在Linux內(nèi)核運行期間向內(nèi)核動態(tài)添加代碼,擴展內(nèi)核的功能嵌入式系統(tǒng)研究室8ChavezWang@G設備驅(qū)動的基本原理-7-內(nèi)核模塊內(nèi)核模塊與應用程序加載的不同:內(nèi)核模塊的加載只是向內(nèi)核預先注冊自己以便服務于將來的某個請求,只是加載了某項功能,而不需要馬上執(zhí)行應用程序加載后就開始執(zhí)行內(nèi)核模塊不能使用外部函數(shù)庫,只能使用內(nèi)核導出的函數(shù)應用程序可以使用外部函數(shù)庫內(nèi)核模塊只能運行在內(nèi)核空間,并且不生成新的進程應用程序運行在用戶空間,一般一個應用程序生成一個新的進程嵌入式系統(tǒng)研究室9ChavezWang@G設備驅(qū)動的基本原理-8-內(nèi)核模塊內(nèi)核模塊的框架#include<linux/init.h>#include<linux/kernel.h>#include<linux/module.h>MODULE_LICENSE("DualBSD/GPL");staticinthello_init(void){ printk(KERN_ALERT"Hello,world\n"); return0;}staticvoidhello_exit(void){ printk(KERN_ALERT"Goodbye,world\n");}module_init(hello_init);module_exit(hello_exit);嵌入式系統(tǒng)研究室10ChavezWang@G設備驅(qū)動的基本原理-9-內(nèi)核模塊2.6系列內(nèi)核模塊的編譯與加載內(nèi)核源碼樹的每個子目錄都有一個kconfig文件,為makefile提供配置數(shù)據(jù)庫,分別描述了所屬目錄源文件相關的內(nèi)核配置菜單項內(nèi)核配置時,從kconfig中讀出配置菜單,配置后生成.config文件編譯內(nèi)核時,makefile讀入對應的.config文件生成內(nèi)核映像加入新驅(qū)動到內(nèi)核源碼樹時,需要修改相應目錄的kconfig,將新驅(qū)動加入內(nèi)核的配置菜單,同時需要修改makefile文件嵌入式系統(tǒng)研究室11ChavezWang@G設備驅(qū)動的基本原理-10-內(nèi)核模塊嵌入式系統(tǒng)研究室12ChavezWang@G.configMakefileKconfigKconfigKconfigmakefilemakefilearch/arm/makefileScrip/makefilemenuconfig輸出Kconfig配置文件Konfig文件樹是內(nèi)核的配置數(shù)據(jù)庫每個Kconfig文件描述一系列內(nèi)核配置菜單項,每個菜單項提供一個關鍵字標識語法:Config<symbol><configoptions>例:configHELLO_MODULE bool“hellotestmodule”嵌入式系統(tǒng)研究室13ChavezWang@G設備驅(qū)動的基本原理-11-內(nèi)核模塊設備驅(qū)動的基本原理-12-內(nèi)核模塊Kconfig配置文件類型定義有:bool、tristate、string、hex、integer等依賴性定義:如果菜單項的出現(xiàn)依賴于另一個定義時,就用關鍵字dependson或者requires標識
config HELLO_MODULE bool“hellotestmodel”dependsonARCH_PXA幫助定義:關鍵字help或者–help--嵌入式系統(tǒng)研究室14ChavezWang@G設備驅(qū)動的基本原理-13-內(nèi)核模塊內(nèi)核的makefile:內(nèi)核源碼根目錄下的頂層makefile可以分為五部分該makefile本身,負責linux內(nèi)核的二進制映像文件vmlinux和內(nèi)核模塊的編譯內(nèi)核配置文件.config,記錄內(nèi)核的當前配置并在編譯時提供給makefile成為其一部分特定體系結(jié)構(gòu)相關目錄下的makefile,提供與體系結(jié)構(gòu)相關的信息Scripts下的makefile.*,包含一些內(nèi)核模塊編譯共用的定義和規(guī)則內(nèi)核源碼樹各子目錄中的與模塊編譯相關的kbuildmakefile。編譯時,集成上層makefile傳下來的宏定義和其他編譯規(guī)則將源代碼編入內(nèi)核或編譯成內(nèi)核模塊嵌入式系統(tǒng)研究室15ChavezWang@GKbuildmakefile內(nèi)容:最簡單的只有一行。以hello.c為例:obj-y+=hello.o:編譯進內(nèi)核的二進制映像中obj-m+=hello.o:編譯成內(nèi)核的可加載模塊obj-$(CONFIG_HELLO_MODULE)+=hello.o根據(jù)變量的不同,既可以編譯進內(nèi)核,也可以編譯為模塊嵌入式系統(tǒng)研究室16ChavezWang@G設備驅(qū)動的基本原理-13-內(nèi)核模塊Kbuildmakefile內(nèi)容:若具有多個文件,如mymodule由file1.cfile2.c構(gòu)成,則Makefile定義為obj-m:=mymodule.oMymodule-objs:=file1.ofile2.o在內(nèi)核源碼樹之外的模塊,則用下面的方式編譯:
make-C<PATH_TO_KERNEL>M=$PWDmodules嵌入式系統(tǒng)研究室17ChavezWang@G設備驅(qū)動的基本原理-13-內(nèi)核模塊驅(qū)動程序的編譯設備驅(qū)動程序的結(jié)構(gòu)-1設備驅(qū)動程序從總體上看可以分為兩部分驅(qū)動與內(nèi)核的接口層:實現(xiàn)在內(nèi)核的注冊加載和卸載清除工作。若采用了中斷處理,還要包括中斷處理函數(shù)的注冊與注銷。硬件設備接口層:主要描述驅(qū)動程序與設備的交互。包括:硬件探測硬件初始化設備讀寫訪問設備控制操作嵌入式系統(tǒng)研究室18ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口1Linux系統(tǒng)中用戶對設備的操作采用文件接口實現(xiàn)。虛擬文件系統(tǒng)將這種對文件的訪問操作轉(zhuǎn)化為對設備的具體操作。虛擬文件系統(tǒng)為設備驅(qū)動提供了一個標準化的文件操作實現(xiàn)接口。該接口定義在:Include/linux/fs.h中的file_operations定義嵌入式系統(tǒng)研究室19ChavezWang@G/**NOTE:*read,write,poll,fsync,readv,writevcanbecalled*withoutthebigkernellockheldinallfilesystems.*/structfile_operations{ structmodule*owner; loff_t(*llseek)(structfile*,loff_t,int); ssize_t(*read)(structfile*,char__user*,size_t,loff_t*); ssize_t(*aio_read)(structkiocb*,char__user*,size_t,loff_t); ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*); ssize_t(*aio_write)(structkiocb*,constchar__user*,size_t,loff_t); int(*readdir)(structfile*,void*,filldir_t); unsignedint(*poll)(structfile*,structpoll_table_struct*); int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);
嵌入式系統(tǒng)研究室20ChavezWang@Gint(*mmap)(structfile*,structvm_area_struct*); int(*open)(structinode*,structfile*); int(*flush)(structfile*); int(*release)(structinode*,structfile*); int(*fsync)(structfile*,structdentry*,intdatasync); int(*aio_fsync)(structkiocb*,intdatasync); int(*fasync)(int,structfile*,int); int(*lock)(structfile*,int,structfile_lock*); ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*); ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*); ssize_t(*sendfile)(structfile*,loff_t*,size_t,read_actor_t,void*); ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int); unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong); int(*check_flags)(int); int(*dir_notify)(structfile*filp,unsignedlongarg); int(*flock)(structfile*,int,structfile_lock*);};嵌入式系統(tǒng)研究室21ChavezWang@G注意:結(jié)構(gòu)體中的函數(shù),并不是每個都需要實現(xiàn)的。不需要實現(xiàn)的函數(shù),可以直接初始化為空。在嵌入式系統(tǒng)中,一般僅僅實現(xiàn)其中的幾個接口函數(shù):read,write,ioctl,open,release等,就可以完成應用系統(tǒng)需要的功能嵌入式系統(tǒng)研究室22ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口2Open方法:方法open用于打開設備,open操作是對設備的第一個操作,如果open方法為空,則設備始終打開成功遞增使用計數(shù)檢查特定設備錯誤如果設備是首次打開,則對其進行初始化識別次設備號嵌入式系統(tǒng)研究室23ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口3虛擬文件系統(tǒng)與硬件驅(qū)動的接口4release方法:方法release在關閉文件時調(diào)用,其工作與open方法相反釋放由open分配的filp->private_data中的左右內(nèi)容使用計數(shù)減一在最后一次關閉操作時關閉設備嵌入式系統(tǒng)研究室24ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口5read方法:方法read從設備中讀取數(shù)據(jù),函數(shù)返回非負值表示成功讀出的字節(jié)數(shù)返回值等于傳遞給read系統(tǒng)調(diào)用的count參數(shù),表明請求的數(shù)據(jù)傳輸成功返回值大于0,但小于傳遞給read系統(tǒng)調(diào)用的count參數(shù),表明部分數(shù)據(jù)傳輸成功,根據(jù)設備的不同,導致這個問題的原因也不同,一般采取再次讀取的方法返回值=0,表示到達文件的末尾返回值為負數(shù),表示出現(xiàn)錯誤,并且指明何種錯誤在阻塞型io中,read調(diào)用會出現(xiàn)阻塞。嵌入式系統(tǒng)研究室25ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口6write方法:方法write向設備中寫入數(shù)據(jù),函數(shù)返回非負值表示成功寫入的字節(jié)數(shù)返回值等于傳遞給write系統(tǒng)調(diào)用的count參數(shù),表明請求的數(shù)據(jù)傳輸成功返回值大于0,但小于傳遞給write系統(tǒng)調(diào)用的count參數(shù),表明部分數(shù)據(jù)傳輸成功,根據(jù)設備的不同,導致這個問題的原因也不同,一般采取再次寫入的方法返回值=0,表示沒有寫入任何數(shù)據(jù)。此時一般會重復調(diào)用write返回值為負數(shù),表示出現(xiàn)錯誤,并且指明是何種錯誤。在阻塞性io中,write調(diào)用會出現(xiàn)阻塞。嵌入式系統(tǒng)研究室26ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口7ioctl方法:方法ioctl為設備調(diào)用ioctl提供了一種執(zhí)行設備特定命令的方法,主要是讀寫之外的其他控制。如配置設備、進入或者退出某種操作模式等。實驗板上的SPI設備通道的選擇操作,即通過這種方式嵌入式系統(tǒng)研究室27ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口8*owner指向擁有該結(jié)構(gòu)的模塊,內(nèi)核使用指針維護模塊的使用計數(shù)llseek用來修改文件當前位置,并將新位置作為結(jié)果返回。loff_t是在linux中定義的長偏移量。出錯時返回負值。嵌入式系統(tǒng)研究室28ChavezWang@G方法poll是系統(tǒng)調(diào)用select和poll的后端實現(xiàn),用這兩個系統(tǒng)調(diào)用來查詢設備是否可以讀寫或者是否處于某種狀態(tài)。如果poll為空,則驅(qū)動設備會被認為既可讀,又可寫,返回值是一個狀態(tài)掩碼。方法mmap將設備內(nèi)存映射到進程地址空間。嵌入式系統(tǒng)研究室29ChavezWang@G虛擬文件系統(tǒng)與硬件驅(qū)動的接口9簡單的字符驅(qū)動-1大多數(shù)字符設備比較簡單,通常直接使用file_operations接口。本課程將以一個虛擬的字符設備test_char為例,說明字符驅(qū)動的結(jié)構(gòu)嵌入式系統(tǒng)研究室30ChavezWang@G簡單的字符驅(qū)動-2虛擬文件系統(tǒng)與設備驅(qū)動程序的接口本設備之設計到讀寫和設備的打開關閉操作。因此可以定義以下file_opertions結(jié)構(gòu)體變量。structfile_operationstestchar_fops{ .read=test_read, .write=test_write, .open=test_open, .release=test_release};注意:定義結(jié)構(gòu)體變量之前需要先實現(xiàn)用到的函數(shù)嵌入式系統(tǒng)研究室31ChavezWang@G簡單的字符驅(qū)動-3staticchartest_val=‘a(chǎn)’;//用全局變量保存虛擬設備讀寫的數(shù)據(jù)staticssize_ttest_read(structfile*filp,char__user*buf,size_tcount,loff_t*l){ copy_to_user(buf,&val,sizeof(val)); returnsizeof(val);}//copy_to_user(void__user*to,constvoid*from,unsignedlongn);Staticssize_ttest_write(structfile*file,constchar__user*buf,size_tcount,loff_t*l){ copy_from_user(&val,buf,sizeof(val); returnsizeof(val);}//copy_from_user(void*to,void__user*from,unsignedlongn)Staticinttest_open(structinode*inode,structfile*filp){ try_module_get(THIS_MODULE);//模塊計數(shù)加一
return0;}Staticinttest_release(structinode*inode,structfile*filp){ module_put(THIS_MODULE);//模塊計數(shù)減一
return0;}嵌入式系統(tǒng)研究室32ChavezWang@G簡單的字符驅(qū)動-4驅(qū)動模塊的加載和卸載操作
#defineTEST_MAJOR251 #defineTEST_NAME “TEST_CHAR” int__initinit_routine(void){ register_chrdev(TEST_MAJOR,TEST_NAME,&testchar_fops); return0;}//intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations//*fops)Voidcleanup_routine(void){ unregister_chrdev(TEST_MAJOR,TEST_NAME);} module_init(init_routine); module_exit(cleanup_routine);嵌入式系統(tǒng)研究室33ChavezWang@GLinux2.6內(nèi)核設備模型-1Linux2.2版之前沒有統(tǒng)一的驅(qū)動形式,2.4通過使用一組通用接口將PCI、PCMIA等整合到一個單一的設備結(jié)構(gòu)中,2.6內(nèi)核則更進一步,試圖在整個系統(tǒng)的范圍內(nèi)對硬件設備進行抽象,建立一個統(tǒng)一的全新設備模型新模型包括四個重要數(shù)據(jù)結(jié)構(gòu):structkobjectstructksetstructktypestructsubsystem嵌入式系統(tǒng)研究室34ChavezWang@GLinux2.6內(nèi)核設備模型-2structkobject結(jié)構(gòu):最底層的基礎數(shù)據(jù)結(jié)構(gòu)structkobject{ char *k_name;//動態(tài)分配空間的設備名稱
char name[KOBJ_NAME_LEN];//長度受限的設備名稱
atomic_t refcount;//引用計數(shù)
struct list_head entry;//掛接到所有集合中去的入口
structkobject*parent;// 商機對象的指針
structkset *kset;//所屬對象集合的指針
structkobj_type ktype;// 所屬對象類型指針
structdentry*dentry;//在sysfs系統(tǒng)中的文件節(jié)點路徑指針}嵌入式系統(tǒng)研究室35ChavezWang@GLinux2.6內(nèi)核設備模型-3structkset結(jié)構(gòu):用于描述同一類kobject集合structkset{ structsubsystem *subsys;//所在的subsystem的指針
structkobj_type *ktype;//集合中的對象類型
structlist_head list;//集合中的對象鏈表
structkobject kobj;//集合自身相關信息的內(nèi)核對象
structkset_hotplug_ops *hotplug_ops;//該集合的熱插拔函數(shù)}嵌入式系統(tǒng)研究室36ChavezWang@GLinux2.6內(nèi)核設備模型-4structkobj_ktype結(jié)構(gòu):structkobj_type{ void(*release)(structkobject*);//本類對象的釋放函數(shù)
structsysfs_ops *sysfs_ops;//本類對象在sysfs中的操作函數(shù)
structattribute**default_attrs;//本類對象在sysfs中的屬性}嵌入式系統(tǒng)研究室37ChavezWang@GLinux2.6內(nèi)核設備模型-5structsubsystem內(nèi)核對象子系統(tǒng):是最上層的數(shù)據(jù)結(jié)構(gòu),用于描述同屬一類設備的子系統(tǒng)structsubsystem{ structksetkset;//該子系統(tǒng)的內(nèi)核對象集合
structrw-semaphorerwsem;//互斥訪問信號量}嵌入式系統(tǒng)研究室38ChavezWang@GLinux2.6內(nèi)核設備模型-6系統(tǒng)初始化時,drivers/base/init.c中的driver-init()函數(shù)將幾個頂層子系統(tǒng)的subsystem數(shù)據(jù)結(jié)構(gòu)注冊到內(nèi)核初始化子系統(tǒng)數(shù)據(jù)結(jié)構(gòu)在sysfs文件系統(tǒng)下建立各個子系統(tǒng)的目錄樹五個子系統(tǒng):設備子系統(tǒng)devices_subbus總線子系統(tǒng)bus_subbus設備基類子系統(tǒng)class_subbus固件子系統(tǒng)(fireware_subbus)虛擬系統(tǒng)總線子系統(tǒng)(system_subbus)嵌入式系統(tǒng)研究室39ChavezWang@GLinux2.6內(nèi)核設備模型-7五個子系統(tǒng)構(gòu)成了管理框架初始化時,初始化程序調(diào)用內(nèi)核對象注冊函數(shù)將設備數(shù)據(jù)結(jié)構(gòu)中的成員kobject結(jié)構(gòu)注冊到相應的子系統(tǒng)中最終用戶可以通過sysfs文件系統(tǒng)看到所有設備的信息嵌入式系統(tǒng)研究室40ChavezWang@GLinux內(nèi)核的中斷處理-1中斷機制是實現(xiàn)外部I/O異步操作的重要方法Linux內(nèi)核對外部設備的中斷處理在設備驅(qū)動程序里實現(xiàn)嵌入式系統(tǒng)研究室41ChavezWang@GLinux內(nèi)核的中斷處理-2中斷處理程序的注冊注冊函數(shù)Intrequest_irq(unsignedintirq,irqreturn_t(*handler)(int,void*,structpt_regs*), unsignedlongirq_flags,constchar*devname,void*dev_id);該函數(shù)成功則返回0;irq為要注冊的中斷號Handler指向中斷處理程序的函數(shù)指針irq-flags為中斷標志,含義如下:SA_INTERRUPT:不受中斷屏蔽的影響,任何情況下都可以響應。一般只有時鐘中斷具有此標志。SA_SAMPLE_RAMDOM:產(chǎn)生中斷的間隔時間放入系統(tǒng)隨機數(shù)的內(nèi)核熵池SA_SHIRQ:表明為共享中斷嵌入式系統(tǒng)研究室42ChavezWang@GLinux內(nèi)核的中斷處理-3中斷處理程序的注冊dev_name:與中斷相關的設備名字。dev_id:主要用于共享中斷中,釋放共享中斷時,根據(jù)dev_id的標志信息來刪除指定的那個中斷處理程序處理的中斷。若dev_id設為null,則為獨占式的中斷嵌入式系統(tǒng)研究室43ChavezWang@GLinux內(nèi)核的中斷處理-4中斷處理程序的釋放Voidfree_irq(unsignedintirq,void*dev_id)若釋放的中斷是共享的,則dev_id對應的中斷處理程序與中斷的綁定關系被刪除若刪除了最后一個中斷處理程序的綁定關系,則此中斷被禁用若要釋放的中斷是非共享的,則刪除中斷處理程序的同時也將禁用中斷嵌入式系統(tǒng)研究室44ChavezWang@GLinux內(nèi)核的中斷處理-5中斷處理程序的編寫中斷處理程序與其他內(nèi)核函數(shù)的不同之處:中斷處理程序發(fā)送或者接受數(shù)據(jù)都必須在內(nèi)核空間,不能在內(nèi)核與用戶空間之間發(fā)送或者接受數(shù)據(jù)中斷不能做任何可能發(fā)生休眠的操作,也不能調(diào)用schedule函數(shù)進行進程調(diào)度。staticirqreturn_tirq_handler(intirq,void*dev_id,structpt_regs*regs)當中斷程序被調(diào)用并正確處理時,返回IRQ_HANDLED,否則返回IRQ_NONE嵌入式系統(tǒng)研究室45ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-1問題引入:通常中斷處理程序需要盡量做到短小和快速處理,以免中斷阻塞時間過長,影響實時性和中斷響應速度但是,有些設備產(chǎn)生中斷后需要處理較多的與中斷相關的工作,所以速度會比較慢處理方法將中斷處理分為兩個部分:中斷處理程序部分:只做必要的有嚴格時限的工作,如中斷應答和復位硬件等,一般需要屏蔽中斷的情況下處理其他需要時間的不是很緊急的工作推后處理。嵌入式系統(tǒng)研究室46ChavezWang@G內(nèi)核工作推后執(zhí)行的機制主要有:軟中斷tasklet工作隊列嵌入式系統(tǒng)研究室47ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-2軟中斷:通常用于執(zhí)行頻率很高的強實時性的場合。作為一種底層機制,很少由內(nèi)核程序員直接使用。enum{ HI_SOFTIRQ=0,//優(yōu)先級高的tasklet軟中斷
TIMER_SOFTIRQ,//定時器軟中斷
NET_TX_SOFTIRQ,//網(wǎng)絡數(shù)據(jù)包發(fā)送軟中斷
NET_RX_SOFTIRQ,//網(wǎng)絡數(shù)據(jù)包接收軟中斷
SCSI_SOFTIRQ,//SCSI軟中斷的軟中斷
TASKLET_SOFTIRQ.//tastlet軟中斷的軟中斷}嵌入式系統(tǒng)研究室48ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-3tasklet:小任務,指一小段可以執(zhí)行的嗲嗎,通常以函數(shù)的形式出現(xiàn),對于io驅(qū)動程序,是實現(xiàn)工作推后執(zhí)行的首選方法。tasklet基于軟中斷機制實現(xiàn),實際上只是一種軟中斷的應用和包裝structtasklet_struct{ structtasklet_struct*next;//指向鏈表中的下一個結(jié)構(gòu)體
unsignedlongstate;//tasklet的狀態(tài),初始化時為0,被調(diào)用時為1 atomic_tcount;//引用計數(shù)器,若不為0,則不能執(zhí)行;若為0則可以執(zhí)行
void(*func)(unsignedlong);//tasklet處理函數(shù)
unsignedlongdata;//給tasklet處理函數(shù)的參數(shù)}嵌入式系統(tǒng)研究室49ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-4tasklet的使用tasklet聲明:DECLARE_TASKLET(name,func,data)//初始值為0,激活狀態(tài)DECLARE_TASKLET_DISABLED(name,func,data)//初始值為1,停用狀態(tài)name:tasklet_struct變量的名字func:是tasklet的執(zhí)行函數(shù)data:是tasklet執(zhí)行函數(shù)的參數(shù)嵌入式系統(tǒng)研究室50ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-5tasklet的使用tasklet執(zhí)行函數(shù)定義Voidfunc(unsignedlongdata)注意:必須與structtasklet_struct結(jié)構(gòu)中的func定義一致Func()要在tasklet聲明之前定義不能使用信號量或者其他可能引起阻塞的函數(shù),因為tasklet不能休眠嵌入式系統(tǒng)研究室51ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-6tasklet的使用tasklet的調(diào)度tasklet_schedule(&name):將一個tasklet狀態(tài)置為準備執(zhí)行狀態(tài),系統(tǒng)由合適的機會時,就會盡快執(zhí)行Tasklet_disable():將tasklet的count計數(shù)增1,從而停用該taskletTasklet_enable():激活tasklet。Tasklet_kill():從等待執(zhí)行的tasklet隊列中刪除一個tasklet嵌入式系統(tǒng)研究室52ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-6工作隊列每個工作隊列有一個專門的線程,稱之為工作隊列線程工作隊列中推后執(zhí)行的工作由此線程完成,所有的工作在線程的上下文中被執(zhí)行。因此,允許重新調(diào)度甚至睡眠嵌入式系統(tǒng)研究室53ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-7工作隊列:structwork_struct數(shù)據(jù)結(jié)構(gòu)Structwork_struct{ unsignedlongpending;//工作是否等待處理
structlist_headentry;//工作隊列中的工作鏈表
void(*func)(void*);//處理函數(shù)
void*data;//處理函數(shù)的參數(shù)
void*wq_data;//內(nèi)部使用
structtimer_listtimer;//定時器}嵌入式系統(tǒng)研究室54ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-8工作隊列的使用創(chuàng)建工作隊列:Structworkquene_struct*create_workquene(constchar*name)//創(chuàng)建一個新工作隊列,返回新工作隊列的指針例如:structworksquene_struct*my_workqe; my_workqe=create_workquene(“my_workqe”);創(chuàng)建推后執(zhí)行的工作編譯時創(chuàng)建工作隊列:#defineDECLARE_WORK(name,func,data)\structwork_structn=__WORK_INITALIZER(name,func,data)運行時動態(tài)創(chuàng)建:Structwork_structmy_work;INIT_WORK(my_work,my_work_func,data);嵌入式系統(tǒng)研究室55ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-9工作隊列的使用定義工作的任務處理函數(shù)Voidfunc(void*data)將工作加入工作隊列中intquene_work(structworkquene_struct*squene,structwork_struct*work);//即時加入工作隊列intquene_delayed_work(structworkquene_struct*quene,structwork_struct*work,unsignedlongdelay);//延遲一段時間加入工作隊列Intcancel_delayed_work(structwork_struct*work)//取消延期加入工作隊列的工作;如果已經(jīng)加入則不受影響嵌入式系統(tǒng)研究室56ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-10工作隊列的使用刷新工作隊列Voidfastcallflush_workquene(structworkquene_struct*wq);//在卸載前,保證操作都已經(jīng)執(zhí)行完畢。如果沒有執(zhí)行完畢,會進入休眠狀態(tài)銷毀工作隊列Voiddestroy_workquene(structworkquene_struct*wq);//銷毀使用完畢的工作隊列注意:不是所有的驅(qū)動都需要自己的工作隊列。嵌入式系統(tǒng)研究室57ChavezWang@GLinux2.6內(nèi)核的工作推后執(zhí)行機制-6串行通信的基本概念串行通信與串口定義串行方式傳輸數(shù)據(jù)傳輸速度用bps或者波特率描述常用的串口為RS-232-C串口通信的基本參數(shù)每秒位數(shù)—波特率數(shù)據(jù)位奇偶校驗位停止位數(shù)據(jù)流控制在Linux下進行串口通信
打開串口類似于打開文件,必須使用O_NOCTTY方式:如果打開的是一個終端設備,程序不會成為對應這個端口的控制終端#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>intfd;if((fd=open(“dev/ttyS0”,O_RDWR|O_NOCTTY))==1)perrro(“…”)設置串口通信參數(shù)波特率設置獲得端口波特率通過cfgetispeed函數(shù)和cfgetospeed函數(shù)實現(xiàn)設置端口波特率通過cfsetispeed函數(shù)和cfsetospeed函數(shù)實現(xiàn)數(shù)據(jù)位數(shù)據(jù)位指的是每次輸入字節(jié)中實際數(shù)據(jù)所占的比特數(shù),通過修改termios結(jié)構(gòu)體中的c_cflag成員來實現(xiàn)。其中CS5CS6CS7CS8分別表示數(shù)據(jù)位為5、6、7、8位。設置時,必須先使用CSIZE做位屏蔽。奇偶校驗位奇偶校驗可以選擇偶校驗、奇校驗、空格等方式,也可以不使用校驗。如果要設置偶檢驗的話,首先將ternios結(jié)構(gòu)體中c_cflag設置PARENB標志,并清除PARODD標志。奇校驗同時設置ternios結(jié)構(gòu)體中c_cflag設置PARENB標志和PARODD標志。
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年床上用品品牌代理合同
- 2024醫(yī)院藥品零售許可合同
- 2024年建筑合同糾紛預防及處理辦法
- 2024年度IT企業(yè)軟件許可使用合同
- 2024年度搬廠工程機械設備租賃合同
- 2024年度委托加工合同:甲乙雙方在二零二四年就某產(chǎn)品委托加工的詳細條款
- 2024年度量子科技實驗室建設安裝工程分包合同
- 2024年度智能停車安防監(jiān)控系統(tǒng)安裝合同
- 2024展廳裝飾裝修合同范文
- 2024年商標許可使用合同商標范圍
- 認識計算機系統(tǒng)的組成
- 人教版版中國歷史八年級上冊知識點歸納梳理
- 國家職業(yè)技術(shù)技能標準 3-02-03-01 消防員(2022年版)
- GB/T 36242-2018燃氣流量計體積修正儀
- GB/T 2818-2014井用潛水異步電動機
- 5 汪曾祺《跑警報》.電子教案教學課件
- 敘事療法課件
- 國家開放大學電大《計算機應用基礎(本)》終結(jié)性考試試題答案(格式已排好)任務一
- 阿米巴經(jīng)營管理課件
- 小學質(zhì)量檢測匯報材料范文推薦11篇
- 質(zhì)量管理體系內(nèi)部審核培訓知識課件
評論
0/150
提交評論