<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 嵌入式Linux字符設備驅動(dòng)的設計與應用

嵌入式Linux字符設備驅動(dòng)的設計與應用

作者: 時(shí)間:2012-02-20 來(lái)源:網(wǎng)絡(luò ) 收藏

摘要:描述了基于程序的方法和實(shí)現過(guò)程。以電機、數碼管、串口和mini鍵盤(pán)的驅動(dòng)為例,詳細闡述了linux下中的關(guān)鍵技術(shù),包括設備的設備號、設備的操作及設備的注冊和卸載等。通過(guò)編寫(xiě)相應硬件設備的程序,測試的正確性。介紹了Troolltech公司開(kāi)發(fā)的開(kāi)源圖形用戶(hù)界面庫-Qt,并使用Qt編程方法設計出良好的人機交互界面。試驗結果表明設計的驅動(dòng)程序完全正確,可以被程序使用。

本文引用地址:http://dyxdggzs.com/article/149619.htm

1引言

隨著(zhù)系統的發(fā)展,嵌入式 以其穩定性和開(kāi)放源代碼的優(yōu)點(diǎn)在嵌入式系統的開(kāi)發(fā)中得到廣泛。越來(lái)越多的軟硬件廠(chǎng)商使用嵌入式 來(lái)開(kāi)發(fā)自己的產(chǎn)品,對基于嵌入式 Linux平臺開(kāi)發(fā)設備的驅動(dòng)程序和應用程序的需求在成倍增長(cháng)。本文通過(guò)實(shí)現對 PXA255開(kāi)發(fā)板外圍設備(電機、數碼管、串口和 mini鍵盤(pán))的操作和控制,詳細討論了嵌入式 linux字符設備驅動(dòng)的設計與應用。

2系統的設計框架

系統的設計分為字符設備驅動(dòng)程序和人機交互界面兩部分。驅動(dòng)程序為應用程序提供了操作設備的接口;人機交互界面的設計實(shí)現設備應用程序并完成人機交互的功能。整個(gè)系統軟硬件的關(guān)系如圖 1:字符設備被映射到 Linux文件系統的文件和目錄,通過(guò)文件系統的系統調用接口 open(),write(),read(),close()等函數訪(fǎng)問(wèn)字符設備,實(shí)現設備的操作。

圖 1 系統軟硬件的關(guān)系

3系統字符設備驅動(dòng)程序的設計方法

Linux驅動(dòng)程序是設備與具體的應用程序的中間層,它提供操作設備的接口,應用程序員不需要知道具體設備工作細節,只要調用一組標準化的函數就能完成對設備的操作,這些標準化的函數與具體的驅動(dòng)沒(méi)有關(guān)系,而將這些函數映射到作用于具體設備上的操作則與驅動(dòng)程序相關(guān)[1]。Linux設備分為字符設備,塊設備和網(wǎng)絡(luò )設備,字符設備是能夠像字節流一樣被訪(fǎng)問(wèn)的設備。以下通過(guò)描述字符設備(電動(dòng)機、數碼管、串口、mini鍵盤(pán))驅動(dòng)的實(shí)現方法,深入討論了基于嵌入式 linux的字符設備驅動(dòng)的設計方法和實(shí)現過(guò)程。

3.1初始化函數與清除函數

Linux系統中,設備驅動(dòng)的初始化函數負責注冊設備,并完成驅動(dòng)程序必要的初始化以及申請中斷等[2],Linux系統使用 module_init宏指定初始化函數。在初始化函數中調用 regiSTer_chrdev函數向系統注冊字符設備,通過(guò) request_IRq 函數申請中斷。例如電機設備的初始化函數如下:

  static int __init moto_init(void){

  int ret;

  ret = register_chrdev(MOTO_MAJOR, moto, moto_fops);//注冊電機設備

  if (ret) {

  printk(KERN_ERR %s: can't get major %d.n,

  __func__, MOTO_MAJOR);

  return ret;

  }

  printk(KERN_INFO %s: register moto device successfully.n, __func__);

  return 0;

  } 其中,register_chrdev函數的第一個(gè)參數為主設備號,如果為0 則系統為此驅動(dòng)程序動(dòng)態(tài)地分配一個(gè)主設備號;第二個(gè)參數是設備名稱(chēng),這里是以moto為設備名稱(chēng);第三個(gè)參數moto_fops是默認的struct file_operations結構體 [3]。

清除函數的功能和初始化函數的功能相反,它將驅動(dòng)程序所占用的系統資源、中斷號進(jìn)行釋放。Linux系統使用 module_exit宏指定清除函數。

3.2中斷

在 Linux 系統中,中斷是由系統來(lái)管理與維護的。中斷服務(wù)子程序在初始化函數中調用 request_irq 函數與相應中斷號關(guān)聯(lián),并將該中斷的相關(guān)信息添加到系統的中斷信息列表中。中斷發(fā)生時(shí), Linux系統響應中斷號來(lái)實(shí)現中斷處理程序的執行。mini鍵盤(pán)按鍵觸發(fā)產(chǎn)生中斷號為 SIMPLE_KEY_IRQ的中斷,系統自動(dòng)檢索并調用鍵盤(pán)中斷服務(wù)子程序。鍵盤(pán)中斷處理流程如圖 2:

3.3 設備驅動(dòng)接口的實(shí)現

在Linux內核中,字符設備使用 struct file_operations結構體來(lái)實(shí)現設備的各種操作接口,這些操作主要用來(lái)實(shí)現系統調用,命名為 open、read等等。file_operations結構是定義在 linux/fs.h>中的函數指針數組,每個(gè)設備文件都與它自己的操作函數相關(guān)聯(lián)。編寫(xiě)字符設備驅動(dòng)程序,主要是實(shí)現 struct file_operations結構中的各個(gè)函數。

本系統各設備驅動(dòng)的設計主要實(shí)現 open、read、write和 release這四個(gè)方法接口。 file_operation結構成員如下: /* DEVICE驅動(dòng)程序設備操作方法集 */ struct file_operations device_fops = {

open方法提供給驅動(dòng)程序以初始化的能力,從而為以后的操作完成初始化做準備。本系統中存在多個(gè)設備共用一個(gè)驅動(dòng)的情況,驅動(dòng)中的 open方法程序框架如下:

  int device_open(struct inode *inode, struct file *filp){ int minor = MINOR(kdev); //次設備號的讀取 switch(minor) {

  case first_device: device_first_vaddr = (unsigned long)ioremap (DEVICE_ FIRST _ADDR, 2);

  ……

  case second_device:

  ……

  default:

  ……

  } MOD_INC_USE_COUNT; // 遞增模塊引用計數 , 防止模塊在使用中被卸載 if (down_interruptible(device_mutex)) { …… }; }

1)open方法調用 MINOR(kdev)宏實(shí)現次設備號的讀取,使用 switch語(yǔ)句完成設備的匹配初始化。Linux系統為每一個(gè)設備分配了一個(gè)主設備號和次設備號。主設備號標識具體的設備驅動(dòng)程序,次設備號標識具體設備。開(kāi)發(fā)板電機設備有直流電機和步進(jìn)電機,它們的主設備號都是 252,次設備號分別為 0和 1。數碼管、串口、 mini鍵盤(pán)的驅動(dòng)設計只針對單個(gè)設備,次設備號設計為 0。

2)ioremap函數在 open方法中實(shí)現對電機、數碼管、串口、mini鍵盤(pán)寄存器的訪(fǎng)問(wèn)。 PXA255處理器有專(zhuān)門(mén)的存儲器管理單元(MMU),在驅動(dòng)中不能直接對設備 I/O內存的物理地址進(jìn)行讀寫(xiě),需要調用ioremap 等內核函數將寄存器的實(shí)際物理地址映射到內核統一的地址空間中,從而實(shí)現了對物理地址的間接調用。例如寄存器 DEVICE_ FIRST _ADDR的讀寫(xiě)操作,通過(guò)讀寫(xiě) device_first_vaddr變量實(shí)現。在 asm/arch/pxa-regs.h頭文件中定義了各種寄存器的宏,文件中的宏變量都是經(jīng)過(guò)地址映射的可以直接使用。

release方法的作用正好與 open相反,通過(guò)調用 iounmap函數撤銷(xiāo) device設備的虛擬地址映射,同時(shí)釋放互斥鎖,遞減模塊引用計數,當模塊引用計數減到 0時(shí),close函數才能真正的關(guān)閉設備。read和 write方法的任務(wù)是相似的,主要完成用戶(hù)空間和內核空間之間的數據拷貝。

read方法程序框架如下:

  ssize_t device_read(struct file *filp, char *buf, size_t count, loff_t *offp){

  ……

  if (copy_to_user(buf, (u8 *)BUF, count)) { ……} //寫(xiě)數據給用戶(hù)空間

  return count; // 返回成功讀取的字節數 }

其中,copy_to_user函數實(shí)現內核空間到用戶(hù)空間的數據拷貝。應用程序調用該方法接口實(shí)現串口數據的接收。

write方法的實(shí)現同read方法類(lèi)似。通過(guò)調用 copy_from_user函數實(shí)現用戶(hù)空間到內核空間的數據拷貝。該方法接口實(shí)現串口數據的發(fā)送、LED和MOTO控制寄存器的設置。

3.4 驅動(dòng)的裝載和卸載

Linux驅動(dòng)程序的編譯加載有兩種方式。一種是編譯成模塊在運行時(shí)加載,不需要重新啟動(dòng)內核,它使用 insmod工具將驅動(dòng)模塊加載進(jìn)內核,使用 rmmod從內核中卸載模塊。該方法實(shí)現如下:1)編譯驅動(dòng)并下載驅動(dòng)到開(kāi)發(fā)板:$ arm-linux-gcc device_driver.c -I /home/eflag/kernel/include/ -c生成 device_driver.o文件,通過(guò) tftp工具下載到開(kāi)發(fā)板;2)驅動(dòng)的加載:$ insmod device_driver.o。設備驅動(dòng)的加載成功后,可以編寫(xiě)應用程序進(jìn)行設備驅動(dòng)的檢測;3)驅動(dòng)的卸載:$ rmmod device_driver。

另一種是將驅動(dòng)程序靜態(tài)編譯進(jìn)內核,再運行新的內核來(lái)測試驅動(dòng),該方法是在linux系統字符設備驅動(dòng)文件夾linux/driver/char/中加入設備驅動(dòng)源程序,同時(shí)修改 makefile文件,重新編譯內核,下載新內核到開(kāi)發(fā)板,系統啟動(dòng)后自動(dòng)加載設備驅動(dòng) [3]。在驅動(dòng)加載成功后就可以對該驅動(dòng)的設備進(jìn)行讀寫(xiě)等操作。 4 Qt人機界面的實(shí)現

Qt是由 Troolltech公司開(kāi)發(fā)的一套開(kāi)源圖形用戶(hù)界面庫。它給應用程序開(kāi)發(fā)者提供了開(kāi)發(fā)圖形界面所需的各種功能。Qtopia core是嵌入式環(huán)境下所使用的 Qt,很多嵌入式產(chǎn)品如 PDA、手機都采用 qtopia core的圖形庫作為人機界面設計的框架。本系統使用 qtopia core的圖形庫進(jìn)行用戶(hù)界面的開(kāi)發(fā)。

4.1 Qt應用程序的設計

Qt的事件驅動(dòng)機制是 single/slot(信號/槽)機制,通過(guò) connect函數連接控件信號(Single)與槽函數(slot)。首先控件觸發(fā)產(chǎn)生 Single信號,然后由 signal信號觸發(fā)執行槽函數[4]。本系統中槽函數為具體設備應用程序。

設備應用程序的開(kāi)發(fā)主要是系統函數的調用,如 open(打開(kāi)設備),read/write(讀寫(xiě)設備),close(關(guān)閉設備)等。本系統設備應用程序開(kāi)發(fā)如下: RS232收發(fā)數據功能; LED跑馬燈功能;操控電機轉動(dòng)功能;mini鍵盤(pán)鍵值讀取功能。

Linux系統中設備作為文件被訪(fǎng)問(wèn),對設備進(jìn)行訪(fǎng)問(wèn)前需建立設備節點(diǎn):

  $mknod /dev/device_name c MAJOR MINOR

其中 device_name是設備節點(diǎn)名, c是字符設備標志, MAJOR是主設備號,MINOR是

次設備號。open函數使用/dev/device_name作為文件路徑來(lái)打開(kāi)設備。

4.2Qt應用程序的運行

1)編譯 Qtopia core應用程序生成可執行文件 application。通過(guò) tftp工具下載可執行文件到開(kāi)發(fā)板;2)開(kāi)發(fā)板中 application可執行文件的運行: $ chomd +x application $ ./application –qws。

LCD顯示器顯示人機交互界面如圖 3,通過(guò)輸入設備如鼠標、鍵盤(pán)、觸摸屏可以完成設備的操作。

5 總結

實(shí)現了電機、數碼管、串口和 mini鍵盤(pán)的驅動(dòng)程序和應用程序的開(kāi)發(fā),設計了人機交互界面。本文作者創(chuàng )新點(diǎn):詳細分析了嵌入式 Linux下字符設備驅動(dòng)程序的構建過(guò)程。整個(gè)系統的設計和實(shí)現過(guò)程對嵌入式 Linux系統的開(kāi)發(fā)有一定的參考價(jià)值。

linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)

linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)

linux相關(guān)文章:linux教程




評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>