国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Linux中斷子系統(tǒng)的初始化

Linux中斷子系統(tǒng)的初始化 時(shí)間:2018-09-29      來源:未知

Linux中斷子系統(tǒng)的初始化

注:以2.6.39內(nèi)核源碼講解

Linux整個(gè)中斷處理體系其實(shí)可以分為兩個(gè)部分,一部分是系統(tǒng)完成的部分,另一部分是驅(qū)動(dòng)工程師需要完成的部分(也就是我們用requst_irq注冊(cè)的處理函數(shù)),本次我們主要討論的是系統(tǒng)啟動(dòng)的過程中對(duì)中斷子系統(tǒng)做了哪些事?

一、搬移異常向量表

內(nèi)核在啟動(dòng)的時(shí)候就是先運(yùn)行start_kernel() , 然后她就會(huì)調(diào)用體系結(jié)構(gòu)相關(guān)的setup_arch(&command_line), 如arm體系結(jié)構(gòu)的在arch/arm/kernel/setup.c中, 進(jìn)一步, 她就要初始化板級(jí)相關(guān)的設(shè)備,內(nèi)核會(huì)在這個(gè)工程中調(diào)用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的位置。

}

二、初始化中斷管理子系統(tǒng)

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

asmlinkage void __init start_kernel(void)

{

……

setup_arch(&command_line);

   trap_init();

……

   early_irq_init();

   init_IRQ();

……

}

 Linux中斷機(jī)制的核心數(shù)據(jù)結(jié)構(gòu) irq_desc, 它完整地描述了一條中斷線 (或可簡(jiǎn)單理解為 “一個(gè)中斷源” )。start_kernel()函數(shù)調(diào)用early_irq_init()和init_IRQ()兩個(gè)函數(shù)來初始化中斷管理系統(tǒng)。其實(shí)就是初始化irq_desc的結(jié)構(gòu)。

1、early_irq_init()函數(shù)

注:這個(gè)函數(shù)在kernel/irq/irqdesc.c文件中定義。

在start_kernel()函數(shù)中調(diào)用了early_irq_init()函數(shù),linux調(diào)用early_irq_init()初始化linux中斷系統(tǒng)的核心數(shù)據(jù)。early_irq_init屬于與硬件和平臺(tái)無關(guān)的通用邏輯層,為irq_desc[]中個(gè)元素的某些成員填充默認(rèn)值,完成后調(diào)用體系相關(guān)的arch_early_irq_init函數(shù)完成進(jìn)一步的初始化工作,不過ARM體系沒有實(shí)現(xiàn)arch_early_irq_init。

注:irq_desc[] 全局?jǐn)?shù)組

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();

}

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

2、init_IRQ()函數(shù)

init_IRQ(void)函數(shù)是一個(gè)特定與體系結(jié)構(gòu)的函數(shù),對(duì)于ARM體系結(jié)構(gòu),在文件arch/arm/kernel/irq.c

void __init init_IRQ(void)

{

machine_desc->init_irq();

}

mdesc結(jié)構(gòu)的init_irq成員,這是一個(gè)struct machine_desc類型的結(jié)構(gòu),mach_desc里定義了一些關(guān)鍵的體系架構(gòu)相關(guān)的信息。

以mini2440為例:

其machine_desc結(jié)構(gòu)的init_irq成員在文件arch/arm/mach-s3c2440/mach-mini2440.c中被賦值為s3c24xx_init_irq函數(shù)

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宏的作用是對(duì)mach_desc結(jié)構(gòu)體進(jìn)行初始化。OK,終于找到了init_IRQ() 真正內(nèi)容,在arch/arm/plat-s3c24xx/irq.c中定義:

/* s3c24xx_init_irq

 *

 * Initialise S3C2410 IRQ system

*/

3、init_IRQ()實(shí)例

對(duì)應(yīng)平臺(tái)下面的代碼,和硬件平臺(tái)相關(guān),為各個(gè)中斷源設(shè)置默認(rèn)的處理函數(shù)

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);

}

}

/* 設(shè)置外部中斷的控制器(操作方法集),默認(rèn)前級(jí)處理函數(shù)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);

}

 

......

}

這個(gè)函數(shù)完成對(duì)于中斷控制器的初始化,并且設(shè)置中斷描述符的相應(yīng)的函數(shù)指針的值,以在中斷發(fā)生時(shí)發(fā)生時(shí),調(diào)用這些函數(shù)來完成芯片級(jí)的處理。

irq_set_chip_and_handler()介紹:

1、可以設(shè)置中斷號(hào)對(duì)應(yīng)的中斷描述符的chip,里面其實(shí)是一系列操作對(duì)于控制器的方法,以在中斷發(fā)生或者管理中斷時(shí)可以完成對(duì)于芯片的操作。

以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、可以設(shè)置中斷發(fā)生的第一級(jí)處理函數(shù)比如 handle_level_irq 或者 handle_edge_irq,本質(zhì)上就是設(shè)置irq_desc[irqno].handle_irq 的值。

其實(shí)中斷處理的時(shí)候一般分為兩級(jí),第一級(jí)是調(diào)用irq_desc[irqno].handle_irq。它主要面向GIC的莫一中斷線IRQ line,跟當(dāng)前中斷觸發(fā)電信號(hào)相關(guān)的一個(gè)函數(shù),不同的中斷觸發(fā)方式,其中斷線處理的函數(shù)是不同的,不過主要是電平處理和邊沿處理兩種。 第二級(jí)才是我們驅(qū)動(dòng)開發(fā)者自己注冊(cè)的中斷函數(shù),也就是irq_desc[irqno].action->handler的調(diào)用。

上面這個(gè)函數(shù)就是為特定的中斷號(hào)設(shè)置好一個(gè)中斷處理例程,這里的例程可不是我們r(jià)equest_irq注冊(cè)的例程,Linux支持中斷共享,共享同一個(gè)中斷號(hào)的每一設(shè)備都可以有自己特定的中斷處理程序,用來描述這些中斷處理程序的結(jié)構(gòu)會(huì)形成一個(gè)鏈表,這里設(shè)置的例程將會(huì)逐個(gè)調(diào)用特定中斷號(hào)上的各設(shè)備的中斷處理例程。

上一篇:ARM中非對(duì)其的存儲(chǔ)訪問操作

下一篇:嵌入式指針數(shù)組

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺(tái)專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號(hào)-5,京公海網(wǎng)安備11010802025203號(hào)

回到頂部