按键中断
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/io.h>
#include <asm/string.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <asm-generic/errno-base.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/wait.h>
#include <linux/sched.h>
#define DEV_NAME "key"
static wait_queue_head_t wq;
static int condition = 0;
irqreturn_t irq_handler(int num, void * arg)
{
printk("num = %d arg = %d\n", num, *(int *)arg);
condition = 1;
wake_up_interruptible(&wq);
return IRQ_HANDLED;
}
static int open (struct inode * inode, struct file * file)
{
printk("key open ...\n");
return 0;
}
static ssize_t read (struct file * file, char __user * buf, size_t len, loff_t * offset)
{
//copy_to_user(buf, &value, sizeof(value));
condition = 0;
wait_event_interruptible(wq, condition);
printk("key read ...\n");
return 4;
}
static ssize_t write (struct file * file, const char __user * buf, size_t len, loff_t * offset)
{
return 0;
}
static int close (struct inode * inode, struct file * file)
{
printk("key close ...\n");
return 0;
}
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = open,
.read = read,
.write = write,
.release = close
};
static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEV_NAME,
.fops = &fops
};
static int arg = 100;
static int __init key1_init(void)
{
int ret = misc_register(&misc);
if(ret < 0)
goto err_misc_register;
ret = request_irq(IRQ_EINT8, irq_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, "key_irq", &arg);
if(ret < 0)
goto err_request_irq;
init_waitqueue_head(&wq);
printk("key_init ...\n");
return ret;
err_misc_register:
misc_deregister(&misc);
printk("key misc_register faikey\n");
return ret;
err_request_irq:
disable_irq(IRQ_EINT8);
free_irq(IRQ_EINT8, &arg);
return ret;
}
static void __exit key_exit(void)
{
disable_irq(IRQ_EINT8);
free_irq(IRQ_EINT8, &arg);
misc_deregister(&misc);
printk("key_exit ###############################\n");
}
module_init(key1_init);
module_exit(key_exit);
MODULE_LICENSE("GPL");
adc
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/io.h>
#include <asm/string.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <asm-generic/errno-base.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/wait.h>
#include <linux/sched.h>
#define DEV_NAME "adc"
#define ADCCON 0x58000000
#define ADCDAT0 0x5800000C
#define CLKCON 0x4C00000C
static volatile unsigned long * adccon;
static volatile unsigned long * adcdat0;
static volatile unsigned long * clkcon;
static wait_queue_head_t wq;
static int condition = 0;
irqreturn_t irq_handler(int num, void * arg)
{
printk("num = %d arg = %d\n", num, *(int *)arg);
condition = 1;
wake_up_interruptible(&wq);
return IRQ_HANDLED;
}
static void init_adc(void)
{
*adccon = (1 << 14) | (49 << 6);
}
static void start_adc(void)
{
*adccon |= (1 << 0);
}
static unsigned short read_adc(void)
{
unsigned short data = *adcdat0 & 0x3ff;
return data;
}
static int open (struct inode * inode, struct file * file)
{
init_adc();
printk("adc open ...\n");
return 0;
}
static ssize_t read (struct file * file, char __user * buf, size_t len, loff_t * offset)
{
//copy_to_user(buf, &value, sizeof(value));
unsigned short value = 0;
printk("adc read start ...\n");
condition = 0;
start_adc();
wait_event_interruptible(wq, condition);
value = read_adc();
copy_to_user(buf, &value, sizeof(value));
printk("adc read ...\n");
return sizeof(value);
}
static ssize_t write (struct file * file, const char __user * buf, size_t len, loff_t * offset)
{
return 0;
}
static int close (struct inode * inode, struct file * file)
{
printk("adc close ...\n");
return 0;
}
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = open,
.read = read,
.write = write,
.release = close
};
static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEV_NAME,
.fops = &fops
};
static int arg = 100;
static int __init adc_init(void)
{
int ret = misc_register(&misc);
if(ret < 0)
goto err_misc_register;
ret = request_irq(IRQ_ADC, irq_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, "adc_irq", &arg);
if(ret < 0)
goto err_request_irq;
adccon = ioremap(ADCCON, sizeof(*adccon));
adcdat0 = ioremap(ADCDAT0, sizeof(*adcdat0));
clkcon = ioremap(CLKCON, sizeof(*clkcon));
*clkcon |= (1 << 15);
printk("clkcon = 0x%lx\n", *clkcon);
init_waitqueue_head(&wq);
printk("adc_init ...\n");
return ret;
err_misc_register:
misc_deregister(&misc);
printk("adc misc_register faiadc\n");
return ret;
err_request_irq:
disable_irq(IRQ_ADC);
free_irq(IRQ_ADC, &arg);
return ret;
}
static void __exit adc_exit(void)
{
iounmap(clkcon);
iounmap(adcdat0);
iounmap(adccon);
disable_irq(IRQ_ADC);
free_irq(IRQ_ADC, &arg);
misc_deregister(&misc);
printk("adc_exit ###############################\n");
}
module_init(adc_init);
module_exit(adc_exit);
MODULE_LICENSE("GPL");
应用层adc
1 #include <fcntl.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6
7 int main(int argc, const char *argv[])
8 {
9 int fd = open("/dev/adc",O_RDWR);
10 if (fd < 0)
11 {
12 perror("open adc fail");
13 return -1;
14 }
15
16 unsigned short value = 0;
17 while(1)
18 {
19 int ret = read(fd, &value, sizeof(value));
20 float v = 3.3 * value / 1024.0;
21 printf("ret = %d adc value = %d v = %.3f\n",ret, value,v);
22 sleep(2);
23 }
24
25 close(fd);
26 return 0;
27 }