- /* drivers/char/davinci_dm644x_button.c*/
- /*******************************************************************************
- * HEADER FILES
- */
- #include <linux/device.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/err.h>
- #include <linux/kdev_t.h>
- #include <linux/slab.h>
- #include <linux/mm.h>
- #include <linux/io.h>
- #include <linux/platform_device.h>
- #include <linux/types.h>
- #include <linux/cdev.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/psc.h>
- #include <linux/delay.h>
- #include <asm/arch/gpio.h>
- #include <asm/delay.h>
- #include <linux/errno.h>
- #include <asm/arch/gpio.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h> //define for irq number
- #include <asm-arm/arch-davinci/irqs.h>
- #include <asm-arm/arch-davinci/clock.h>
- #include <asm/arch-davinci/gpio.h>
- //#include <linux/interrupt.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
- /*******************************************************************************
- * LOCAL DEFINES
- */
- #define DEVICE_NAME "buttontest" /*定义设备驱动的名字,或设备节点名称*/
- #define BUTTON_MAJOR 200 /*使用 cat /proc/devices查看不要和存在的char节点重复*/
- /*my app gpio define*/
- #define DM644X_GPIO_BUTTON 3 /*GPIO3*/
- //#define DM644X_GPIO_INIT IRQ_GPIO3
- #define DM644X_GPIO_INIT 51
- /* 中断事件标志, 中断服务程序将它置1,buttons_read将它清0 */
- static int value=1; //按键的电平值,按下为0
- /*******************************************************************************
- * FUNCTION DEFINITIONS
- */
- /***************************************************************************
- * Function - gpio_demux_pins
- * Functionality - interrupt register set
- * Input Params - None
- * Return Value - None
- * Note - None
- ****************************************************************************/
- void gpio_demux_pins(void)
- {
- /* PINMUX address in dm6446 */
- unsigned long pmux0;
- int addr = IO_ADDRESS(0x01c40000);
- pmux0 = inl(addr)&0xfd7fffff;
- outl(pmux0,addr);
- printk("The PINMUX0 value is %x\n!",inl(addr));
- /*ARM INTERRUPT CONTROLLER REGISTER*/
- int io_add = IO_ADDRESS(0x01c48000);
- int irq = inl(io_add + 0x0c)|0x00800000;
- outl(irq,io_add + 0x0c);
- printk("irq value is %x\n",inl(io_add + 0x0c));
- int eint = inl(io_add + 0x1c)|0x80000;
- outl(eint,io_add + 0x1c);
- printk("eint value is %x\n",inl(io_add + 0x1c));
- /* GPIO3 interrupt controller register*/
- int io_addr = IO_ADDRESS(0x01c67000);
- /*set GPIO3 interrupt enable*/
- int binen = inl(io_addr + 0x08)|0x01;
- outl(binen,io_addr+0x08);
- printk("binen value is %x\n",inl(io_addr + 0x08));
- /*set GPIO3 direction*/
- int dir = inl(addr + 0x10)|0x08;
- outl(dir,addr+0x10);
- printk("dir value is %x\n",inl(addr + 0x10));
- /*set GPIO3 raising disable*/
- int ris_clr = inl(io_addr + 0x28)|0x08;
- outl(ris_clr,io_addr+0x28);
- printk("ris_clr value is %x\n",inl(io_addr + 0x28));
- /*set GPIO3 raising set*/
- int ris = inl(io_addr + 0x24)|0x08;
- outl(ris,io_addr+0x24);
- printk("ris value is %x\n",inl(io_addr + 0x24));
- /*the GPIO3 status*/
- printk("insta value is %x\n",inl(io_addr + 0x34));
- }
- static irqreturn_t buttons_interrupt(int irq, void *dev_id,struct pt_regs *regs)
- {
- value = gpio_get_value(DM644X_GPIO_BUTTON);
- printk(KERN_INFO "key is pressed!\n");
- printk("test, value = %d\n", value);
- return IRQ_HANDLED;
- }
- static int buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
- {
- value = gpio_get_value(DM644X_GPIO_BUTTON);
- printk("In kernel key_read()!\n"); //打印调试信息
- /* 将按键状态复制给用户 */
- copy_to_user(buff, (void *)&value, sizeof(value));
- // ev_press = 0;
- printk("this is at kernel, value = %d\n", value);
- return 0;
- }
- static int buttons_open(struct inode *inode, struct file *file)
- {
- int result;
- int value;
- gpio_direction_input(DM644X_GPIO_BUTTON);
- set_irq_type(DM644X_GPIO_INIT, IRQ_TYPE_EDGE_RISING); //RISING or Edge Falling type
- disable_irq(DM644X_GPIO_INIT);
- enable_irq(DM644X_GPIO_INIT);
- result = request_irq(DM644X_GPIO_INIT,buttons_interrupt,IRQ_DISABLED,"buttontest","key");
- if (result < 0)
- {
- printk(KERN_INFO "Cannot initialize IRQ \n");
- return result;
- }
- printk(KERN_INFO "initialize IRQ successful, result = %d\n", result);
- value = gpio_get_value(DM644X_GPIO_BUTTON);
- disable_irq(DM644X_GPIO_INIT);
- enable_irq(DM644X_GPIO_INIT);
- printk(KERN_INFO "value = %d\n", value);
- return 0;
- }
- static int buttons_close(struct inode *inode,struct file *filp)
- {
- free_irq(DM644X_GPIO_INIT, "key");
- disable_irq(DM644X_GPIO_INIT);
- gpio_free(DM644X_GPIO_BUTTON);
- return 0;
- }
- /*定义驱动设备文件API,在linux系统当中,任何设备都可以当做文件的方式操作,这一点和单片机和MCU有很大差别*/
- static const struct file_operations davinci_dm644x_gpio_fileops = {
- .owner = THIS_MODULE,
- .open = buttons_open,
- .release = buttons_close,
- .read = buttons_read,
- //.ioctl = buttons_ioctl,
- };
- static int __init davinci_dm644x_button_open(void) /*内核初始化会调用该函数*/
- {
- int ret;
- int test;
- gpio_demux_pins();
- gpio_direction_input(DM644X_GPIO_BUTTON);
- if(gpio_is_valid(DM644X_GPIO_BUTTON) < 0)
- {
- printk("gpio is invalid\n");
- return -EINVAL;
- }
- printk("gpio is valid\n");
- test = gpio_request(DM644X_GPIO_BUTTON, "buttons_interrupt");
- if(test < 0 )
- {
- printk("failed to request gpio\n");
- return -EINVAL;
- }
- printk("request gpio ok!\n");
- ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &davinci_dm644x_gpio_fileops);
- if(ret < 0)
- {
- printk(KERN_INFO "dm644x_button register falid!\n");
- return ret;
- }
- printk(KERN_INFO "dm644x_button initialized\n");
- return ret;
- }
- static void __exit davinci_dm644x_button_exit(void)
- {
- unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
- printk(KERN_INFO "dm644x_button:exit\n");
- }
- module_init(davinci_dm644x_button_open);
- module_exit(davinci_dm644x_button_exit);
- MODULE_AUTHOR("azhgul");
- MODULE_LICENSE("Dual BSD/GPL");
这里选用GPIO3作为中断源,包括设置相应中断控制寄存器,bank0中断使能, RISING or Edge Falling type,已经GPIO管脚复用等问题。
应用程序如下所示。
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <errno.h> /
- int main(void)
- {
- int fd,key_value,ret;
- fd=open("/dev/key",0);
- if(fd<0){
- perror("open /dev/key error!\n");
- exit(1);
- }
- printf("open /dev/key sucessfully!\n");
- while(1){
- ret=read(fd,&key_value,sizeof(key_value));
- printf("In main(),key_value is '%d'\n\n",key_value);
- }
- close(fd);
- return 0;
- }