这部分是比较简单的,了解下边几个函数:
一、
//GPIO申请函数,include/linux/gpio.h中
static inline int gpio_request(unsigned gpio, const char *label)
//GPIO状态查询函数原型在include/linux/gpio.h中
static inline int gpio_get_value(unsigned gpio)
//三星平台配置GPIO函数,linux/arch/arm/plat-s3c/gpio-config.c
int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
主要是通过注册杂项设备然后通过file_operations结构体中的read成员来实现的;
二、代码部分,比较简单就是在大体的框架中把上边的几个函数加进去就可以了,编译后运行之前一定要烧写配置了平台文件(这里就是通过平台文件来注册设备)的内核:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
//#include <mach/gpio-bank.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
//#include "gps.h"
#include <linux/delay.h>
//copy_to_user的头文件
#include <asm/uaccess.h>
/*声明是开源的,没有内核版本限制*/
MODULE_LICENSE("Dual BSD/GPL");
/*声明作者*/
MODULE_AUTHOR("iTOPEET_dz");
#define DPRINTK(x...) printk("POLLKEY_CTL DEBUG:" x)//调试用
#define DRIVER_NAME "pollkey"//驱动NAME
static int key_gpios[] = {
EXYNOS4_GPX1(1),
EXYNOS4_GPX1(2),
};
int pollkey_open(struct inode *inode,struct file *filp)
{
DPRINTK("Device Opened Success!\n");
return nonseekable_open(inode,filp);
}
int pollkey_release(struct inode *inode,struct file *filp)
{
DPRINTK("Device Closed Success!\n");
return 0;
}
/*状态读取*/
static ssize_t pollkey_read(struct file *filp, char __user *buff, size_t size, loff_t *ppos)
{
unsigned char key_value[2];
if(size != sizeof(key_value)){
return -1;
}
key_value[0] = gpio_get_value(key_gpios[0]);
key_value[1] = gpio_get_value(key_gpios[1]);
copy_to_user(buff,key_value,sizeof(key_value));
return 0;
}
static struct file_operations pollkey_ops = {
.owner = THIS_MODULE,
.open = pollkey_open,
.release= pollkey_release,
.read = pollkey_read,
};
static struct miscdevice pollkey_dev = {
.minor = MISC_DYNAMIC_MINOR,
.fops = &pollkey_ops,
.name = "pollkey",
};
/*初始化函数*/
static int pollkey_probe(struct platform_device *pdev)
{
int ret,i;
char *banner = "pollkey Initialize\n";
printk(banner);
for(i=0;i<2;i++){
ret = gpio_request(key_gpios[i],"KEY_GPIO");//GPIO申请函数
s3c_gpio_cfgpin(key_gpios[i],S3C_GPIO_INPUT); //输入INPUT
s3c_gpio_setpull(key_gpios[i],S3C_GPIO_PULL_NONE);//浮空
}
ret = misc_register(&pollkey_dev);//注册杂项设备
return 0;
}
static int pollkey_remove (struct platform_device *pdev)
{
misc_deregister(&pollkey_dev);//移除杂项设备
return 0;
}
static int pollkey_suspend (struct platform_device *pdev, pm_message_t state)
{
DPRINTK("pollkey suspend:power off!\n");
return 0;
}
static int pollkey_resume (struct platform_device *pdev)
{
DPRINTK("leds resume:power on!\n");
return 0;
}
static struct platform_driver pollkey_driver = {
.probe = pollkey_probe,
.remove = pollkey_remove,
.suspend = pollkey_suspend,
.resume = pollkey_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
static void __exit pollkey_exit(void)
{
platform_driver_unregister(&pollkey_driver);//卸载驱动
}
static int __init pollkey_init(void)
{
return platform_driver_register(&pollkey_driver);//注册驱动
}
/*初始化函数*/
module_init(pollkey_init);
/*卸载函数*/
module_exit(pollkey_exit);
下一篇文章就是,中断的注册以及外部中断的应用(按键外部中断),敬请关注!!
又到了这个环节,请欣赏我的鸡汤时刻!一GO我嘞GOGO!!!!
送给阅读过这篇文章的人:把语言化为行动,比把行动化为语言困难得多。
下篇文章见。