linux系統和驅動中按鍵驅動的編寫詳解

2020-11-23 電子發燒友

我們改了compitable的內容,同時要關注inerrupts,xlnx,all-inputs,xlnx,gpio-width這些屬性。Gpio-width是寬度,all-inputs是表示為輸入。

設備樹修改完後就可以編譯設備樹文件,然後用fsbl,u-boot,設備樹來製作boot.bin了。放到SD卡,啟動linux系統。接下來進入關鍵環節,key驅動的編寫。

2. 按鍵驅動代碼剖析

對於一個剛剛入門的人來說,其實了解了驅動的基本框架就好了。每個驅動都按照它的框架進行編寫和修改。能理解驅動的各個模塊功能,在驅動調試或者編寫中就能有的放矢。一個簡單的驅動的構成也很複雜,代碼也很多,篇幅有限,我只介紹主要部分。

1)platform框架

Platform是一種虛擬的平臺,提供了驅動和具體硬體交互的接口。Platform_device類似於虛擬的總線,IIC,LCD,GPIO等外設都可以看做platform_device,通過它可以遍歷所有的總線設備,而對應的驅動就是platform_driver。基本流程是:先註冊platform_device,再註冊platform_driver,然後匹配設備和驅動,最後註冊整個驅動。

在linux3以前的版本,需要定義platform_device結構體,然後通過platform_device_register函數來註冊設備。但是linux3.0以後出現了設備樹,內核函數of_platform_default_populate_init會在內核啟動後遍歷設備樹,自動註冊每個節點對應的設備。因此只需要修改設備樹參數就行了。首先看這個結構體:

static const struct of_device_id key_of_match[] __devinitdata={ {.compatible="xlnx,gpio-keys",}, {/*end of list*/},};

這實際上定義了設備的匹配號,compatible就是在設備樹節點axi-gpio中對應的節點匹配名稱。我們只要讓compitable和設備樹中對應節點的值匹配上就可以將節點對應的設備註冊到總線上了。

platform_driver用於對設備的搜索和配置,主要就是去解析設備樹,根據設備樹中節點信息來填充設備結構體對應信息或者直接對設備完成配置。

static struct platform_driver key_driver={ .driver={ .name=DRIVER_NAME, .owner=THIS_MODULE, .of_match_table=key_of_match, }, .probe=key_probe, .remove=key_remove,};

我們主要關注其三個變量,of_match_table就是of_device_id結構體定義的,用來匹配節點。Probe函數用來解析節點,配置設備。Remove主要是釋放在probe中使用的資源等。

編寫key驅動主要就是去填充probe和remove兩個函數。

來看probe函數是如何查找到設備的一些屬性的,比如我們要確定key鍵的數量,那麼我們可以這樣來做:

if(of_property_read_u32(node, "xlnx,gpio-width", &width)){ printk(KERN_ERR "get the gpio-width/n"); }

通過匹配「xlnx,gpio-width」來獲得key的位寬,這個屬性就在設備中定義的。

如果我們要操作key,需要獲得key設備的內存映射空間,這個可以通過函數platform_get_resource函數來完成。

mem=platform_get_resource(pdev, IORESOURCE_MEM, 0); if(!mem){ printk(KERN_ERR "get memory resource/n"); return -ENODEV; }

第一個參數pdev是platform_device結構體,在進入probe函數之前就已經被註冊了,其指向的就是key對應的設備。第二個參數是類型,主要有IORESOURCE_MEM, IORESOURCE_IRQ等。最後一個參數是號碼,指示platform_device結構體中不同的資源類型,即IORESOURCE類型。

以上獲得的mem就是在設備樹中由reg指定的內存映射:

reg = <0x41210000 0x10000>;

中斷的獲得可以通過函數:

r_irq=irq_of_parse_and_map(node, 0); if(!r_irq){ printk(KERN_ERR "get interrupt/n"); }

其中device_node就是設備節點,在platform_device註冊的時候,含有該節點,所以可以通過該結構體獲得。第二個參數表示一個設備樹節點有多個中斷時的索引。

通過設備樹獲得了硬體信息後,我們將其填充到key_device中,key_device定義如下:

struct key_dev{ struct cdev dev; struct work_struct work; int irq; int major; unsigned long start_addr; unsigned long size; void __iomem *baseaddr; int width; int inout; int key_prs;};

其中irq為中斷號,cdev是字符設備結構體,因為key等屬於字符設備。填充如下:

lp->start_addr=mem->start; lp->size=mem->end-mem->start; lp->irq=r_irq; lp->width=width;

2)中斷處理

在platform中我們談到了對中斷號的獲取,那麼取得了中斷號之後如何來檢測中斷事件呢?中斷處理過程可以被分成兩部分:頂半部和底半步。頂半部主要處理硬體上比較緊急的事物,比如檢測中斷,底半部用於處理中斷產生之後需要進行的事務處理。在底半部處理過程中不會耽誤檢測下一個中斷。這兩個部分不是絕對的,也可以只有一個部分。

驅動中首先需要定義一個中斷函數,用於中斷產生後進行的操作。然後申請中斷,實現函數:

err=request_irq(k_dev->irq,key_interrupt, IRQF_SHARED|IRQF_TRIGGER_RISING, DRIVER_NAME, k_dev);

第一個是中斷號,第二個為中斷處理函數,第三個參數為中斷產生類型,上升沿下降沿一類,第四個為名字,可以命名中斷,最後一個是設備結構體。

釋放中斷就通過free_irq(unsigned int irq, void *dev_id)來完成。

實現中斷底半部處理機制主要有tasklet,工作隊列,軟中斷和線程化irq。中斷機制較為複雜,任何一種機制都可以讓你竭盡腦汁。入門者還是循序漸進,所以我也只用了一種簡單的方法。類似鎖機制,我們定義一個事件:

static DECLARE_WAIT_QUEUE_HEAD(press_queue);

然後在中斷函數中喚醒這個事件,在其他函數中可以通過等待這個事件來進行中斷處理。我們的中斷函數為:

static irqreturn_t key_interrupt(int irq, void *dev_id){ struct key_dev *dev=dev_id; dev->key_prs++; printk(KERN_INFO "interruptted/n"); wake_up_interruptible(&press_queue); return IRQ_HANDLED;}

而等待該事件放在key_read函數中:

ssize_t key_read(struct file *filp, char __user *buf, size_t count, loff_t *fops){ int err; struct key_dev *dev=filp->private_data; wait_event_interruptible(press_queue, event_press); event_press=0; err=copy_to_user(buf, &dev->key_prs, count); return err ? -EFAULT : 0;}

3)文件結構

Linux一切皆文件,任何驅動最終都被封裝為一個文件,用戶空間通過讀寫文件來操作驅動。文件操作包括打開,關閉,讀和寫等。我們不做具體介紹,簡單列出文件結構體為:

struct file_operations key_fops={ .owner=THIS_MODULE, .open=key_open, .read=key_read, .release=key_close,};

總結

對以上進行總結就是:
1) 首先進行設備樹節點屬性修改;
2) 填充platform框架下的probe,remove等函數,並定義of_device_id和platform_driver結構體;
3) 申請中斷,釋放中斷,編寫中斷函數等;
4) 填充文件結構,編寫open,close,read等函數;

編輯:hfy

相關焦點

  • Linux內核學習:簡單的字符設備驅動
    學習Linux內核最好的入門方式之一是從字符設備驅動開始模仿(來自於《奔跑吧 Linux內核——入門篇》)。對於我們日常生活中存在的大量設備,如攝像頭,USB充電器,藍牙,Wi-Fi等,這些設備在電氣特性和實現原理均不相同,對Linux系統來說如何抽象和描述他們呢?Linux很早就根據設備共同特徵將其劃分為三大類型:1,字符設備;塊設備;網絡設備。
  • 從串口驅動到Linux驅動模型,想轉Linux的必會!
    本文通過對Linux下串口驅動的分析。由最上層的C庫。到作業系統系統調用層的封裝。再到tty子系統的核心。再到一系列線路規程。再到最底層的硬體操作。對Linux中的tty子系統進行簡要的說明。從理論到實踐。以便讀者能對OS原理有更深入的了解和更具體的掌握。在具體分析之前。我們必須對串口。驅動。和Linux作業系統有一定的了解。
  • 「正點原子Linux連載」第五十八章Linux INPUT子系統實驗
    本章我們就來學習一下Linux內核中的input子系統。58.1 input子系統58.1.1input子系統簡介input就是輸入的意思,因此input子系統就是管理輸入的子系統,和pinctrl和gpio子系統一樣,都是Linux內核針對某一類設備而創建的框架。
  • 「正點原子Linux連載」第五十九章Linux LCD驅動實驗
    第五十九章Linux LCD驅動實驗LCD是很常用的一個外設,在裸機篇中我們講解了如何編寫LCD裸機驅動,在Linux下LCD的使用更加廣泛,在搭配QT這樣的GUI庫下可以製作出非常精美的UI界面。本章我們就來學習一下如何在Linux下驅動LCD屏幕。
  • 「正點原子Linux連載」第四十二章新字符設備驅動實驗
    register_chrdev和unregister_chrdev這兩個函數是老版本驅動使用的函數,現在新的字符設備驅動已經不再使用這兩個函數,而是使用Linux內核推薦的新字符設備驅動API函數。本節我們就來學習一下如何編寫新字符設備驅動,並且在驅動模塊加載的時候自動創建設備節點文件。
  • win10系統的驅動管理在哪
    驅動程序是硬體廠商根據作業系統編寫的配置文件,沒有驅動程序,計算機中的硬體就無法正常工作。那麼我們要怎麼查看win10系統電腦中已安裝的驅動程序呢?其實很簡單,今天小編就和大家分享win10系統查看管理已安裝的驅動的方法。
  • NTFS Linux驅動升級:現支持更好的壓縮處理
    今年 Linux Kernel 領域比較出人意外的一件事就是 Paragon Software 希望上遊他們的「NTFS3」內核驅動,以支持在微軟的 NTFS 文件系統中進行讀寫操作,並且比現有的以讀取為重點的NTFS內核功能更強大。
  • Linux基礎教程:CentOS開機流程詳解
    (Basic Input Output System)基本輸入輸出系統,它是一組固化到計算機內主板上一個ROM晶片 上的程序,保存著計算機最重要的基本輸入輸出的程序、開機後自檢程序和系統自啟動程序,可從CMOS中讀寫系統設置的具體信息。
  • CF的AWM 雷柏VT30幻彩遊戲滑鼠驅動詳解
    近日,領軍國產外設品牌,實力大廠上市企業——Rapoo雷柏為旗下高端電競VT系列推出了VT30幻彩RGB遊戲滑鼠,配套的強大驅動讓滑鼠的性能得到更強的發揮。約1680萬色的幻彩RGB背光,PMW3327不可見光傳感器給予了7檔DPI,特別是遊戲滑鼠至關重要的宏定義功能,也是應有盡有。而這些都可以通過驅動來一併掌控。本文將對強大的宏定義功能以及燈光系統等功能做出詳盡描述。
  • vxworks和linux有什麼區別
    server關係,這種服務並不一定非得留在內核中,它本身也可以被設計實現成「服務進程」,其中必須留在內核中的部分只有進程間的通信,如果把這些服務從內核轉移到進程的層次上,那麼內核本身的結構就可以大大減小和減化,而各個服務進程也可以單獨設計、實現及調試。
  • 女武神驅動比丘尼按鍵操作說明 作業系統介紹
    其實不難,今天這篇文章就來給大家講一講女武神驅動比丘尼的按鍵操作,方便大家快速上手遊戲。設置 Save Delete 刪除存檔 Exit 退出 NEW GAME 開始新遊戲 CONTINUE 繼續遊戲(讀取存檔)   操作介紹   鍵鼠 按鍵
  • 電腦系統安裝第四步:安裝系統和驅動
    1、系統的安裝,要提前把下載好的原版系統放到U盤裡,建議放到根目錄,減少出錯的可能。就在PE裡面找到U盤裡的系統,點滑鼠右鍵,選擇「裝載」後就可以看到下圖這些文件,雙擊setup.exe開始安裝系統。經驗總結:我個人裝系統的時候是把BIOS裡的啟動順序設置為硬碟為第一啟動,USB設置為第二啟動,然後進PE的時候用的是選擇啟動項的快捷鍵,再選擇U盤啟動,這樣系統安裝過程中自動重啟就不用拔U盤了,不用總是一直盯著。
  • Windows 10正式採用全新驅動系統:不再自動下載安裝可選驅動
    從今天開始,微軟正式採用新的驅動分發系統。新的驅動系統將改變Windows 10 2004版(2020年5月更新版)及今後版本中Windows Update針對「自動」和「手動」驅動更新的方式。我們先來了解一下Windows Update中的驅動分發方法:當驅動廠商向Windows Update提交驅動時,微軟「驅動程序分發選項」會顯示兩個單選按鈕:「自動」和「手動」。在「自動」選項下,還有兩個複選框:在Windows升級期間自動分發、自動分發到所有適用的系統。
  • 一鍵重裝系統後怎麼安裝驅動
    當我們的計算機驅動程序出現故障時,計算機的某些硬體或程序將無法運行。那麼,是否有任何軟體可以一鍵式重新安裝驅動程序?以下系統總裁將與您分享怎麼使用驅動程序工具來一鍵式重新安裝系統驅動。驅動程序嚮導包含許多功能,並且更準確的檢測和升級功能要求計算機具有正常的Internet連接。1)首先我們現搜索下載該款工具,然後安裝完成之後進行打開驅動程序嚮導,然後單擊立即檢測。2)驅動程序嚮導可以檢測計算機中哪些驅動程序有問題,並可以安裝和更新驅動程序。
  • 電腦系統萬能驅動怎麼安裝
    驅動精靈是一款集驅動管理和硬體檢測於一體的驅動管理和維護工具,通過硬體檢測技術,能夠智能識別計算機硬體,匹配相應驅動程序並提供快速的下載與安裝,為用戶提供驅動備份、恢復等實用功能。下面就和大家介紹一下驅動精靈的安裝方法。
  • Linux中你分得清什麼是終端,控制臺,外殼程序和內殼嗎?
    隨著現代計算機的發明,我們有了名為「 Terminal」的應用程式,只需單擊即可打開它,但是在80年代,它以前被稱為「 Terminal Emulators」,它不是軟體程序而是硬體,是一種常規輸入輸出設備,由鍵盤和監視器組成。終端的目的不是要處理信息(像典型的計算機一樣),而是將命令發送到另一個系統。
  • 2020 年的 Linux 內核仍為蘋果 Macintosh II 修復驅動
    Linux 內核正在對其驅動程序進行一些修復和改進工作,以更好地支持 Macintosh II 系統上的 Apple Desktop Bus(蘋果桌面總線)。隔一段時間就能看到 Linux 內核驅動對 Apple PowerBook 100 系列產品支持的改進。
  • win10系統顯卡驅動安裝失敗怎麼辦
    大家好,今天分享一篇來自小白系統官網(xiaobaixitong.com)的圖文教程。我們日常在對電腦的使用過程中,經常都會遇到這樣或那樣的問題。比如說win10系統顯卡驅動安裝失敗該怎麼辦呢?別著急,還有小編在呢?
  • 英偉達:將不再為 32 位 Windows/Linux/FreeBSD 提供驅動程序
    IT之家12月22日消息 近日英偉達宣布將終止對32位Windows、Linux和FreeBSD作業系統的驅動程序支持。Build 390將成為英偉達為32位作業系統所發布的驅動程序的最後一個版本。
  • 提高電機驅動系統能效的工業電機控制系統方案
    電機在現代生活中無處不在,從氣候控制、電器和商業製冷到汽車、工廠和基礎設施。根據國際能源署(International Energy Agency)的數據,電機佔全球總電力消耗的45%,因此電機驅動電子產品的可靠性和能效會對世界各地及各種應用的舒適性、便利性和環境產生影響。 一種提高電機驅動系統能效的方法是,用變速驅動器代替在50 / 60 Hz交流線路電壓下驅動的單速電機,從而實現電機的電子速度控制和更高的驅動能效。