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