




下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、armlinux 學習筆記觸摸屏驅動程序分析*/*2007.6.26*Linux 下的觸摸屏驅動程序主要都在/kernel/drivers/char/s3c2410-ts.c 文件中。觸摸屏的file_operations 結構定義如下:staticstructfile_operationss3c2410_fops=owner:THIS_MODULE,open:s3c2410_ts_open,read:s3c2410_ts_read,release:s3c2410_ts_release,#ifdefUSE_ASYNCfasync:s3c2410_ts_fasync,#endifpoll:s3c
2、2410_ts_poll,;在觸摸屏設備驅動程序中,全局變量 structTS_DEVtsdev 是很重要的,用來保存觸摸屏的相關參數、等待處理的消息隊列、當前采樣數據、上一次采樣數據等信息,數據結構 structTS_DEV 的定義如下:typedefstructunsignedintpenStatus;/*PEN_UP,PEN_DOWN,PEN_SAMPLE*/TS_RETbufMAX_TS_BUF;/*protectagainstoverrun(環形緩沖區)*/unsignedinthead,tail;/*headandtailforqueuedevents(環形緩沖區的頭尾)*/wai
3、t_queue_head_twq;/*等待隊列數據結構 spinlock_tlock;/*自旋鎖#ifdefUSE_ASYNCstructfasync_struct*aq;#endif#ifdefCONFIG_PMstructpm_dev*pm_dev;#endifTS_DEV;staticTS_DEVtsdev;在/kernel/include/asm-arm/linuette_ioctl.h 文件中:typedefstructunsignedshortpressure;/*壓力,這里可定義為筆按下,筆抬起,筆拖曳unsignedshortx;/*橫坐標的采樣值unsignedshorty;
4、/*縱坐標的采樣值unsignedshortpad;/*填充位TS_RET;在/kernel/include/linux/wait.h 文件中:struct_wait_queue_headwq_lock_tlock;structlist_headtask_list;#ifWAITQUEUE_DEBUGlong_magic;long_creator;#endif;typedefstruct_wait_queue_headwait_queue_head_t;TS_RET 結構體中的信息就是驅動程序提供給上層應用程序使用的信息,用來存儲觸摸屏的返回值。上層應用程序通過讀接口,從底層驅動中讀取信息,并
5、根據得到的值進行其他方面的操作。TS_DEV 結構用于記錄觸摸屏運行的各種狀態, PenStatu 匏括 PEN_UP、PEN_DOWN 和PEN_FLEETING。bufMAX_TS_BUF是用來存放數據信息的事件隊列,head、tail 分別指向事件隊列的頭和尾。 程序中的筆事件隊列是一個環形結構, 當有事件加入時,隊列頭加一,當有事件被取走時, 隊列尾加一, 當頭尾位置指針一致時讀取筆事件的信息,進程會被安排進入睡眠。wq 等待隊列,包含一個鎖變量和一個正在睡眠進程鏈表。當有好幾個進程都在等待某件事時,Linux 會把這些進程記錄到這個等待隊列。它的作用是當沒有筆觸事件發生時,阻塞上層的
6、讀操作,直到有筆觸事件發生。lock 使用自旋鎖,自旋鎖是基于共享變量來工作的,函數可以通過給某個變量設置一個特殊值來獲得鎖。而其他需要鎖的函數則會循環查詢鎖是否可用。 MAX_TS_BUF 的值為 16,即在沒有被讀取之前,系統緩沖區中最多可以存放 16 個筆觸數據信息。 (關于自旋鎖的作用和概念可以參考一篇 Linux內核的同步機制文章的相關章節。)模塊初始化函數是調用 s3c2410_ts_init 函數來實現的,主要完成觸摸屏設備的內核模塊加載、初始化系統 I/O、中斷注冊、設備注冊,為設備文件系統創建入口等標準的字符設備初始化工作。staticint_inits3c2410_ts_i
7、nit(void)ret=register_chrdev(0,DEVICE_NAME,&s3c2410_fops);tsMajor=ret;這里首先對字符設備進行注冊,將觸摸屏的 file_operations 結構中的函數接口傳入內核,注冊成功后獲得系統自動分配的主設備號。set_gpio_ctrl(GPIO_YPON);set_gpio_ctrl(GPIO_YMON);set_gpio_ctrl(GPIO_XPON);set_gpio_ctrl(GPIO_XMON);在/kernel/include/asm-arm/arch-s3c2410/smdk.h 文件中:# defineG
8、PIO_YPON(GPIO_MODE_nYPON|GPIO_PULLUP_DIS|GPIO_G15)# defineGPIO_YMON(GPIO_MODE_YMON|GPIO_PULLUP_EN|GPIO_G14)# defineGPIO_XPON(GPIO_MODE_nXPON|GPIO_PULLUP_DIS|GPIO_G13)# defineGPIO_XMON(GPIO_MODE_XMON|GPIO_PULLUP_EN|GPIO_G12)GPIO的 PortG 端口有 4 個管腳對應觸摸屏的控制接口,分別是:GPG15-nYPONY+控制信號GPG14-YMONY-控制信號GPG13-nX
9、PONX+控制信號GPG12-XMONX-控制信號需要通過配置 GPGCON 寄存器來設定該端口管腳的輸出模式, 對應位如下:31:3029:2827:2625:24GPG15GPG14GPG13GPG12.參考 S3c2410 芯片 datasheet 的 I/O 口章節,都要設為 11(二進制)。ADCDLY=30000;配置 ADCDLY 寄存器,對自動轉換模式來說是設定 ADC 開始轉換時的延時時間,以及對 X軸和 Y 軸轉換的時間間隔, 對正常模式來說僅設定對 X 軸和 Y 軸轉換的時間間隔。注意該值不能為 0。在/kernel/arch/arm/kernel/irq.c 文件中:/
10、* request_irq-allocateaninterruptline* irq:Interruptlinetoallocate* handler:FunctiontobecalledwhentheIRQoccurs* irqflags:Interrupttypeflags* devname:Anasciinamefortheclaimingdevice* dev_id:Acookiepassedbacktothehandlerfunction* Thiscallallocatesinterruptresourcesandenablesthe* interruptlineandIRQhan
11、dling.Fromthepointthis* callismadeyourhandlerfunctionmaybeinvoked.Since* yourhandlerfunctionmustclearanyinterrupttheboard* raises,youmusttakecarebothtoinitialiseyourhardware* andtosetuptheinterrupthandlerintherightorder.* Dev_idmustbegloballyunique.Normallytheaddressofthe* devicedatastructureisuseda
12、sthecookie.Sincethehandler* receivesthisvalueitmakessensetouseit.* IfyourinterruptissharedyoumustpassanonNULLdev_id* asthisisrequiredwhenfreeingtheinterrupt.* Flags:* SA_SHIRQInterruptisshared* SA_INTERRUPTDisablelocalinterruptswhileprocessing* SA_SAMPLE_RANDOMTheinterruptcanbeusedforentropy*/intreq
13、uest_irq(unsignedintirq,void(*handler)(int,void*,structpt_regs*),unsignedlongirq_flags,constchar*devname,void*dev_id)其中 handler 函數指針的具體參數為:void(*handler)(intirq,void*dev_id,structpt_regs*regs)函數 request_irq 是 Linux 系統中驅動程序注冊中斷的方法。irq 為所要申請的硬件中斷號,handler 為系統所注冊的中斷處理子程序,irq_flags 為申請時的選項,devname 為指向設備
14、名稱的字符指針,dev_id 為申請時告訴系統的設備標識。若中斷申請成功則返回 0,失敗則返回負值。ret=request_irq(IRQ_ADC_DONE,s3c2410_isr_adc,SA_INTERRUPT,DEVICE_NAME,s3c2410_isr_adc);調用該函數來進行 A/D 轉換的中斷注冊,所要申請的硬件中斷號為IRQ_ADC_DONE(62);系統所注冊的中斷處理子程序為 s3c2410_isr_adc 函數;申請中斷選項為 SA_INTERRUPT,表示中斷處理程序是快速處理程序,即快速處理程序運行時,所有中斷都被屏蔽;設備名稱定義為 DEVICE_NAME,即s3
15、c2410-ts;而設備標識仍然用中斷處理子程序代替。ret=request_irq(IRQ_TC,s3c2410_isr_tc,SA_INTERRUPT,DEVICE_NAME,s3c2410_isr_tc);接著繼續調用該函數來進行觸摸屏觸摸的中斷注冊, 所要申請的硬件中斷號為 IRQ_TC(61);系統所注冊的中斷處理子程序為 s3c2410_isr_tc 函數;申請中斷選項為SA_INTERRUPT,表示中斷處理程序是快速處理程序,即快速處理程序運行時,所有中斷都被屏蔽;設備名稱定義為 DEVICE_NAME,即s3c2410-ts;而設備標識仍然用中斷處理子程序代替。/*Waitfo
16、rtouchscreeninterrupts*/wait_down_int();調用該宏函數來設置觸摸屏為等待中斷模式【筆按下產生中斷】,具體定義如下:#definewait_down_int()ADCTSC=DOWN_INT|XP_PULL_UP_EN|XP_AIN|XM_HIZ|YP_AIN|YM_GND|XP_PST(WAIT_INT_MODE);用該宏函數來設置 ADC 觸摸屏控制寄存器,參考 S3C2410 芯片datasheet 中關于觸摸屏的章節,具體設置參數如下:DOWN_INT=18*0 該位保留且應該設為 01 筆按下或筆抬起中斷信號控制位,設為 0表示筆按下產生中斷信號】
17、XP_PULL_UP_EN=13*0 上拉開關使能, 設為 0表示 XP 引腳上拉使能選擇nXPON 引 腳 輸 出 值 , 設 為 1 表 示nXPON引腳輸出 1,則 XP 引腳選擇XMON 引腳輸出值, 設為 0 表示 XMON引腳輸出 0,則 XM 引選擇nYPON 引 腳 輸 出 值 , 設 為 1 表 示nYPON引腳輸出 1,則 YP 引腳選擇 YMON 引腳輸出值,設為 1 表示 YMON 引腳輸出 1,則 YM 引X 坐標 Y坐標手動測量設置,設為 3表示等待中斷模式#ifdefCONFIG_DEVFS_FSdevfs_ts_dir=devfs_mk_dir(NULL,tou
18、chscreen,NULL);devfs_tsraw=devfs_register(devfs_ts_dir,0raw,DEVFS_FL_DEFAULT,tsMajor,TSRAW_MINOR,S_IFCHR|S_IRUSR|S_IWUSR,&s3c2410_fops,NULL);#endifXP_AIN=14*1 連接 AIN7引腳XM_HIZ=15*0 腳為高阻態YP_AIN=16*1 連接 AIN5引腳YM_GND=17*1 腳為接地XP_PST(WAIT_INT_MODE);=3以上這兩個函數在我總結的一篇 LCD 驅動程序分析 中有較詳細的介紹。這里調用了 devfs_mk_
19、dir 函數,在設備文件系統中創建了一個名為touchscreen 的目錄,并返回一個帶有目錄結構的數據結構變量 devfs_ts_dir。將該變量作為下一步 devfs_register函數的參數,該參數在調用設備文件系統注冊清除函數 devfs_unregister 時也要作為參數傳入。調用 devfs_register 函數后,會在剛才創建的 touchscreen 目錄下再創建一個名為 0raw 的設備文件節點。 該函數的參數中, DEVFS_FL_DEFAULT 為該函數的標志選項,tsMajor 為注冊字符設備時系統自動分配的主設備號,TSRAW_MINOR(1)為次設備號,S_I
20、FCHR|S_IRUSR|S_IWUSR 為默認的文件模式, &s3c2410_fops 為傳入內核的觸摸屏 file_operations 結構中的函數接口,私有數據指針為空。返回一個devfs_handle_t 數據結構的變量 devfs_tsraw,這會在調用設備文件系統注冊清除函數 devfs_unregister 時作為參數傳入。模塊的退出函數為s3c2410_ts_exit,該函數的工作就是清除已注冊的字符設備,中斷以及設備文件系統。#ifdefCONFIG_DEVFS_FSdevfs_unregister(devfs_tsraw);devfs_unregister(dev
21、fs_ts_dir);#endif這里首先清除原先后一步創建設備文件節點 0raw 的結構變量devfs_tsraw,然后再清除創建 touchscreen 目錄的結構變量 devfs_ts_dir。unregister_chrdev(tsMajor,DEVICE_NAME);接下來疝除字符設備的注冊信息。在/kernel/arch/arm/kernel/irq.c 文件中:/* free_irq-freeaninterrupt* irq:Interruptlinetofree* dev_id:Deviceidentitytofree* Removeaninterrupthandler.The
22、handlerisremovedandifthe* interruptlineisnolongerinusebyanydriveritisdisabled.* OnasharedIRQthecallermustensuretheinterruptisdisabled* onthecarditdrivesbeforecallingthisfunction.* Thisfunctionmaybecalledfrominterruptcontext.*/voidfree_irq(unsignedintirq,void*dev_id)函數 free_irq 與函數 request_irq 相對應,通常
23、在模塊被卸載時調用,負責注銷一個已經申請的中斷。free_irq(IRQ_ADC_DONE,s3c2410_isr_adc);free_irq(IRQ_TC,s3c2410_isr_tc);最后依次注銷 A/D 轉換和定時器這兩個已經申請的中斷。接下來看一下 A/D 轉換的中斷處理函數:staticvoids3c2410_isr_adc(intirq,void*dev_id,structpt_regs*reg)其中參數 irq 為中斷號,dev_id 為申請中斷時告訴系統的設備標識,regs為中斷發生時寄存器內容。該函數在中斷產生時由系統來調用,調用時以上參數已經由系統傳入。在/kernel/
24、include/linux/spinlock.h 文件中:/*# Thesearethegenericversionsofthespinlocksandread-write# locks.# /# definespin_lock_irq(lock)dolocal_irq_disable();spin_lock(lock);while(0)# definespin_unlock_irq(lock)dospin_unlock(lock);local_irq_enable();while(0)# defineDEBUG_SPINLOCKS0/*0=nodebugging,1=maintainlock
25、state,2=fulldebug# /# if(DEBUG_SPINLOCKS1)typedefstructspinlock_t;#defineSPIN_LOCK_UNLOCKED(spinlock_t)# definespin_lock_init(lock)dowhile(0)#definespin_lock(lock)(void)(lock)/*Notunusedvariable.*/# definespin_unlock_wait(lock)dowhile(0)# definespin_unlock(lock)dowhile(0)可見上面這四個宏函數都是空函數,這樣白話 spin_lo
26、ck_irq(lock)和spin_unlock_irq(lock)這兩個宏函數就相當于分別只調用了 local_irq_disable();和 local_irq_enable();兩個宏函數。關于自旋鎖的作用和概念可以參考一篇Linux 內核的同步機制文章的相關章節。在/kernel/include/asm-arm/system.h 文件中:# definelocal_irq_disable()_cli()# definelocal_irq_enable()_sti()在/kernel/include/asm-arm/proc-armo/system.h 文件中:/* EnableIRQs
27、* /*define_sti()dounsignedlongtemp;_asmvolatile_(mov%0,pcstinbic%0,%0,#0 x08000000nteqp%0,#0n:=r(temp):memory);while(0)/*DisableIRQs*/#define_cli()dounsignedlongtemp;_asmvolatile_(mov%0,pcclinorr%0,%0,#0 x08000000nteqp%0,#0n:=r(temp):memory);while(0)最后用 ARM 匯編指令實現了對 IRQ 的使能和禁止。spin_lock_irq(&(ts
28、dev.lock);這樣調用spin_lock_irq宏函數, 實際上只是做了local_irq_disable();一步,就是禁止 IRQ 中斷。if(tsdev.penStatus=PEN_UP)s3c2410_get_XY();然 后 根 據 變 量 tsdev.penStatus 所 處 的 狀 態 , 若 為 筆 抬 起 則 調 用s3c2410_get_XY 函數來取得 A/D 轉換得到的坐標值,該函數會在后面說明。#ifdefHOOK_FOR_DRAGelses3c2410_get_XY();#endif這里表示如果定義了筆拖曳,且在筆沒有抬起的情況下,繼續調用s3c2410_g
29、et_XY 函數來得到最新的坐標值。spin_unlock_irq(&(tsdev.lock);最后調用spin_unlock_irq宏函數, 相當于只做了local_irq_enable();一步,來重新使能 IRQ 中斷。最后退出這個中斷服務子程序。繼續來看一下另一個中斷處理函數,即觸摸屏觸摸中斷處理函數:staticvoids3c2410_isr_tc(intirq,void*dev_id,structpt_regs*reg)該函數的參數和上面 A/D 轉換中斷處理函數的定義一樣,不再累贅。spin_lock_irq(&(tsdev.lock);也同上面的意思一樣,首先禁
30、止 IRQ 中斷。if(tsdev.penStatus=PEN_UP)start_ts_adc();接著根據變量 tsdevpenStatus 的狀態值判斷是否進行 A/D 轉換。若筆抬起,則調用函數start_ts_adc 來進行 A/D 轉換,該函數會在后面說明。elsetsdev.penStatus=PEN_UP;DPRINTK(PENUP:x:%08d,y:%08dn”,x,y);wait_down_int();tsEvent();如果變量 tsdev.penStatus 的狀態值不是筆抬起,則先將該變量狀態設為筆抬起,然后調用宏函數 wait_down_int()。該宏函數已在前面說
31、明,用來設置觸摸屏為等待中斷模式。最后調用 tsEvent 函數指針所指的函數,在模塊初始化函數 s3c2410_ts_init 中,tsEvent 指向的是一個空函數 tsEvent_dummy,而在打開設備函數 s3c2410_ts_open 中,tsEvent 會指向 tsEvent_raw 函數,該函數負責填充觸摸屏緩沖區,并喚醒等待的進程。該函數也會在后面加以說明。spin_unlock_irq(&(tsdev.lock);中斷處理函數的最后一步都一樣,重新使能 IRQ 中斷。退出中斷服務子程序。下面先來看啟動 A/D 轉換的函數:staticinlinevoidstart_
32、ts_adc(void)adc_state=0;mode_x_axis();start_adc_x();簡簡單單的 3 步。第一步,對 A/D 轉換的狀態變量清零。第二步,調用 mode_x_axis 宏函數,具體定義如下:#definemode_x_axis()ADCTSC=XP_EXTVLT|XM_GND|YP_AIN|YM_HIZ|XP_PULL_UP_DIS|XP_PST(X_AXIS_MODE);*/*2007.6.27*該宏函數用來設置 ADC 觸摸屏控制寄存器為測量 X 坐標模式,參考S3c2410 芯片 datasheet 中關于觸摸屏的章節,具體設置參數如下:XP_EXTVL
33、T=14*0 選擇 nXPON 引腳輸出值, 設為 0 表示 nXPON 引腳輸出 0,貝 UXP引腳為接外部電壓XM_GND=15*1 選擇 XMON 引腳輸出值,設為 1 表示 XMON 引腳輸出 1,則 XM 引腳為接地YP_AIN=16*1 選擇 nYPON 引腳輸出值,設為 1 表示 nYPON 引腳輸出 1,則 YP 引腳連接 AIN5引腳YM_HIZ=17*0 選擇 YMON 引腳輸出值,設為 0 表示 YMON 引腳輸出 0,則 YM 引腳為高阻態XP_PULL_UP_DIS=13*1 上拉開關使能,設為 1 表示 XP 引腳上拉禁止XP_PST(X_AXIS_MODE);=1
34、X 坐標丫坐標手動測量設置,設為 1 表示 X 坐標測量模式第三步,調用 start_adc_x 宏函數,具體定義如下:#definestart_adc_x()ADCCON=PRESCALE_EN|PRSCVL(49)|ADC_INPUT(ADC_IN5)|ADC_START_BY_RD_EN|ADC_NORMAL_MODE;ADCDAT0;該宏函數用來設置 ADC 控制寄存器啟動 X 坐標的 A/D 轉換,參考S3c2410 芯片 datasheet 中關于觸摸屏的章節,具體設置參數如下:PRESCALE_EN=114*1A/D 轉換器使能,設為 1 表示使能 A/D 轉換器PRSCVL(4
35、9)=496A/D 轉換器值,設為 49ADC_INPUT(ADC_IN5)=53 選擇模擬輸入通道,設為 5 表示 AIN5引腳作為模擬輸入通道ADC_START_BY_RD_EN=11*1A/D 轉換通過讀啟動, 設為 1 表示通過讀操作啟動A/D 轉換使能ADC_NORMAL_MODE;=12*0 選擇待命模式,設為 0 表示正常操作模式ADCDAT0;讀取 X 坐標的 ADC 轉換數據寄存器由于設置了 A/D 轉換通過讀啟動,則該 ADCCON 寄存器的最低位ENABLE_START 啟動A/D 轉換位就無效了。在最后一步讀取 ADCDAT0 寄存器這一操作時就啟動了 A/D 轉換。s
36、taticinlinevoids3c2410_get_XY(void)這就是獲取 A/D 轉換所得到的坐標值的函數。if(adc_state=0)adc_state=1;disable_ts_adc();y=(ADCDAT0&0 x3ff);mode_y_axis();start_adc_y();這里首先查看 A/D 轉換的狀態變量,若為 0 表示進行過 X 坐標的 A/D 轉換,將該變量設為 1。然后調用宏函數 disable_ts_adc,該宏函數定義如下:#definedisable_ts_adc()ADCCON&=(ADCCON_READ_START);這個宏函數主要工
37、作就是禁止通過讀操作啟動 A/D 轉換,參考 S3C2410芯片 datasheet 中關于觸摸屏的章節,具體設置參數如下:ADCCON_READ_START=11A/D 轉換通過讀啟動, 設為 0 表示通過讀操作啟動 A/D 轉換禁止然后 y=(ADCDAT0&0 x3ff);這一步將 X 坐標的 ADC轉換數據寄存器的 D9D0 這 10 為讀出到變量 y(這里由于是豎屏,參考原理圖后知道,硬件連線有過改動,將XP,XM 和YP,YM 進行了對換, 這樣 ADCDAT0 里讀出的是 YP,YM 方向電阻導通的值,也就是 y 軸坐標值)。這個 mode_y_axis 宏函數定義如下:
38、#definemode_y_axis()ADCTSC=XP_AIN|XM_HIZ|YP_EXTVLT|YM_GND|XP_PULL_UP_DIS|XP_PST(Y_AXIS_MODE);該宏函數用來設置 ADC 觸摸屏控制寄存器為測量 Y 坐標模式,參考S3c2410 芯片 datasheet 中關于觸摸屏的章節,具體設置參數如下:XP_AIN=14*1 選擇 nXPON 引腳輸出值,設為 1 表示 nXPON 引腳輸出 1,則 XP 引腳連接 AIN7引腳XM_HIZ=15*0 選擇 XMON 引腳輸出值,設為 0 表示 XMON 引腳輸出 0,則 XM 引腳為高阻態YP_EXTVLT=16
39、*0 選擇 nYPON 引腳輸出值, 設為 0 表示 nYPON 引腳輸出 0,貝 UYP引腳為接外部電壓YM_GND=17*1 選擇 YMON 引腳輸出值,設為 1 表示 YMON 引腳輸出 1,則 YM 引腳為接地XP_PULL_UP_DIS=13*1 上拉開關使能,設為 1 表示 XP 引腳上拉禁止XP_PST(Y_AXIS_MODE);=2X 坐標丫坐標手動測量設置,設為 2 表示丫坐標測量模式最后調用 start_adc_y 宏函數,具體定義如下:#definestart_adc_y()ADCCON=PRESCALE_EN|PRSCVL(49)|ADC_INPUT(ADC_IN7)|
40、ADC_START_BY_RD_EN|ADC_NORMAL_MODE;ADCDAT1;該宏函數用來設置 ADC 控制寄存器啟動 Y 坐標的 A/D 轉換,參考S3c2410 芯片 datasheet 中關于觸摸屏的章節,具體設置參數如下:PRESCALE_EN=114*1A/D 轉換器使能,設為 1 表示使能 A/D 轉換器PRSCVL(49)=496A/D 轉換器值,設為 49ADC_INPUT(ADC_IN7)=73 選擇模擬輸入通道,設為 7 表示 AIN7引腳作為模擬輸入通道ADC_START_BY_RD_EN=11*1A/D 轉換通過讀啟動, 設為 1 表示通過讀操作啟動A/D 轉換
41、使能ADC_NORMAL_MODE;=12*0 選擇待命模式,設為 0 表示正常操作模式ADCDAT1;讀取 Y 坐標的 ADC 轉換數據寄存器elseif(adc_state=1)adc_state=0;disable_ts_adc();x=(ADCDAT1&0 x3ff);tsdev.penStatus=PEN_DOWN;DPRINTK(PENDOWN:x:%08d,y:%08dn,x,y);wait_up_int();tsEvent();若查看 A/D 轉換的狀態變量,若為 1 表示進行過 Y 坐標的 A/D 轉換,將該變量設為 0。然后調用宏函數 disable_ts_adc
42、來禁止通過讀操作啟動 A/D 轉換。接著將 x=(ADCDAT1&0 x3ff);這一步將 Y 坐標的 ADC 轉換數據寄存器的D9D0 這 10 為讀出到變量 x(這里由于是豎屏,參考原理圖后知道,硬件連線有過改動,將 XP,XM 和 YP,YM 進行了對換,這樣 ADCDAT1 里讀出的是 XP,XM 方向電阻導通的值,也就是 x 軸坐標值)。隨后將變量 tsdev.penStatus 的狀態值改為筆按下,并調用 wait_up_int宏函數來設置觸摸屏為等待中斷模式【筆抬起產生中斷】,具體定義如下:#definewait_up_int()ADCTSC=UP_INT|XP_PULL
43、_UP_EN|XP_AIN|XM_HIZ|YP_AIN|YM_GND|XP_PST(WAIT_INT_MODE);用該宏函數來設置 ADC 觸摸屏控制寄存器,參考 S3C2410 芯片datasheet 中關于觸摸屏的章節,具體設置參數如下:UP_INT=18*1 該位保留且應該設為 0,這里設為 1 不知道為什么【筆按下或筆抬起中斷信號控制位,設為 1 表示筆抬起產生中斷信號】XP_PULL_UP_EN=13*0 上拉開關使能, 設為 0表示 XP 引腳上拉使能選擇nXPON 引腳輸出值,設為 1 表示nXPON引腳輸出 1,則 XP 引腳選擇XMON 引腳輸出值, 設為 0 表示 XMON
44、引腳輸出 0,則 XM 引選擇nYPON 引腳輸出值,設為 1 表示nYPON引腳輸出 1,則 YP 引腳選擇 YMON 引腳輸出值,設為 1 表示 YMON 引腳輸出 1,則 YM 引XP_PST(WAIT_INT_MODE);=3X 坐標丫坐標手動測量設置,設為 3 表示等待中斷模式最后調用函數指針 tsEvent所指向的函數。 在 s3c2410_get_XY函數里面,應該表示這個驅動的設備文件已經打開,在打開設備文件函數中,tsEvent函數指針就指向了 tsEvent_raw 這XP_AIN=14*1 連接 AIN7引腳XM_HIZ=15*0 腳為高阻態YP_AIN=16*1 連接
45、AIN5引腳YM_GND=1lock,flags);_wake_up_common(q,mode,nr,0);wq_read_unlock_irqrestore(&q-lock,flags);宏函數 wq_read_lock_irqsave 的作用主要就是保存 IRQ 和 FIQ 的中斷使能狀態,并禁止 IRQ 中斷;而宏函數 wq_read_unlock_irqrestore 的作用就是恢復 IRQ 和 FIQ 的中斷使能狀態。現在可以得知_wake_up 這個函數的作用,它首先保存 IRQ 和 FIQ 的中斷使能狀態,并禁止IRQ 中斷,接著調用_wake_up_common 函數
46、來喚醒等待 q 隊列的進程,最后再恢復 IRQ和 FIQ 的中斷使能狀態。/* Thecorewakeupfunction.Non-exclusivewakeups(nr_exclusive=0)justwakeeverything* up.Ifitsanexclusivewakeup(nr_exclusive=small+venumber)thenwewakeallthe*non-exclusivetasksandoneexclusivetask.* Therearecircumstancesinwhichwecantrytowakeataskwhichhasalready* started
47、torunbutisnotinstateTASK_RUNNING.try_to_wake_up()returnszero* inthis(rare)case,andwehandleitbycontonuingtoscanthequeue.*/staticinlinevoid_wake_up_common(wait_queue_head_t*q,unsignedintmode,intnr_exclusive,constintsync)該函數的作用是喚醒在等待當前等待隊列的進程。參數 q 表示要操作的等待隊列,mode 表示要喚醒任務的狀態,如 TASK_UNINTERRUPTIBLE 或TASK
48、_INTERRUPTIBLE 等。nr_exclusive 是要喚醒的互斥進程數目,在這之前遇到的非互斥進程將被無條件喚醒。sync表不?在/kernel/include/linux/wait.h 文件中:struct_wait_queue_headwq_lock_tlock;structlist_headtask_list;#ifWAITQUEUE_DEBUGlong_magic;long_creator;#endif;typedefstruct_wait_queue_headwait_queue_head_t;這是等待隊列數據結后。*definewq_read_lock_irqsavesp
49、in_lock_irqsave*definewq_read_unlock_irqrestorespin_unlock_irqrestore看到這里可以知道其實宏函數 wq_read_lock_irqsave 和wq_read_unlock_irqrestore 等價于宏函數 spin_lock_irqsave 和 spin_unlock_irqrestore,并直接將自己的參數傳了下去。在/kernel/include/linux/spinlock.h 文件中:/*Thesearethegenericversionsofthespinlocksandread-write*locks.*/#definespin_lock_irqsave(lock,flags)dolocal_irq_save(flags);spin_lock(lock);while(0)#definespin_unlock_irqrestore(lock,flags)dospin_unlock(lock);local_irq_restore(flags);while(0)在這
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 創新驅動的未來區塊鏈技術在教育領域的應用與挑戰
- 利用區塊鏈技術為醫療行業提供更高級別的數據安全與信任保障
- 以實踐說事區塊鏈助力體育行業知識產管理實例解析
- 創新個性化健康管理助力人類健康發展
- 以用戶體驗為核心打造基于區塊鏈的知識產權服務模式
- 單一稀土金屬企業數字化轉型與智慧升級戰略研究報告
- 硬質材料加工鋸床企業ESG實踐與創新戰略研究報告
- 夾膠玻璃彎曲設備企業縣域市場拓展與下沉戰略研究報告
- 冷軋卷板企業縣域市場拓展與下沉戰略研究報告
- 直接還原鐵企業ESG實踐與創新戰略研究報告
- 彝文《指路經》課件
- 高考閱讀理解(main-idea)(課堂)課件
- 有限元分析研究匯報課件
- 境外貨物管控應急預案方案
- 江蘇省醫療服務項目價格標準
- 公司報廢申請單
- 高新區市政道路可行性研究報告
- TSSITS 2002-2022 低速無人駕駛清掃車安全規范
- 籍貫對照表完整版
- 個人理財分期還款計劃管理表1
- 畢業生就業推薦表word模板
評論
0/150
提交評論