Linux GPIO & IRQ Driver

本文深入探讨了Linux内核中GPIO接口的使用,包括GPIO的申请、高电平和低电平输出、输入操作,以及中断的申请和处理。通过源码分析,解析了request_irq函数的各个参数及其作用,并提供了查看中断号的命令示例。同时,讨论了/proc/interrupts和/proc/stat文件在监控中断活动中的作用。

本文主要描述了GPIO口的申请和高低电平输出、输入,以及中断的申请和调用等

Linux Kernel 中使用GPIO,不能直接引用和操作GPIO的物理地址,而需要把物理地址映射为内存中的虚拟地址,然后对映射的虚拟地址进行操作。

大致情况是这样的,以下通过实际代码分析linux GPIO的简单的驱动分析。

一、一种情况的GPIO驱动和IRQ中断服务申请

1.1、源码实例:

#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial.h>

#include <asm/irq.h>
#include <mach/hardware.h>
#include <plat/regs-serial.h>
#include "samsung.h"

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/clk.h>

#include <linux/io.h>
#include <mach/hardware.h>
#include <linux/delay.h>
#include <asm/irq.h>

#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>

#include <plat/s5pv210.h>
#include <plat/gpio-cfg.h>
#include <linux/gpio.h>
struct scan_button_irq_desc
{	
	int irq;
	int pin;
	int pin_setting;
//	int number;
	char *name;
};

static struct scan_button_irq_desc scan_button_irq[] =
{
	{IRQ_EINT7,S5PV210_GPH0(7),IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"scan_trig"},
};

static irqreturn_t  s3c_gpio_scan_isr(int irq,void* dev_id)
{

	unsigned int key_status;	
	u32 cfg;

	//void __iomem *base = S5PV210_GPG1DAT;
	cfg = readl(S5PV210_GPG1CON);
	cfg &= (0xf<<20); //clear gpg1_5 con
	cfg |= (1 << 20); //out put cfg
	writel(cfg,S5PV210_GPG1CON);
	printk("scanmodule pwr ctrl con: %d",readl(S5PV210_GPG1CON));
	
	cfg = readl(S5PV210_GPG1DAT);
	cfg |= (1 << 5);
	writel(cfg,S5PV210_GPG1DAT);
	printk("scanmodule pwr ctrl dat: %d",readl(S5PV210_GPG1DAT));

	key_status = (readl(S5PV210_GPH0DAT)) & (1 << 7);
	printk("scan_button,keyval:%d : %s\n", GPIO_KEY, key_status?"released":"pressed");
	
	return IRQ_HANDLED;
}

static int s3c_gpio_scan_isr_setup(void)
{
	int ret;
~~~~
	s3c_gpio_cfgpin(S5PV210_GPH0(7), S3C_GPIO_SPECIAL(0xf)); //配置gpio为中断输出,Eint7  
	s3c_gpio_setpull(S5PV210_GPH0(7), S3C_GPIO_PULL_UP);  //S3C_GPIO_PULL_NONE
	
	set_irq_wake(scan_button_irq[0].irq, 1);
	ret = request_irq(scan_button_irq[0].irq, s3c_gpio_scan_isr,  
		IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING,
		scan_button_irq[0].name, (void *)&scan_button_irq);
	if (ret) {
		printk("request IRQ for scan triger failed\n");
		ret = -EIO;
	}
~~~~
	return ret;
}

static int __init XXX_init(void)
{
~~~~
	//中断申请
	ret = s3c_gpio_scan_isr_setup();
	if(!ret)
		printk("IRQ request successfully\n");
	else
		printk("IRQ request failed");
~~~~
	return 0;
}

static void __exit XXX_exit(void)
{

~~~~
        //IRQ srv free
	free_irq(scan_button_irq[0].irq,(void *)&scan_button_irq);

~~~~

}

1.2、中断申请函数原型及分析:

1.2.1、原型

int request_irq(unsigned int irqirqreturn_t (*handler)(int, void *,struct pt_regs *),unsigned long flags, const char *dev_name, void *dev_id);
void free_irq(unsigned int irq, void *dev_id);

1.2.2、分析

1)、unsigned int irq:所要注册的中断号
2)、irqreturn_t (*handler)(int, void *, struct pt_regs *):中断服务程序的入口地址。
3)、unsigned long flags:与中断管理有关的位掩码选项,有三组值:
          SA_INTERRUPT : 快速中断处理程序,当使用它的是后处理器上所有的其他中断都被禁用;
          SA_SHIRQ :           该中断是在设备之间可共享的;
          SA_SAMPLE_RANDOM :  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值