硬件对应
HOME→UART_RING→GPX1_1
BACK→SIM_DET→GPX1_2
SWITCH3→AP_SLEEP→GPC0_3
SWITCH4→XEINT6→GPX0_6
GPIO读取
步骤:
- 申请GPIO gpio_request(EXYNOS4_GPX1(1),"HOME");
- 设置模式,输入模式 s3c_gpio_cfgpin(EXYNOS4_GPX1(1),S3C_GPIO_INPUT);
- 设置上下拉,既不上拉也不下拉 s3c_gpio_setpull(EXYNOS4_GPX1(1),S3C_GPIO_PULL_NONE);
- 读取 gpio_get_value(EXYNOS4_GPC0(3));
中断注册
头文件
#include <linux/irq.h>
#include <linux/interrupt.h>
结合技术手册查找中断号:
HOME→UART_RING→GPX1_1 → GPX1CON→KP_COL[1] →XEINT_9
中断注册函数:
static inline int __must_check
request_irq(
unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char *name,
void *dev_id)
参数:
- irq中断号。(和平台架构相关,结合datasheet以及平台文件) IRQ_EINT(x)
- 中断处理函数 中断发生时,系统调用这个函数,dev_id参数将被传递给它
- 中断标记 IRQ_TYPE_EDGE_FALLING 上升或下降中断触发
- 中断名字
- dev_id 一般使用设备的设备结构体或者NULL
返回值:request_irq()返回0表示成功,返回-EINVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用,且不能被共享。
中断卸载函数:
void free_irq(unsigned int irq, void *dev_id)
中断服务函数:
irq_handler_t irq16_handler(int irq,void *dev_id)
简单程序
驱动程序:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-exynos4.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("SZA");
static dev_t dev;
static int major_num;
static int minor_num;
#define CHR_NAME "Epic_chr"
#define CLS_NAME "Epic_cls"
#define DEV_NAME "Epic_dev"
static int gpios[] = {EXYNOS4_GPX1(1),EXYNOS4_GPX1(2),EXYNOS4_GPC0(3),EXYNOS4_GPX0(6),EXYNOS4_GPL2(0)};
static irq_handler_t home_handler(int irq,void *dev_id)
{
printk("home--\n");
gpio_set_value(gpios[4],1);
return IRQ_HANDLED;
}
static irq_handler_t back_handler(int irq,void *dev_id)
{
printk("back--\n");
gpio_set_value(gpios[4],0);
return IRQ_HANDLED;
}
static int pocky330_open(struct inode *inode, struct file *file)
{
int i;
printk("pocky330_open \n");
for(i=0;i<4;i++)
{
gpio_request(gpios[i],"gpio");
s3c_gpio_cfgpin(gpios[i],S3C_GPIO_INPUT);
s3c_gpio_setpull(gpios[i],S3C_GPIO_PULL_NONE);
}
return 0;
}
static int pocky330_release(struct inode *inode, struct file *file)
{
int i;
printk("pocky330_release \n");
for(i=0;i<4;i++)
{
gpio_free(gpios[i]);
}
return 0;
}
static long pocky330_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
if(cmd == 3)
{
return gpio_get_value(gpios[2]);
}
else if(cmd == 4)
{
return gpio_get_value(gpios[3]);
}
else
{
printk(KERN_EMERG "cmd err!! \n");
}
return 0;
}
static struct cdev my_cdev;
static struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = pocky330_open,
.release = pocky330_release,
.unlocked_ioctl = pocky330_unlocked_ioctl,
};
static struct class *myclass;
static int pocky330_init(viod)
{
int ret;
printk("pocky330_init!!! \n");
ret = alloc_chrdev_region(&dev,minor_num,1,CHR_NAME);
if(ret < 0)
{
printk("alloc_chrdev_region fail!!! \n");
}
cdev_init(&my_cdev,&my_fops);
cdev_add(&my_cdev, dev, 1);
myclass = class_create(THIS_MODULE,CLS_NAME);
device_create(myclass,NULL,dev,NULL,DEV_NAME);
gpio_request(gpios[4],"led");
s3c_gpio_cfgpin(gpios[4],S3C_GPIO_OUTPUT);
gpio_set_value(gpios[4],0);
request_irq(IRQ_EINT(9),home_handler,IRQ_TYPE_EDGE_FALLING,"home",NULL);
request_irq(IRQ_EINT(10),back_handler,IRQ_TYPE_EDGE_FALLING,"back",NULL);
return 0;
}
static void pocky330_exit(void)
{
gpio_free(gpios[4]);
cdev_del(&my_cdev);
device_destroy(myclass,dev);
class_destroy(myclass);
unregister_chrdev_region(dev,1);
free_irq(IRQ_EINT(9),NULL);
free_irq(IRQ_EINT(10),NULL);
}
module_init(pocky330_init);
module_exit(pocky330_exit);
应用程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(void){
int fd,io_val;;
char *path = "/dev/Epic_dev";
fd = open(path,O_RDWR|O_NDELAY);
if(fd < 0)
{
printf("open led failed!!");
}
else
{
io_val = ioctl(fd,3,0);
printf("switch3 is %d",io_val);
io_val = ioctl(fd,4,0);
printf("switch4 is %d",io_val);
}
close(fd);
return 0;
}