八、【interrupt】按键中断

一、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:中断的结构体

 

二、查看中断

八、【interrupt】按键中断

 

三、中断号

中断号其实就是一个整数,该整数是内核给每个中断源的唯一编号。

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

  

  

 

  

 

  

  

 

上一篇:浅谈深度学习、Pytorch框架的一些必备的理论知识


下一篇:几种方式保存爬虫爬取的数据 - Python