加载uio驱动
sudo modprobe uio
simple.c源代码
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <linux/slab.h>
struct uio_info kpart_info = {
.name = "kpart",
.version = "0.1",
.irq = UIO_IRQ_NONE,
};
static int drv_kpart_probe(struct device *dev);
static int drv_kpart_remove(struct device *dev);
static struct device_driver uio_dummy_driver={
.name = "kpart",
.bus = &platform_bus_type,
.probe = drv_kpart_probe,
.remove = drv_kpart_remove,
};
static int drv_kpart_probe(struct device *dev)
{
printk("drv_kpart_probe(%p)\n", dev);
kpart_info.mem[0].addr = (unsigned long)kmalloc(1024,GFP_KERNEL);
if(kpart_info.mem[0].addr==0)
{
return -ENOMEM;
}
kpart_info.mem[0].memtype = UIO_MEM_LOGICAL;
kpart_info.mem[0].size = 1024;
if(uio_register_device(dev,&kpart_info))
return -ENODEV;
return 0;
}
static int drv_kpart_remove(struct device *dev)
{
uio_unregister_device(&kpart_info);
return 0;
}
static struct platform_device *uio_dummy_device;
static struct platform_device *uio_dummy_device;
static int __init uio_kpart_init(void)
{
uio_dummy_device = platform_device_register_simple("kpart",-1,NULL,0);
return driver_register(&uio_dummy_driver);
}
static void __exit uio_kpart_exit(void)
{
platform_device_unregister(uio_dummy_device);
driver_unregister(&uio_dummy_driver);
}
module_init(uio_kpart_init);
module_exit(uio_kpart_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("IGB_UIO_TEST");
MODULE_DESCRIPTION("UIO dummy driver");
编译simple.c的Makefile文件
obj-m := simple.o
执行make进行驱动编译
make -C /lib/modules/4.15.0-111-generic/build M=`pwd` modules
生成了simple.ko后加载simple.ko
sudo insmod simple.ko
用户应用程序uio_test.c
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#define UIO_DEV "/dev/uio0"
#define UIO_ADDR "/sys/class/uio/uio0/maps/map0/addr"
#define UIO_SIZE "/sys/class/uio/uio0/maps/map0/size"
static char uio_addr_buf[16]={0};
static char uio_size_buf[16]={0};
int main(void)
{
int uio_fd,addr_fd,size_fd;
int uio_size;
void *uio_addr,*access_address;
int n=0;
char test_buf[20];
uio_fd = open(UIO_DEV, O_RDWR);
if(uio_fd<0)
{
printf("open uio_dev failed. error number:%s\n",strerror(errno));
return -1;
}
addr_fd = open(UIO_ADDR, O_RDONLY);
if (addr_fd<0)
{
printf("open addr_fd failed.\n");
return -1;
}
size_fd = open(UIO_SIZE, O_RDONLY);
if(size_fd<0)
{
printf("open size_fd failed.\n");
return -1;
}
n = read(addr_fd, uio_addr_buf, sizeof(uio_addr_buf));
if(n<0)
{
printf("read addr_fd failed.\n");
return -1;
}
n = read(size_fd, uio_size_buf, sizeof(uio_size_buf));
if(n<0)
{
printf("read size_fd failed.\n");
return -1;
}
uio_addr = (void*)strtoul(uio_addr_buf,NULL,0);
uio_size = (int)strtol(uio_size_buf,NULL,0);
printf("uio_size %d\n", uio_size);
access_address = mmap(NULL,uio_size,PROT_READ|PROT_WRITE,MAP_SHARED,uio_fd,0);
if(access_address==(void *)-1)
{
printf("mmap failed. error number:%s\n",strerror(errno));
return -1;
}
memcpy(test_buf, access_address, 17);
printf("test_buf: %s\n", access_address);
return 0;
}
编译用户应用测试程序
gcc uio_test.c -o uio_test
执行./uio_test输出