- 论坛徽章:
- 0
|
您好,我最近在写Linux下的FPGA驱动程序,想要实现ARM与FPGA通信,实现二者之间的数据和命令传输,ARM芯片的arm920T,arm与fpga之间通过总线连接,fpga相当有挂接在arm片选nGCS2上的寄存器。对应的物理地址为0x10000000
,在内核空间,我已经通过测试了,通过ioremap内存映射,然后利用iowrite等函数可以对实现二者之间的数据传输。而现在我的问题是:在用户空间操作FPGA,我利用的是mmap函数,通过系统调用,在用户空间通过操作mmap返回的指针来实现通信,可是通过测试,发现数据没有写到FPGA中,应该是地址出现问题了,我有一个困惑:
如下是LDD3中一段
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
unsigned long physical = simple_region_start + off;
...........
remap_pfn_range(vma, vma_>vm_start, physical, vsize, vma->vm_page_prot);
这里的remap_pfn_range中的第三个参数不是pfn页帧号吗?为啥是物理地址,对于这个参数我一直没弄清楚,如果我操作物理设备,那么这里的pfn 该怎么写,比如我的物理地址是physical 0x10000000 那么Pfn =physical>> PAGE_SHIFT ,是这样吗?
下面是我的驱动程序以及测试程序,希望大家帮位看看,谢谢啦
//s3c2440_fpga.c
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/signal.h>
#include <asm-generic/siginfo.h>
#include <asm/irq.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <mach/regs-gpio.h>
#include <mach/regs-mem.h>
#include <mach/hardware.h>
#include <mach/regs-irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/irqreturn.h>
#include <linux/irqnr.h>
#include <linux/hardirq.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include<linux/mm_types.h>
#include<linux/cdev.h>
#include<linux/io.h>
#include <linux/miscdevice.h>
#include <linux/pci.h>
#define DEVICE_NAME "FPGA"
#define FPGA_MAJOR 240
#define FPGA_ADDR 0x10000000 //物理地址0x10000000 ~ 0x18000000
#define FPGA_NR_DEVS 1
#define FPGA_DEVS_SIZE 4096
#define FPGA_ADDR_SIZE 1024//申请IO内存的大小
#define GPACON (0x56000000)
#define BWSCON (0x48000000)
#define BANKCON2 (0x4800000C)
static volatile unsigned long *gpacon_addr;
static volatile unsigned long *bwscon_addr;
static volatile unsigned long *bankcon2_addr;
//static volatile unsigned long *FPGA_BASE;
static void __iomem *FPGA_BASE;
static unsigned long reg;
unsigned int ret = 0;
struct cdev cdev;
/************open***************/
static int fpga_open(struct inode *inode, struct file *file)
{
printk("virt_addr = 0x%lx\n",(unsigned long)FPGA_BASE);
printk("FPGA opened\n"
return 0;
}
/************read***************/
static ssize_t fpga_read(struct file *file, char __user *buffer, size_t size, loff_t *ppos)
{
reg=readl(FPGA_BASE+24);
printk("0x%lx\n",reg);
return ret;
}
/************write***************/
static ssize_t fpga_write(struct file *file,const char __user *buffer, size_t size, loff_t *ppos)
{
iowrite16(0x456, FPGA_BASE+0x00000030);
//writel(0x456, FPGA_BASE+12);
return ret;
}
static struct file_operations s3c2440_fpga_fops = {
.owner = THIS_MODULE,
.read =fpga_read,
.write =fpga_write,
.open =fpga_open,
};
static int __init s3c2440_fpga_init(void)
{
int ret;
struct resource *fpga_res;
ret = register_chrdev(FPGA_MAJOR,DEVICE_NAME,& s3c2440_fpga_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't register major number\n"
return ret;
}
/**************************** 申请I/O内存 *******************************/
fpga_res=request_mem_region(FPGA_ADDR,FPGA_ADDR_SIZE,DEVICE_NAME);
if(fpga_res==NULL)
{
printk("request io memery fail\n"
ret =-EINVAL;
goto fail_request_mem;
}
//×××××××××××××××××××I/O内存映物理地址映射到虚拟地址××××××××××××××××××××××××××××××××//
FPGA_BASE=(volatile unsigned long *)ioremap(FPGA_ADDR,FPGA_ADDR_SIZE);
if(!FPGA_BASE)
{
printk("remap address fail\n"
ret = -ENOMEM;
goto fail_ioremap;
}
//×××××××××××××××××××配置I/O寄存器设置时序和位宽以及片选nGCS2××××××××××××××××××××××××××××××//
gpacon_addr=(volatile unsigned long *)ioremap_nocache(GPACON,0x0000004);
bwscon_addr=(volatile unsigned long *)ioremap_nocache(BWSCON,0x0000004);
bankcon2_addr=(volatile unsigned long *)ioremap_nocache(BANKCON2,0x0000004);
writel( readl(gpacon_addr)|(0x01<<13),gpacon_addr);
writel( (readl(bwscon_addr)&~(0xF<<)|(0XE<<,bwscon_addr);
writel( (readl(bankcon2_addr)&~(0x8003)),bankcon2_addr);
writel( (readl(bankcon2_addr)&~(0x03)),bankcon2_addr);
/*cdev结构分配,注册,初始化,与linux内核之间传参数,涉内*/
cdev_init(&cdev, &s3c2440_fpga_fops);
cdev.owner = THIS_MODULE;
cdev.ops = &s3c2440_fpga_fops;
cdev_add(&cdev,MKDEV(FPGA_MAJOR,0), FPGA_NR_DEVS);//注册字符设备
return 0;
fail_request_mem:unregister_chrdev_region(MKDEV(FPGA_MAJOR,0),FPGA_NR_DEVS);
return ret;
fail_ioremap: release_mem_region(FPGA_ADDR,FPGA_ADDR_SIZE); //释放IO内存
unregister_chrdev_region(MKDEV(FPGA_MAJOR,0), FPGA_NR_DEVS);
return ret;
}
static void __exit s3c2440_fpga_exit(void)
{
unregister_chrdev(FPGA_MAJOR, DEVICE_NAME);
iounmap(FPGA_BASE);
iounmap(gpacon_addr);
iounmap(bwscon_addr);
iounmap(bankcon2_addr);
release_mem_region(FPGA_ADDR,FPGA_ADDR_SIZE); //释放IO内存
cdev_del(&cdev);
}
MODULE_LICENSE("GPL"
module_init(s3c2440_fpga_init);
module_exit(s3c2440_fpga_exit);
//fpga_test.c
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<string.h>
#define FPGA_Address 0x10000000
#define SIZE (100)
typedef struct
{
unsigned long r_MemUnit1[65536]; //32位无符号数据 Total Size:1MB Address Space
}MEMUNIT;
int main(void)
{
int fd,i;
MEMUNIT record, *addrs;
char *buf="butterfly!";
fd = open("/dev/FPGA",O_RDWR);
if(fd == -1)
{
printf("Error!!\n"
exit(-1);
}
// addrs =( MEMUNIT *)mmap(NULL,SIZE* sizeof(record),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
addrs =( MEMUNIT *)mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(addrs==MAP_FAILED)
{
printf("mmap error!!!\n"
exit(-1);
}
addrs->r_MemUnit1[12]=12;
msync((void *)addrs,4096, MS_ASYNC);
printf("addrs[12]:0x%lx\n",addrs);
printf("addrs[12]:0x%lx\n",addrs->r_MemUnit1[0]);
printf("addrs[12]:0x%lx\n",addrs->r_MemUnit1[1]);
printf("addrs[12]:0x%lx\n",addrs->r_MemUnit1[2]);
printf("addrs[12]:0x%x\n",addrs->r_MemUnit1[12]);
/* while(1)
{
read(fd,buf,3);
}*/
munmap((void *)addrs,4096);
close(fd);
exit(0);
}
|
|