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

📄 s3c2410_fpga0301.c

📁 ARM和FPGA通信的接口程序
💻 C
字号:
/** Filename: s3c2410_fpga.c* Function: driver for FPGA on the s3c2410 board**/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>	/* printk() */#include <linux/init.h>#include <linux/ioport.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>	/* udelay */#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <asm/hardware.h>#include <asm/io.h> /* for outb(), inl(),etc. */#include <asm/irq.h> /* for IRQ_EINT1 */#include <asm/signal.h>#include <asm/arch/S3C2410.h>//#include "s3c2410_fpga-01.h"/* There are something differences between kernel-2.6 and kernel-2.4(MIZI provided). * For kernel 2.6, there are no need to do these macro definitions. *//* Just for kernel-2.4(MIZI) */#define S3C2410_SRCPND SRCPND#define S3C2410_INTMSK INTMSK#define S3C2410_INTMOD INTMOD#define S3C2410_EXTINT0 EXTINT0/*#ifdef __FPGA_ADDR_V#define FPGA_ADDR_V io_p2v(0x10000000)#else#define FPGA_ADDR_P (0x10000000) 	//request_men_region() use physical memery address#endif*/#define FPGA_ADDR (0x10000000)#define DEVICE_NAME "fpga"static volatile unsigned char *FPGA_BASE;static int fpga_major = 0;#define MEN_SZ (0x100)unsigned char *kbuffer = 0;unsigned int length = 0;static int ready = 0;  #define FPGA_CONFIG (0X00)#define FPGA_DATA   (0X01)static int status = FPGA_DATA; /* 0=FPGA_CONFIG; 1=FPGA_DATA */   #define FPGA_DEBUG#undef Jdebug#ifdef FPGA_DEBUG#		ifdef __KERNEL__#			define Jdebug(fmt,args...) printk(KERN_EMERG fmt,## args)#  else #    define Jdebug(fmt, args...) fprintf(stderr, fmt, ## args)#  endif#else#  define Jdebug(fmt, args...)  /* not debugging: nothing */#endif  //////////////////////////////////////////////////////////////////////////////////////////// This is equal to using init_waitqueue_head(&fpga_wait)static DECLARE_WAIT_QUEUE_HEAD(fpga_wait);   //ȴᅣ17//* FPGA �жϷ���/static void fpga_irq(int irq, void *dev_id, struct pt_regs *regs){	int i;		Jdebug("fpga_irq:entering irq processing.\n");	if (irq != IRQ_EINT1)	{		printk("bad irq %d in fpga \n",irq);		return;	}		S3C2410_SRCPND  = (0x1 << 1);	if (ready)		return 1;	memset(kbuffer, 0, MEM_SZ);		length = readb(FPGA_BASE)+ readb(FPGA_BASE+1)<<8;	for (i=0; i<length; i++)		{ 			*(kbuffer+i) = readb(FPGA_BASE+i);			udelay(5);		}	ready = 1;	wake_up_interruptible(&fpga_wait);    //���}ᅣ17}static int fpga_read(struct file *file, char *buffer, size_t count, loff_t *ppos){	int ret; 	if (status != FPGA_DATA)  	{  	 		printk("FPGA's status is CONFIG,no data to read!\n");  			return 0;    	 	} 	if(!ready) //not ready yet ?			return 0;		if (length == 0)		return 0;		if (count == -1)  	{		count = length;				ret =  copy_to_user(buffer, kbuffer,count); 	} 	else 		ret = copy_to_user(buffer, kbuffer,count);	if (ret)		return -EINVAL;	ready = 0;	return count;}static int fpga_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg){	int i;	switch(cmd)	{	case FPGA_CONFIG:	/*		ARM           FPGA     |    GPBCON		GPB10 -----> nCONFIG   |[21,20]01:Output		GPB9  <----- nSTATUS   |[19,18]00:input		GPB8  <----- CONF_DONE |[17,16]00:input	*/			Jdebug("doing fpga config...\n");			status = FPGA_CONFIG;			GPBCON &= 0X10 << 16; /*01,0000*/				Jdebug("GPBCON = 0X%0X!\n",GPBCON);			/* GPBUP = 0; */			GPBDAT &= 0X0 << 10; /* draw low */			for (i=0;i<1000;i++); /* wait more than 40us,100MIPS,1000enought */ 			GPBDAT &= 0X1 << 10; /* pull up */			Jdebug("GPBDAT is OK!\n");						while ( !(GPBDAT&(0x1<<9)) ); /* wait GPB9(nSTATUS) high */			printk("FPGA is ready to write data!\n");	   		break;	case FPGA_DATA: 			status = FPGA_DATA ; 	default:		printk("two options: FPGA_DATA(1) or FPGA_CONFIG(0)\n");		break;	}	return 0;}static int fpga_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){	int i, len;	len = 1;		/*	len = (buffer[1]<<8)+buffer[0];	printk("writing len is %d\n",len);	if (len != count)		return -EINVAL;	*/			//printk("writing %c\n", buffer[0]);	memset(kbuffer, 0, 256);	copy_from_user(kbuffer, buffer, len);	printk("entering while...\n");		while(1)	{		//writeb(0x33, FPGA_BASE);		*FPGA_BASE = 0X33;		printk("write 0x33 to fpga\n");		for (i=0; i<10000; i++);		//delay(1);		//*FPGA_BASE = 0X34;	//	writeb(0x34, FPGA_BASE);	//	printk("write 0x34 to fpga\n");	//	delay(1);	//	for (i=0; i<10000; i++);		//writeb(0x34, FPGA_BASE);	}	//printk("write finished.\n");	return count;}static int fpga_release(struct inode *inode, struct file *file){	kfree(kbuffer);	Jdebug("fpga: release() done!\n");	return 0;}static int fpga_open(struct inode *inode, struct file *file){ 	int i;	BWSCON &= ~(0x03 << 8); 	BWSCON |= (0X00 << 8); 		// set bank2 to 8bit	GPHCON &= ~(0xF << 18);	GPHCON |= (0xA << 18);		// set gpio to the clkout mode	MISCCR &= ~(0x7 << 8 );			MISCCR |= (0x4 << 8);		// set clkout1 to pclk	MISCCR &= ~(0x7 << 4 );			MISCCR |= (0x3 << 4);		// set clkout0 to hclk	printk("BWSCON = 0x%0x\n",BWSCON );	printk("MISCCR = 0x%0x\n",MISCCR );	printk("GPHCON = 0x%0x\n",GPHCON);	kbuffer = (unsigned char *)kmalloc(256, GFP_KERNEL);	if(!kbuffer)	{		printk("failed assigned small mem for buffer1 ! \n");		return -ENOMEM;	}	Jdebug("fpga: open() done!\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_ADDR + off;	unsigned long vsize = vma->vm_end - vma->vm_start;	unsigned long psize = MEM_SZ - 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_page_range(vma, vma->vm_start, physical, vsize, vma->vm_page_prot);	return 0;}/*�ϵͳӿڶ�*/static struct file_operations fpga_fops = {owner: THIS_MODULE,open: fpga_open,read: fpga_read,ioctl: fpga_ioctl,write: fpga_write,release: fpga_release,mmap: fpga_mmap,};#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_handle;#endif/* FPGA ��*/static int __init fpga_init(void){	int ret;	ready = 0;	/*ע�豸*/	ret = register_chrdev(fpga_major, DEVICE_NAME, &fpga_fops );	if(ret<0)	{		printk(DEVICE_NAME "can't register fpga major number \n" ); 		return ret;	}	if (fpga_major == 0) fpga_major = ret;// use not only int1, but also 2,4,5,6, should be set!	Jdebug("original INTMSK= 0x%x\n", S3C2410_INTMSK); 	S3C2410_INTMSK  &= ~(0x1 << 1); /* open INT1 interrupt, othets not change*/  Jdebug("new INTMSK = 0x%x\n",S3C2410_INTMSK);/*	temp = inl(S3C2410_INTMOD);	printk("original value of INTMOD is 0x%x", temp);	temp |= 0x1 << 1; 	outl(temp,S3C2410_INTMOD); //INT1 using FIQ(fast interrupt)	printk("Value changed of INTMOD using outl() is 0x%x", temp);*/	//	__raw_writel((__raw_readl(S3C2410_INTMSK)&~(0x1<<1)), S3C2410_INTMSK); 	// set 0 to INT1 of INTMSK//	__raw_writel((__raw_readl(S3C2410_INTMOD)| (0x1<<1), S3C2410_INTMOD);		// set 1 to INT1 of INTMOD	init_waitqueue_head(&fpga_wait);	if( request_irq(IRQ_EINT1, &fpga_irq, 0/*SA_INTERRUPT*/, DEVICE_NAME, NULL))	{		unregister_chrdev( fpga_major, DEVICE_NAME );		printk( DEVICE_NAME "can't request irq \n" );		return (-1);	}	Jdebug( DEVICE_NAME" assigned IRQ  %d\n", IRQ_EINT1);#ifdef CONFIG_DEVFS_FS	devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT, fpga_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &fpga_fops, NULL );#endif	FPGA_BASE = ioremap(FPGA_ADDR,0X100);	if (!FPGA_BASE)	{			prink("ioremap fpga base address failed!\n");		return -EINVAL;	}	if (check_mem_region(FPGA_BASE, 0x100))	{		printk("fpga: memory already in use.\n");		return -EBUSY;	}  	request_mem_region(FPGA_BASE,0X100,DEVICE_NAME); 		printk("CLKDIVN = 0X%0x\n",CLKDIVN);	CLKDIVN = 3;//	CLKDIVN = 1;	printk("CLKDIVN = 0X%0x\n",CLKDIVN);		Jdebug("fpga: init() done!\n"); 	return 0;}static void __exit fpga_exit(void){	release_mem_region(FPGA_BASE,0X100);		iounmap(FPGA_BASE); #ifdef CONFIG_DEVFS_FS	devfs_unregister(devfs_handle);#endif	free_irq( IRQ_EINT1, fpga_irq);	unregister_chrdev(fpga_major, DEVICE_NAME);	Jdebug("fpga: exit() done!\n");}module_init(fpga_init);module_exit(fpga_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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