linux内核为了应对此问题,引入了IRQ-domain的概念 irq-domain的引入相当于一个中断控制器就是一个irq-domain。就是一个中断区域。...; } 开机已经分配好了的,用于irq比较少 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ......_RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), } }; 通过irq_to_desc函数来获取desc通过irq的值,两种方式 struct irq_desc...*irq_to_desc(unsigned int irq) { return radix_tree_lookup(&irq_desc_tree, irq); } struct irq_desc...= desc->irq_data.irq; struct irqaction *action; record_irq_time(desc); for_each_action_of_desc
本节目标: 分析在linux中的中断是如何运行的,以及中断3大结构体:irq_desc、irq_chip、irqaction 在裸板程序中(参考stmdb和ldmia详解): 1.按键按下, 2...., { r0-r12,pc }^ //^表示将spsr的值复制到cpsr,因为异常返回后需要恢复异常发生前的工作状态 在linux中: 需要先设置异常向量地址(参考linux应用手册P412): 在ARM...而linux内核中异常向量基地址是0xffff0000(虚拟地址), 位于代码arch/cam/kernel/traps.c,代码如下: void __init trap_init(void) {...*desc = irq_desc + irq; // irq_desc是个数组(位于kernel/irq/handle.c) if (irq >= NR_IRQS) desc = &bad_irq_desc...代码如下: desc->handle_irq(irq, desc);//相当于执行irq_desc[irq]-> handle_irq(irq, irq_desc[irq]); 它会执行handle_irq
前段时间一工程师向我咨询了一个问题,问我为什么他的MCU KEIL工程代码里没有找到__disable_irq() 和 __enable_irq()的具体定义,是不是有问题。...__disable_irq() 和 __enable_irq() 是所谓的intrinsic函数,编译器自动识别并替换为相关的指令,它们其实是编译器的一部分,实际的定义位于arm_compat.h 文件中...这说明__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,当中断发生后,相应的寄存器会将中断标志置位,在__enable_irq()开启中断后,由于相应的中断标志没有清空...实际测试如果在调用__disable_irq()后、__enable_irq()之前的这3s时间内按下按键,并不会进入中断翻转LED,虽然这时中断标志位已经产生了。...但是调用__enable_irq()之后就会立刻进入到中断服务函数中。
unsigned *)0x4a000008) //Interrupt mask control #define rPRIORITY (*(volatile unsigned *)0x4a00000c) //IRQ..._ISR_STARTADDRESS+0x10)) #define pISR_RESERVED (*(unsigned *)(_ISR_STARTADDRESS+0x14)) #define pISR_IRQ
; } kernel/include/linux/irqflags.h #define raw_local_irq_disable() arch_local_irq_disable() #define...desc->depth++) 369 irq_disable(desc); 370 } chip.c 216 void irq_disable(struct irq_desc *desc...desc->irq_data.chip->irq_disable(&desc->irq_data); 221 irq_state_set_masked(desc); 222 }...static inline void mask_ack_irq(struct irq_desc *desc) { if (desc->irq_data.chip->irq_mask_ack)...->irq_mask(&desc->irq_data); if (desc->irq_data.chip->irq_ack) desc->irq_data.chip
EXPORT声明一个符号Default_IRQ_ISR可以被其它文件引用 Default_IRQ_ISR ;定义一个Default_IRQ_ISR,并且啥也不干 B ....;B Default_IRQ_ISR代表啥都不干(因为上面对Default_IRQ_ISR中的操作定义就是啥都没干) EINT1_Handle B Default_IRQ_ISR...B Default_IRQ_ISR TICK_Handle B Default_IRQ_ISR WDT_AC97_Handle B Default_IRQ_ISR...Default_IRQ_ISR ISR_SDI_Handle B Default_IRQ_ISR ISR_SPI0_Handle B Default_IRQ_ISR ISR_UART1...B Default_IRQ_ISR ISR_ADC_Handle B Default_IRQ_ISR IRQ_Handler PROC EXPORT IRQ_Handler
EXPORT声明一个符号Default_IRQ_ISR可以被其它文件引用 Default_IRQ_ISR ;定义一个Default_IRQ_ISR,并且啥也不干 B ....;B Default_IRQ_ISR代表啥都不干(因为上面对Default_IRQ_ISR中的操作定义就是啥都没干) EINT1_Handle B Default_IRQ_ISR..._Handle B Default_IRQ_ISR ISR_UART2_Handle B Default_IRQ_ISR ISR_LCD_Handle B Default_IRQ_ISR...Default_IRQ_ISR ISR_DMA3_Handle B Default_IRQ_ISR ISR_SDI_Handle B Default_IRQ_ISR ISR_SPI0...B Default_IRQ_ISR ISR_ADC_Handle B Default_IRQ_ISR IRQ_Handler PROC EXPORT IRQ_Handler
处理流程对比 在这里插入图片描述 参考资料: linux kernel的中断子系统之(七):GIC代码分析 Linux 4.9.88内核源码 Linux-4.9.88\drivers...\gpio\gpio-mxc.c Linux-4.9.88\arch\arm\boot\dts\imx6ull.dtsi Linux 5.4内核源码 Linux-5.4\drivers\pinctrl...\stm32\pinctrl-stm32mp157.c Linux-5.4\drivers\irqchip\irq-stm32-exti.c Linux-5.4\arch\arm\boot\dts\stm32mp151...mask/ack中断: 调用irq_desc[102].irq_data->irq_chip的函数 调用irq_desc[102].action链表中用户注册的函数 unmask中断: 调用irq_desc...irq_dataA->irq_chip的函数 调用irq_desc[236].action链表中用户注册的函数 unmask中断: 调用irq_desc[236].irq_data->irq_chip
EXPORT声明一个符号Default_IRQ_ISR可以被其它文件引用 Default_IRQ_ISR ;定义一个Default_IRQ_ISR,并且啥也不干 B ....;B Default_IRQ_ISR代表啥都不干(因为上面对Default_IRQ_ISR中的操作定义就是啥都没干) EINT1_Handle B Default_IRQ_ISR...B Default_IRQ_ISR TICK_Handle B Default_IRQ_ISR WDT_AC97_Handle B Default_IRQ_ISR...Default_IRQ_ISR ISR_TIMER3_Handle B Default_IRQ_ISR ISR_TIMER4_Handle B Default_IRQ_ISR ISR_UART2...Default_IRQ_ISR ISR_SDI_Handle B Default_IRQ_ISR ISR_SPI0_Handle B Default_IRQ_ISR ISR_UART1
Interrupt mode control INTMSK EQU 0x4a000008 ;Interrupt mask control PRIORITY EQU 0x4a00000c ;IRQ...SUB_STACK_SIZE EQU 128 ;定义变量子栈大小 STACK_BASE EQU (0x00001000) ;定义栈的基址 IRQStack_BASE EQU STACK_BASE ;定义IRQ
Interrupt mode control INTMSK EQU 0x4a000008 ;Interrupt mask control PRIORITY EQU 0x4a00000c ;IRQ
SUB_STACK_SIZE EQU 128 ;定义变量子栈大小 STACK_BASE EQU (0x00001000) ;定义栈的基址 IRQStack_BASE EQU STACK_BASE ;定义IRQ...unsigned *)0x4a000008) //Interrupt mask control #define rPRIORITY (*(volatile unsigned *)0x4a00000c) //IRQ..._ISR_STARTADDRESS+0x10)) #define pISR_RESERVED (*(unsigned *)(_ISR_STARTADDRESS+0x14)) #define pISR_IRQ
最核心的结构体是irq_desc,之前为了易于理解,我们说在Linux内核中有一个中断数组,对于每一个硬件中断,都有一个数组项,这个数组就是irq_desc数组。...1.irq_desc数组 irq_desc结构体在include/linux/irqdesc.h中定义,主要内容如下图: ?...注意: irq_desc[A].handle_irq细分出中断后B,调用对应的irq_desc[B].handle_irq。...3. irq_data结构体 irq_data结构体在include/linux/irq.h中定义,主要内容如下图: ?...② map 把hwirq转换为irq。 5.irq_chip结构体 irq_chip结构体在include/linux/irq.h中定义,主要内容如下图: ?
在内核中每条IRQ线由结构体 irq_desc_t 来描述,irq_desc_t 定义如下: typedef struct { unsigned int status; /* IRQ...unsigned int depth; /* nested irq disables */ spinlock_t lock; } irq_desc_t; 下面介绍一下 irq_desc_t...unsigned long flags; struct irqaction *old, **p; irq_desc_t *desc = irq_desc + irq; ......[irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); status = desc->status & ~(IRQ_REPLAY...return 1; } do_IRQ() 函数首先通过IRQ号获取到其对应的 irq_desc_t 结构,注意的是同一个中断有可能发生多次,所以要判断当前IRQ是否正在被处理当中(判断 irq_desc_t
GIC中断处理流程源码分析 参考资料: linux kernel的中断子系统之(七):GIC代码分析 Linux 4.9.88内核源码 Linux-4.9.88\drivers\irqchip...\irq-gic.c Linux-4.9.88/arch/arm/boot/dts/imx6ull.dtsi Linux 5.4内核源码 Linux-5.4\drivers\irqchip\irq-gic.c...1.1 一级中断控制器处理流程 对于irq_desc,内核有两种分配方法: 一次分配完所有的irq_desc 按需分配(用到某个中断才分配它的irq_desc 现在的内核基本使用第1种方法。...\irqchip.c) of_irq_init (drivers\of\irq.c) desc->irq_init_cb = match->data;...ret = desc->irq_init_cb(desc->dev, desc->interrupt_parent); 2.1 内核支持多种GIC
(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2])...(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2])...(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2])...(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2])...(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2])
EXPORT声明一个符号Default_IRQ_ISR可以被其它文件引用 Default_IRQ_ISR ;定义一个Default_IRQ_ISR,并且啥也不干 B ....;B Default_IRQ_ISR代表啥都不干(因为上面对Default_IRQ_ISR中的操作定义就是啥都没干) EINT1_Handle B Default_IRQ_ISR...Default_IRQ_ISR ISR_UART2_Handle B Default_IRQ_ISR ISR_LCD_Handle B Default_IRQ_ISR ISR_DMA0...B Default_IRQ_ISR ISR_USBH_Handle B Default_IRQ_ISR ISR_IIC_Handle B Default_IRQ_ISR...Default_IRQ_ISR ISR_ADC_Handle B Default_IRQ_ISR IRQ_Handler PROC EXPORT IRQ_Handler
EXPORT声明一个符号Default_IRQ_ISR可以被其它文件引用 Default_IRQ_ISR ;定义一个Default_IRQ_ISR,并且啥也不干 B ....Default_IRQ_ISR TICK_Handle B Default_IRQ_ISR WDT_AC97_Handle B Default_IRQ_ISR ISR_TIMER0...Default_IRQ_ISR ISR_LCD_Handle B Default_IRQ_ISR ISR_DMA0_Handle B Default_IRQ_ISR ISR_DMA1...B Default_IRQ_ISR ISR_IIC_Handle B Default_IRQ_ISR ISR_UART0_Handle B Default_IRQ_ISR...B Default_IRQ_ISR ISR_ADC_Handle B Default_IRQ_ISR IRQ_Handler PROC EXPORT IRQ_Handler
interrupt.h> #include #include #include #include struct pin_desc{ int irq; char *name; unsigned int pin; unsigned int key_val; }; struct pin_desc...pins_desc[4] = { {IRQ_EINT0, "S2", S3C2410_GPF0, KEY_L}, {IRQ_EINT2, "S3", S3C2410_GPF2, KEY_S...(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]); } return 0; }...static void buttons_exit(void) { int i; for (i = 0; i < 4; i++) { free_irq(pins_desc[i].irq, &pins_desc
领取专属 10元无门槛券
手把手带您无忧上云