linux中斷驅動
『壹』 ZYNQ XC7Z020的PL PS中斷驅動程序編寫測試(linux4.14版本下)
設計目的旨在實現ARM與FPGA的高效交互,特別聚焦於PL與PS間的中斷驅動通信。通過使用BRAM存儲數據並觸發外部PL端中斷,通知PS端進行數據讀寫操作,本文將詳細闡述這一過程。程序設計邏輯圍繞按鍵觸發中斷,通過按鍵直接連接至PL端,驅動產生非同步通知。應用開始向BRAM寫入數據,隨後阻塞等待讀取數據,讀取後進行比較。
Vivado平台中,增加BRAM控制器與BRAM配置,以及中斷機制的集成。本文重點介紹了在中斷系統中使用第11個中斷,連接至IRQ_F2P介面。此外,需在Linux設備樹中添加相應的中斷配置,明確中斷號為86,通過計算得出實際中斷號為54,並設置為上升沿觸發模式。
中斷程序設計包含驅動注冊、字元驅動注冊以及中斷注冊,考慮到數據交換量可能較大,本文提出使用mmap函數優化數據讀寫效率。中斷處理函數中,首先產生非同步通知信號,隨後清除阻塞等待隊列信號。
應用程序測試階段,接收中斷觸發信號後,通過mmap功能將數據寫入BRAM,接著執行阻塞等待讀取數據,直至喚醒後讀取並列印數據。通過 printk 功能,直觀展示了中斷觸發的數據處理流程,具體步驟如下:
中斷處理函數 plps_handler 觸發。
先前阻塞狀態的 plpsirq_read 函數被激活,用於處理非同步通知信號。
應用層的非同步通知函數 my_signal_fun 被調用。
最終執行完成阻塞讀取操作,read(fd, str, 10)完成數據讀取。
綜上,本文詳細介紹了ZYNQ XC7Z020晶元下中斷驅動程序的編寫與測試過程,特別關注了Linux環境下的設備樹配置、中斷機制實現,以及程序的高效數據交換邏輯。通過實證分析,驗證了設計方法的有效性,為後續FPGA與ARM交互應用提供了參考依據。
『貳』 《Linux設備驅動程序》(十六)-中斷處理
設備與處理器之間的工作通常來說是非同步,設備數據要傳遞給處理器通常來說有以下幾種方法:輪詢、等待和中斷。
讓CPU進行輪詢等待總是不能讓人滿意,所以通常都採用中斷的形式,讓設備來通知CPU讀取數據。
2.6內核的函數參數與現在的參數有所區別,這里都主要介紹概念,具體實現方法需要結合具體的內核版本。
request_irq函數申請中斷,返回0表示申請成功,其他返回值表示申請失敗,其具體參數解釋如下:
flags 掩碼可以使用以下幾個:
快速和慢速處理常式 :現代內核中基本沒有這兩個概念了,使用SA_INTERRUPT位後,當中斷被執行時,當前處理器的其他中斷都將被禁止。通常不要使用SA_INTERRUPT標志位,除非自己明確知道會發生什麼。
共享中斷 :使用共享中斷時,一方面要使用SA_SHIRQ位,另一個是request_irq中的dev_id必須是唯一的,不能為NULL。這個限制的原因是:內核為每個中斷維護了一個共享處理常式的列表,常式中的dev_id各不相同,就像設備簽名。如果dev_id相同,在卸載的時候引起混淆(卸載了另一個中斷),當中斷到達時會產生內核OOP消息。
共享中斷需要滿足以下一個條件才能申請成功:
當不需要使用該中斷時,需要使用free_irq釋放中斷。
通常我們會在模塊載入的時候申請安裝中斷處理常式,但書中建議:在設備第一次打開的時候安裝,在設備最後一次關閉的時候卸載。
如果要查看中斷觸發的次數,可以查看 /proc/interrupts 和 /proc/stat。
書中講述了如何自動檢測中斷號,在嵌入式開發中通常都是查看原理圖和datasheet來直接確定。
自動檢測的原理如下:驅動程序通知設備產生中斷,然後查看哪些中斷信號線被觸發了。Linux提供了以下方法來進行探測:
探測工作耗時較長,建議在模塊載入的時候做。
中斷處理函數和普通函數其實差不多,唯一的區別是其運行的中斷上下文中,在這個上下文中有以下注意事項:
中斷處理函數典型用法如下:
中斷處理函數的參數和返回值含義如下:
返回值主要有兩個:IRQ_NONE和IRQ_HANDLED。
對於中斷我們是可以進行開啟和關閉的,Linux中提供了以下函數操作單個中斷的開關:
該方法可以在所有處理器上禁止或啟用中斷。
需要注意的是:
如果要關閉當前處理器上所有的中斷,則可以調用以下方法:
local_irq_save 會將中斷狀態保持到flags中,然後禁用處理器上的中斷;如果明確知道中斷沒有在其他地方被禁用,則可以使用local_irq_disable,否則請使用local_irq_save。
locat_irq_restore 會根據上面獲取到flags來恢復中斷;local_irq_enable 會無條件打開所有中斷。
在中斷中需要做一些工作,如果工作內容太多,必然導致中斷處理所需的時間過長;而中斷處理又要求能夠盡快完成,這樣才不會影響正常的系統調度,這兩個之間就產生了矛盾。
現在很多操作系統將中斷分為兩個部分來處理上面的矛盾:頂半部和底半部。
頂半部就是我們用request_irq來注冊的中斷處理函數,這個函數要求能夠盡快結束,同時在其中調度底半部,讓底半部在之後來進行後續的耗時工作。
頂半部就不再說明了,就是上面的中斷處理函數,只是要求能夠盡快處理完成並返回,不要處理耗時工作。
底半部通常使用tasklet或者工作隊列來實現。
tasklet的特點和注意事項:
工作隊列的特點和注意事項:
『叄』 Linux內核:中斷、軟中斷、tasklet
在Linux驅動程序開發中,中斷機制是關鍵組件之一,廣泛應用於各類硬體驅動,例如CC1100高頻驅動和倒車雷達驅動。通常,我們主要使用中斷的頂半部功能,即通過注冊中斷處理函數和請求中斷,以便在中斷觸發時自動執行特定的代碼段。雖然中斷的底半部技術同樣存在,但因其復雜性和性能考慮,我們通常在驅動程序中較少使用。本文將深入探討中斷的底半部、軟中斷以及tasklet微線程,以提供更直觀的理解。
中斷的底半部與頂半部存在顯著差異。在頂半部中,當中斷觸發時,處理器會暫停當前執行的進程,並執行相應的中斷處理程序。而底半部在中斷處理過程中可能涉及耗時操作,這可能會打斷其他中斷處理或進程執行,對系統響應造成影響。為避免這種情況,底半部功能被設計為延遲執行,即在中斷處理程序的最後將耗時任務放入特定隊列中,由專門的線程或機制在適當時間執行。此設計允許系統在中斷處理過程中保持高效響應,同時確保耗時操作不會影響整體性能。
軟中斷是底半部實現的一種重要方式,它允許內核在中斷上下文外執行延遲任務。軟中斷通過do_softirq函數進行調度,允許多個CPU同時執行,從而提高系統處理效率。通過注冊特定類型的軟中斷和相應的處理函數,開發者可以將任務放入軟中斷隊列中,由系統在合適時機執行。軟中斷機制簡化了在中斷上下文外執行任務的流程,但要求任務實現遵循線程安全和可重入原則,以避免數據競爭。
tasklet微線程進一步優化了軟中斷機制,針對特定場景提供更靈活的線程管理。與軟中斷類似,tasklet允許在中斷處理之外執行延遲任務,但其通過為每個CPU提供獨立的tasklet隊列,以及在隊列內部執行任務,進一步減少了任務執行過程中的互斥需求。這不僅降低了對任務執行函數的並發要求,還提高了整體系統性能。開發者通過調用tasklet_schele函數將任務加入隊列,並通過tasklet_init函數創建tasklet結構體對象,以實現在驅動程序中的高效、並發執行。
綜合而言,中斷的底半部、軟中斷和tasklet微線程為Linux內核提供了多種實現延遲任務執行的機制。這些技術通過優化任務執行方式,顯著提高了系統在處理中斷和復雜任務時的響應能力和性能,是驅動程序開發中不可或缺的工具。理解並合理運用這些機制,能夠有效提升驅動程序的可靠性和效率。
『肆』 linux中,中斷注冊和中斷服務程序只能寫在驅動層還是能寫在應用層
我也不完全理解,但是比你知道的多點。
Linux中,分內核態和用戶態。
你寫的所有的驅動,都是出於內核態->可以直接使用內核相關資源;
應用層,都是用戶態->無法直接操作底層的東西 -> 想要操作,比如獲得許可權,切換到內核態,然後才能操作。
你這里的需求,我的理解是:
對應你這句
「在中斷服務程序中操作另一個外設」
不知道你的目的和打算用的手段是啥
一般的,ISR中,操作別的設備,常見的是:
設置對應的(比如該硬體本身,或者別的設備B的)寄存器的對應的位,以便通知其某種事情發送或狀態變化了。
然後設備B會:
要麼是由於(被修改了寄存器而)發生了中斷,然後可以接著處理其所要做的事情;
要麼是一直輪訓,檢測對應的某種資源釋放變化,比如上面被改的寄存器的對應的位,發現變化了,再去調用你的函數,做對應的處理。
注意:
中斷,不論是哪個設備的中斷,都不應該佔用(CPU)太長時間
-> 導致別的中斷或服務無法及時運行
僅供參考。
『伍』 怎樣看linux串口驅動中斷 dma
查詢就是一直在查看標志位,是不是被置1了,如果是就去讀或者其他操作
中斷就是平時不用管,一單有東西來就會進入中斷服務程序,你再去操作
DMA是你初始化的時候把串口地址和需要傳輸的地址寫上,來東西他就自己把數據存到你初始化的地址上