電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 2563|回復(fù): 1
收起左側(cè)

卓越嵌入式培訓(xùn)機(jī)構(gòu)_嵌入式Linux字符設(shè)備驅(qū)動(dòng)的設(shè)計(jì)與應(yīng)用

[復(fù)制鏈接]

2607

主題

2607

帖子

7472

積分

高級(jí)會(huì)員

Rank: 5Rank: 5

積分
7472
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2020-8-18 14:41:29 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
卓越嵌入式培訓(xùn)機(jī)構(gòu)_嵌入式Linux字符設(shè)備驅(qū)動(dòng)的設(shè)計(jì)與應(yīng)用,   

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

1引言

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

2系統(tǒng)的設(shè)計(jì)框架

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

  

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

3系統(tǒng)字符設(shè)備驅(qū)動(dòng)程序的設(shè)計(jì)方法

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

3.1初始化函數(shù)與清除函數(shù)

Linux系統(tǒng)中,設(shè)備驅(qū)動(dòng)的初始化函數(shù)負(fù)責(zé)注冊(cè)設(shè)備,并完成驅(qū)動(dòng)程序必要的初始化以及申請(qǐng)中斷等[2],Linux系統(tǒng)使用 module_init宏指定初始化函數(shù)。在初始化函數(shù)中調(diào)用 regiSTer_chrdev函數(shù)向系統(tǒng)注冊(cè)字符設(shè)備,通過(guò) request_IRq 函數(shù)申請(qǐng)中斷。例如電機(jī)設(shè)備的初始化函數(shù)如下:

  static int __init moto_init(void){

  int ret;

  ret = register_chrdev(MOTO_MAJOR, “moto“, &moto_fops);//注冊(cè)電機(jī)設(shè)備

  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函數(shù)的第一個(gè)參數(shù)為主設(shè)備號(hào),如果為0 則系統(tǒng)為此驅(qū)動(dòng)程序動(dòng)態(tài)地分配一個(gè)主設(shè)備號(hào);第二個(gè)參數(shù)是設(shè)備名稱,這里是以moto為設(shè)備名稱;第三個(gè)參數(shù)moto_fops是默認(rèn)的struct file_operations結(jié)構(gòu)體 [3]。

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

3.2中斷

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

  

3.3 設(shè)備驅(qū)動(dòng)接口的實(shí)現(xiàn)

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

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

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

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

  case first_device: device_first_vaddr = (unsigned long)ioremap (DEVICE_ FIRST _ADDR, 2);嵌入式與軟件編程, qt4做嵌入式界面, 嵌入式硬件仿真軟件, 創(chuàng)建嵌入式圖表, 嵌入式概念問(wèn)題, 非嵌入式淘菜盆, 安卓嵌入式工程師, 嵌入式大作業(yè)期末, 嵌入式系統(tǒng)最新進(jìn)展, 嵌入式硬件技能, 嵌入式換電容怎么換, 嵌入式安全原件, 嵌入式燃?xì)獗? 嵌入式專題論文, 銀川嵌入式工程師, 華清遠(yuǎn)見(jiàn)嵌入式時(shí)間, 嵌入式軟件結(jié)構(gòu)圖像, 嵌入式馬桶怎么裝, 陽(yáng)臺(tái)吊頂嵌入式, 嵌入式驅(qū)動(dòng)加載模塊, 玄關(guān)嵌入式衣帽間, 嵌入式ip廣播主機(jī),

  ……

  case second_device:

  ……

  default:

  ……

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

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

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

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

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ě)數(shù)據(jù)給用戶空間

  return count; // 返回成功讀取的字節(jié)數(shù) }

其中,copy_to_user函數(shù)實(shí)現(xiàn)內(nèi)核空間到用戶空間的數(shù)據(jù)拷貝。應(yīng)用程序調(diào)用該方法接口實(shí)現(xiàn)串口數(shù)據(jù)的接收。

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

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

Linux驅(qū)動(dòng)程序的編譯加載有兩種方式。一種是編譯成模塊在運(yùn)行時(shí)加載,不需要重新啟動(dòng)內(nèi)核,它使用 insmod工具將驅(qū)動(dòng)模塊加載進(jìn)內(nèi)核,使用 rmmod從內(nèi)核中卸載模塊。該方法實(shí)現(xiàn)如下:1)編譯驅(qū)動(dòng)并下載驅(qū)動(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)驅(qū)動(dòng)的加載:$ insmod device_driver.o。設(shè)備驅(qū)動(dòng)的加載成功后,可以編寫(xiě)應(yīng)用程序進(jìn)行設(shè)備驅(qū)動(dòng)的檢測(cè);3)驅(qū)動(dòng)的卸載:$ rmmod device_driver。

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

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

4.1 Qt應(yīng)用程序的設(shè)計(jì)

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

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

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

  $mknod /dev/device_name c MAJOR MINOR

其中 device_name是設(shè)備節(jié)點(diǎn)名, c是字符設(shè)備標(biāo)志, MAJOR是主設(shè)備號(hào),MINOR是

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

4.2Qt應(yīng)用程序的運(yùn)行

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

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

  

5 總結(jié)

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

發(fā)表回復(fù)

本版積分規(guī)則

關(guān)閉

站長(zhǎng)推薦上一條 /1 下一條


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表