色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > Linux中斷子系統的初始化

Linux中斷子系統的初始化 時間:2018-09-29      來源:未知

Linux中斷子系統的初始化

注:以2.6.39內核源碼講解

Linux整個中斷處理體系其實可以分為兩個部分,一部分是系統完成的部分,另一部分是驅動工程師需要完成的部分(也就是我們用requst_irq注冊的處理函數),本次我們主要討論的是系統啟動的過程中對中斷子系統做了哪些事?

一、搬移異常向量表

內核在啟動的時候就是先運行start_kernel() , 然后她就會調用體系結構相關的setup_arch(&command_line), 如arm體系結構的在arch/arm/kernel/setup.c中, 進一步, 她就要初始化板級相關的設備,內核會在這個工程中調用early_trap_init()把異常向量表搬移到0xFFFF0000的位置。

void __init setup_arch(char **cmdline_p)

{

const struct machine_desc *mdesc;

setup_processor();

mdesc = setup_machine(machine_arch_type);

......

early_trap_init(); //把異常向量表搬移到0xFFFF0000的位置。

}

二、初始化中斷管理子系統

我們先來看一下Linux系統中,中斷管理系統的初始化。中斷系統的初始化主要由兩個函數來完成。在系統初始化的start_kernel()函數 (在文件init/main.c中定義)中可以看到:

asmlinkage void __init start_kernel(void)

{

……

setup_arch(&command_line);

   trap_init();

……

   early_irq_init();

   init_IRQ();

……

}

 Linux中斷機制的核心數據結構 irq_desc, 它完整地描述了一條中斷線 (或可簡單理解為 “一個中斷源” )。start_kernel()函數調用early_irq_init()和init_IRQ()兩個函數來初始化中斷管理系統。其實就是初始化irq_desc的結構。

1、early_irq_init()函數

注:這個函數在kernel/irq/irqdesc.c文件中定義。

在start_kernel()函數中調用了early_irq_init()函數,linux調用early_irq_init()初始化linux中斷系統的核心數據。early_irq_init屬于與硬件和平臺無關的通用邏輯層,為irq_desc[]中個元素的某些成員填充默認值,完成后調用體系相關的arch_early_irq_init函數完成進一步的初始化工作,不過ARM體系沒有實現arch_early_irq_init。

注:irq_desc[] 全局數組

struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {

[0 ... NR_IRQS-1] = {

.handle_irq = handle_bad_irq,

.depth = 1,

.lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),

}

};

int __init early_irq_init(void)

{

int count, i, node = first_online_node;

struct irq_desc *desc;

init_irq_default_affinity();

printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);

desc = irq_desc;

count = ARRAY_SIZE(irq_desc);

for (i = 0; i < count; i++) {

desc[i].irq_data.irq = i;

desc[i].irq_data.chip = &no_irq_chip;

desc[i].kstat_irqs = alloc_percpu(unsigned int);

irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);

alloc_masks(desc + i, GFP_KERNEL, node);

desc_smp_init(desc + i, node);

lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);

}

return arch_early_irq_init();

}

注: 在使用設備樹的高版本內核中,管理中斷描述符也可能是用基數樹去管理了,避免空間的浪費。

2、init_IRQ()函數

init_IRQ(void)函數是一個特定與體系結構的函數,對于ARM體系結構,在文件arch/arm/kernel/irq.c

void __init init_IRQ(void)

{

machine_desc->init_irq();

}

mdesc結構的init_irq成員,這是一個struct machine_desc類型的結構,mach_desc里定義了一些關鍵的體系架構相關的信息。

以mini2440為例:

其machine_desc結構的init_irq成員在文件arch/arm/mach-s3c2440/mach-mini2440.c中被賦值為s3c24xx_init_irq函數

MACHINE_START(MINI2440, "MINI2440")

/* Maintainer: Michel Pollet <buserror@gmail.com> */

.boot_params = S3C2410_SDRAM_PA + 0x100,

.map_io = mini2440_map_io,

.init_machine = mini2440_init,

.init_irq = s3c24xx_init_irq,

.timer = &s3c24xx_timer,

MACHINE_END

注:MACHINE_START宏的作用是對mach_desc結構體進行初始化。OK,終于找到了init_IRQ() 真正內容,在arch/arm/plat-s3c24xx/irq.c中定義:

/* s3c24xx_init_irq

 *

 * Initialise S3C2410 IRQ system

*/

3、init_IRQ()實例

對應平臺下面的代碼,和硬件平臺相關,為各個中斷源設置默認的處理函數

void __init s3c24xx_init_irq(void)

{

   unsigned long pend;

   unsigned long last;

   int irqno;

   int i;

for (i = 0; i < 4; i++) {

pend = __raw_readl(S3C24XX_EINTPEND);

if (pend == 0 || pend == last)

break;

__raw_writel(pend, S3C24XX_EINTPEND);

printk("irq: clearing pending ext status %08x\n", (int)pend);

last = pend;

}

.......

for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {

/* set all the s3c2410 internal irqs */

switch (irqno) {

/* deal with the special IRQs (cascaded) */

case IRQ_EINT4t7:

case IRQ_EINT8t23:

case IRQ_UART0:

case IRQ_UART1:

case IRQ_UART2:

case IRQ_ADCPARENT:

irq_set_chip_and_handler(irqno, &s3c_irq_level_chip, handle_level_irq); 

break;

case IRQ_RESERVED6:

case IRQ_RESERVED24:

/* no IRQ here */

break;

default:

//irqdbf("registering irq %d (s3c irq)\n", irqno);

irq_set_chip_and_handler(irqno, &s3c_irq_chip, handle_edge_irq); 

set_irq_flags(irqno, IRQF_VALID);

}

}

/* 設置外部中斷的控制器(操作方法集),默認前級處理函數handle_irq */

for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {

irq_set_chip_and_handler(irqno, &s3c_irq_eint0t4, handle_edge_irq); 

set_irq_flags(irqno, IRQF_VALID);

}

for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {

irq_set_chip_and_handler(irqno, &s3c_irqext_chip, handle_edge_irq); 

set_irq_flags(irqno, IRQF_VALID);

}

 

......

}

這個函數完成對于中斷控制器的初始化,并且設置中斷描述符的相應的函數指針的值,以在中斷發生時發生時,調用這些函數來完成芯片級的處理。

irq_set_chip_and_handler()介紹:

1、可以設置中斷號對應的中斷描述符的chip,里面其實是一系列操作對于控制器的方法,以在中斷發生或者管理中斷時可以完成對于芯片的操作。

以IRQ_EINT4-IRQ_EINT23為例,它的chip是s3c_irqext_chip

static struct irq_chip s3c_irqext_chip = {

.name = "s3c-ext",

.irq_mask = s3c_irqext_mask,

.irq_unmask = s3c_irqext_unmask,

.irq_ack = s3c_irqext_ack,

.irq_set_type = s3c_irqext_type,

.irq_set_wake = s3c_irqext_wake

};

2、可以設置中斷發生的第一級處理函數比如 handle_level_irq 或者 handle_edge_irq,本質上就是設置irq_desc[irqno].handle_irq 的值。

其實中斷處理的時候一般分為兩級,第一級是調用irq_desc[irqno].handle_irq。它主要面向GIC的莫一中斷線IRQ line,跟當前中斷觸發電信號相關的一個函數,不同的中斷觸發方式,其中斷線處理的函數是不同的,不過主要是電平處理和邊沿處理兩種。 第二級才是我們驅動開發者自己注冊的中斷函數,也就是irq_desc[irqno].action->handler的調用。

上面這個函數就是為特定的中斷號設置好一個中斷處理例程,這里的例程可不是我們request_irq注冊的例程,Linux支持中斷共享,共享同一個中斷號的每一設備都可以有自己特定的中斷處理程序,用來描述這些中斷處理程序的結構會形成一個鏈表,這里設置的例程將會逐個調用特定中斷號上的各設備的中斷處理例程。

上一篇:ARM中非對其的存儲訪問操作

下一篇:嵌入式指針數組

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5,京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: www精品视频 | 一道本AV免费不卡播放 | 亚洲爆乳精品无码一区二区三区 | 欧美成免费A级毛片 | 青青草18在线视频免费 | 国产精品免费看久久久8精臀av | 妇女性内射冈站HDWWW000 | 日本成熟少妇高潮A片 | 中国一级毛片 | 亚洲欧美日韩国产综合精品二区 | 国产成人精品视频A片 | 一本无码久本草在线中文字幕DVD | 大尺度吃奶摸下激烈视频 | 末成年av女网站 | 亚洲人交乣女bbw | 亚洲成aⅴ人最新无码 | 伊人久久大香线蕉AV最新午夜 | 大粗鳮巴征服少妇视频 | 欧美躁天天躁无码中文字 | 五月综合激情婷婷六月色窝 | 国产成人69视频午夜福利在线观看 | 亚洲A∨精品无码一区二区 亚洲精品一区二区三区精品 | 野花视频最新免费完整在线观看 | 忘忧草在线影院WWW日本二 | 成年女人毛片免费视频播放器 | 久久99精品久久久久久久不卡 | 国产精品自在在线午夜 | 嗯大JB插我好深视频 | 中文字幕无码视频手机免费看 | 亚洲欧美一级黄色录像视频 | 成人美女摇乱后入式内射视频 | 国产成人8x人网站在线视频 | 国产精品VA无码一区二区 | 岛国无码免费不卡av | 亚洲欧美日韩高清一区 | 国产精品久久无码不卡 | 一区二区免费视频中文乱码 | 美女网站亚洲一区 | 奇米影视在线播放 | 被黑人伦流澡到高潮HNP动漫 | 亚洲AV永久无码精品表情包 |