LINUX 中斷子系統專欄之二 虛擬中斷控制器驅動實現

2020-08-29 jerry的編程路

在上一篇文章中,我們簡要分析了中斷子系統框架,本章我們將通過實現一個虛擬的中斷控制器驅動,說明如何進行中斷控制器驅動開發。本章的內容大概分為如下幾部分:

一、實現虛擬中斷控制器的可行性說明

二、中斷控制器驅動的開發流程

三、虛擬中斷控制器驅動設計說明

一、實現虛擬中斷控制器的可行性說明

在進行虛擬中斷控制器的設計之前,我們先說明下linux系統中硬體中斷觸發後的處理過程。如下圖所示,當硬體中斷觸發後,各架構的CPU板級代碼經過處理後,大都會調用do_IRQ/generic_handle_irq接口,從而調用具體irq_desc的irq flow handler接口,進行中斷處理函數的調用等工作。基於此,我們可以提供操作接口調用generic_handle_irq,從而模擬硬體中斷觸發,實現中斷處理流程的觸發操作,這是我們實現虛擬中斷控制器的理論基礎。

二、中斷控制器驅動的開發流程

在提供了模擬硬體中斷觸發的機制後,我們再確認下中斷控制器驅動的開發流程,主要分為如下幾個部分:

  1. 為該中斷控制器的所有hw irq line,均創建對應的irq_desc(因為我是在ubuntu16.04上開發的虛擬中段控制器驅動,並沒有提供設備樹支持,因此在驅動開發時完成了所有irq_desc的申請,如使用設備樹開發的話,則無須申請所有的irq_desc。當有外設用到其中的一個hw irq line時,則在該設備的設備節點中引用對應的hw irq index及該hw irq index對應controller的設備節點名即可,然後在外設的驅動中調用irq_of_parse_and_map接口即可(而在該接口中若檢測到該hw irq line尚未創建irq_desc,則進行irq_desc的創建,同時在該hw irq所屬的irq domain中,完成hw irq index與logic irq index的映射)。設備樹這種方式確實很好,僅在hw irq被使用時方進行irq_desc的創建及註冊操作);
  2. 為該irq controller 提供操作接口,即完成struct irq_chip類型變量的定義及賦值,主要包括中斷的使能控制、中斷觸發方式的設置等等;
  3. 為該中斷控制器創建irq domain,以便存儲該irq controller的hw irq line與logic irq index的映射關係,並完成該irq_desc與irq_chip、irq flow handler的map操作操作等。

三、虛擬中斷控制器驅動設計說明

有了以上的基礎後,我們即可以進行虛擬中斷控制器驅動的開發,以便了解中斷控制器驅動的開發流程。

虛擬中斷控制器型號介紹與說明

本次我們開發的虛擬中斷控制器包含兩個型號virt0808、virt0813,這兩個中斷控制器均提供16個hw irq line。然後這兩個中斷控制器級聯在一起(virt0813連接至virt0808的第16個中斷號,virt0808作為root controller),連接方式如下圖所示。

這兩個中斷控制器均提供如下幾個寄存器:

  1. 中斷狀態寄存器(status reg);
  2. 中斷使能寄存器(mask reg);
  3. 中斷電平觸發控制寄存器(level reg);
  4. 中斷邊沿觸發控制寄存器(edeg reg)

以上即為虛擬中斷控制器的主要內容,下面為這兩個中斷控制器進行驅動開發。

虛擬中斷控制器驅動開發設計

針對虛擬中斷控制器驅動,主要包括如下幾步部分內容:

  1. 提供virt0808虛擬中斷控制器驅動,並在sysfs目錄下創建屬性文件irq_trigger,供應用程式模擬觸發硬體中斷;
  2. 提供外設驅動,申請中斷,作為對虛擬中斷的驗證。

相關的數據結構

針對virt0808,定義數據結構virt_irq_provider,主要的成員包括:

  1. 存儲應用程式設置的模擬觸發中斷的hw irq line index(irq_trigger_value);
  2. 定義struct irq_work類型的變量work,主要用於觸發irq中斷使用;
  3. 該irq控制器的logic irq base id,及hw irq line的個數;
  4. 該irq controller的寄存器;
  5. 該irq controller對應的irq_chip、irq_domain;
  6. 該irq controller driver所對應的platform device。

針對模擬硬體中斷觸發,我們主要藉助irq work實現。主要的調用流程如下圖所示

  1. 當應用程式通過向irq_trigger寫入需要模擬觸發的hw irq line後,則會調用virt0808 driver定義的函數virt0808_irq_store,在該函數中調用irq_work_queue,將該irq work加入irq work queue中,並觸發irq work interrupt;
  2. 而在irq work interrupt的處理函數中調用irq_work_run,處理virt0808 driver定義的處理函數,即virt0808_hwirq_trigger;
  3. 在virt0808_hwirq_trigger接口中則調用generic_handle_irq接口中,則調用該irq controller對應hw irq line的irq_desc進行中斷的處理操作

而針對virt0813而言,其數據結構定義如下,該數據結構的定義與virt_irq_provider的定義類似。

Virt0808 driver

  • Virt0808對應irq chip的定義,主要是完成virt0808的操作接口,定義如下
  • 定義irq domain操作接口

在進行irq domain的map接口中完成irq desc與irq chip、irq flow handler的綁定操作

  • Irq domain、irq desc的創建操作

在probe接口中通過調用如下接口完成irq domain、irq desc的創建操作

以上就是virt0808的驅動程序,完成以上功能後,就完成針對virt0808 irq controller的驅動操作。

Virt0813 driver

該設備驅動與virt0808 driver的驅動類似,唯一區別的是,因為virt0813是掛載在virt0808上的,因此當virt0813上中斷發生時,cpu首先得到的是virt0808對應引腳中斷,然後在virt0808的chain hw irq line的中斷處理函數中,通過讀取virt0813的中斷狀態寄存器,確認virt0813上是哪一個hw irq line發生中斷,再調用generic_handle_irq接口去處理該中斷。處理過程如下圖所示:

virt0813_sub_irq_handler的定義如下:

測試驅動

在測試驅動中主要申請兩個irq,一個irq是virt0808 irq controller的hw irq line;一個irq是virt0813 irq controller 的hw irq line,該驅動僅僅是測試用,比較簡單,代碼如下:

測試驗證

在該virt irq的目錄下執行make &&make install,驅動鏡像即在image目錄下。

驅動加載:

insmod virt0808_dev.ko

insmod virt0808_irq.ko

insmod virt0813_irq.ko

insmod irq_consumer_dev.ko

insmod irq_consumer_driver.ko

Virt0808 irq controller中斷觸發驗證

因我們在測試驅動中,申請了virt0808的第7個中斷,因此我們觸發該中斷,看下該中斷對應的中斷處理程序有沒有調用:

cd /sys/devices/platform/virt0808_irq_dev.0/

echo 6 >>irq_trigger

dmesg

如上圖所示,中斷處理函數已經執行。下面我們進行virt0813中斷的測試,我們申請的是virt0813的第一個中斷,執行

命令如下:

cd /sys/devices/platform/virt0813_irq_dev.0

echo 1 >>irq_status

cd /sys/devices/platform/virt0808_irq_dev.0/

echo 15 >>irq_trigger

dmesg

如上圖所示,中斷處理函數也已經執行成功,測試成功。

以上就是本篇文章的主要內容,我們主要實現了virt irq controller driver,熟悉irq controller driver的開發流程,我們實現的驅動中,兩個irq controller通過級聯的方式連接,也比較有代表性。我們學習了irq子系統下irq controller driver的開發後,對我們平常的開發有沒有幫助呢?當我們需要為一個gpio controller開發驅動,且該gpio controller支持中斷時,則可以為該gpio controller創建irq controller driver即可完成該功能(此種功能需求下,可參考virt0813的驅動程序實現該需求)。至此我們完成了irq子系統的學習,針對irq子系統我也就是會開發相應驅動,若要徹底理解中斷子系統,還有很長的路要走…後續如果有可能,會再深入學習(本次虛擬驅動的源碼連結稍後會發出來,或者在gitee上搜索用戶jerry_chg,也可以找到本次的驅動代碼)。

相關焦點

  • Linux的IRQ中斷子系統分析
    本文以Linux中斷子系統架構為視角,旨在提供一個對Linux中斷系統的全局認識,不涉及具體實現細節。 一、Linux中斷子系統架構 在Linux中斷子系統(generic irq)出現之前,內核使用__do_IRQ處理所有的中斷,這意味著__do_IRQ中要處理各種類型的中斷,這會導致軟體的複雜性增加,層次不分明,而且代碼的可重用性也不好。
  • LINUX IIO子系統分析之三 IIO trigger分析
    irq chip,在trigger內部,當多個trigger consumer註冊時,則trigger內部會為其分配一個虛擬的irq,並根據trigger consumer提供給pollfunc,為該irq註冊中斷處理函數,這樣當該trigger觸發後,則會遍歷所有該trigger上已註冊的虛擬irq,調用其中斷處理函數從而執行trigger consumer提供的處理函數(關於linux中斷子系統的內容可參考我之前寫的中斷子系統專欄
  • LINUX 中斷子系統專欄之一 子系統架構簡述
    之前在做spi、iic等虛擬設備驅動時,就在思考如何開發虛擬的irq controller驅動,因為完成虛擬irqcontroller驅動後,進行虛擬外設驅動開發時,就可以使用irq。因此這周就簡要介紹irq子系統框架,然後再開發一個虛擬的irq controller driver 。
  • Linux中斷(interrupt)子系統之一:中斷系統基本原理
    ,不過這也依賴於作業系統對中斷系統的軟體實現。在驅動程序中申請中斷  Linux中斷子系統向驅動程序提供了一系列的API,其中的一個用於向系統申請中斷:  [cpp] view plain copyint request_threaded_irq(unsigned int irq, irq_handler_t handler,  irq_handler_t thread_fn, unsigned long
  • LINUX IIO子系統分析之七 虛擬iio設備驅動實現
    前面幾章我們基本完成了IIO子系統的所有內容,而該章即為本專欄的結束篇,主要用來實現一個虛擬的IIO DEVICE DRIVER,本章的內容主要包括如下幾部分:一、 虛擬IIO DEVICE的說明 二、虛擬IIO DEVICE DRIVER實現所需的知識點 三、虛擬IIO DEVICE DRIVER的數據結構及實現說明
  • LINUX IIO子系統分析之二 IIO子系統數據結構分析
    到event 的kfifo中,雖然IIO子系統設計上期望通過trigger將數據push到buffer或event上去,但event信息一般並不是連續事件,且trigger內部又實現了虛擬的irq chip,而在虛擬irq的中斷處理函數中實現數據push到buffer或event的kfifo中。
  • 基於Linux系統的觸控螢幕驅動方案
    3 Linux觸控螢幕驅動的實現3.1 觸控螢幕觸點數據採集S3C2440觸控螢幕控制器有四種工作模式,通過讀寫ADCTSC、ADCDA、ADCDATl和ADCDLY寄存器完成觸控螢幕控制器工作模式的選擇和觸控螢幕觸點數據採集。由於觸摸動作時間的隨機性,驅動設計時選擇中斷工作方式。
  • 嵌入式Linux設備驅動開發之:中斷編程
    前面所講述的驅動程序中都沒有涉及中斷處理,而實際上,有很多Linux的驅動都是通過中斷的方式來進行內核和硬體的交互。中斷機制提供了硬體和軟體之間異步傳遞信息的方式。硬體設備在發生某個事件時通過中斷通知軟體進行處理。
  • Linux V4l2子系統專欄之一 子系統概述
    從本章開始,我們開始分析V4L2子系統(Video for Linux two),主要用於音視頻設備的框架。V4l2主要用於驅動視頻輸出設備(video outpt interface)、Video overlay interface、Video output overlay device、VBI interface、Radio interface等。
  • Linux regulator子系統分析之四 虛擬regulator device驅動實現
    在前面幾章,我們分析了regulator子系統框架,主要是從數據結構及數據結構間的關聯分析了regulator子系統。為了讓大家對regulator子系統有一個深入的認識,我們本章將實現一個虛擬的regulator device驅動,從而掌握對regulator子系統的開發流程。
  • LINUX IIO子系統專欄分析之一 IIO子系統概述
    從本章開始,我們進行IIO子系統專欄的分析文檔,本次IIO子系統專欄分析文檔大概包含如下幾章:一、 IIO子系統概述二、IIO子系統相關數據結構分析三、iio trigger 介紹四、iio event介紹五、iio buffer介紹六、iio device的註冊與註銷介紹七、iio trigger
  • Linux CommonClock Framework分析之四 gpio clk gate驅動實現
    前面我們已經完成了CCF子系統的分析,也說明了如何實現CCF驅動,本章為該專欄的最後一篇文章, 本章我們將實現一個虛擬的gpio clk gate驅動。本章大概分為如下幾個章節:一、 本次驅動開發涉及的知識點 二、clk provider driver的實現流程說明 三、gpio clk gate driver驅動設計一、 本次驅動開發涉及的知識點本次驅動實踐主要涉及如下幾個方面的知識點
  • 輕鬆掌握pinctrl子系統驅動開發——一個虛擬pinctrl dev驅動開發
    本章即是pinctrl子系統分析的最後一章,本章我們主要實現一個虛擬的pinctrl device驅動,以便我們能夠使用pinctrl子系統提供的接口,實現pinctrl device的驅動開發(本章實現的驅動代碼可以在ubuntu18.04系統上正常運行)。
  • 內核不斷升級 如何學習linux設備驅動
    由於高版本內核並不完全兼容低版本內核,所以內核升級對從事linux開發的技術人員造成了一定的影響,特別對於linux入門人員。  內核的升級對應從事linux應用程式開發的人員來說影響較小,因為系統調用基本保持兼容。而影響比較大的是驅動開發人員。每次內核的更新都可以導致很多內核函數使用上的變化。
  • Linux 內核如何處理中斷|Linux 中國
    中斷服務程序(ISR)是一個小的程序,用來處理具體的數據,其具體的處理方式依賴於造成中斷請求(IRQ)的原因。之前正在運行的進程在中斷服務程序(ISR)運行結束前都會被中斷。 在過去,中斷請求由單獨的晶片處理(中斷控制器晶片 PIC),I/O 設備直接與中斷控制器(PIC)相連。
  • 基於華邦W90P710處理器的Linux內核應用及串口驅動的實現
    滋CLinux-2.4.20內核,支持4組通用異步接收發送口(UART),下面基於華邦W90P710的串口驅動詳細分析串口驅動的實現方法,實現嵌入式設備通過串口對外通信。(5)接收超時寄存器(UART_TOR):收到首個字節後接收器啟動本超時,之後每收到一個字節後都會重置該值,在此超時時間內不再收到數據時,接收器會產生一個接收中斷。(6)中斷控制器(UART_IER):設置接收、發送、行中斷等。在使用RXDn、TXDn前必須對GPIO進行配置,使能RXDn、TXDn,串口才可正常運行。GPIO配置對應表如表1所示。
  • 剝絲抽繭分析linux中斷系統的重要數據結構
    通用中斷控制器)的A號中斷,GIC再去中斷CPU。指廠家),這個函數需要讀取晶片的GPIO控制器,細分發生的是哪一個GPIO中斷(假設是B),再去調用irq_desc[B]. handle_irq。作用有二:① 中斷處理函數執行時,可以使用dev_id② 卸載中斷時要傳入dev_id,這樣才能在action鍊表中根據dev_id找到對應項所以在共享中斷中必須提供dev_id,非共享中斷可以不提供。
  • arm驅動linux內核中斷編程
    二、中斷申請函數參數int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char *devname, void *dev_id)1)參數:irq:是要申請的硬體中斷號。
  • linux內核是如何處理中斷的
    中斷的定義一個中斷請求(IRQ)是可編程中斷控制器(PIC)發出的,PIC是為了中斷CPU以執行中斷服務程序(ISR)。ISR是處理由IRQ產生的數據的一個小程序,電腦中正在運行的處理會因為中斷的產生而停止,直到ISR運行結束。
  • Linux中斷機制:硬體處理,初始化和中斷處理
    來源: CSDN | phenix_lord的專欄最近解決一個關於Linux中斷的問題,把相關機制整理了一遍,記錄在此。不同的外部設備、不同的體系結構、不同的OS其中斷實現機制都有差別,本文對應的OS為linux3.4版本,外部設備為PCI設備、系統為X86。