基于S3C2410微處理器的觸摸屏設(shè)計(jì)
TS_RET結(jié)構(gòu)體中的信息就是驅(qū)動(dòng)程序提供給上層應(yīng)用程序使用的信息,用來存儲(chǔ)觸摸屏的返回值。上層應(yīng)用程序通過讀接口,從底層驅(qū)動(dòng)中讀取信息,并根據(jù)得到的值進(jìn)行其他方面的操作。
TS_DEV結(jié)構(gòu)用于記錄觸摸屏運(yùn)行的各種狀態(tài),PenStatus包括PEN_UP、PEN_DOWN和PEN_FLEETING。buf[MAX_TS_BUF]是用來存放數(shù)據(jù)信息的事件隊(duì)列,head、tail分別指向事件隊(duì)列的頭和尾。程序中的筆事件隊(duì)列是一個(gè)環(huán)形結(jié)構(gòu),當(dāng)有事件加入時(shí),隊(duì)列頭加一,當(dāng)有事件被取走時(shí),隊(duì)列尾加一,當(dāng)頭尾位置指針一致時(shí)讀取筆事件的信息,進(jìn)程會(huì)被安排進(jìn)入睡眠。wq等待隊(duì)列,包含一個(gè)鎖變量和一個(gè)正在睡眠進(jìn)程鏈表。當(dāng)有好幾個(gè)進(jìn)程都在等待某件事時(shí),Linux會(huì)把這些進(jìn)程記錄到這個(gè)等待隊(duì)列。它的作用是當(dāng)沒有筆觸事件發(fā)生時(shí),阻塞上層的讀操作,直到有筆觸事件發(fā)生。lock使用自旋鎖,自旋鎖是基于共享變量來工作的,函數(shù)可以通過給某個(gè)變量設(shè)置一個(gè)特殊值來獲得鎖。而其他需要鎖的函數(shù)則會(huì)循環(huán)查詢鎖是否可用。MAX_TS_BUF的值為16,即在沒有被讀取之前,系統(tǒng)緩沖區(qū)中最多可以存放16個(gè)筆觸數(shù)據(jù)信息。
s3c2410_fops就是內(nèi)核對(duì)驅(qū)動(dòng)的調(diào)用接口,完成了將驅(qū)動(dòng)函數(shù)映射為標(biāo)準(zhǔn)接口。上面的這種特殊表示方法不是標(biāo)準(zhǔn)C的語法,而是GNU編譯器的一種特殊擴(kuò)展,它使用名字進(jìn)行結(jié)構(gòu)字段的初始化,它的好處體現(xiàn)在結(jié)構(gòu)清晰,易于理解,并且避免了結(jié)構(gòu)發(fā)生變化帶來的許多問題。
init_module函數(shù)
這是模塊的入口函數(shù)。在函數(shù)內(nèi)部通過s3c2410_ts_init( )實(shí)現(xiàn)模塊的初始化工作。在本設(shè)計(jì)中設(shè)備與系統(tǒng)之間以中斷方式進(jìn)行數(shù)據(jù)交換。整個(gè)觸摸屏的驅(qū)動(dòng)程序處理比較復(fù)雜,而且耗時(shí)較長,因而觸摸屏驅(qū)動(dòng)程序不可能在中斷服務(wù)程序中完成。在Linux操作系統(tǒng)中一般把中斷處理切為兩個(gè)部分或兩半。中斷處理程序是上半部——接收到一個(gè)中斷,它就立即開始執(zhí)行,但只做有嚴(yán)格時(shí)限的工作,例如對(duì)接收的中斷進(jìn)行應(yīng)答或復(fù)位硬件。這些工作都是在所有中斷被禁止的情況下完成的,能夠被允許稍后完成的工作會(huì)推遲到下半部去。在Linux中下半部的實(shí)現(xiàn)有多種機(jī)制。按觸摸屏?xí)r,從ADS7843輸出的數(shù)值有一個(gè)抖動(dòng)過程,即從ADS7846輸出的數(shù)值有一個(gè)不穩(wěn)定時(shí)期,這個(gè)過程大約為10ms。所以中斷處理程序的下半部處理函數(shù)采用內(nèi)核定時(shí)器機(jī)制,使下半部在中斷發(fā)生50ms后再作處理。這樣有效地避開了ADS7843輸出值的不穩(wěn)定時(shí)期,使中斷服務(wù)程序和中斷處理任務(wù)串行化,達(dá)到了處理時(shí)間較長的觸摸屏事件的目的。驅(qū)動(dòng)程序通過request_irq函數(shù)注冊(cè)并激活一個(gè)中斷處理程序,以便處理中斷。
圖2 設(shè)備驅(qū)動(dòng)在內(nèi)核中的掛接、卸載和系統(tǒng)調(diào)用過程
int reguest_irq(unsigned int irq, void(*handler)(int, void *, struct pt_regs *), unsigned long irq_flags, const char *dev_name, void *dev_id)
參數(shù)irq表示所要申請(qǐng)的中斷號(hào);handler為向系統(tǒng)登記的中斷處理子程序,中斷產(chǎn)生時(shí)由系統(tǒng)來調(diào)用;dev_name為設(shè)備名;dev_id為申請(qǐng)時(shí)告訴系統(tǒng)的設(shè)備標(biāo)識(shí)符;irq_flags是申請(qǐng)時(shí)的選項(xiàng),它決定中斷處理程序的一些特性,其中最重要的是中斷處理程序是快速處理程序還是慢速處理程序。
本設(shè)計(jì)中觸摸屏控制器ADS7843的中斷輸出通過外部中斷5接在中斷控制器上,當(dāng)觸摸屏上有觸摸事件發(fā)生時(shí),會(huì)引發(fā)中斷號(hào)為IRQ_EINT5的中斷服務(wù)程序s3c2410_isr_tc()。圖3所示為該中斷處理程序的流程圖。
圖3 觸摸屏硬件中斷處理程序流程圖
在s3c2410_isr_tc()中設(shè)定了定時(shí)器的定時(shí)時(shí)間為50ms,并立即激活。因此有觸摸屏硬件中斷的情況下50ms后就會(huì)引發(fā)定時(shí)中斷,中斷服務(wù)程序?yàn)閠s_timer_handler(),這個(gè)程序?qū)崿F(xiàn)了觸摸屏中斷的下半部,即在過了抖動(dòng)時(shí)間之后如果觸摸屏確實(shí)有有效事件發(fā)生則采集觸摸屏坐標(biāo),并將定時(shí)器的時(shí)間重新設(shè)為100ms并重新激活,這樣做的目的是如果觸摸筆是拖動(dòng)的情況,以后每100ms采集一次坐標(biāo)值,并存入緩沖區(qū),如果不是拖動(dòng)在采集一次坐標(biāo)值之后,在第二次進(jìn)入ts_timer_handler()時(shí),查詢管腳的狀態(tài)值,則變?yōu)楦唠娖?就將觸摸屏狀態(tài)tsdev.PenStatus設(shè)為PEN_UP,并釋放定時(shí)器,為下次觸摸屏事件做好準(zhǔn)備,定時(shí)中斷服務(wù)程序流程圖如圖4所示。
評(píng)論