uio中断简化版

时间:2021-01-24 02:28:30

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\n");
}

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 \n", 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!\n");
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!\n");
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\n", strerror(errno));
exit(
-1);
}

while (1) {
ret
= read(uio_fd, &c, sizeof(int));
if (ret > 0) {
printf(
"current event count %d\n", 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\n", strerror(errno));
exit(
-1);
}

ret
= pthread_create(&my_thread, NULL, (void *)thread_1, NULL);
if(ret != 0)
{
printf(
"Create pthread error!\n");
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\n", 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