`
xiaoer_1982
  • 浏览: 1821570 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

三读内核中断处理(2):中断配置

阅读更多

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

本文适用于

ADSP-BF561

优视BF561EVB开发板

uclinux-2008r1.5-rc3(smp patch)

Visual DSP++ 5.0(update 5)

欢迎转载,但请保留作者信息

1.1 中断入口设置

setup_arch函数的末尾,调用了一个函数进行中断处理函数的配置:

init_exception_vectors();

B核启动时,其调用的第一个函数也是它:

void __cpuinit secondary_start_kernel(void)

{

unsigned int cpu = smp_processor_id();

struct mm_struct *mm = &init_mm;

/*

* We want the D-cache to be enabled early, in case the atomic

* support code emulates cache coherence (see

* __ARCH_SYNC_CORE_DCACHE).

*/

init_exception_vectors();

……………………….

}

init_exception_vectors这个函数的实现在arch/blackfin/mach-common/ints-priority.c中:

void __init init_exception_vectors(void)

{

SSYNC();

/* cannot program in software:

* evt0 - emulation (jtag)

* evt1 - reset

*/

bfin_write_EVT2(evt_nmi);

bfin_write_EVT3(trap);

bfin_write_EVT5(evt_ivhw);

bfin_write_EVT6(evt_timer);

bfin_write_EVT7(evt_evt7);

bfin_write_EVT8(evt_evt8);

bfin_write_EVT9(evt_evt9);

bfin_write_EVT10(evt_evt10);

bfin_write_EVT11(evt_evt11);

bfin_write_EVT12(evt_evt12);

bfin_write_EVT13(evt_evt13);

bfin_write_EVT14(evt14_softirq);

bfin_write_EVT15(evt_system_call);

CSYNC();

}

从这里可以看出各个中断的中断入口,共13个,其余3个未设置。如下所示:

EVT0EmulationHighest priority. Vector address is provided by JTAG.

EVT1ResetRead-only.

EVT4ReservedReserved vector.

561内部,每个核都有自己的中断向量表,但是在硬件上可以保证只要往同一个地址写入就可以达到目的,因此在这里ab核可以共用这样一段代码。

Note: Each core has its own separate Event Vector Table MMRs (EVT15–EVT0) but the MMR memory locations are aliased such that each core always accesses only its own set of these registers.

1.2 优先级设置

在内核初始化的时候,会调用一个叫program_IAR的函数:

void program_IAR(void)

{

/* Program the IAR0 Register with the configured priority */

bfin_write_SICA_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |

((CONFIG_IRQ_DMA1_ERROR - 7) << IRQ_DMA1_ERROR_POS) |

((CONFIG_IRQ_DMA2_ERROR - 7) << IRQ_DMA2_ERROR_POS) |

((CONFIG_IRQ_IMDMA_ERROR - 7) << IRQ_IMDMA_ERROR_POS) |

((CONFIG_IRQ_PPI0_ERROR - 7) << IRQ_PPI0_ERROR_POS) |

((CONFIG_IRQ_PPI1_ERROR - 7) << IRQ_PPI1_ERROR_POS) |

((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) |

((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS));

bfin_write_SICA_IAR1(((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS) |

((CONFIG_IRQ_UART_ERROR - 7) << IRQ_UART_ERROR_POS) |

((CONFIG_IRQ_RESERVED_ERROR - 7) << IRQ_RESERVED_ERROR_POS) |

((CONFIG_IRQ_DMA1_0 - 7) << IRQ_DMA1_0_POS) |

((CONFIG_IRQ_DMA1_1 - 7) << IRQ_DMA1_1_POS) |

((CONFIG_IRQ_DMA1_2 - 7) << IRQ_DMA1_2_POS) |

((CONFIG_IRQ_DMA1_3 - 7) << IRQ_DMA1_3_POS) |

((CONFIG_IRQ_DMA1_4 - 7) << IRQ_DMA1_4_POS));

bfin_write_SICA_IAR2(((CONFIG_IRQ_DMA1_5 - 7) << IRQ_DMA1_5_POS) |

((CONFIG_IRQ_DMA1_6 - 7) << IRQ_DMA1_6_POS) |

((CONFIG_IRQ_DMA1_7 - 7) << IRQ_DMA1_7_POS) |

((CONFIG_IRQ_DMA1_8 - 7) << IRQ_DMA1_8_POS) |

((CONFIG_IRQ_DMA1_9 - 7) << IRQ_DMA1_9_POS) |

((CONFIG_IRQ_DMA1_10 - 7) << IRQ_DMA1_10_POS) |

((CONFIG_IRQ_DMA1_11 - 7) << IRQ_DMA1_11_POS) |

((CONFIG_IRQ_DMA2_0 - 7) << IRQ_DMA2_0_POS));

bfin_write_SICA_IAR3(((CONFIG_IRQ_DMA2_1 - 7) << IRQ_DMA2_1_POS) |

((CONFIG_IRQ_DMA2_2 - 7) << IRQ_DMA2_2_POS) |

((CONFIG_IRQ_DMA2_3 - 7) << IRQ_DMA2_3_POS) |

((CONFIG_IRQ_DMA2_4 - 7) << IRQ_DMA2_4_POS) |

((CONFIG_IRQ_DMA2_5 - 7) << IRQ_DMA2_5_POS) |

((CONFIG_IRQ_DMA2_6 - 7) << IRQ_DMA2_6_POS) |

((CONFIG_IRQ_DMA2_7 - 7) << IRQ_DMA2_7_POS) |

((CONFIG_IRQ_DMA2_8 - 7) << IRQ_DMA2_8_POS));

bfin_write_SICA_IAR4(((CONFIG_IRQ_DMA2_9 - 7) << IRQ_DMA2_9_POS) |

((CONFIG_IRQ_DMA2_10 - 7) << IRQ_DMA2_10_POS) |

((CONFIG_IRQ_DMA2_11 - 7) << IRQ_DMA2_11_POS) |

((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |

((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |

((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |

((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |

((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS));

bfin_write_SICA_IAR5(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |

((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |

((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |

((CONFIG_IRQ_TIMER8 - 7) << IRQ_TIMER8_POS) |

((CONFIG_IRQ_TIMER9 - 7) << IRQ_TIMER9_POS) |

((CONFIG_IRQ_TIMER10 - 7) << IRQ_TIMER10_POS) |

((CONFIG_IRQ_TIMER11 - 7) << IRQ_TIMER11_POS) |

((CONFIG_IRQ_PROG0_INTA - 7) << IRQ_PROG0_INTA_POS));

bfin_write_SICA_IAR6(((CONFIG_IRQ_PROG0_INTB - 7) << IRQ_PROG0_INTB_POS) |

((CONFIG_IRQ_PROG1_INTA - 7) << IRQ_PROG1_INTA_POS) |

((CONFIG_IRQ_PROG1_INTB - 7) << IRQ_PROG1_INTB_POS) |

((CONFIG_IRQ_PROG2_INTA - 7) << IRQ_PROG2_INTA_POS) |

((CONFIG_IRQ_PROG2_INTB - 7) << IRQ_PROG2_INTB_POS) |

((CONFIG_IRQ_DMA1_WRRD0 - 7) << IRQ_DMA1_WRRD0_POS) |

((CONFIG_IRQ_DMA1_WRRD1 - 7) << IRQ_DMA1_WRRD1_POS) |

((CONFIG_IRQ_DMA2_WRRD0 - 7) << IRQ_DMA2_WRRD0_POS));

bfin_write_SICA_IAR7(((CONFIG_IRQ_DMA2_WRRD1 - 7) << IRQ_DMA2_WRRD1_POS) |

((CONFIG_IRQ_IMDMA_WRRD0 - 7) << IRQ_IMDMA_WRRD0_POS) |

((CONFIG_IRQ_IMDMA_WRRD1 - 7) << IRQ_IMDMA_WRRD1_POS) |

((CONFIG_IRQ_WDTIMER - 7) << IRQ_WDTIMER_POS) |

(0 << IRQ_RESERVED_1_POS) | (0 << IRQ_RESERVED_2_POS) |

(0 << IRQ_SUPPLE_0_POS) | (0 << IRQ_SUPPLE_1_POS));

SSYNC();

}

通过对IAR的编程,可以控制64个外部中断的优先级,在此内核使用了60个宏定义来描述它们的优先级(因为60-634个外部中断是系统保留的)。在默认情况下,内核是这样配置其优先级的:

#define CONFIG_IRQ_SPI_ERROR 7

#define CONFIG_IRQ_DMA1_ERROR 7

#define CONFIG_IRQ_DMA2_ERROR 7

#define CONFIG_IRQ_PPI0_ERROR 7

#define CONFIG_IRQ_PPI1_ERROR 7

#define CONFIG_IRQ_UART_ERROR 7

#define CONFIG_IRQ_RESERVED_ERROR 7

#define CONFIG_IRQ_IMDMA_ERROR 7

#define CONFIG_IRQ_SPORT0_ERROR 7

#define CONFIG_IRQ_SPORT1_ERROR 7

#define CONFIG_IRQ_PLL_WAKEUP 7

#define CONFIG_IRQ_DMA1_WRRD0 8

#define CONFIG_IRQ_DMA1_WRRD1 8

#define CONFIG_IRQ_DMA1_0 8

#define CONFIG_IRQ_DMA1_1 8

#define CONFIG_IRQ_DMA1_2 8

#define CONFIG_IRQ_DMA1_3 8

#define CONFIG_IRQ_DMA1_4 8

#define CONFIG_IRQ_DMA1_5 8

#define CONFIG_IRQ_DMA1_6 8

#define CONFIG_IRQ_DMA1_7 8

#define CONFIG_IRQ_DMA1_8 8

#define CONFIG_IRQ_DMA1_9 8

#define CONFIG_IRQ_DMA1_10 8

#define CONFIG_IRQ_DMA1_11 8

#define CONFIG_IRQ_DMA2_WRRD0 9

#define CONFIG_IRQ_DMA2_WRRD1 9

#define CONFIG_IRQ_DMA2_0 9

#define CONFIG_IRQ_DMA2_1 9

#define CONFIG_IRQ_DMA2_2 9

#define CONFIG_IRQ_DMA2_3 9

#define CONFIG_IRQ_DMA2_4 9

#define CONFIG_IRQ_DMA2_5 9

#define CONFIG_IRQ_DMA2_6 9

#define CONFIG_IRQ_DMA2_7 9

#define CONFIG_IRQ_DMA2_8 9

#define CONFIG_IRQ_DMA2_9 9

#define CONFIG_IRQ_DMA2_10 9

#define CONFIG_IRQ_DMA2_11 9

#define CONFIG_IRQ_TIMER0 10

#define CONFIG_IRQ_TIMER1 10

#define CONFIG_IRQ_TIMER2 10

#define CONFIG_IRQ_TIMER3 10

#define CONFIG_IRQ_TIMER4 10

#define CONFIG_IRQ_TIMER5 10

#define CONFIG_IRQ_TIMER6 10

#define CONFIG_IRQ_TIMER7 10

#define CONFIG_IRQ_TIMER8 10

#define CONFIG_IRQ_TIMER9 10

#define CONFIG_IRQ_TIMER10 10

#define CONFIG_IRQ_TIMER11 10

#define CONFIG_IRQ_PROG0_INTA 11

#define CONFIG_IRQ_PROG1_INTA 11

#define CONFIG_IRQ_PROG2_INTA 11

#define CONFIG_IRQ_PROG0_INTB 11

#define CONFIG_IRQ_PROG1_INTB 11

#define CONFIG_IRQ_PROG2_INTB 11

#define CONFIG_IRQ_IMDMA_WRRD0 12

#define CONFIG_IRQ_IMDMA_WRRD1 12

#define CONFIG_IRQ_WDTIMER 13

在此只定义了7-13,因为中断14留做软件中断,而中断15则留做系统功能调用。

1.3 初始化过程

A核执行的start_kernel函数中,调用了

init_IRQ();

进行中断相关结构体的初始化,而B核则不需要这个过程。init_IRQ这个函数的实现在arch/blackfin/kernel/irqchip.c中:

void __init init_IRQ(void)

{

struct irq_desc *desc;

int irq;

spin_lock_init(&irq_controller_lock);

for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {

*desc = bad_irq_desc;

}

init_arch_irq();

}

在此函数中对irq_desc这一全局数组赋了一个初值bad_irq_desc,这是一个全局变量:

static struct irq_chip bad_chip = {

.ack = dummy_mask_unmask_irq,

.mask = dummy_mask_unmask_irq,

.unmask = dummy_mask_unmask_irq,

};

static struct irq_desc bad_irq_desc = {

.chip = &bad_chip,

.handle_irq = handle_bad_irq,

.depth = 1,

};

实际上handle_bad_irq总不被执行,因此略过它。此函数的最后调用init_arch_irq进行下一步的设置。

1.4 init_arch_irq

此函数位于arch/blackfin/mach-common/int-priority-dc.c

/*

* This function should be called during kernel startup to initialize

* the BFin IRQ handling routines.

*/

int __init init_arch_irq(void)

{

int irq;

unsigned long ilat = 0;

/* Disable all the peripheral intrs - page 4-29 HW Ref manual */

bfin_write_SICA_IMASK0(SIC_UNMASK_ALL);

bfin_write_SICA_IMASK1(SIC_UNMASK_ALL);

#ifdef CONFIG_SMP

bfin_write_SICB_IMASK0(SIC_UNMASK_ALL);

bfin_write_SICB_IMASK1(SIC_UNMASK_ALL);

#endif

SSYNC();

local_irq_disable();

for (irq = 0; irq < SYS_IRQS; irq++) {

if (irq <= IRQ_CORETMR)

set_irq_chip(irq, &bf561_core_irqchip);

else

set_irq_chip(irq, &bf561_internal_irqchip);

#ifdef CONFIG_IRQCHIP_DEMUX_GPIO

if ((irq == IRQ_PROG0_INTA) ||

(irq == IRQ_PROG1_INTA) || (irq == IRQ_PROG2_INTA))

set_irq_chained_handler(irq, bf561_demux_gpio_irq);

else

#endif

#ifdef CONFIG_TICK_SOURCE_SYSTMR0

if (irq == IRQ_TIMER0)

set_irq_handler(irq, handle_percpu_irq);

else

#endif

set_irq_handler(irq, handle_simple_irq);

}

#ifdef CONFIG_IRQCHIP_DEMUX_GPIO

for (irq = IRQ_PF0; irq <= IRQ_PF47; irq++) {

set_irq_chip(irq, &bf561_gpio_irqchip);

/* if configured as edge, then will be changed to do_edge_IRQ */

set_irq_handler(irq, handle_level_irq);

}

#endif

bfin_write_IMASK(0);

CSYNC();

ilat = bfin_read_ILAT();

CSYNC();

bfin_write_ILAT(ilat);

CSYNC();

printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");

/* IMASK=xxx is equivalent to STI xx or irq_flags=xx,

* local_irq_enable()

*/

program_IAR();

/* Therefore it's better to setup IARs before interrupts enabled */

search_IAR();

/* Enable interrupts IVG7-15 */

irq_flags = irq_flags | IMASK_IVG15 |

IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |

IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;

bfin_write_SICA_IWR0(IWR_ENABLE_ALL);

bfin_write_SICA_IWR1(IWR_ENABLE_ALL);

return 0;

}

这个函数完成了中断的基本配置。

分享到:
评论

相关推荐

    STM32f407中断矩阵键盘

    2. 初始化中断:在代码中初始化外部中断,设置中断触发条件(例如上升沿、下降沿、边沿触发等)。 3. 中断处理:当按键被按下时,对应的列引脚将会触发外部中断,进入中断服务程序(ISR)。在ISR中,可以读取行引脚...

    疯狂内核之——内核初始化

    5.10 初始化中断处理系统 256 5.10.1 设置APIC中断服务 256 5.10.2 初始化本地软时钟 264 5.10.3 软中断初始化 268 5.10.4 初始化定时器中断 271 5.11 走进start_kernel尾声 273 5.11.1 初始化slab的后续工作 273 ...

    Linux内核 内容很全

    中断处理与设备驱动程序 60 6.1 中断与中断处理 60 6.1.1 可编程中断控制器 61 6.1.2 初始化中断处理数据结构 61 6.1.3 中断处理 62 6.2 设备驱动程序 63 6.2.1 测试与中断 64 6.2.2 直接...

    cortex_m3的中断优先级描述及设置

    cotex_m3中断优先级的描述和配置,非常仔细

    Windows内核安全与驱动开发光盘源码

    第1章 内核上机指导 2 1.1 下载和使用WDK 2 1.1.1 下载并安装WDK 2 1.1.2 编写第一个C文件 4 1.1.3 编译一个工程 5 1.2 安装与运行 6 1.2.1 下载一个安装工具 6 1.2.2 运行与查看输出信息 7 1.2.3 在虚拟机...

    寒江独钓-Windows内核安全编程(高清完整版).part4

    11.6.4 处理读请求 368 11.6.5 处理写请求 370 11.7 协议驱动的接收问题 374 11.7.1 和接收包有关的回调函数 374 11.7.2 ReceiveHandler的实现 376 11.7.3 TransferDataCompleteHandler的实现 380 11.7.4 ...

    寒江独钓-Windows内核安全编程(高清完整版).part1

    11.6.4 处理读请求 368 11.6.5 处理写请求 370 11.7 协议驱动的接收问题 374 11.7.1 和接收包有关的回调函数 374 11.7.2 ReceiveHandler的实现 376 11.7.3 TransferDataCompleteHandler的实现 380 11.7.4 ...

    龙芯内核开发

    根据龙芯平台 Linux 内核实际情况,将内核的源码文件分为三部分: 驱动部分、体系架构相关部分 以及公共部分。 a) 驱动部分: 包含内核 driver 目录下所有的文件。 b) 体系架构相关部分:内核源码中与体系架构相关的...

    寒江独钓-Windows内核安全编程(高清完整版).part3

    11.6.4 处理读请求 368 11.6.5 处理写请求 370 11.7 协议驱动的接收问题 374 11.7.1 和接收包有关的回调函数 374 11.7.2 ReceiveHandler的实现 376 11.7.3 TransferDataCompleteHandler的实现 380 11.7.4 ...

    寒江独钓-Windows内核安全编程(高清完整版).part7

    11.6.4 处理读请求 368 11.6.5 处理写请求 370 11.7 协议驱动的接收问题 374 11.7.1 和接收包有关的回调函数 374 11.7.2 ReceiveHandler的实现 376 11.7.3 TransferDataCompleteHandler的实现 380 11.7.4 ...

    Linux编程--Linux内核

    6.1 中断与中断处理 60 6.1.1 可编程中断控制器 61 6.1.2 初始化中断处理数据结构 61 6.1.3 中断处理 62 6.2 设备驱动程序 63 6.2.1 测试与中断 64 6.2.2 直接存储器访问(DMA) 65 6.2.3 存储器 66 6.2.4 设备驱动...

    寒江独钓-Windows内核安全编程(高清完整版).part5

    11.6.4 处理读请求 368 11.6.5 处理写请求 370 11.7 协议驱动的接收问题 374 11.7.1 和接收包有关的回调函数 374 11.7.2 ReceiveHandler的实现 376 11.7.3 TransferDataCompleteHandler的实现 380 11.7.4 ...

    寒江独钓-Windows内核安全编程(高清完整版).part6

    11.6.4 处理读请求 368 11.6.5 处理写请求 370 11.7 协议驱动的接收问题 374 11.7.1 和接收包有关的回调函数 374 11.7.2 ReceiveHandler的实现 376 11.7.3 TransferDataCompleteHandler的实现 380 11.7.4 ...

    使用proc系统访问linux内核

    使用proc系统访问linux内核的原理,读写方式,

    寒江独钓-Windows内核安全编程(高清完整版).part2

    11.6.4 处理读请求 368 11.6.5 处理写请求 370 11.7 协议驱动的接收问题 374 11.7.1 和接收包有关的回调函数 374 11.7.2 ReceiveHandler的实现 376 11.7.3 TransferDataCompleteHandler的实现 380 11.7.4 ...

    Windows内核安全驱动开发(随书光盘)

    第1章 内核上机指导 2 1.1 下载和使用WDK 2 1.1.1 下载并安装WDK 2 1.1.2 编写第一个C文件 4 1.1.3 编译一个工程 5 1.2 安装与运行 6 1.2.1 下载一个安装工具 6 1.2.2 运行与查看输出信息 7 1.2.3 在虚拟机...

    基于Linux内核的键盘模拟实现

    当前,由于Linux资源完全公开,使得Linux的发展日益广泛快速。基于Linux的各种应用已逐渐深入日常生活的方方面面,尤其是在嵌入式领域,由于内核可裁减定制,因此可随意地根据用户需求进行整个系统的定制与重构

    数字信号处理器DSP原理及其应用

    资料2:DSP典型应用解决方案 187 资料3:基于算法的DSP硬件结构分析 194 资料4:数字信号处理器的选择策略 197 资料5:基于DSP混合编程关键问题的研究 202 资料6:DSP高手的经验介绍,编写基于DSP程序的注意事项...

    Linux内核编程part1

    x86和PPC汇编语言●查看内核内部状态●Linux进程模型●用户空间和内核空间●中断和异常●内存分配和跟踪●跟踪子系统行为●I/O交互●文件系统和文件操作●调度和同步●内核启动过程●内核构建过程●配置选项●设备...

    三级嵌入式系统开发技术题库.docx

    2:嵌入式系统硬件的核心是CPU。下面关于嵌入式系统CPU特点的叙述中,错误的是()。 A:支持实时处理 B:低功耗 C:字长在16位以下 D:集成了测试电路 3:下面关于微控制器的叙述中,错误的是()。 A:微控制器将整个...

Global site tag (gtag.js) - Google Analytics