#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/interrupt.h>
static void __iomem *LRADC_BASE_Data0;
static void __iomem *LRADC_BASE_Inter_S;
static void __iomem *LRADC_BASE_Inter_C;
static void __iomem *LRADC_BASE_Control;
static void __iomem *LRADC_BASE;
static struct cdev LRADC_cdev; //字符设备结构体
static dev_t LRADC_num = 0; //设备号
static struct class *LRADC_class;
static struct device *LRADC_device;
short int irq_key = 30;
char name[]={"key"};
static int LRADC_open(struct inode * inode, struct file *file)
{
printk("LRADC_open \n");
return 0;
}
static int LRADC_release(struct inode * inode, struct file *file)
{
printk("LRADC_release \n");
return 0;
}
static ssize_t LRADC_write(struct file * file, const char __user * buf, size_t len,loff_t * off)
{
printk("LRADC_BASE_Data0=0x%x\r\n",ioread32(LRADC_BASE_Data0));
printk("LRADC_BASE_Inter_C=0x%x",ioread32(LRADC_BASE_Inter_C));
printk("LRADC_BASE_Inter_S=0x%x\r\n",ioread32(LRADC_BASE_Inter_S));
return ioread32(LRADC_BASE_Data0);
}
static const struct file_operations LRADC_fops = {
.owner = THIS_MODULE,
.write = LRADC_write,
.open = LRADC_open,
.release = LRADC_release
};
static irqreturn_t r_irq_handler(int irq, void *dev_id)
{
printk("being interrupt\r\n");
printk("LRADC_BASE_Inter_S=0x%x\r\n",ioread32(LRADC_BASE_Inter_S));
if(ioread32(LRADC_BASE_Inter_S) != 0)
{
printk("KEY RISING\r\n");
printk("LRADC_BASE_Data0=0x%x\r\n",ioread32(LRADC_BASE_Data0));
}
return IRQ_HANDLED;
}
//入口函数
static int __init init_LRADC(void)
{
int rt = 0;
struct resource * LRADC_res = NULL;
//动态申请设备号
rt = alloc_chrdev_region(&LRADC_num, 0, 1, "LRADC");
if (rt < 0)
{
printk("alloc_chrdev_region fail\n");
return rt;
}
//字符设备初始化
cdev_init(&LRADC_cdev, &LRADC_fops);
//字符设备添加到内核
rt = cdev_add(&LRADC_cdev, LRADC_num, 1);
if (rt < 0)
{
printk("cdev_add fail\n");
goto fail_cdev_add;
}
//创建类
LRADC_class = class_create(THIS_MODULE, "LRADC");
if (IS_ERR(LRADC_class))
{
rt = PTR_ERR(LRADC_class);
printk("class_create LRADC fail\n");
goto fail_class_create;
}
//创建设备
LRADC_device = device_create(LRADC_class, NULL, LRADC_num, NULL, "LRADC");
if (IS_ERR(LRADC_device))
{
rt = PTR_ERR(LRADC_device);
printk("device_create LRADC fail\n");
goto fail_device_create;
}
//申请物理内存区
//起始地址GPIOg寄存器基址0x01C20000
//申请大小0xffff字节
//申请到的名字为GPIOH_MEM
LRADC_res = request_mem_region(0x01C20000,0xFFFF,"GPIOG_MEM");
if(LRADC_res == NULL)
{
printk("request_mem_region fail\n");
// goto fail_request_mem_region;
}
//IO内存动态映射,得到物理地址相应的虚拟地址
LRADC_BASE = ioremap(0x01C22000,0XFFFF);
printk("LRADC_BASE=0x%x",((unsigned int)LRADC_BASE));
if(LRADC_BASE == NULL)
{
printk("ioremap fail\n");
goto fail_ioremap;
}
//得到每个寄存器的虚拟地址
LRADC_BASE_Control = LRADC_BASE + 0x800;
printk("addr:LRADC_BASE_Control=0x%x",((unsigned int)LRADC_BASE_Control));
LRADC_BASE_Data0 = LRADC_BASE + 0x80C;
printk("addr:LRADC_BASE_Data0=0x%x",((unsigned int)LRADC_BASE_Data0));
LRADC_BASE_Inter_S = LRADC_BASE + 0x808;
printk("addr:LRADC_BASE_Inter_S=0x%x",((unsigned int)LRADC_BASE_Inter_S));
LRADC_BASE_Inter_C = LRADC_BASE + 0x804;
printk("addr:LRADC_BASE_Inter_C=0x%x",((unsigned int)LRADC_BASE_Inter_C));
iowrite32(0x1000141 , LRADC_BASE_Control);
iowrite32(0x2 , LRADC_BASE_Inter_C); //down
printk("LRADC_BASE_Data0=0x%x",ioread32(LRADC_BASE_Data0));
printk("LRADC_BASE_Inter_C=0x%x",ioread32(LRADC_BASE_Inter_C));
printk("LRADC_BASE_Inter_S=0x%x",ioread32(LRADC_BASE_Inter_S));
printk("key init\r\n");
if (request_irq(irq_key,(irq_handler_t ) r_irq_handler, IRQF_TRIGGER_FALLING , name , NULL))
{
printk("Irq Request failure\n");
return 0;
}
return 0;
fail_ioremap:
release_mem_region(0x01C22000, 0xffff);
fail_request_mem_region:
device_destroy(LRADC_class, LRADC_num);
fail_device_create:
class_destroy(LRADC_class);
fail_class_create:
cdev_del(&LRADC_cdev);
fail_cdev_add:
unregister_chrdev_region(LRADC_num, 1);
return rt;
}
//出口函数
static void __exit exit_LRADC(void)
{
iounmap(LRADC_BASE);
release_mem_region(0x01C22000,0xffff);
device_destroy(LRADC_class, LRADC_num);
class_destroy(LRADC_class);
cdev_del(&LRADC_cdev);
unregister_chrdev_region(LRADC_num, 1);
free_irq(irq_key, NULL);
printk("key remove\r\n");
return ;
}
module_init(init_LRADC);
module_exit(exit_LRADC);
MODULE_LICENSE("GPL");//驱动程序符合的协议
离线
我这样写是申请失败的
离线
板子是荔枝派zero,那个if (request_irq(irq_key,(irq_handler_t ) r_irq_handler, IRQF_TRIGGER_FALLING , name , NULL))中的第三个参数我到底填什么,这个中断事件怎么找???
离线
devname设置中断名称,通常是设备驱动程序的名称 在cat /proc/interrupts中可以看到此名称。
离线
devname设置中断名称,通常是设备驱动程序的名称 在cat /proc/interrupts中可以看到此名称。
是第三个那个(IRQF_TRIGGER_FALLING),是中断标志,我不知道在哪里找?你说的中断名称是第四个。
离线
参考这个帖子: https://whycan.cn/t_1916.html
离线
参考这个帖子: https://whycan.cn/t_1916.html
这个帖子我看过了,但最后也没有给出解决方法。。。。
离线
参考晕哥的GPIO中断就可以,但这个lradc中断却不行。。。。。有大神救救吗
离线