uio中断简化版

1、内核态
struct uio_info irq_info =
{
.name = "fpga_irq2",
.version = "0.1",
.irq = 155,
.irq_flags = IRQ_TYPE_LEVEL_HIGH | IRQF_SHARED | IRQF_DISABLED,
.handler = irq2_handler, //disable_irq_nosync(irq);uio_event_notify(info);
.irqcontrol = irq_irqcontrol,//case: enable_irq(info->irq);disable_irq_nosync
};
uio_register_device(pdev, &irq_info); //pdev指向一个字符设备

2、用户态
fd = open(xx)
while(1) { read , handle, write}

内核态:

#include <linux/init.h>  
#include <linux/version.h>  
#include <linux/module.h>  
#include <linux/mm.h>  
#include <linux/cdev.h>  
#include <linux/sched.h>
#include <linux/uaccess.h>  
#include <linux/proc_fs.h>  
#include <linux/fs.h>  
#include <linux/seq_file.h>   
#include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <asm/io.h>
#include <linux/slab.h> /* kmalloc, kfree */
#include <linux/irq.h> /* IRQ_TYPE_EDGE_BOTH */
#include <asm/uaccess.h>  


#if 1
static irqreturn_t my_interrupt(int irq, void *dev_id)
{
    struct uio_info *info = (struct uio_info *)dev_id;

    disable_irq_nosync(info->irq);
    
    uio_event_notify(info);

    return IRQ_RETVAL(IRQ_HANDLED);
}

static int irq_control(struct uio_info *info, s32 irq_on)
{
    if(irq_on) 
        enable_irq(info->irq);
    else 
        disable_irq_nosync(info->irq);

    return 0;
}

struct uio_info irq_info = {  
    .name = "uio_irq",
    .version = "0.1",
    .irq = 10, 
    .handler = my_interrupt,
    .irq_flags = IRQ_TYPE_EDGE_RISING, 
    .irqcontrol = irq_control, 
};
#endif

#if 1

#define IO_CMD_LEN      256  
#define CHAR_DEV_NAME   "kdev"

static int user_cmd_proc(char *user_cmd, char *out_str)
{
    if(strncmp(user_cmd, "sendsig", 7) == 0) {
        uio_event_notify(&irq_info);
        sprintf(out_str, "send ok
");
    }
    
    return 0;
}
  
int mem_open(struct inode *inode, struct file *filp)  
{  
    return 0;   
}  
  
int mem_release(struct inode *inode, struct file *filp)  
{  
    return 0;  
}  

char user_cmd[IO_CMD_LEN] = {0};
char out_str[IO_CMD_LEN] = {0};

static int mem_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
{    
    printk("mem_ioctl: %d 
", cmd);    
    
    if(copy_from_user(user_cmd,  (int *)arg, IO_CMD_LEN)) 
        return -EFAULT;
    
    user_cmd_proc(user_cmd, out_str);
    
    if(copy_to_user( (int *)arg, out_str, IO_CMD_LEN)) 
        return -EFAULT;
    
    return 0;
}

static int mem_major = 0;
struct class *pclass = NULL;  
struct cdev my_dev;   
struct device *pdev;   

static const struct file_operations mem_fops =  
{  
    .owner = THIS_MODULE,  
    .unlocked_ioctl = mem_ioctl,
    .open = mem_open,  
    .release = mem_release,  
};  

static int memdev_init(void)  
{  
    int result;  

    dev_t devno = MKDEV(mem_major, 0);  

    if (mem_major) { /* 静态申请设备号*/  
        result = register_chrdev_region(devno, 2, CHAR_DEV_NAME);  
    } else { /* 动态分配设备号 */  
        result = alloc_chrdev_region(&devno, 0, 2, CHAR_DEV_NAME);  
        mem_major = MAJOR(devno);  
    }   

    if (result < 0)  {  
        printk("alloc_chrdev failed!
");  
        return result;  
    }  

    cdev_init(&my_dev, &mem_fops);  
    my_dev.owner = THIS_MODULE;  
    my_dev.ops = &mem_fops;  
    cdev_add(&my_dev, MKDEV(mem_major, 0), 2);   /*设备数2*/  

    pclass = class_create(THIS_MODULE, CHAR_DEV_NAME);  
    if (IS_ERR(pclass))  {  
        printk("class_create failed!
");  
        goto failed;  
    }  

    pdev = device_create(pclass, NULL, devno, NULL, CHAR_DEV_NAME);  
    uio_register_device(pdev, &irq_info); //todo
    
    return 0;  

failed:   
    cdev_del(&my_dev);
    unregister_chrdev_region(devno, 1);  
    return result;  
}  
  
static void memdev_exit(void)  
{  
    uio_unregister_device(&irq_info); //todo
    device_destroy(pclass, MKDEV(mem_major, 0));  
    class_destroy(pclass);
    
    cdev_del(&my_dev);
    unregister_chrdev_region(MKDEV(mem_major, 0), 2); 
}  
#endif
  
MODULE_AUTHOR("derek yi");  
MODULE_LICENSE("GPL");  
  
module_init(memdev_init);  
module_exit(memdev_exit);  

用户态:

#include <stdio.h>  
#include <fcntl.h>  
#include <stdlib.h>  
#include <pthread.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>  
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/mman.h>  

int thread_1(void)  
{
    int uio_fd;
    int c, ret;

    uio_fd  = open("/dev/uio0", O_RDWR); ///sys/class/uio/uio0/name: uio_irq
    if(uio_fd < 0) {
        fprintf(stderr, "open: %s
", strerror(errno));
        exit(-1);
    }

    while (1) {
        ret = read(uio_fd, &c, sizeof(int));
        if (ret > 0) {
            printf("current event count %d
", c);
            c = 1;
            write(uio_fd, &c, sizeof(int));
        }
    }

    close(uio_fd);

    return 0;
}  

#define IO_CMD_LEN      256  
char kdev_io_buf[IO_CMD_LEN] = {0};

int main()
{
    pthread_t my_thread;
    int char_fd, ret, i;

    char_fd  = open("/dev/kdev", O_RDWR);
    if(char_fd < 0) {
        fprintf(stderr, "open: %s
", strerror(errno));
        exit(-1);
    }

    ret = pthread_create(&my_thread, NULL, (void *)thread_1, NULL);  
    if(ret != 0)  
    {  
        printf("Create pthread error!
");  
        return -1;  
    }  
    sleep(1);

    for(i = 0; i < 10; i++){
        sprintf(kdev_io_buf, "sendsig");
        ret = ioctl(char_fd, 0, kdev_io_buf);
        printf("ioctl: ret=%d rdata:%s
", ret, kdev_io_buf);
        sleep(1);
    }

    close(char_fd);

    return 0;
}

测试:

derek@ubox:~/share/ldd5$ sudo insmod myuio.ko 
derek@ubox:~/share/ldd5$ gcc app.c -lpthread
derek@ubox:~/share/ldd5$ sudo ./a.out 
ioctl: ret=0 rdata:send ok

current event count 1
ioctl: ret=0 rdata:send ok

current event count 2
ioctl: ret=0 rdata:send ok

current event count 3
ioctl: ret=0 rdata:send ok

current event count 4
ioctl: ret=0 rdata:send ok

current event count 5
ioctl: ret=0 rdata:send ok

current event count 6
ioctl: ret=0 rdata:send ok

current event count 7
ioctl: ret=0 rdata:send ok

current event count 8
ioctl: ret=0 rdata:send ok

current event count 9
ioctl: ret=0 rdata:send ok

current event count 10
原文地址:https://www.cnblogs.com/soul-stone/p/6721371.html