首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

如何在ZYNQ下写驱动程序?????

如何在ZYNQ下写驱动程序?????

如何在ZYNQ下写驱动程序????? 首先,要下一个内核源码:使用git命令下载似乎不是很好使,提供个下载地址: https://github.com/Digilent/linux-digilent/releases 解压源码:  tar -xvzf linux-digilent-3.6-digilent-13.01.tar.gz 直接make会出现错误  配置内核源码:     在arch/arm/configs/目录下有这个配置文件   digilent_zed_defconfig root@ubuntu:/home/jumn/linux-digilent-3.6-digilent-13.01# make ARCH=arm digilent_zed_defconfig###########################root@ubuntu:/opt/zedboard/kernel# cd  linux-digilent-3.6-digilent-13.01root@ubuntu:/opt/zedboard/kernel/linux-digilent-3.6-digilent-13.01# make ARCH=arm digilent_zed_defconfig  HOSTCC  scripts/basic/fixdep  HOSTCC  scripts/kconfig/conf.o  SHIPPED scripts/kconfig/zconf.tab.c  SHIPPED scripts/kconfig/zconf.lex.c  SHIPPED scripts/kconfig/zconf.hash.c  HOSTCC  scripts/kconfig/zconf.tab.o  HOSTLD  scripts/kconfig/conf## configuration written to .config#  编译Linux内核:root@ubuntu:/home/jumn/linux-digilent-3.6-digilent-13.01# make编译过程在arch/arm/boot目录下生成Image和zImage文件  这样以后就可以写驱动了。。。。。。 下面是一个简单的驱动模块例子:#include #include #include #include #include #include #include #include  #define DEVICE_NAME         "my_gpio_dev"  #define MY_GPIO_PHY_ADDR    0x75c80000 //Modify the address to your peripheral #define MY_GPIO_REG_NUM     2 #define MY_GPIO_REG_WIDTH   32  static void __iomem *GPIO_Regs; /****************************************************************GPIO_Regs指针指向映射后的空间,通过ioremap函数,为I/O地址为MY_GPIO_PHY_ADDR的设备分配了MY_GPIO_REG_NUM大小的空间。****************************************************************/  static int my_gpio_open(struct inode * inode , struct file * filp) {   return 0; }  static int my_gpio_release(struct inode * inode, struct file *filp) {   return 0; }  static int my_gpio_read(struct file *filp, char *buffer, size_t length, loff_t * offset) {   int bytes_read = 0;    int i=0;      if (filp->f_flags & O_NONBLOCK)     return -EAGAIN;      if (length>0 && length<=(MY_GPIO_REG_NUM*4))   {     for(i=0;i     {       *(buffer+i)=(char)ioread8(GPIO_Regs+i);     }     bytes_read=i;   }   return bytes_read; }   //ioctl就是写寄存器操作的封装函数了,使用的方法依旧是iowrite32 static int my_gpio_ioctl(struct file *filp, unsigned int reg_num, unsigned long arg) {   if(reg_num>=0 && reg_num   {     iowrite32(arg, GPIO_Regs+reg_num*4); //通过iowrite32和ioread32就可以简单便捷地实现写入和读    printk("my_gpio: Write 0x%x to 0x%x!\n", arg, GPIO_Regs+reg_num*4);   }   else   {     printk("my_gpio:[ERROR] Wrong register number!\n");     return -EINVAL;   }      return 0; } //在MicroBlaze中,就可以通过of_platform实现读取DeviceTree的compatible信息,来匹配设备和驱动://{ .compatible = "xlnx, my_gpio-1.00.a", } static const struct file_operations my_gpio_fops =  //文件系统 {   .owner = THIS_MODULE,   .open = my_gpio_open,   .release = my_gpio_release,   .read = my_gpio_read,   .unlocked_ioctl = my_gpio_ioctl,   };  static struct miscdevice my_gpio_dev = {   .minor = MISC_DYNAMIC_MINOR,   .name = DEVICE_NAME,   .fops = &my_gpio_fops, };  int __init my_gpio_init(void) {   int ret, val;         //Map device to the virtual address of kernel   GPIO_Regs = ioremap(MY_GPIO_PHY_ADDR, MY_GPIO_REG_NUM); /* Verify it's non-null! */  //GPIO_Regs指针指向映射后的空间,通过ioremap函数,为I/O地址为MY_GPIO_PHY_ADDR的设备分配了MY_GPIO_REG_NUM大小的空间。   printk("my_gpio: Access address to device is:0x%x\n", (unsigned int)GPIO_Regs);   if(GPIO_Regs == NULL)   {     printk("my_gpio:[ERROR] Access address is NULL!\n");     return -EIO;   }       //misc_register函数对设备进行注册   ret = misc_register(&my_gpio_dev);   if (ret)   {     printk("my_gpio:[ERROR] Misc device register failed\n");     return ret;   }      printk("my_gpio: Tata! Module init complete\n");      val = ioread32(GPIO_Regs);   printk("my_gpio: Read 0x%x from switches, writing to LED...", val);    iowrite32(val, GPIO_Regs+4);   printk("OK!\n");    return 0; /* Success */ }  void __exit my_gpio_exit(void) {   iounmap(GPIO_Regs);   //release_mem_region(GPIO_Regs, MY_GPIO_REG_NUM*MY_GPIO_REG_WIDTH);   misc_deregister(&my_gpio_dev);      printk("my_gpio: Module exit\n"); }  module_init(my_gpio_init); module_exit(my_gpio_exit);  MODULE_AUTHOR("Jumn"); MODULE_ALIAS("my_gpio"); MODULE_DESCRIPTION("ZYNQ  my_gpio module"); MODULE_LICENSE("GPL"); 程序在这里:GPIO_Driver.zip 还有MAKEFILE文件# Cross compiler makefile for my_gpio KERN_SRC=/opt/zedboard/kernel/linux-digilent-3.6-digilent-13.01obj-m := my_gpio.o all:        make -C $(KERN_SRC) ARCH=arm M=`pwd` modulesclean:        make -C $(KERN_SRC) ARCH=arm M=`pwd=` clean其中,对于KERNELDIR:=/opt/zedboard/kernel/linux-digilent-3.6-digilent-13.01如果你认为太麻烦了,可以用  mv    旧文件名   新文件名改为KERN_SRC=/opt/zedboard/kernel/linux-3.6-digilentmake结果为:root@ubuntu:/home/jumn/DRIVER__MODULE/My_GPIO_Driver# lsMakefile       Module.symvers  my_gpio.ko     my_gpio.mod.omodules.order  my_gpio.c       my_gpio.mod.c  my_gpio.o其中,my_gpio.ko 就是我们要的文件。。。。。。
记录学习中的点点滴滴,让每一天过的更加有意义!
返回列表