很晚了,不多说了,还是在以前的led灯中断控制的基础上写的,以下直接附程序:
1、led_device.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
//#include <linux/ioport.h>
static struct resource led_rsrc[] = {
{
.start = 0xE0200060,
.end = 0xE0200067,
.flags = IORESOURCE_MEM,
},
{
.start = 0xE0200060+0xc00-0x60,
.end = 0xE0200060+0xc00-0x60+0x07,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_EINT(1),
.end = IRQ_EINT(4),
.flags = IORESOURCE_IRQ,
}
};
static void led_device_release(struct device * dev)
{
}
static struct platform_device led_keys_device = {
.name = "led-keys",
.num_resources = ARRAY_SIZE(led_rsrc),
.resource = led_rsrc,
.dev = {
.release = led_device_release,
},
};
static int __init led_keys_init(void)
{
return platform_device_register(&led_keys_device);
}
static void __exit led_keys_exit(void)
{
platform_device_unregister(&led_keys_device);
}
module_init(led_keys_init);
module_exit(led_keys_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ethyn Blog:blog.csdn.net/humanspider1");
MODULE_DESCRIPTION("Keys device for led test");
2、led_driver.c
#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/io.h>
#include <asm/uaccess.h>
#define led_keys_of_match NULL
static unsigned char KeyFlag;
wait_queue_head_t my_waitqueue;
struct s5pv210_resource {
struct platform_device *pdev;
u64 cur_format;
unsigned int cur_rate;
unsigned long flags;
int playback_period, capture_period;
/* Serialize access to opened variable */
spinlock_t lock;
void __iomem *regs;
int irq;
int opened;
int reset_pin;
};
static int major;
static volatile int press = 0;
static struct class *led_class;
volatile unsigned long *gpcxcon, *gpcxdat,*gpchcon;//用与存放两个个寄存器的地址
static unsigned char witch_key = 0;
static void led1_on(void)
{
*gpcxdat |= 1 << 3;
*gpcxdat &= ~(0x01 << 4);
}
static void led2_on(void)
{
*gpcxdat |= 1 << 4;
*gpcxdat &= ~(0x01 << 3);
}
static void all_leds_on(void)
{
*gpcxdat |= 1 << 3; // 点亮LED1
*gpcxdat |= 1 << 4; // 点亮LED2
}
static void all_leds_off(void)
{
*gpcxdat &= ~(0x3 << 3); // 熄灭LED1和LED2
printk("all leds off\n");
}
static void led_config(void)
{
*gpcxcon &= ~(0xFF << 12);
*gpcxcon |= 0x11 << 12; // 配置GPC0_3和GPC0_4为输出
*gpchcon &= ~0x0F; //配置为输入
all_leds_off();
}
static ssize_t led_device_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
int ret = -1;
unsigned char from[1]={0};
wait_event_interruptible(my_waitqueue,press);
press = 0;
if(KeyFlag)
{
led1_on();
}
else
{
led2_on();
}
from[0] = witch_key;
if(witch_key>0)
{
ret = copy_to_user(buf,from,sizeof(from));
if(ret)
{
printk("copy to user failed\n");
}
witch_key = 0;
}
return 0;
}
static irqreturn_t led_keys_interrupt(int irq, void *dev)
{
printk("led-keys-interrupt just happened\n");
press = 1;
wake_up_interruptible(&my_waitqueue);
KeyFlag = !KeyFlag;
printk("KERNEL:irq == %d witch_key= %d\n",irq,witch_key);
return IRQ_RETVAL(IRQ_HANDLED);
}
static struct file_operations led_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.read = led_device_read,
};
static int __devinit led_keys_probe(struct platform_device *pdev)
{
struct s5pv210_resource *chip= NULL;
struct resource *regs = NULL;
int i;
unsigned int irq =0;
unsigned long regs_data = 0;
int retval=0;
printk("find led-keys module success\n");
printk("excute 12221\n");
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs_data = (unsigned long)ioremap(regs->start, regs->end - regs->start + 1);
if (!regs_data) {
dev_dbg(&pdev->dev, "could not remap register memory\n");
goto err_ioremap;
}
printk("excute 444\n");
gpcxcon = (unsigned long *)regs_data;
gpcxdat = (unsigned long *)(regs_data + 0x04);
regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!regs) {
dev_dbg(&pdev->dev, "no memory resource\n");
return -ENXIO;
}
regs_data = (unsigned long)ioremap(regs->start, regs->end - regs->start + 1);
if (!regs_data) {
dev_dbg(&pdev->dev, "could not remap register memory\n");
goto err_ioremap;
}
gpchcon = (unsigned long *)regs_data;
led_config();
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_dbg(&pdev->dev, "could not get irq\n");
return -ENXIO;
}
for(i=0;i<4;i++)
{
retval = request_irq(irq+i, led_keys_interrupt, IRQ_TYPE_EDGE_FALLING, "led-irq", chip);
if (retval) {
dev_dbg(&pdev->dev, "unable to request irq %d\n",irq+i );
goto err_request_irq;
}
}
init_waitqueue_head(&my_waitqueue);
major = register_chrdev(0, "myled", &led_fops);
led_class = class_create(THIS_MODULE, "myled");
device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");
return 0;
err_ioremap:
free_irq(irq, chip);
err_request_irq:
return retval;
}
static int led_keys_remove(struct platform_device *pdev)
{
device_destroy(led_class, MKDEV(major, 0));
class_destroy(led_class);
unregister_chrdev(major, "myled");
return 0;
}
static struct platform_driver led_keys_driver = {
.probe = led_keys_probe,
.remove = led_keys_remove,
.driver = {
.name = "led-keys",
.owner = THIS_MODULE,
.of_match_table = led_keys_of_match,
}
};
static int __init led_keys_init(void)
{
return platform_driver_register(&led_keys_driver);
}
static void __exit led_keys_exit(void)
{
platform_driver_unregister(&led_keys_driver);
}
module_init(led_keys_init);
module_exit(led_keys_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ethyn Blog:blog.csdn.net/humanspider1");
MODULE_DESCRIPTION("Keys driver for led test");
3测试程序apptest.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>
int main(int argc,char **argv)
{
int fd = -1;
char val = 0;
char buf[10]={0};
char temp= 0;
char *s = malloc(100);
unsigned char key[1];
fd = open("/dev/led",O_RDWR);
if(fd<0)
printf("can't open \n");
while(1)
{
val++;
read(fd,key,sizeof(key));
//temp =key[0]?1:(key[1]?2:(key[2]?3:(key[3]?4:0)));
temp = key[0];
if(temp)
printf("pressed key is key[%x]\n",temp);
temp = 0;
}
free(s);
return 0;
}
以上程序适用于s5pv210,如果其它的开发板稍微改下io口和中断号就可以了