⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpga_driver.c

📁 这是嵌入式中的FPGA的驱动
💻 C
字号:
 /* FPGA device driver, remap physical addr to kernel virtual addr, then to user space addr// Kernel Module//	marxuxp@gmail.com//	for v2.6 kernel */#include <linux/module.h>#include <linux/init.h>#include <linux/version.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <linux/vmalloc.h>#include <linux/mman.h>#include <linux/slab.h>#include <linux/cdev.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/moduleparam.h>#include <linux/ioctl.h>#include <linux/string.h>#include <linux/list.h>#include <linux/pci.h>#include <asm/atomic.h>#include <asm/unistd.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/delay.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/arch/gpio.h>#include <asm/uaccess.h>#undef DEBUG#define DEBUG#ifdef DEBUG#define DPRINTK(x) printk(x)#else#define DPRINTK(x)#endif #ifndef FPGA_MAJOR#define FPGA_MAJOR 253   /* if 0, it is allocated by kernel */#endif/*high addr, and non-cache area*/#define FPGA_PHY_START		0x4000000/*length = 1k*/#define FPGA_PHY_SIZE		0x400//for download firmware#define 	FPGA_IO_DATA		AT91_PIN_PD30#define		FPGA_IO_CLK			AT91_PIN_PD31#define		BUFFER_SIZE 		512u#define 	DEVICE_NAME "AT91_FPGA_Driver"static int FPGA_Major = FPGA_MAJOR;static int FPGA_Minor = 0;struct cdev* FPGA_cdev = NULL;struct class* FPGA_class = NULL;	static unsigned char FPGA_DATA[BUFFER_SIZE];static int WriteByte(unsigned char Byte){	int i;	for(i = 0; i < sizeof(unsigned char); i++)	{			if(Byte & (1 << i))			{					at91_set_gpio_value(FPGA_IO_DATA, 1);/*here to simulate I2C*/					at91_set_gpio_value(FPGA_IO_CLK, 1);			}			else			{					at91_set_gpio_value(FPGA_IO_DATA, 0);					at91_set_gpio_value(FPGA_IO_CLK, 1);			}	}	return 0;}static int FPGA_open(struct inode *inode, struct file* filp){	DPRINTK("open\n");	return 0;}static int FPGA_release(struct inode * inode, struct file * filp){	DPRINTK("release\n");	return 0;}static int FPGA_mmap(struct file * filp, struct vm_area_struct * vma) {	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;	unsigned long physical = FPGA_PHY_START + off;	unsigned long vsize = vma->vm_end - vma->vm_start;	unsigned long psize = FPGA_PHY_SIZE - off;	if(vsize > psize)		return -EINVAL; /*spans too high*/	vma->vm_flags |= VM_IO|VM_RESERVED;	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);	/*remap physic addr to kernel virtual addr*/	remap_pfn_range(vma, vma->vm_start, physical, vsize, vma->vm_page_prot);	DPRINTK("memory mapped to user space\n");	return 0;}static int FPGA_ioctl(struct inode * fnode, struct file* filp, unsigned int param1, unsigned long param2) {	DPRINTK("no ctl command\n");	return -EINVAL;}static ssize_t FPGA_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){	DPRINTK("FPGA read\n");	return 0;}            static ssize_t FPGA_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){	int i, j;	int ret;	int loop = count/BUFFER_SIZE;	int left = count - loop*BUFFER_SIZE;		/*init FPGA here*/	for(i = 0; i < loop; i++)	{			ret = copy_from_user(FPGA_DATA, buf+i*BUFFER_SIZE, BUFFER_SIZE);			if(ret)			{					return -EFAULT;			}						for(j = 0; j < BUFFER_SIZE; j++)			{					WriteByte(FPGA_DATA[j]);			}	}	/*copy left data */	if(left != 0)	{			ret = copy_from_user(FPGA_DATA, buf+loop*BUFFER_SIZE, left);			if(ret)			{					return -EFAULT;			}								for(j = 0; j < left; j++)			{					WriteByte(FPGA_DATA[j]);			}	}				printk("FPGA write, size: %d\n", count);	return count;}                    static struct file_operations at9200_fops={.owner = THIS_MODULE,.open = FPGA_open,.mmap = FPGA_mmap,.ioctl = FPGA_ioctl,.read = FPGA_read,.write = FPGA_write,.release = FPGA_release,};static int __init at9200_FPGA_init(void){	int ret;	dev_t dev = 0;			FPGA_cdev = cdev_alloc();		printk(DEVICE_NAME"start init\n");	/*register device, if FPGA_Major is not 0, it will get this major number, or allocated by kernel	 * register_chrdev_region instead of register_chrdev for v2.6 kernel*/	if (FPGA_Major) 	{		dev = MKDEV(FPGA_Major, FPGA_Minor);		ret = register_chrdev_region(dev, 1, DEVICE_NAME);	} 	else 	{		ret = alloc_chrdev_region(&dev, FPGA_Minor, 1,	DEVICE_NAME);		FPGA_Major = MAJOR(dev);	}	if (ret < 0) 	{		printk(KERN_WARNING "FPGA: can't get major %d\n", FPGA_Major);		return ret;	}		/*ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &at9200_fops);	if(ret < 0)	{		printk(DEVICE_NAME "can't get major number \n");		return ret;	}	DbLedMajor = ret;*/		cdev_init(FPGA_cdev, &at9200_fops);		FPGA_cdev->owner = THIS_MODULE;		FPGA_cdev->ops = &at9200_fops;		ret = cdev_add (FPGA_cdev, MKDEV(FPGA_Major, FPGA_Minor), 1);		/* Fail gracefully if need be */		if (ret)		{			printk(KERN_NOTICE "Error %d adding FPGA", ret);			return ret;		}		/* creating your own class */  FPGA_class = class_create(THIS_MODULE, DEVICE_NAME);  if(IS_ERR(FPGA_class))   	{      printk("Err: failed in creating class.\n");  			return -1;     }  /* register your own device in sysfs, and this will cause udevd to create corresponding device node */  class_device_create(FPGA_class, NULL, MKDEV(FPGA_Major, FPGA_Minor), NULL, DEVICE_NAME"%d", FPGA_Minor);  /*if(!ret)  	{  		printk(KERN_NOTICE "Error %d class_device_create", ret);			return ret;  	}*/     	printk(DEVICE_NAME"inited\n");	return 0;}static void __exit at9200_FPGA_exit(void){				dev_t dev;		dev = MKDEV(FPGA_Major, FPGA_Minor);		unregister_chrdev_region(dev, 1);/*	unregister_chrdev(FPGA_Major, DEVICE_NAME);*/	if(FPGA_cdev)	{			cdev_del(FPGA_cdev);			printk(DEVICE_NAME"delete cdev\n");	}	if(FPGA_class)	{ 			class_device_destroy(FPGA_class, MKDEV(FPGA_Major, FPGA_Minor));		 	class_destroy(FPGA_class);		 	printk(DEVICE_NAME"delete class\n"); 	}	printk(DEVICE_NAME"exit\n");	return;}module_init(at9200_FPGA_init);module_exit(at9200_FPGA_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("marxuxp@gmail.com");MODULE_DESCRIPTION("FPGA for at9200");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -