linux内核学习10.2:编写一个I/O中断

linux驱动编写一个中断,有下面几步操作:

  1. 申请中断
  2. 注册的中断服务函数
  3. 卸载中断

申请中断使用的函数有

inline int __must_check  request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)

int request_threaded_irq(unsigned int irq, irq_handler_t handler,
			 irq_handler_t thread_fn, unsigned long irqflags,
			 const char *devname, void *dev_id)

request_irq实际调用的是request_threaded_irq

static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
	    const char *name, void *dev)
{
	return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

参数如下:

unsigned int irq:为要注册中断服务函数的中断号,定义在mach/irqs.h
irq_handler_t handler:为要注册的中断服务函数
unsigned long irqflags: 触发中断的参数,比如边沿触发, 定义在linux/interrupt.h。
const char *devname:中断程序的名字,使用cat /proc/interrupt 可以查看中断程序名字
void *dev_id:传入中断处理程序的参数,注册共享中断时不能为NULL,因为卸载时需要这个做参数,避免卸载其它中断服务函数

例如,我们要对GPIO35检查上拉中断,进行如下配置:

request_irq(gpio_to_irq(SABRESD_POWER_OFF), button_irq, IRQ_TYPE_EDGE_FALLING, "S1",(void *)&pin_desc[0]);

button_irq是中断服务函数
IRQ_TYPE_EDGE_FALLING //下降沿触发
#define IRQ_TYPE_NONE        0
#define IRQ_TYPE_EDGE_RISING    1//上升沿触发
#define IRQ_TYPE_EDGE_FALLING    2//下降沿触发
#define IRQ_TYPE_EDGE_BOTH    (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)//双边沿触发
#define IRQ_TYPE_LEVEL_HIGH    4//高电平触发
#define IRQ_TYPE_LEVEL_LOW    8//低电平触发

"S1":中断程序的名字
(void *)&pin_desc[0]:传入中断处理程序的参数,即button_irq的参数
/* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */
/* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */
/* 主要是为了区分是按下还是松开 */
static unsigned char key_val = 0;
irqreturn_t button_irq(int irq, void *devid)
{
 
	int pin_val;
	struct pin_desc *pin_readed;
 
	pin_readed = (struct pin_desc *)devid;
	/* 1 获取当前引脚的电平值 */
	pin_val = gpio_get_value(pin_readed->pin);
	/* 2 根据电平值判断当前是按下还是松开 */
	if (pin_val) /* 松开为高电平,返回0x8x */
	{
		key_val = 0x80 | pin_readed->key_val;
	}
	else /* 按下为低电平,返回0x0x */
	{
		//把当前按键的键值给一个全局静态变量,在read函数里给用户
		key_val = pin_readed->key_val;
	}
 
	printk("%02x ", key_val);
 
	wake_up(&Key_Status_Read_Wait);
	wait_flag = 1;
	/* 3 标记中断已经触发 */
	return IRQ_RETVAL(IRQ_HANDLED);
}



/*退出函数*/
static void ButtonDriver_Exit(void)
{
	free_irq(gpio_to_irq(SABRESD_POWER_OFF), (void *)&pin_desc[0]);
	....

	/* 释放注册的4个中断 */
	/*********************************************************
	free_irq(unsigned int irq, void *dev_id);
	参数说明:
	unsigned int  irq:要卸载的中断号
	void  *dev_id:这个是要卸载的中断action下的哪个服务函数,
	***********************************************************/
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值