项目中需要用ARM与FPGA进行通信,通信方式是通过FPGA生成的SRAM作为数据的交换区,ARM9芯片为ATMEL的AT91SAM9260,采用Linux 2.6.19的内核,今天搞了一天,总算是读写成功,下面简要的说明一下。
ARM中只有I/O内存的没有I/O端口,ARM9运行后默认是开启MMU的,Linux采用虚拟存储管理内存,具体的内存管理方式本文不作展开。所以要使用Linux访问外设必须要先进行内存映射。这里主要涉及两个函数:
Ø Request_mem_region:该函数检查所需要转换的内存是否被占用,进行合法性检查,有些驱动中没有,个人认为安全性起见还是使用为妙。
Ø Ioremap:该函数完成物理地址到虚拟地址的映射,映射后的地址才能被Linux内核使用。
下面给出代码:
驱动程序:
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/cdev.h>
- #include <linux/ioctl.h>
- #include <linux/gpio.h>
- #include <linux/mm.h>
- #include <linux/errno.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/gpio.h>
- #include <asm/uaccess.h>
- #include <linux/slab.h> /*for Kmalloc*/
- #include <asm/io.h>/*for virt_to_phys*/
- #include <asm/hardware.h>
- #include <asm/arch/at91_pio.h>
- #include <asm/arch/at91rm9200.h>/*for sram address and size*/
- #define SRAM0_PHYADDR 0x300000
- #define SRAM0_SIZE 0x1000 /*4K*/
- int sram_major = 242;
- int sram_open(struct inode *inode,struct file *filp);
- int sram_release(struct inode *inode,struct file *filp);
- int sram_release(struct inode *inode,struct file *filp);
- ssize_t sram_read(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos);
- ssize_t sram_write(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos);
- //int sram_mmap(struct file *filp, struct vm_area_struct *vma );
- //static void sram_setup_cdev(struct sram_dev *dev,int index);
- int sram_init(void);
- void sram_cleanup(void);
- MODULE_AUTHOR("Cun Tian Rui");
- MODULE_LICENSE("Dual BSD/GPL");
- struct sram_dev
- {
- struct cdev cdev;
- unsigned long startAddr;
- unsigned long size;
- char *mapPtr;
- }sram_dev;
- struct sram_dev *sramdevp;
- struct file_operations sram_fops =
- {
- .owner = THIS_MODULE,
- // .ioctl = sram_ioctl,
- .open = sram_open,
- .release = sram_release,
- .read = sram_read,
- .write = sram_write,
- // .mmap = sram_mmap
- };
- int sram_open(struct inode *inode,struct file *filp)
- {
- struct sram_dev *devp;
- devp = container_of(inode->i_cdev,struct sram_dev,cdev);
- filp->private_data = devp;
- return 0;
- }
- int sram_release(struct inode *inode,struct file *filp)
- {
- return 0;
- }
- ssize_t sram_read(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos)
- {
- unsigned long p = *f_pos;
- struct sram_dev *devp = filp->private_data;
- printk("Driver read function running\n");
- printk("p is %d\n",p);
- if (p >= devp->size)
- return -EINVAL;
- if (count > devp->size-p)
- count = devp->size-p;
- printk("count is %d\n",count);
- if (copy_to_user(buf, devp->mapPtr+p,count))
- return -EFAULT;
- *f_pos+= count;
- return count;
- }
- ssize_t sram_write(struct file *filp , char __user *buf ,size_t count,loff_t *f_pos)
- {
- unsigned long p = *f_pos;
- printk("Driver write function running\n");
- printk("p is %d\n",p);
- struct sram_dev *devp = filp->private_data;
- if (p >= devp->size)
- return -EINVAL;
- if (count > devp->size-p)
- count = devp->size-p;
- printk("count is %d\n",count);
- if (copy_from_user( devp->mapPtr+p,buf,count))
- return -EFAULT;
- *f_pos += count;
- return count;
- }
- /*
- int sram_mmap(struct file *filp, struct vm_area_struct *vma )
- {
- unsigned long offset = vma->vm_pgoff<<PAGE_SHIFT;
- unsigned long size = vma->vm_end - vma->vm_start;
- if ( size > SRAM0_SIZE )
- {
- printk("size too big\n");
- return(-ENXIO);
- }
- offset = offset + SRAM0_PHYADDR;
- vma->vm_flags |= VM_LOCKED;
- if ( remap_pfn_range(vma,vma->vm_start,offset,size,PAGE_SHARED))
- {
- printk("remap page range failed\n");
- return -ENXIO;
- }
- return(0);
- }
- */
- int sram_init(void)
- {
- int result;
- int err,ret;
- int devno = MKDEV(sram_major,0);
- dev_t dev = MKDEV(sram_major,0);
- if(sram_major)
- {
- result = register_chrdev_region(dev,1,"SRAM0");
- }
- if(result < 0)
- {
- return result;
- }
- sramdevp = kmalloc(sizeof(struct sram_dev),GFP_KERNEL);
- if(!sramdevp)
- {
- result = - ENOMEM;
- goto fail_malloc;
- }
- memset(sramdevp,0,sizeof(struct sram_dev));
- //sram_setup_cdev(sramdevp,0);
- sramdevp->startAddr = SRAM0_PHYADDR;
- sramdevp->size = SRAM0_SIZE;
- ret = request_mem_region(SRAM0_PHYADDR, SRAM0_SIZE, "SRAM0 Region");
- if(ret==NULL)
- {
- printk("Request Memory Region Failed!\n");
- return -1;
- }
- sramdevp->mapPtr = ioremap(SRAM0_PHYADDR,SRAM0_SIZE);
- cdev_init(&sramdevp->cdev,&sram_fops);
- sramdevp->cdev.owner = THIS_MODULE;
- sramdevp->cdev.ops = &sram_fops;
- err = cdev_add(&sramdevp->cdev,devno,1);
- if(err)
- {
- printk(KERN_NOTICE "Error %d adding SRAM%d",err,0);
- }
- printk( "SRAM0_virt_addr = 0x%lx\n", (unsigned long)sramdevp->mapPtr );
- return 0;
- fail_malloc:
- unregister_chrdev_region(dev,sramdevp);
- kfree(sramdevp);
- return result;
- }
- void sram_cleanup(void)
- {
- cdev_del(&sramdevp->cdev);
- iounmap(sramdevp->mapPtr);
- kfree(sramdevp);
- unregister_chrdev_region(MKDEV(sram_major,0),1);
- }
- module_init(sram_init);
- module_exit(sram_cleanup);
写SRAM:
- #include<sys/types.h>
- #include<sys/stat.h>
- #include<fcntl.h>
- #include<stdio.h>
- #include<linux/fs.h>
- #include<stdlib.h>
- #include<unistd.h>
- #define SRAM_DEV "/dev/SRAM0"
- int main()
- {
- int fd;
- char * data="ctrboss";
- fd=open(SRAM_DEV,O_WRONLY);
- if(fd<0)
- {
- printf("Unable to open sram device %s\n",SRAM_DEV);
- return 0;
- }
- write(fd,data,sizeof(data));
- close(fd);
- return 1;
- }
读SRAM:
- #include<sys/types.h>
- #include<sys/stat.h>
- #include<fcntl.h>
- #include<stdio.h>
- #include<linux/fs.h>
- #include<stdlib.h>
- #include<unistd.h>
- #define SRAM_DEV "/dev/SRAM0"
- int main()
- {
- int i,fd;
- char data[6];
- fd=open(SRAM_DEV,O_RDONLY);
- if(fd<0)
- {
- printf("Unable to open sram device %s\n",SRAM_DEV);
- return 0;
- }
- read(fd,data,sizeof(data));
- printf("data is %x\n",data[0]);
- printf("data is %x\n",data[1]);
- printf("data is %x\n",data[2]);
- printf("data is %x\n",data[3]);
- printf("data is %x\n",data[4]);
- printf("data is %x\n",data[5]);
- printf("data is %c\n",data[0]);
- printf("data is %c\n",data[1]);
- printf("data is %c\n",data[2]);
- printf("data is %c\n",data[3]);
- printf("data is %c\n",data[4]);
- printf("data is %c\n",data[5]);
- close(fd);
- return 1;
- }