uio驱动编写 实例2 //增加了中断部分

http://blog.csdn.net/ganggexiongqi/article/details/6794215

AUTHOR: Joseph Yang (杨红刚) <ganggexiongqi@gmail.com>
CONTENT: uio驱动编写 实例2
NOTE: Linux-3.0
LAST MODIFIED:09-20-2011
-----------------------------------------------------------------------------------------------------------
Distributed and Embedded System Lab (分布式嵌入式系统实验室,兰州大学)
===============================================================

第一个例子: uio驱动编写 实例


原理简述:

在第一个例子的基础上,增加了中断部分。但是,我们没有实际产生中断的硬件。但是我们可以”模拟“硬件中断。

每当中断发生时,uio_event_notify 将被调用,用来对设备的中断事件计数器()增一,并通知各读进程,
有数据可读。所以,我们通过内核定时器,来周期性的产生中断,而在定时器的处理程序中

调用uio_event_notify,从而产生的效果和有硬件是相同。


如下,是内核部分 simple1.c

  1. /** 
  2. *  This is a simple demon of uio driver. 
  3. *  Last modified by  
  4.         09-20-2011   Joseph Yang(Yang Honggang)<ganggexiongqi@gmail.com> 
  5. * 
  6. * Compile:   
  7. *   Save this file name it simple.c 
  8. *   # echo "obj-m := simpleX.o" > Makefile 
  9. *   # make -Wall -C /lib/modules/`uname -r`/build M=`pwd` modules 
  10. * Load the module: 
  11. *   #modprobe uio 
  12. *   #insmod simpleX.ko 
  13. */  
  14.   
  15. #include <linux/module.h>  
  16. #include <linux/platform_device.h>  
  17. #include <linux/uio_driver.h>  
  18. #include <linux/slab.h> /* kmalloc, kfree */  
  19. #include <linux/device.h> /* class_create */  
  20. #include <linux/kobject.h> /* kobject_uevent */  
  21. #define FREQ HZ   
  22.   
  23. static long freq = FREQ;  
  24. static long my_event_count = 0;  
  25.   
  26. struct uio_info kpart_info = {  
  27.         .name = "kpart",  
  28.         .version = "0.1",  
  29.         .irq = UIO_IRQ_NONE,  
  30. };  
  31.   
  32. static int drv_kpart_probe(struct device *dev);  
  33. static int drv_kpart_remove(struct device *dev);  
  34. static struct device_driver uio_dummy_driver = {  
  35.         .name = "kpart",  
  36.         .bus = &platform_bus_type,  
  37.         .probe = drv_kpart_probe,  
  38.         .remove = drv_kpart_remove,  
  39. };  
  40.   
  41. static struct timer_list poll_timer;// generate interruption   
  42.   
  43. static void drv_kpart_timer(unsigned long data)  
  44. {  
  45.         struct uio_info *info = (struct uio_info *)data;  
  46.         unsigned long *addr = (unsigned long *)info->mem[0].addr;  
  47.          unsigned long swap = 0;  
  48.    
  49.         if (my_event_count == 0) {  
  50.                 printk(KERN_EMERG"first timer interrupt \n");  
  51.                 *addr = my_event_count;  
  52.         } else if (my_event_count == 10){  
  53.                 printk(KERN_EMERG"timer interrupt happened 10 times\n"  
  54.                                 "it works well\n");  
  55.         }  
  56.         swap = *addr;  
  57.         if ( swap != my_event_count){  
  58.                 printk(KERN_EMERG"counter reset\n");  
  59.                 my_event_count = swap;  
  60.         } else {  
  61.                my_event_count++;  
  62.                *addr = my_event_count;  
  63. //             printk(KERN_EMERG"update counter \n");  
  64.         }  
  65. //      *addr = my_event_count;  
  66.         uio_event_notify(&kpart_info); // gernerate a interrupt here  
  67.         mod_timer(&poll_timer, jiffies + freq); // reset the timer  
  68. }  
  69.   
  70. static int drv_kpart_probe(struct device *dev)  
  71. {  
  72.   
  73.         printk(KERN_EMERG"----->  /// drv_kpart_probe( %p)\n", dev);  
  74.         kpart_info.mem[0].addr = (unsigned long)kmalloc(1024,GFP_KERNEL);  
  75.   
  76.         if(kpart_info.mem[0].addr == 0)  
  77.                 return -ENOMEM;  
  78.         kpart_info.mem[0].memtype = UIO_MEM_LOGICAL;  
  79.         kpart_info.mem[0].size = 1024;  
  80.         // for the timer interruption  
  81.         kpart_info.irq_flags = UIO_IRQ_CUSTOM;   
  82.   
  83.         if( uio_register_device(dev, &kpart_info)){  
  84.                 kfree((void *)kpart_info.mem[0].addr);  
  85.                 return -ENODEV;  
  86.         }  
  87.         //initiate and add the timer  
  88.         init_timer(&poll_timer);  
  89.         poll_timer.data = (unsigned long)&kpart_info;  
  90.         poll_timer.function = drv_kpart_timer;  
  91.         mod_timer(&poll_timer, jiffies + freq);//set timer  
  92.   
  93.         return 0;  
  94. }  
  95.   
  96. static int drv_kpart_remove(struct device *dev)  
  97. {  
  98.     uio_unregister_device(&kpart_info);  
  99.       
  100.     //delet the timer  
  101.     del_timer_sync(&poll_timer);  
  102.   
  103.     return 0;  
  104. }  
  105.   
  106. static struct platform_device * uio_dummy_device;  
  107.   
  108. static int __init uio_kpart_init(void)  
  109. {  
  110.         uio_dummy_device = platform_device_register_simple("kpart", -1,  
  111.                         NULL, 0);  
  112.         printk("&platform_device->dev = (%p)\n", &uio_dummy_device->dev);  
  113.         return driver_register(&uio_dummy_driver);  
  114.   
  115. }  
  116.   
  117. static void __exit uio_kpart_exit(void)  
  118. {  
  119.         platform_device_unregister(uio_dummy_device);  
  120.         driver_unregister(&uio_dummy_driver);  
  121. }  
  122.   
  123. module_init(uio_kpart_init);  
  124. module_exit(uio_kpart_exit);  
  125.   
  126. MODULE_LICENSE("GPL");  
  127. MODULE_AUTHOR("Benedikt Spranger");  
  128. MODULE_DESCRIPTION("UIO dummy driver");  

这是用户空间的测试部分。

我们通过mmap返回的地址addr跟驱动的内核部分进行交互。在用户空间写入addr的值0,可以重新设置驱动内核部分的

内部变量my_event_count。从而驱动程序会打印出”update counter“提示。

  1. #include <stdio.h>  
  2. #include <fcntl.h>  
  3. #include <stdlib.h>  
  4. #include <unistd.h>  
  5. #include <sys/mman.h>  
  6. #include <errno.h>  
  7.   
  8. #define UIO_DEV "/dev/uio0"  
  9. #define UIO_ADDR "/sys/class/uio/uio0/maps/map0/addr"  
  10. #define UIO_SIZE "/sys/class/uio/uio0/maps/map0/size"  
  11.   
  12. static char uio_addr_buf[16], uio_size_buf[16];  
  13.   
  14. int main(void)  
  15. {  
  16.   int uio_fd, addr_fd, size_fd;  
  17.   int uio_size;  
  18.   void* uio_addr, *access_address;  
  19.    
  20.   uio_fd = open(UIO_DEV, /*O_RDONLY*/O_RDWR);  
  21.   addr_fd = open(UIO_ADDR, O_RDONLY);  
  22.   size_fd = open(UIO_SIZE, O_RDONLY);  
  23.   if( addr_fd < 0 || size_fd < 0 || uio_fd < 0) {  
  24.        fprintf(stderr, "open: %s\n", strerror(errno));  
  25.        exit(-1);  
  26.   }  
  27.   read(addr_fd, uio_addr_buf, sizeof(uio_addr_buf));  
  28.   close(addr_fd);  
  29.   read(size_fd, uio_size_buf, sizeof(uio_size_buf));  
  30.   close(size_fd);  
  31.   uio_addr = (void*)strtoul(uio_addr_buf, NULL, 0);  
  32.   uio_size = (int)strtol(uio_size_buf, NULL, 0);  
  33.   
  34.   access_address = mmap(NULL, uio_size, PROT_READ | PROT_WRITE,  
  35.                      MAP_SHARED, uio_fd, 0);  
  36.   if ( access_address == (void*) -1) {  
  37.       fprintf(stderr, "mmap: %s\n", strerror(errno));  
  38.       exit(-1);  
  39.   }  
  40.   printf("The device address %p (lenth %d)\n"  
  41.          "can be accessed over\n"  
  42.          "logical address %p\n", uio_addr, uio_size, access_address);  
  43.   
  44.   printf("*access_address = %u\n",*((unsigned long*) access_address));  
  45.     
  46.   unsigned long * addr = (unsigned long*) access_address;  
  47.   
  48.   printf("1: read addr:%u\n", *addr);  
  49.   printf("1: write 0 to access_address\n");  
  50.  //读写操作  
  51.   *addr = 0;  
  52. //  sleep(10);  
  53. //  printf("2: read addr:%u\n", *addr);  
  54.  // read out the timer interuption times    
  55. /*  unsigned long counter = 0; 
  56.   int ret; 
  57.   while ((ret = read(uio_fd, &counter, sizeof(counter))) 
  58.                   == sizeof(counter)) { 
  59.           printf("Interrupt number is %d\n", 
  60.                           counter); 
  61.   } 
  62.    
  63.   if(ret < 0)  
  64.           fprintf(stderr, "read error: %s\n", strerror(errno)); 
  65.   printf("exit: counter is %d\n", counter); 
  66. */  
  67.   munmap(access_address, uio_size);  
  68.   close(uio_fd);  
  69.   return 0;  


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于PetaLinux开发UIO驱动,我可以给你一些基本的指导。 首先,UIO是一种通用的用户空间I/O框架,它允许用户空间的应用程序访问设备驱动程序。在PetaLinux,你可以使用UIO驱动程序来访问PL的IP核。下面是一些基本的步骤: 1.首先,在PetaLinux启用UIO支持。你可以使用petalinux-config命令来打开配置菜单,选择Kernel菜单,然后选择Device Drivers -> Userspace I/O driver support -> Userspace I/O platform driver with generic IRQ handling支持。 2.然后,编写你的UIO驱动程序。你需要创建一个新的内核模块,实现UIO驱动程序的基本功能。你需要实现的主要函数是probe和remove,它们分别在设备被识别和移除时调用。在probe函数,你需要初始化设备并注册UIO设备,然后将设备映射到用户空间。在remove函数,你需要取消设备的映射和UIO设备的注册。 3.编译并加载你的UIO驱动程序。在PetaLinux,你可以使用petalinux-build命令来编译内核模块,并使用petalinux-module命令将其加载到系统。 4.在用户空间使用UIO设备。一旦你的UIO驱动程序加载到系统,你就可以在用户空间使用它了。你需要使用mmap函数将UIO设备映射到用户空间,并使用read和write函数访问设备。 希望这些基本的指导对你有所帮助。如果你需要更详细的指导,可以参考PetaLinux文档或者一些UIO驱动程序的示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值