linux驅(qū)動編程初級+makefile_第1頁
linux驅(qū)動編程初級+makefile_第2頁
linux驅(qū)動編程初級+makefile_第3頁
linux驅(qū)動編程初級+makefile_第4頁
linux驅(qū)動編程初級+makefile_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

驅(qū)動編程TOC\o"1-5"\h\z\o"CurrentDocument"模塊的概述2\o"CurrentDocument"sourceinsight加載內(nèi)核源碼方法2\o"CurrentDocument"模塊makefile的編寫3\o"CurrentDocument"模塊makefile編寫方法4\o"CurrentDocument"在X86上運行模塊:5\o"CurrentDocument"編寫模塊5\o"CurrentDocument"模塊的加載進內(nèi)核命令5\o"CurrentDocument"最簡單的上層調(diào)用+調(diào)用驅(qū)動方法6\o"CurrentDocument"復(fù)雜框架上層應(yīng)用+驅(qū)動調(diào)用方法7\o"CurrentDocument"復(fù)雜框架字符設(shè)備創(chuàng)建并注冊過程7\o"CurrentDocument"file_operations常用函數(shù)9\o"CurrentDocument"同步互斥操作10\o"CurrentDocument"同步互斥函數(shù)總結(jié)10阻塞IO編程流程11\o"CurrentDocument"輪詢操作上層select下層poll12\o"CurrentDocument"信號處理12\o"CurrentDocument"中斷13\o"CurrentDocument"中斷新模型--上半部中斷和下半部中斷的實現(xiàn)14\o"CurrentDocument"內(nèi)核定時器編程15\o"CurrentDocument"內(nèi)核延時函數(shù)15\o"CurrentDocument"內(nèi)核源代碼中頭文件分配方式15\o"CurrentDocument"linux內(nèi)核管理和內(nèi)核的內(nèi)存管理16\o"CurrentDocument"設(shè)備io端口和io內(nèi)存訪問-如何控制led的亮滅16*驅(qū)動-設(shè)備分離思想編程內(nèi)核進階18驅(qū)動-設(shè)備分離-核心最小架構(gòu)18驅(qū)動設(shè)備分離思想-上層架構(gòu)(基于封裝)20\o"CurrentDocument"頭文件總結(jié)24\o"CurrentDocument"設(shè)置系統(tǒng)自啟動命令u-boot24第一天需要理清的東西模塊的概念,模塊與應(yīng)用的區(qū)別模塊主要的組成頭文件、module_init()modoule_exit()module_lisence()模塊的如何編輯,如何編譯,如何加載到內(nèi)核中運行使用makefile模塊驅(qū)動編寫,必須通過上層應(yīng)用程序調(diào)用。1模塊的概述模塊是內(nèi)核的一部分,內(nèi)核的直接編譯進內(nèi)核。存儲位置運行時環(huán)境模塊的編譯問題:為了防止內(nèi)核太大,把它放在文件系統(tǒng)里面。也可以在編譯1,2、模塊是內(nèi)核的一部分,內(nèi)核的直接編譯進內(nèi)核。存儲位置運行時環(huán)境模塊的編譯問題:為了防止內(nèi)核太大,把它放在文件系統(tǒng)里面。也可以在編譯1,2、3、匹配4、模塊編譯使用makefile注意makefile的編寫可以在開始時編譯進內(nèi)核,也可以編譯進模塊,最后加載在哪個內(nèi)核樹下編譯,就對應(yīng)這個運行環(huán)境前提條件是需要對應(yīng)的內(nèi)核源碼樹,或者必須有對應(yīng)的內(nèi)核版本;userspace:appIscd:syscall;kerne1space:wodule:app:lib;inodule:[:ernelapi:app:lib;inodule:[:ernelapi2sourceinsight加載內(nèi)核源碼方法在windows下創(chuàng)建工程,使用sourceinsight查看內(nèi)核代碼:2.1先將內(nèi)核源碼拷到對應(yīng)的文件夾2.2在sourceinsight里添加工程,篩選需要添加的文件注意選擇=二’按照樹來添加,然后.按照remove來踢出不需要的文件夾FileName:CloseFileName:CloseFURM_boot_kernelMinux_kernel_copyDirectory□Qf:'1'.曰OARM_boot_kernel:一…可二SlArchj??…□Directory□Qf:'1'.曰OARM_boot_kernel:一…可二SlArchj??…□Block隹}…口Cnr'pto1+}QjDocumentation?QDrivers?■■■QFirmware田…口Fs國??口IncludeProjectFiles:(16303)f:\arrn_f:\arrnf:\arrnf:\armf:\armf:\arrnf:\arrnf:'''..3rrrif:\armf:\armf:\arrnf:\armoooooooooooooooooooooooooooobbbbbbbbbbbbbb.kerriBr-diriLJKkerriBr-diriLJ:-:kerriBr-diriLJ:-:kerneMinuxkerneMinuxkerneMinuxkerriBr-diriLJ:-:kerriBr-diriLJ:-:kerner'dinu:-:kerneMinuxkerneMinuxkerneMinuxkerriBr-diriLJ:-:kerneMinux_kernel_kernelkernelkernelkernelkernelkernelkernelkernelkernelkernelkernelkernelkernelFileName0口口口口口口口口口口EllockCryptoDocumentationDriversFirmwareFsInclude,copy\arch\arm\boot\bootp\init.Scopy\arch\arm\boot\bootp\initrd.Scopiy\arch\arrri\bool:\bootp\kerriBLScopy\arch\arm\boot\compressed\big-endian.Scopjr'\arch\arrri','.boot\ciiirripressed','.Deciiirripres2.ccopy\arch\arm\boot\compressed\head-l7200.Scopijr'\arch\arrri\bool:\corripre:5:5Bd','.head-:5a1100.Scopijr'\arch\arrri\bool:\corripre:5:5Bd','.head-:5hark.Scopjri\arch\arrri,,'.boot\corripre:5:i:ed,,'.head-:i:harp:5LScopy\arch\arm\boot\compressed\head-xscale.Scopy\arch\arm\boot\compressed\head.Scopijr'\arch\arm,\bool:\corripre:5:5Bd','.ll_char_'A'r.Scopy\arch\arm\boot\compressed\Misc.ccoDu\arch\arm\boot\comDressed\0fw-shark.cAddAddAll向Showonlyknown~documenttypesRemoveFileRemoveAllAddfromlist...HelpFileN:=jTieMach;s3c2443Mach-s3c24a0Mach-s3c64xxMach-s5p6440Mach-s5p6442Mach-s5pv210Mach-sal100Mach-sharkMach-shmobileMach-spear3:-::-:IPlat-s5pIPlat-samsung福匚:E:5p匚Mach-s5pv210Mach-sal100Mach-sharkMach-shmobileMach-spear3:-::-:IPlat-s5pIPlat-samsung主要添加arm下s5pc100和s5p平臺的drivesinclude文件夾等,后面的許多不需要添加。2.3最后同步3模塊makefile的編寫模塊的編譯:1)、模塊編譯的核心語句:$(MAKE)-C$(KERNELDIR)M=$(PWD)modules-C:進入內(nèi)核源碼樹M=:返回到當(dāng)前目錄,再次執(zhí)行該目錄下的makefileeg:/tnt/abc.c>abc.ko1、在/tnt目錄下敲make,只有/tnt目錄下的Makefile被調(diào)用2、目的是要進入到內(nèi)核源碼樹中,一進一回,-C來進,M=帶著內(nèi)核源碼樹中的makefile的功能回來了內(nèi)核源碼樹中Makefile的目標(biāo):obj-y:匯集了所有編譯進內(nèi)核的目標(biāo)文件obj-m:匯集了所有編譯成模塊的目標(biāo)文件3、回來過后,我們只有確定obj-m變量的集合4、makemodules告訴內(nèi)核的makefile,只做編譯模塊的功能

4模塊makefile編寫方法ifeq($(KERNELRELEASE),)KERNELDIR:=/work/linux-2.6.35-farsightPWD:=$(shellpwd)modules:$(MAKE)-C$(KERNELDIR)M=$(PWD)modulesinstall:$(MAKE)-C$(KERNELDIR)M=$(PWD)modules_installclean:rm-rf.tmp_versions*.ko*.o.*.cmd*.mod.c*.order*.symvers.PHONY:modulescleanelseobj-m:=ex1.oendif以上是makefile的內(nèi)容,注意原來的內(nèi)核目錄樹不要進行makeclean或者makedistcleanKERNELDIR表示模塊加載在哪個內(nèi)核的文件夾(又叫內(nèi)核源碼樹),$(MAKE)-C$(KERNELDIR)M=$(PWD)modules表示進入該內(nèi)核文件夾,將頂層makefile中的內(nèi)容帶回,再重新執(zhí)行一次該makefile將obj-m:=ex1.o編譯,并執(zhí)行makemodules(并只編譯ex1.c,不編譯其它模塊)$(MAKE)-C$(KERNELDIR)M=$(PWD)modules_install表示執(zhí)行頂層makefile的modulesinstall標(biāo)簽下的命令?安裝的位置原來默認(rèn)在/lib下面,所以需要修改其到我們制作的根文件系統(tǒng)下/work/rootfs/在頂層Makefile位置搜索:MODLIBMODLIB=S(INSTALLMODPATH)/lib/modules/S(KERNELRELEASE)exportMODLIB修改為:MODLIB=/work/rootfs/lib/modules/[KERNELRELEASE)exportMODLIB?obj-m:=ex1.o你需要編譯的.c的文件名****************************此時簡單的編譯環(huán)境已經(jīng)搭建完畢*******************執(zhí)行makeinstall****************************執(zhí)行make*******************業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè)業(yè),不不夢不不不不夢叩不不不不夢不不不不夢不不不不夢叩不不不在/work/rootfs/lib/modules/2.6.35/extra即可找到該模塊.koes++++++++++“$$$e“$$$$$$$$s“$$$kJ-ee力力力力力力“$執(zhí)行makeinstall搭建好環(huán)境,保證虛擬機與板子與計算機網(wǎng)絡(luò)連通,并設(shè)置板子u-boot從nfs掛載,啟動內(nèi)核,并成功通過nfs加載rootfs,此時環(huán)境完畢,進入/work/rootfs/lib/modules/2.6.35/extra,找到模塊,加載卸裝模塊操縱5在X86上運行模塊:修改Makefile中的內(nèi)核源碼樹的目錄X86下的內(nèi)核源碼樹:/lib/modules/2.6.35-22-generic/build如果沒有在控制臺上交互,默認(rèn)是看不到信息的,需要dmesg這個命令去查看6編寫模塊模塊最小組成如下:00001:|ffinclude<linux/module.h>00002:#include<lin.ux/init.h>00003:|00004:00005:00006:staticintinitIl6d_i111jit(void)00007:{—printk(T,youareentering...\elti);00009:return0;00010:}00011:00012:staticvoidexitled_eXit(void)00013:{—00014:printk("youareouting..-\n.T,);00015:}00016:ooai7:module_init(ied^nitj;ooaie:module_exit(iedexitj;00015:MODULE_LICENSE("spl"i;00020:—i-注意:module_initmodule_exit必須放在末尾注意:函數(shù)的原型返回值頭文件7模塊的加載進內(nèi)核命令insmod_rooT@localhosTextra]=insnioclhf_first_module.koyouareentering.,.rmmod_foot?localhostextra]=?rmmodhf_first_moduleyouareouTing...Ismod_rooT@localhosTextra]=ls:modhf_firsT_moduLe5930-Live0xbf0120008最簡單的上層調(diào)用+調(diào)用驅(qū)動方法8.1首先在module_init(abc)abc函數(shù)中注冊設(shè)備ret=registerchrdev(245f"hf_c;har",sfops);if(注七)<printk("registerfdev^^eerrorJ\r");return-ret;register_chrdev(注冊設(shè)備號,上層可見的設(shè)備名,操作封裝)該函數(shù)完成設(shè)備注冊,在板子上用cat/proc/devices便可以看見該設(shè)備204s3c2410_serial245hf_char252led254ttySDIO8.2完成fops操作的封裝structfile_operatiQ:nsfops={.owner=THIS_MODULEfopen=my_openfrelease=my_closez注意格式必須在函數(shù)后面聲明該結(jié)構(gòu)體?頭文件#include<linux/fs.h>8.3查看到該字符設(shè)備后,創(chuàng)建設(shè)備節(jié)點,則上層通過設(shè)備字符名與該設(shè)備號綁定mknod/dev/hf_charc2450ls/dev/可以查看注冊的所有設(shè)備節(jié)點8.4此時上層應(yīng)用的open(”hf_char”,O_RDWR),即可完成該設(shè)備的打開,即可以完成上層應(yīng)用于下層驅(qū)動相關(guān)fops的操作。由此可以理解:上層應(yīng)用通過設(shè)備名稱在目錄Mev/下查找設(shè)備,下層驅(qū)動通過設(shè)備號如254,在內(nèi)核注冊,在/porc/devices查看,兩者通過mknod/dev/abcc2450進行連接9復(fù)雜框架上層應(yīng)用+驅(qū)動調(diào)用方法9.1知識前期準(zhǔn)備9.1.1設(shè)備號的操作設(shè)備號是由兩部分組成的號,一個是主設(shè)備號,一個是次設(shè)備號。操作的主要函數(shù):MKDEV();MINOR();MAJOR();注冊的兩者方式:動態(tài)注冊,靜態(tài)注冊、靜態(tài)注冊:register_chrdev_region(dev_tfrom,unsignedcount,constchar*name)、動態(tài)注冊:alloc_chrdev_region(dev_t*dev,unsignedbaseminor,unsignedcount,constchar*name)設(shè)備號:銜接應(yīng)用空間到內(nèi)核空間的符號dev_t32bitdev_tnum;--->得到主設(shè)備號:MAJOR(XXX)XXX:必須是主次設(shè)備號的一個整體#defineMAJOR(dev)((unsignedint)((dev)>>MINORBITS))#defineMINOR(dev)((unsignedint)((dev)&MINORMASK))#defineMKDEV(ma,mi)(((ma)<<MINORBITS)|(mi))10復(fù)雜框架字符設(shè)備創(chuàng)建并注冊過程10.1完成基本模塊框架如:module_init()module_exit()module_licence()頭文件10.2申請cdev結(jié)構(gòu)體、申請file_operations結(jié)構(gòu)體、創(chuàng)建設(shè)備號變量major在文件開頭創(chuàng)建設(shè)備號,模塊代碼中創(chuàng)建cdev變量和fops變量初始化fops結(jié)構(gòu)體中的實現(xiàn)操作函數(shù)00019:intmajor=l;staticstructz;devmycdev;stati"strnatfile_operationsfops=…10.3在函數(shù)中完成設(shè)備號注冊與設(shè)備注冊使用regester_chrdev_region()完成設(shè)備號注冊,動態(tài)注冊于靜態(tài)注冊兩者,注意:出錯處理,設(shè)備號與整形數(shù)的轉(zhuǎn)化MKDEV()使用cdev_init()完成fops與cdev結(jié)構(gòu)體綁定使用cdev_add()完成內(nèi)核的注冊

intret;dev_tdev_t;printk("moduleinstall.??\n");n%成設(shè)備號的注冊if(major)(dev_t=MKDEV(jn^jozrf0);char");ret=registerchrdevregion(MKDEV(mcijorr0)zlz*'hfelse(ret=alloc_chrdev_region(&dev_tr0,1/T'hf_charn);if(!ret){mcijor=MAJOR(dev_t);if(ret){printk(Mregistnombererror\nM);returnret;"完-成設(shè)備ccte-■/初始化cdevinit(&mycdeiTr&fops);"完成鑫個設(shè)-備注冊cdevadd(&my_cd.evrMKDEV(majorr0)z1);char");10.4模塊驅(qū)動的卸載設(shè)備的注銷設(shè)備號的注銷staticvoidexitmyoxl_oxit(void)printk('"noduLetaLLL\nr,j;cdevdel(smy^odev);ekl.kl.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&&+*******************************************************************************需要記住所有操作的函數(shù)名,不知用法可以使用城海insight搜索例子,照抄例子完成?JOR(XXX)見下圖:一個是設(shè)備號注冊子系統(tǒng),一個是操作子系統(tǒng)?RBITS)|(mi))字有效必須通過注冊的下11file_operations常用函數(shù)頭文件?JOR(XXX)#include<asm/uaccess.h>#include<asm/io.h>(*read)對應(yīng)上層的read函數(shù)copy_to_usercopy_to_user(void—user*to,constvoid*from,unsignedlongn)(*write)對應(yīng)上層的write函數(shù)copy_from_usercopy_from_user(void*to,constvoid—user*from,unsignedlongn)(*ioctl)多用于設(shè)備控制,如lcd等long(*unlocked_ioctl)(structfile*,unsignedint,unsignedlong);int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);常用系統(tǒng)封裝好的宏定義,完成命令的命名如下:#defineWDIOC_GETSUPPORT_IOR(WATCHDOG_IOCTL_BASE,0,structwatchdog_info)#defineWDIOC_GETSTATUS_IOR(WATCHDOG_IOCTL_BASE,1,int)#defineWDIOC_GETBOOTSTATUS_IOR(WATCHDOG_IOCTL_BASE,2,int)#defineWDIOC_GETTEMP_IOR(WATCHDOG_IOCTL_BASE,3,int)#defineWDIOC_SETOPTIONS_IOR(WATCHDOG_IOCTL_BASE,4,int)#define_IOR(type,nr,size)_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))#define_IOC(dir,type,nr,size)\(((dir)<<_IOC_DIRSHIFT)|\((type)<<_IOC_TYPESHIFT)|\((nr)<<_IOC_NRSHIFT)|\((size)<<_IOC_SIZESHIFT))(*open)設(shè)備的打開int(*open)(structinode*,structfile*);(*release)對應(yīng)上層的closeint(*release)(structinode*,structfile*);(*fasync)用于信號的操作12同步互斥操作?同步互斥是為了解決臨界資源訪問問題?就是控制一個資源誰先訪問,誰后訪問,并且只允許一個進程訪問它,其它進程訪問時等待。?多用于多進程、多線程12.1內(nèi)核工作狀態(tài):12.1.1搶占式內(nèi)核和非搶占式內(nèi)核區(qū)別搶占式內(nèi)核就是內(nèi)核擁有多進程運行,并與應(yīng)用程序共享cpu非搶占式內(nèi)核就是內(nèi)核一個進程獨享cpu,內(nèi)核不返回,應(yīng)用程序不執(zhí)行。12.1.2三種解決同步互斥的情況、單CPU不具備搶占式的內(nèi)核但cpu,當(dāng)cup執(zhí)行操作某個資源時,不可能出現(xiàn)同時執(zhí)行操作另一個進程操作這個資源,所以,進程上下文中,不需要考慮并發(fā)和互斥的問題唯一可能出現(xiàn)該問題,只有中斷。解決辦法:開關(guān)中斷:local_irq_disable()>local_irq_save(flags)local_irq_enable()>local_irq_restore(flags)、單CPU具備搶占內(nèi)核進程上下文中,中斷上下文都要考慮解決辦法:同步互斥+開關(guān)中斷、多CPUcpu可以同時操作某個資源,所以必須考慮同步互斥問題,并且中斷和進程都要考慮解決辦法:同步互斥+開關(guān)中斷Local_irq_disable(j>LocaL_irq_save(flagsj(j>store(flagsi13同步互斥函數(shù)總結(jié)整型原子自旋鎖信號量13.1自旋鎖當(dāng)?shù)却龝r候執(zhí)行while(1),cpu一直占用,所以一般內(nèi)部執(zhí)行時間必須很短,如果沒有解鎖前又取鎖,就會導(dǎo)致系統(tǒng)崩潰,所以使用時請慎行!spinlock_tlock;定義spin_lock_init(lock);初始化spin_lock(lock);獲得鎖spin_unlock(lock)釋放鎖spin_lock_irq()=spin_lock()+local_irq_disable()spin_unlock_irq()=spin_unlock()+local_irq_enablespin_lock_irq()=spin_lock()+local_irq_save()spin_unlock_irq()=spin_unlock()+local_irq_restore()13.2信號量structsemaphoresem;sema_init()DECLARE_MUTEX(name)完成兩步:初始化并設(shè)置初始值為1DECLARE_MUTEX_LOCKED(name):初始化并設(shè)置初始值為0down(&sem);獲得信號,消耗信號up(&sem);釋放信號14阻塞IO編程流程1、隊列頭結(jié)點的定義和初始化2、人為的定義一個邏輯表達式作為我們的條件3、wait_event(隊列名)喚醒4、wake_up(隊列名的地址)DECLARE_WAIT_HEAD(NAME)定義初始化隊列頭wait_event()wait_up()在全局聲明DECLARE_WAIT_HEAD(my_wait)wait_event(my_wait,(i==0));當(dāng)i==0的時候則運行(等到i==0的時候)wait_up(&my_wait)用于喚醒該隊列還有其它函數(shù):wait_event_interruptible(queue,conditon)可以中斷喚醒15輪詢操作上層select下層poll上層應(yīng)用使用select下層內(nèi)核調(diào)用poll,實現(xiàn)非阻塞方式,上層通過select訪問內(nèi)核子系統(tǒng)(內(nèi)核有專門的子系統(tǒng)負(fù)責(zé)這功能),下次值需要將連個隊列注冊,則一旦有變化將mask放回內(nèi)核子系統(tǒng),再有內(nèi)核子系統(tǒng)返回給上層的select函數(shù)fd。unsignedint(*poll)(structfile*filp,structpoll_table*table);主要結(jié)構(gòu):staticunsignedintglobalfifo_poll(structfile*filp,poll_table*wait){unsignedintmask=0;structglobalfifo_dev*dev=filp->private_data;/*獲得設(shè)備結(jié)構(gòu)體指針*/down(&dev->sem);poll_wait(filp,&dev->r_wait,wait);poll_wait(filp,&dev->w_wait,wait);/*fifo非空*/if(dev->current_len!=0){mask|=POLLIN|POLLRDNORM;/*標(biāo)示數(shù)據(jù)可獲得*/}/*fifo非滿*/if(dev->current_len!=GLOBALFIFO_SIZE){mask|=POLLOUT|POLLWRNORM;/*標(biāo)示數(shù)據(jù)可寫入*/}up(&dev->sem);returnmask;}16信號處理16.1上層應(yīng)用:#if1fcntl(fd,F_SETOWN,getpid());oflags=fcntl(fd,F_GETFL);fcntl(fd,F_SETFL,oflags|FASYNC);即調(diào)用下層的globalfifo_fasync#endif#if0fcntl(0,F_SETOWN,getpid());oflags=fcntl(0,F_GETFL);fcntl(0,F_SETFL,oflags|FASYNC);16.2下層:kill_fasync(&dev->async_queue,SIGIO,POLL_IN);staticintglobalfifo_fasync(intfd,structfile*filp,intmode){structglobalfifo_dev*dev=filp->private_data;returnfasync_helper(fd,filp,mode,&dev->async_queue);}17中斷17.1中斷簡介中斷與內(nèi)核調(diào)度的重要方式,中斷可以搶cpu。內(nèi)核對每一個中斷源,都使用structirqdescirq_desc結(jié)構(gòu)體來描述,每一個SOC芯片,都有很多的中斷源,內(nèi)核通過一個叫做NR_IRQS的宏定義這些中斷源的數(shù)量structirqdescirq_desc[NR_IRQS]這個中斷源不等于芯片廠商直接提供的中斷源數(shù)量S5PC100:在內(nèi)核中arch/arm/mach-s5pc100/include/mach/irqs.h這個文件描述了該SOC芯片在內(nèi)核的中斷子系統(tǒng)的源數(shù)量structirqdescirq_desc[NR_ZRQS][root?farsightlinux-2.6.35-farsight]#viarch/arm/mach-s5pcl00/include/mach./irqs.h17.2中斷程序編寫步驟和方式17.2.1查找硬件你產(chǎn)生中斷的引腳由原理圖找出key1在ENIT1上,然后找到該引腳對應(yīng)的中斷號,17.2.2申請irqrequest_irq(unsignedintirq,irq_handler_thandler,unsignedlongflags,constchar*name,void*dev)使用這個函數(shù)即可向內(nèi)核子系統(tǒng)申請irq,注意參數(shù)的填寫。分別是。irq號,irq處理函數(shù),irq標(biāo)志(有宏定義),可以看見的名稱,傳給處理函數(shù)的參數(shù)注意:中斷號不是我們查得的中斷號,是系統(tǒng)通過一種線性映射維護的一張中斷向量表,我們?nèi)ゲ?,在?nèi)核源代碼中:/work/linux_kernel_copy/arch/arm/mach-s5pc100/include/mach/irqs.h(沒有)/work/linux_kernel_copy/arch/arm/plat-s5p/include/plat/irqs.h(找到)root@ubuntu:/work/linux_kernel_copy/include/linux#viinterrupt.hirq_eint(1)表示外部中斷號1#incLudeinterrupt.h>^include<plat/irqs.h>|17.2.3編寫中斷處理函數(shù)staticirqreturn_tmy_irq(intirq,void*my_arg){printk("irq_yes...=\n");returnIRQ_HANDLED;}

17.2.4exit的時候釋放中斷free_irq(IRQ_EINT(1),NULL);17.3具體編程實現(xiàn)截圖注冊,在init里面注意:flagesirq注冊ret=requestirq(IRQEIMT(1)ZRQE_TRZGGER_FALLINGfT,hf_LrqT,fNULL)釋放,在exit里面free_irq(IRQ_EINT(1ijrXULL);中斷服務(wù)程序注意返回值,//中斷服務(wù)程序.staticirqretu.rn_tITiy_lTC|(intirq,void■myargi<printk(T,.=\n7');returnZRQ_H7\NELED;***********此時中斷即可完成,但中斷里面不能執(zhí)行阻塞和循環(huán)鎖,時間不能太長,所以中斷有幾種處理機制***************見書:19718中斷新模型--上半部中斷和下半部中斷的實現(xiàn)1,軟中斷和18中斷新模型--上半部中斷和下半部中斷的實現(xiàn)2,工作隊列是將剩余的處理函數(shù)壓入進程,與進程同級別受cpu調(diào)度。卜T?部i-.I'Z瓶序枇行■障軟中斷中斷iitfrTaskkjiHE不―執(zhí)行「?作怯舛沒4(和進WhK文?忤.被調(diào)度)工作隊列:structwork_structmy_wq申請一個voidmy_wq_func(unsignedlong)聲明一個處理函數(shù)INIT_WORK(&my_wq,(void(*)void*))my_wq_func,NULL);初始化,注冊進內(nèi)核schedule_work(&my_wq);調(diào)度,開始執(zhí)行tasklet:voidmy_tasklet_func(unsignedlong);定義你要執(zhí)行的處理函數(shù)DECLARE_TASKLET(my_tasklet,my_tasklet_func,data);聲明tasklet并綁定處理函數(shù)tasklet_schedule(&my_tasklet);調(diào)度taskletsoftirq:步驟同上:自行搜索

I必屏幕廣播窗口fTasklet的實現(xiàn)二二?定義一個處理函數(shù)voidmy_tasklet_func(unsignedlong);?定義一個tasklet結(jié)構(gòu)my_tasklet,與my_tasklet_func(data)函數(shù)相關(guān)聯(lián)—一一?DECLARE_TASKLET(my_tasklet,mytaskletfunc,data);?調(diào)度tasklet?tasklet_schedule(&my_tasklet);19內(nèi)核定時器編程概念:jiffies是內(nèi)核的心跳,它一直在不停的增加,HZ表示多少數(shù)量是1s19.1編程流程1)申明一個定時器結(jié)構(gòu)體structtimer_list()2)初始化該結(jié)構(gòu)體init_timer()具體不懂可以再內(nèi)核代碼中搜索如何使用3)setup_timer()初始化結(jié)構(gòu)體內(nèi)部各值,包括定時調(diào)用函數(shù)4)voidadd_timer()向內(nèi)核注冊該定時器一旦注冊開始計時5)del_timer()不需要時可以刪除。6)mod_timer()修改時間第2和3步驟可以用:DEFINE_TIMER(_name,—function,_expires,_data)替換;時間的定時例子:timer.expires=jiffies+HZ表示定時1s20內(nèi)核延時函數(shù)voidndelay(unsignedlongusecs)voidudelay(unsignedlongusecs)voidmdelay(unsignedlongmsecs)21內(nèi)核源代碼中頭文件分配方式左驅(qū)動中,我i門使用的頭文件蘭要形式:iinclude<Linux/xxx.h>^include<asm/xxx.h>^incLude<ma?h/xxx.h>^incLude<plat/xxx.h>?linux是體系結(jié)構(gòu)無關(guān)的頭文件,通用的頭文件,一般在頂層文件目錄中/work/!inux_kernei_eopy/inciude,?asm是體系結(jié)構(gòu)相關(guān)頭文件,主要與arm相關(guān),一般在:一般在:/work/!inux_kernei_copy/arch/arm/inciude/asm?mach板文件相關(guān)目錄,主要與最小系統(tǒng)版文件的

一般在:/work/linux_kernel_copy/arch/arm/mach-s5pc100/include/mach對應(yīng)的版文件目錄下plat是平臺相關(guān)目錄主要與制作開發(fā)板的相關(guān)目錄下/work/linux_kernel_copy/arch/arm/plat-s5p/include/plat22linux內(nèi)核管理和內(nèi)核的內(nèi)存管理概念1:每個應(yīng)用程序都有0?4G的空間,簡稱為用戶空間0?4G,但0?3G是用戶空間獨享的,而3G?4G空間是共享的內(nèi)核空間。0?3G用戶空間每個程序都有,但是是虛擬空間,都通過某種映射關(guān)系映射到內(nèi)核空間,映射關(guān)系及其復(fù)雜,但是內(nèi)核空間的3G?3.896G是與內(nèi)核空間一一映射的關(guān)系由此可以總結(jié)為:所有內(nèi)存都有內(nèi)核管理,用戶空間通過內(nèi)核調(diào)度使用內(nèi)存空間,用戶空間是不可見內(nèi)存的,而內(nèi)核空間是也是內(nèi)核調(diào)度,但可以通過某種線性關(guān)系得到實際的內(nèi)存地址。概念2:內(nèi)存空間分為兩種申請:1,動態(tài)申請2,靜態(tài)申請1,動態(tài):kmalloc()vmalloc()2,靜態(tài):全局申明23設(shè)備io端口和io內(nèi)存訪問-如何控制led的亮滅23.1編程流程和方法23.1.1靜態(tài)申請在頭文件找到你要控制的寄存器口的映射地址,/work/linux_kernel_copy/arch/arm/mach-s5pc100/include/mach/regs-gpio.h找到你要控制的寄存器使用這個映射相關(guān)寄存器地址,并操作即可完成對其的操作1)在頭文件找到你要控制的寄存器口的映射地址2)3)4)找到你要控制的寄存器使用這個映射相關(guān)寄存器地址,并操作即可完成對其的操作1)在頭文件找到你要控制的寄存器口的映射地址或者archarmmach-s5pc100includemachregs-gpio.h=fviarch/arm/p_aT-s5p/inc_ude/p_at/map-s5p.h2S^defineS5FC100_GPGl_BASE或者2S^defineS5FC100_GPGl_BASE29鈕沛FC10。GFG2BASE3。鈿S5FC100_GPG3_BASE鈕沛FC100_GFH0_BASEdefineS5FC100_GFHl_BASE鈕就:neS5FC100GPE2BASE(S5PC100_GPI0_RASE-。商ISO)(克PC100_GPI0_RASE-OxQlA。)(S5PC100_GPI0_RASE-。商ICO)(克PC100_GPI0_RASE-OxQCO。)(S5PC100_GPI0_BASE-。商C20)(S5PC100GPI0BASE-0MC40)2)找到你要控制的寄存器30陽Hine$5PO1OO[GPG3[BA$E(S3PC1OO[GPI"BASE-0S1C0)使用這個映射相關(guān)寄存器地址,并操作//i??诳刂萍拇嫫髟O(shè)置為輸出模式=ioread32(S5PCI?:.j_GPG3_BASE);io_vaL&=-Ckffff;io_val|=CxL111;iowrite32(io^aljrS5PCI■:j_GPG3_BASE);1o_ya.l_lrq-Ckff;iowriteQ(lo_^a.Z_lrqT(S5PCICl_GPG3_BASE-4j);數(shù)據(jù)寄存器賦值:staticirqreturn._tITiy_lTC|(in七irqfvoid*myarg){printk(T,\nT,);printk(T,keydown.--.\nT,);iowriteB(S5PC100_GPG3_BASE+4));return.ZRQ_HANDLED;主要函數(shù):ioread8ioread16ioread32iowrite8iowrite16iowrite3223.1.2動態(tài)申請主要函數(shù):void*ioremap(unsignedlongoffset,unsignedlongsize)gpg3_con=ioremap(0xE03001C0,8);gpg3_dat=gpg3_con+1;為防止物理地址的重復(fù)使用,造成使用混亂,最后先向內(nèi)核申請資源structresource*request_mem_region(unsignedlongstart,unsignedlonglen,char*name);voidrelease_mem_region(unsignedlongstart,unsignedlonglen);24*驅(qū)動-設(shè)備分離思想編程內(nèi)核進階在內(nèi)核中,上層應(yīng)用調(diào)用底層驅(qū)動然后執(zhí)行相關(guān)操作并不是以上驅(qū)動那樣寫的,而是使用驅(qū)動、設(shè)備分離思想編程的,設(shè)備1總線o"o0已1)設(shè)備只負(fù)責(zé)描述有哪些資源,有哪些接口,接口地址在哪兒2)驅(qū)動只負(fù)責(zé)如何操作,如何寫,如何讀3)總線則為其中兩者的橋梁當(dāng)設(shè)備加入時,總線自動按照一種邏輯配對驅(qū)動,如果找到則配對,如何找不到則顯示為驅(qū)動找不到,一個設(shè)備只有一個驅(qū)動與他對應(yīng),而多個設(shè)備可以指向一種驅(qū)動,因為他們的操作方法是一樣的,如:u盤和移動硬盤都是usb驅(qū)動,雖然他們資源地址不同,但是操作方法是相同的,這就是驅(qū)動與設(shè)備分離思想的精髓。25驅(qū)動-設(shè)備分離-核心最小架構(gòu)在該頭文件中定義<linux/device.h>/work/linux_kernel_copy/include/linux/device.h上層在封裝的結(jié)構(gòu)的定義在<linux/device.h>structbus_type總線結(jié)構(gòu)structdevice_driver驅(qū)動結(jié)構(gòu)structdevice設(shè)備結(jié)構(gòu)25.1前期知識準(zhǔn)備?設(shè)備和驅(qū)動都是由總線連接的,簡單來講都是掛在總線上的查看系統(tǒng)已經(jīng)擁有的總線/sys/bus/就可以看對應(yīng)bus下掛載的驅(qū)動和設(shè)備首先掛載總線insmodmy_bus?然后掛載驅(qū)動或者設(shè)備insmodmy_drvinsmodmy_dev?驅(qū)動結(jié)構(gòu)和設(shè)備結(jié)構(gòu)中都有一個bus指針,該指針正好指向一個總線結(jié)構(gòu)?每來一個新的驅(qū)動結(jié)構(gòu)或者設(shè)備結(jié)構(gòu),內(nèi)核子系統(tǒng)會自動調(diào)用總線結(jié)構(gòu)中的match函數(shù)。而match函數(shù)返回0為不匹配,返回非0就匹配,一旦匹配成功,子系統(tǒng)就會調(diào)用匹配成功的驅(qū)動結(jié)構(gòu)里的probe函數(shù)詳細(xì)代碼見mycode/mod/bus1以下摘抄幾個重點必須包含《linux/device.h》由三個結(jié)構(gòu)體描述bus總線里的重點代碼staticintmybus_match(structdevice*dev,structdevice_driver*drv){printk("mybusmatch...\n");return1;}structbus_typemybus={.name="hfrbus",.match=mybus_match,};staticint__initmybus_init(void){returnbus_register(&mybus);〃注冊}EXPORT_SYMBOL(mybus);//將my_bus可外部訪問staticvoid__exitmybus_exit(void){bus_unregister(&mybus);}driver里的重點代碼externstructbus_typemybus;〃使用外部訪問staticintmydrv_probe(structdevice*dev){printk("mydrv_probe...\n");return0;}structdevice_drivermydrv={.name="hfrdisk_drv",.bus=&mybus,//綁定be=mydrv_probe,//申請成功,自動調(diào)用bus};device里的重點代碼externstructbus_typemybus;〃夕卜部變量使用voidmydev_release(structdevice*dev){printk("fardiskrelease...\n");}structdevicemydev={.init_name="hfrdisk",.bus=&mybus,.release=mydev_release,//必'須要這個,不然要報錯};************************這就是最小的框架****************************externstructbus_typemybus;EXPORT_SYMBOL(mybus);26驅(qū)動設(shè)備分離思想-上層架構(gòu)(基于封裝)26.1基本知識包含頭文件:<linux/platfdrm_devices.h>/work/linux_kernel_copy/include/linux/platform_device.h1)編輯兩個模塊,platform_driver和platform_devmydev.cmydrv.cNutHp:=Ld++Ilucmentirty?吊門捉口洞++DocuitiAnt至11KB駐^3KB2)必須用到的結(jié)構(gòu)體和函數(shù)mydev.c中:sturctplatform_devicestructplatform_devic:emyleddev=<.nanie="fT.resource=myJ.e<i_resr.rmni_resou.rc:es=AREiAYSIZEe<i_res).dev=<.release=mydevrelease,驅(qū)動模塊加載卸裝使用structresoucestatic:structresourcemyledres::=<二:=:一.start=CxEC3CCLCC,.end=CxECSCClCC-7,.flags=LORESOURCE_MEMf封裝資源用注意:.name是設(shè)備名稱必須在.dev里面定義.release.dev是platfOrm_device中的小零件resource是定義的資源,必須包含著三個點,且最好定義為數(shù)組?模塊結(jié)構(gòu)不能少mydrv.c中:structplatform_driverstructpLatform_drivermyleddrv=?:.probe=myledprobe7.remove=myledremovef.driver=<.name="fsrLed11r:'—驅(qū)動模塊加載,卸裝使用structresourcestructresourceplatfOrm_get_resourcemem=platformgetresource(pdev7ZORES0JRCE_MEMfjj;meml=platformgetresource(pdevfZORESOJRCE_ZF.QfJj;用于獲

溫馨提示

  • 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

提交評論