www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 嵌入式 > 嵌入式軟件

作者:劉洪濤,華清遠見嵌入式學院金牌講師。

四、中斷處理模型

要想弄清楚desc->handle_IRq(irq, desc)和我們注冊的中斷有什么關聯,就要了解中斷處理模型了。

4.1 中斷處理模型結構

中斷處理模型如下圖所示,


其中NR_IRQS表示最大的中斷號,在include/asm/arch/irq.h中定義。

irq_desc[]是一個指向irq_desc_t結構的數組, irq_desc_t結構是各個設備中斷服務例程的描述符。Irq_desc_t結構體中的成員action指向該中斷號對應的irqaction結構體鏈表。Irqaction結構體定義在include/linux/interrupt.h中,如下:

truct irqaction {

irq_handler_t handler; //中斷處理函數,注冊時提供

unsigned long flags; //中斷標志,注冊時提供

CPUmask_t mask; //中斷掩碼

const char *name; //中斷名稱

void *dev_id; //設備id,本文后面部分介紹中斷共享時會詳細說明這個參數的作用

struct irqaction *next; //如果有中斷共享,則繼續(xù)執(zhí)行,

int irq; //中斷號,注冊時提供

struct proc_dir_entry *dir; //指向IRQn相關的/proc/irq/n目錄的描述符

};

在注冊中斷號為irq的中斷服務程序時,系統(tǒng)會根據注冊參數封裝相應的irqaction結構體。并把中斷號為irq的irqaction結構體寫入irq_desc [irq]->action。這樣就把設備的中斷請求號與該設備的中斷服務例程irqaction聯系在一起了。樣當CPU接收到中斷請求后,就可以根據中斷號通過irq_desc []找到該設備的中斷服務程序。

4.2 中斷共享的處理模型

共享中斷的不同設備的iqraction結構體都會添加進該中斷號對應的irq_desc結構體的action成員所指向的irqaction鏈表內。當內核發(fā)生中斷時,它會依次調用該鏈表內所有的handler函數。因此,若驅動程序需要使用共享中斷機制,其中斷處理函數必須有能力識別是否是自己的硬件產生了中斷。通常是通過讀取該硬件設備提供的中斷flag標志位進行判斷。也就是說不是任何設備都可以做為中斷共享源的,它必須能夠通過的它的中斷flag判斷出是否發(fā)生了中斷。

中斷共享的注冊方法是:

int request_irq(unsigned int irq, irq_handler_t handler,

IRQF_SHARED, const char *devname, void *dev_id)

很多權威資料中都提到,中斷共享注冊時的注冊函數中的dev_id參數是必不可少的,并且dev_id的值必須唯一。那么這里提供唯一的dev_id值的究竟是做什么用的?

根據我們前面中斷模型的知識,可以看出發(fā)生中斷時,內核并不判斷究竟是共享中斷線上的哪個設備產生了中斷,它會循環(huán)執(zhí)行所有該中斷線上注冊的中斷處理函數(即irqaction->handler函數)。因此irqaction->handler函數有責任識別出是否是自己的硬件設備產生了中斷,然后再執(zhí)行該中斷處理函數。通常是通過讀取該硬件設備提供的中斷flag標志位進行判斷。那既然kernel循環(huán)執(zhí)行該中斷線上注冊的所有irqaction->handler函數,把識別究竟是哪個硬件設備產生了中斷這件事交給中斷處理函數本身去做,那request_irq的dev_id參數究竟是做什么用的?

很多資料中都建議將設備結構指針作為dev_id參數。在中斷到來時,迅速地根據硬件寄存器中的信息比照傳入的dev_id參數判斷是否是本設備的中斷,若不是,應迅速返回。這樣的說法沒有問題,也是我們編程時都遵循的方法。但事實上并不能夠說明為什么中斷共享必須要設置dev_id。

下面解釋一下dev_id參數為什么必須的,而且是必須唯一的。

當調用free_irq注銷中斷處理函數時(通常卸載驅動時其中斷處理函數也會被注銷掉),因為dev_id是唯一的,所以可以通過它來判斷從共享中斷線上的多個中斷處理程序中刪除指定的一個。如果沒有這個參數,那么kernel不可能知道給定的中斷線上到底要刪除哪一個處理程序。

注銷函數定義在Kernel/irq/manage.c中定義:

void free_irq(unsigned int irq, void *dev_id)

五、S3C2410子中斷的注冊的實現

5.1 S3C2410子中斷注冊問題的提出

參看3.5節(jié)中判斷中斷號的方法,可以看到只是通過S3C2410中斷控制器中的INTOFFSET寄存器來判斷的。對于INTPND中的EINT4_7、EINT8_23、INT_UART0、INT_ADC 等帶有子中斷的向量,INTOFFSET無法判斷出具體的中斷號。平臺留給我們的注冊方法如下:

在include/asm/arch/irqs.h中有類似如下定義:

/* interrupts generated from the external interrupts sources */

#define IRQ_EINT4 S3C2410_IRQ(32) /* 48 */

#define IRQ_EINT5 S3C2410_IRQ(33)

#define IRQ_EINT6 S3C2410_IRQ(34)

#define IRQ_EINT7 S3C2410_IRQ(35)

#define IRQ_EINT8 S3C2410_IRQ(36)

#define IRQ_EINT9 S3C2410_IRQ(37)

#define IRQ_EINT10 S3C2410_IRQ(38)

#define IRQ_EINT11 S3C2410_IRQ(39)

#define IRQ_EINT12 S3C2410_IRQ(40)

#define IRQ_EINT13 S3C2410_IRQ(41)

#define IRQ_EINT14 S3C2410_IRQ(42)

#define IRQ_EINT15 S3C2410_IRQ(43)

#define IRQ_EINT16 S3C2410_IRQ(44)

#define IRQ_EINT17 S3C2410_IRQ(45)

#define IRQ_EINT18 S3C2410_IRQ(46)

#define IRQ_EINT19 S3C2410_IRQ(47)

#define IRQ_EINT20 S3C2410_IRQ(48) /* 64 */

#define IRQ_EINT21 S3C2410_IRQ(49)

#define IRQ_EINT22 S3C2410_IRQ(50)

#define IRQ_EINT23 S3C2410_IRQ(51)

可以看到平臺為每種子中斷都定義了中斷號,如果你想實現EINT10的中斷注冊,直接按照IRQ_EINT10這個中斷號注冊都可以了。那么平臺代碼是如何實現這部分中斷注冊的呢?

5.2 S3C2410子中斷注冊問題的解決

/*arch/arm/plat-s3c24xx/irq.c*/

void __init s3c24xx_init_irq(void)

{……

set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);

set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);

set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);

set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);

set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);

set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);

……

}

平臺在初始化時會調用到s3c24xx_init_irq,在此函數中實現了對EINT4_7、EINT8_23、INT_UART0、INT_ADC等中斷的注冊。下面看看這些帶有子中斷的中斷號對應的處理函數的內容。以IRQ_EINT4t7為例,其它情況類似。

/*arch/arm/plat-s3c24xx/irq.c*/

s3c_irq_demux_extint4t7(unsigned int irq,

struct irq_desc *desc)

{

unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);

unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);

eintpnd &= ~eintmsk;

eintpnd &= 0xff; /* only lower irqs */

/* eintpnd中可以有多個位同時置1,這一點和intpnd的只能有1個位置1是不一樣的 */

while (eintpnd) { //循環(huán)執(zhí)行所有置位的子中斷

irq = __ffs(eintpnd); //算出第一個不為0的位,類似arm v5后的clz前導0的作用

eintpnd &= ~(1<<irq);//清除相應的位

irq += (IRQ_EINT4 - 4);//算出對應的中斷號

desc_handle_irq(irq, irq_desc + irq);//執(zhí)行對應子中斷的注冊函數

}

}

從上面的函數可以看出子中斷是如何注冊及被調用到的。有人可能會問為何不在include/asm/arch-s3c2410/entry-macro.s 文件中get_irqnr_and_base函數判斷中斷號時,直接算出對應的子中斷號,就可以直接找到子中斷處理了呢?

原因是: get_irqnr_and_base是平臺給系統(tǒng)提供的函數,對于多個子中斷同時置位的情況無法通過一個值返回(因為子中斷中,如eintpnd是可以多個位同時置位的))。而intpnd則沒有這個問題。

“本文由華清遠見http://www.embedu.org/index.htm提供”



華清遠見

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯系該專欄作者,如若文章內容侵犯您的權益,請及時聯系本站刪除。
換一批
延伸閱讀

CPU親和度通過限制進程或線程可以運行的CPU核心集合,使得它們只能在指定的CPU核心上執(zhí)行。這可以減少CPU緩存的失效次數,提高緩存命中率,從而提升系統(tǒng)性能。

關鍵字: Linux 嵌入式

ARM系統(tǒng)幾乎都采用Linux的操作系統(tǒng),而且?guī)缀跛械挠布到y(tǒng)都要單獨構建自己的系統(tǒng),與其他系統(tǒng)不能兼容,這也導致其應用軟件不能方便移植,這一點一直嚴重制約了ARM系統(tǒng)的發(fā)展和應用。GOOGLE開發(fā)了開放式的Andro...

關鍵字: Linux x86 ARM

隨著計算需求的多樣化,尤其是隨著移動設備、嵌入式系統(tǒng)和云計算的興起,ARM 和 x86 架構之間的爭論變得更加突出。ARM(高級 RISC 機器)和 x86 代表兩種不同類型的處理器架構,每種架構都針對不同的工作負載和用...

關鍵字: Linux x86 ARM

從畫質優(yōu)化 (NSS) 到幀率提升 (NFRU) 和光線追蹤(NSSD),Arm 計劃覆蓋移動端圖形處理的多個維度,推動邊緣 AI 圖形革命。而未來通過持續(xù)的技術迭代,Arm也將保持在移動計算領域的技術領先,滿足手游、A...

關鍵字: ARM 神經圖形技術 GPU AI ML

在Linux系統(tǒng)性能優(yōu)化中,內存管理與網絡連接處理是兩大核心領域。vm.swappiness與net.core.somaxconn作為關鍵內核參數,直接影響系統(tǒng)在高負載場景下的穩(wěn)定性與響應速度。本文通過實戰(zhàn)案例解析這兩個...

關鍵字: Linux 內存管理

7月31日消息,據媒體報道,芯片架構提供商Arm Holdings首席執(zhí)行官Rene Haas宣布,公司正加大投入開發(fā)自有芯片產品,此舉標志著其從傳統(tǒng)IP授權模式向提供實體芯片的戰(zhàn)略重大轉變。

關鍵字: ARM META
關閉