一、linux内核中中断的使用
1、申请中断
static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
参数:
- irq: 中断号
- handler:中断处理程序
- flags:中断标志,
对应外部中断,flags表示中断触发的方式:
#define IRQF_TRIGGER_NONE 0x00000000 #define IRQF_TRIGGER_RISING 0x00000001 #define IRQF_TRIGGER_FALLING 0x00000002 #define IRQF_TRIGGER_HIGH 0x00000004 #define IRQF_TRIGGER_LOW 0x00000008
对于其他一般中断,flags用于设置中断的处理方式:
#define IRQF_DISABLED 0x00000020 #define IRQF_SAMPLE_RANDOM 0x00000040 #define IRQF_SHARED 0x00000080
- name:自定义的中断名。
- dev:传递给中断处理程序的实参。
返回值:
成功返回0,否则返回负值。
2、中断处理程序
irqreturn_t xxx_handler(int irq, void * dev
参数:
- irq:中断号。
- dev:中断申请函数传过来的参数。
返回值:
返回值为以下三个枚举值,IR_HANDLED表示中断被正确处理了
enum irqreturn { IRQ_NONE = (0 << 0), IRQ_HANDLED = (1 << 0), IRQ_WAKE_THREAD = (1 << 1), };
3、中断注销
void free_irq(unsigned int irq, void *dev_id)
参数:
- irq:中断号。
- dev_id:中断的结构体
二、查看中断
三、中断号
中断号其实就是一个整数,该整数是内核给每个中断源的唯一编号。
6818主板的中断号定义在s5p6818_irq.h中
1、外部中断号
#define IRQ_GPIO_A_START (IRQ_GPIO_START + PAD_GPIO_A) #define IRQ_GPIO_B_START (IRQ_GPIO_START + PAD_GPIO_B) #define IRQ_GPIO_C_START (IRQ_GPIO_START + PAD_GPIO_C) #define IRQ_GPIO_D_START (IRQ_GPIO_START + PAD_GPIO_D) #define IRQ_GPIO_E_START (IRQ_GPIO_START + PAD_GPIO_E)
2、其他一般中断的中断号
#define IRQ_PHY_MCUSTOP (0 + 32) #define IRQ_PHY_DMA0 (1 + 32) #define IRQ_PHY_DMA1 (2 + 32) #define IRQ_PHY_CLKPWR_INTREQPWR (3 + 32) #define IRQ_PHY_CLKPWR_ALIVEIRQ (4 + 32) #define IRQ_PHY_CLKPWR_RTCIRQ (5 + 32) #define IRQ_PHY_UART1 (6 + 32) // pl01115_Uart_modem #define IRQ_PHY_UART0 (7 + 32) // UART0_MODULE #define IRQ_PHY_UART2 (8 + 32) // UART1_MODULE #define IRQ_PHY_UART3 (9 + 32) // pl01115_Uart_nodma0 #define IRQ_PHY_UART4 (10 + 32) // pl01115_Uart_nodma1 #define IRQ_PHY_UART5 (11 + 32) // pl01115_Uart_nodma2 #define IRQ_PHY_SSP0 (12 + 32) #define IRQ_PHY_SSP1 (13 + 32) #define IRQ_PHY_SSP2 (14 + 32) #define IRQ_PHY_I2C0 (15 + 32) #define IRQ_PHY_I2C1 (16 + 32) #define IRQ_PHY_I2C2 (17 + 32) #define IRQ_PHY_DEINTERLACE (18 + 32) #define IRQ_PHY_SCALER (19 + 32) #define IRQ_PHY_AC97 (20 + 32) #define IRQ_PHY_SPDIFRX (21 + 32) #define IRQ_PHY_SPDIFTX (22 + 32) #define IRQ_PHY_TIMER_INT0 (23 + 32) #define IRQ_PHY_TIMER_INT1 (24 + 32) #define IRQ_PHY_TIMER_INT2 (25 + 32) #define IRQ_PHY_TIMER_INT3 (26 + 32) #define IRQ_PHY_PWM_INT0 (27 + 32) #define IRQ_PHY_PWM_INT1 (28 + 32) #define IRQ_PHY_PWM_INT2 (29 + 32) #define IRQ_PHY_PWM_INT3 (30 + 32) #define IRQ_PHY_WDT (31 + 32) #define IRQ_PHY_MPEGTSI (32 + 32) #define IRQ_PHY_DPC_P (33 + 32) #define IRQ_PHY_DPC_S (34 + 32) #define IRQ_PHY_RESCONV (35 + 32) #define IRQ_PHY_HDMI (36 + 32) #define IRQ_PHY_VIP0 (37 + 32) #define IRQ_PHY_VIP1 (38 + 32) #define IRQ_PHY_MIPI (39 + 32) #define IRQ_PHY_VR (40 + 32) #define IRQ_PHY_ADC (41 + 32) #define IRQ_PHY_PPM (42 + 32) #define IRQ_PHY_SDMMC0 (43 + 32) #define IRQ_PHY_SDMMC1 (44 + 32) #define IRQ_PHY_SDMMC2 (45 + 32) #define IRQ_PHY_CODA960_HOST (46 + 32) #define IRQ_PHY_CODA960_JPG (47 + 32) #define IRQ_PHY_GMAC (48 + 32) #define IRQ_PHY_USB20OTG (49 + 32) #define IRQ_PHY_USB20HOST (50 + 32) #define IRQ_PHY_CAN0 (51 + 32) #define IRQ_PHY_CAN1 (52 + 32) #define IRQ_PHY_GPIOA (53 + 32) #define IRQ_PHY_GPIOB (54 + 32) #define IRQ_PHY_GPIOC (55 + 32) #define IRQ_PHY_GPIOD (56 + 32) #define IRQ_PHY_GPIOE (57 + 32) #define IRQ_PHY_CRYPTO (58 + 32) #define IRQ_PHY_PDM (59 + 32) #define IRQ_PHY_TMU0 (60 + 32) #define IRQ_PHY_TMU1 (61 + 32) #define IRQ_PHY_VIP2 (72 + 32)
3、三个中断共用一个中断处理程序
如何区分是哪个中断发生导致中断处理程序被内核调用的?
(1)通过中断号----某个中断发生,该中断的中断号会传递给中断处理程序的第一个形参
(2)通过注册时,传递给中断处理程序不同 (void * dev)
4、中断处理程序是一个原子过程
中断处理过程是原子的,不能在中断处理程序中使用可能导致阻塞的函数,例如:
ssleep 、copy_to_user/copy_from_user、获取信号量..
不然会导致如下错误:
[ 39.085000] Exception stack(0xc0a93f58 to 0xc0a93fa0) [ 39.085000] 3f40: ffffffed 00000000 [ 39.085000] 3f60: 00000000 00000000 c0a92000 c0b2c248 c0738290 c0a92000 c0a92000 c0ab0128 [ 39.085000] 3f80: 00000000 00000000 00000019 c0a93fa0 c000f83c c000f840 600d0013 ffffffff [ 39.085000] [<c000e840>] (__irq_svc+0x40/0x70) from [<c000f840>] (default_idle+0x2c/0x30) [ 39.085000] [<c000f840>] (default_idle+0x2c/0x30) from [<c000fb90>] (cpu_idle+0xd8/0x104) [ 39.085000] [<c000fb90>] (cpu_idle+0xd8/0x104) from [<c0a5483c>] (start_kernel+0x328/0x334) [ 39.085000] ---[ end trace 340d61c57173f93b ]--- [ 39.085000] BUG: scheduling while atomic: swapper/0/0/0x00010002---------在原子过程中启动了调度器
内核中提供的延时函数
udelay() ndelay()