免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2260 | 回复: 3
打印 上一主题 下一主题

[硬件及驱动] dma读取没有数据 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-12 14:24 |只看该作者 |倒序浏览
程序中使用pio方式写入fpga,然后通过dma方式从fpga的ram读取数据,通过dma方式写回,但是始终得不到数据?请教各位是哪里问题~驱动程序如下


#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
//#include <asm/floppy.h>

#define PCI_VENDOR_ID_XILINX        0x10ee
#define PCI_DEVICE_ID_XILINX_PCIE   0x6011

#define OAD_DEV_NAME                "oad"
#define OAD_DRV_MAJOR               247
#define OAD_BAR_NUM                 2
#define OAD_DRIVER_NAME             "oad_driver"

#define BUF_SIZE                    (1 * 1024)

#define CARD_VERSION_OFFSET                                         0
#define GENERAL_STATUS_OFFSET                                       4
#define PIO_STATUS_OFFSET                                           8
#define DMA_STATUS_OFFSET                                           12
#define INTERRUPT_STATUS_OFFSET                                     16
#define ERROR_STATUS_OFFSET                                         20
#define PIO_READ_ADDRESS_OFFSET                                     24
#define PIO_READ_DATA_OFFSET                                        28
#define PIO_WRITE_ADDRESS_OFFSET                                    32
#define PIO_WRITE_DATA_OFFSET                                       36
#define DMA_UPSTREAM_TIME_COST_OFFSET                         40
#define DMA_DOWNSTREAM_TIME_COST_OFFSET                 44
#define DMA_REQUEST_LENGTH_OFFSET                                   48
#define DMA_ACTUAL_TRANSFERRED_LENGTH_OFFSET                   52
#define DMA_EXTERN_MEMORY_ADDRESS_OFFSET                56
#define DMA_HOST_MEMORY_ADDRESS_OFFSET                        60
#define DMA_UPSTREAM_LENGTH_OFFSET                            64
#define DMA_NEXT_DESCRIPTOR_ADDRESS_OFFSET                    68

enum {
  SUCCESS = 0,
  FAIL
};

struct oad_private {
  char *name;
  struct pci_dev* pci_dev;
  unsigned long pci_bar_phy[OAD_BAR_NUM];
  unsigned long pci_bar_len[OAD_BAR_NUM];
  void *pci_bar_virt[OAD_BAR_NUM];
  dma_addr_t dma_read_phy;
  unsigned long dma_read_size;
  wait_queue_head_t dma_read_wait;
};

static struct oad_private *oad;

static int oad_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static void oad_remove(struct pci_dev *pdev);

static ssize_t oad_pio_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos);
static ssize_t oad_pio_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos);
static ssize_t oad_dma_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos);
static ssize_t oad_dma_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos);
static void oad_interrupt(int irq, void *dev, struct pt_regs *regs);

int oad_open(struct inode *inode, struct file *fp)
{
  printk(KERN_INFO "%s: open: module opened\n", oad->name);
  return SUCCESS;
}

int oad_release(struct inode *inode, struct file *fp)
{
  printk(KERN_INFO "%s: release: module released\n", oad->name);
  return SUCCESS;
}

struct file_operations oad_fops =
{
  .owner    = THIS_MODULE,
  .open     = oad_open,
  .release  = oad_release,
  .read     = oad_dma_read,
  .write    = oad_pio_write,
};

struct pci_device_id oad_ids[] = {
  {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_PCIE),},
  {0,}
};
MODULE_DEVICE_TABLE(pci, oad_ids);

static struct pci_driver oad_driver =
{
  .name     = OAD_DEV_NAME,
  .id_table = oad_ids,
  .probe    = oad_probe,
  .remove   = oad_remove,
};

static int oad_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
  int i;
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_probe\n");

  if(pci_enable_device(pdev))
  {
    printk(KERN_INFO "\t pci_enable_device error\n");
    return FAIL;
  }
  
  if(pci_set_dma_mask(pdev, (u32)0xffffffff))
  {
    printk(KERN_INFO "\t pci_set_dma_mask error\n");
    return FAIL;
  }

  pci_set_master(pdev);

  oad = kmalloc(sizeof(struct oad_private), GFP_KERNEL);
  if(NULL == oad)
  {
    printk(KERN_INFO "\t kmalloc of oad_private error\n");
    return FAIL;
  }
  oad->name = OAD_DEV_NAME;
  oad->pci_dev = pdev;

  for(i = 0; i < OAD_BAR_NUM; i++)
  {
    oad->pci_bar_phy[i] = pci_resource_start(pdev, i);
    oad->pci_bar_len[i] = pci_resource_len(pdev, i);
    request_mem_region(oad->pci_bar_phy[i], oad->pci_bar_len[i], OAD_DEV_NAME);
    oad->pci_bar_virt[i] = ioremap(oad->pci_bar_phy[i], oad->pci_bar_len[i]);

    printk(KERN_INFO "\t oad->pci_bar_phy[%d] = 0x%8lx\n", i, (unsigned long)oad->pci_bar_phy[i]);
    printk(KERN_INFO "\t oad->pci_bar_len[%d] = %ld\n", i, oad->pci_bar_len[i]);
    printk(KERN_INFO "\t oad->pci_bar_virt[%d] = 0x%8lx\n", i, (unsigned long)oad->pci_bar_virt[i]);
  }

  //init_waitqueue_head(&(oad->dma_read_wait));

  //if(request_irq(pdev->irq, oad_interrupt, 0, OAD_DEV_NAME, NULL))
  //{
  //  printk(KERN_INFO "\t request_irq error\n");
  //  return FAIL;
  //}

  if(register_chrdev(OAD_DRV_MAJOR, OAD_DEV_NAME, &oad_fops))
  {
    printk(KERN_INFO "\t register_chrdev error\n");
    return FAIL;
  }
  
  return SUCCESS;
}

static void oad_remove(struct pci_dev *pdev)
{
  int i;
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_remove\n");
  
  for(i = 0; i < OAD_BAR_NUM; i++)
  {
    iounmap(oad->pci_bar_virt);
    release_mem_region(oad->pci_bar_phy[i], oad->pci_bar_len[i]);
  }
  pci_disable_device(pdev);
  unregister_chrdev(OAD_DRV_MAJOR, OAD_DEV_NAME);
  kfree(oad);
}

static int __init oad_init(void)
{
  int rc;
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_init\n");
  
  rc = pci_register_driver(&oad_driver);
  return rc;
}

static void __exit oad_exit(void)
{
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_exit\n");
  pci_unregister_driver(&oad_driver);
}

module_init(oad_init);
module_exit(oad_exit);


static ssize_t oad_pio_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos)
{
  int i;
  void *virt;
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_pio_write\n");

  virt = kmalloc(cnt, GFP_KERNEL);
  printk(KERN_INFO "\t virt = 0x%8lx\n", (unsigned long)virt);
  printk(KERN_INFO "\t oad->pci_bar_phy[0] = 0x%8lx\n", (unsigned long)oad->pci_bar_virt[1]);
  copy_from_user(virt, buf, cnt);

  for(i = 0; i < cnt/4; i++)
  {
    udelay(1);
    iowrite32(*((u32*)(virt + i*4)), ((unsigned long *)(oad->pci_bar_virt[1] + i*4)));
  }
  kfree(virt);

  return SUCCESS;
}

static ssize_t oad_pio_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos)
{
  int i;
  void *virt;
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_pio_read\n");

  virt = kmalloc(cnt, GFP_KERNEL);
  printk(KERN_INFO "\t virt = 0x%8lx\n", (unsigned long)virt);
  printk(KERN_INFO "\t oad->pci_bar_phy[0] = 0x%8lx\n", (unsigned long)oad->pci_bar_virt[1]);

  for(i = 0; i < cnt/4; i++)
  {
    *((u32*)(virt + i*4)) = ioread32(((unsigned long *)(oad->pci_bar_virt[1] + i*4)));
  }
  copy_to_user(buf, virt, cnt);
  kfree(virt);

  return SUCCESS;
}

static ssize_t oad_dma_write(struct file *fp, const char __user *buf, size_t cnt, loff_t *f_pos)
{
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_dma_write\n");
  printk(KERN_INFO "\t[OAD_DEBUG] end of oad_dma_write\n");
  return SUCCESS;
}

static ssize_t oad_dma_read(struct file *fp, char __user *buf, size_t cnt, loff_t *f_pos)
{
  void *dma_addr_virt = NULL;
  dma_addr_t dma_addr_phy;
  //dma_addr_t *dap;
  int i;

  u32 dma_extn_addr, dma_host_addr, dma_up_len, dma_next_desc_addr;

  dma_extn_addr      = 0x00000000;
  dma_host_addr      = 0x00000000;
  dma_up_len         = 0x00000000; // byte based
  dma_next_desc_addr = 0x00000000;

  dma_addr_virt = kmalloc(cnt, GFP_KERNEL|__GFP_DMA);
  //dma_addr_virt = ((void *)dma_mem_alloc(cnt);
  printk("\t size of allocated mem is %d\n", cnt);
  printk("\t addr of dma_addr_virt is 0x%p\n", dma_addr_virt);
  printk("\t addr of buf is %p\n", buf);
  if(NULL == dma_addr_virt)
  {
    printk("\t kmalloc error!\n");
    return FAIL;
  }

  //dma_addr_phy = pci_map_single(oad->pci_dev, dma_addr_virt, cnt, PCI_DMA_FROMDEVICE);
  dma_addr_phy = dma_map_single(oad->pci_dev, dma_addr_virt, cnt, PCI_DMA_FROMDEVICE);
  dap = dma_addr_phy;
  printk("\t addr of dma_addr_phy is 0x%p\n", dma_addr_phy);
  if(NULL == dma_addr_phy)
  {
    printk("\t pci_map_signle error!\n");
    return FAIL;
  }

  //printk(KERN_INFO "\t dma_addr_virt = 0x%8lx, dma_addr_phy = 0x%8lx", (unsigned long)dma_addr_virt, (unsigned long)dma_addr_phy);
  //pci_dma_sync_single_for_cpu(oad->pci_dev, dma_addr_phy, cnt, PCI_DMA_FROMDEVICE);

  //oad->dma_read_phy = dma_addr_t
  dma_extn_addr = 0x00000000;
  dma_host_addr = (u32)dma_addr_phy;
  dma_up_len = (u32)cnt;
  dma_next_desc_addr = 0x00000000;

  iowrite32(dma_extn_addr, (oad->pci_bar_virt[0] + DMA_EXTERN_MEMORY_ADDRESS_OFFSET));
  iowrite32(dma_host_addr, (oad->pci_bar_virt[0] + DMA_HOST_MEMORY_ADDRESS_OFFSET));
  iowrite32(dma_up_len, (oad->pci_bar_virt[0] + DMA_UPSTREAM_LENGTH_OFFSET));
  iowrite32(dma_next_desc_addr, (oad->pci_bar_virt[0] + DMA_NEXT_DESCRIPTOR_ADDRESS_OFFSET));

  iowrite32(0x80000000, (oad->pci_bar_virt[0] + DMA_STATUS_OFFSET));

  //wait_event_interruptible((oad->dma_read_wait), 0);
  for(i = 0; i < 1000; i++)
    udelay(100);

  //pci_dma_sync_single_for_cpu(oad->pci_dev, (dma_addr_t)dma_addr_phy, cnt, PCI_DMA_FROMDEVICE);

  iowrite32(0x40000000, (oad->pci_bar_virt[0] + INTERRUPT_STATUS_OFFSET));
  //pci_unmap_single(oad->pci_dev, dma_host_addr, dma_up_len, PCI_DMA_FROMDEVICE);
  dma_unmap_single(oad->pci_dev, dma_host_addr, dma_up_len, PCI_DMA_FROMDEVICE);
  pci_dma_sync_single_for_cpu(oad->pci_dev, dma_addr_phy, cnt, PCI_DMA_FROMDEVICE);
  
  copy_to_user(buf, dma_addr_virt, cnt);

  kfree(dma_addr_virt);

  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_dma_read\n");
  return SUCCESS;
}

static void oad_interrupt(int irq, void *dev, struct pt_regs *regs)
{
  printk(KERN_INFO "\t[OAD_DEBUG] start of oad_interrupt\n");
  
  iowrite32(0x40000000, (oad->pci_bar_virt[0] + INTERRUPT_STATUS_OFFSET));
  pci_unmap_single(oad->pci_dev, oad->dma_read_phy, oad->dma_read_size, PCI_DMA_FROMDEVICE);
  
  wake_up_interruptible(&(oad->dma_read_wait));

  printk(KERN_INFO "\t[OAD_DEBUG] end of oad_interrupt\n");
}

论坛徽章:
0
2 [报告]
发表于 2012-09-12 15:56 |只看该作者
看到这种代码,就有一股莫名的冲动{:3_183:}

论坛徽章:
0
3 [报告]
发表于 2012-09-12 21:14 |只看该作者
要么贴个附件,这种排版的代码,看起来

论坛徽章:
0
4 [报告]
发表于 2012-09-13 10:06 |只看该作者
不好意思哈,代码确实比较。。。
  1. #include <sys/wait.h>
  2. #include <sys/stat.h>
  3. #include <sys/types.h>
  4. #include <sys/time.h>
  5. #include <sys/ioctl.h>
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <termios.h>
  11. #include <fcntl.h>
  12. #include <errno.h>
  13. #include <fcntl.h>


  14. //char devname[] = "/dev/xpcie";
  15. char devname[] = "/dev/oad";
  16. int g_devFile = -1;
  17. #define TEST_COUNT (16*1024) // 64KB
  18. //#define TEST_COUNT (32)


  19. int write_data(char* buff, int size)
  20. {
  21.   int ret = write(g_devFile, buff, size);                                                                              
  22.   return (ret);
  23. }

  24. int read_data(char *buff, int size)
  25. {
  26.   int ret = read(g_devFile, buff, size);
  27.   return (ret);
  28. }

  29. time_t time_usec_diff(struct timeval* tv, struct timeval* prev_tv)
  30. {
  31.   return ((tv->tv_sec - prev_tv->tv_sec)*1000000 + tv->tv_usec - prev_tv->tv_usec);
  32. }

  33. void write2file(void *buffer, size_t len)
  34. {
  35.         int fd,size;       
  36.         fd=open("/tmp/temp", O_WRONLY|O_CREAT);
  37.         write(fd, buffer, len);
  38.         close(fd);
  39.         //fd=open("/tmp/temp",O_RDONLY);
  40.         //size=read(fd,buffer,sizeof(buffer));
  41.         //close(fd);
  42.         //printf("%lx", buffer);

  43. }
  44. int main(void)
  45. {
  46.   int i, j;
  47.   int iter_count = 1;

  48.   char* devfilename = devname;

  49.   unsigned int* rd_buffer;
  50.   unsigned int* wr_buffer;

  51.   g_devFile = open(devfilename, O_RDWR);

  52.   printf("\n");
  53.   if ( g_devFile < 0 )  {
  54.     printf("Error opening device file\n");
  55.     return 0;
  56.   } else {
  57.     printf("Successfully open device file \n");
  58.   }
  59.   
  60.   struct timeval tv;
  61.   struct timeval prev_tv;

  62.   suseconds_t tv_usec = 0;
  63.   time_t tv_usec_used = 0;
  64.   
  65.   gettimeofday(&prev_tv, NULL);
  66.   gettimeofday(&tv, NULL);
  67.   
  68.   tv_usec_used = time_usec_diff(&tv, &prev_tv);
  69.   printf("\ttv_usec_used = %ldus\n", tv_usec_used);
  70.   
  71.   rd_buffer = (unsigned int*)malloc(TEST_COUNT*sizeof(unsigned int));
  72.   wr_buffer = (unsigned int*)malloc(TEST_COUNT*sizeof(unsigned int));


  73.   for (j = 0; j < iter_count; j++)
  74.   {
  75.     for(i = 0; i < TEST_COUNT; i++)
  76.       *(wr_buffer+i) = rand();

  77.     gettimeofday(&prev_tv, NULL);
  78.     write_data((char*)wr_buffer, TEST_COUNT*4);
  79.     gettimeofday(&tv, NULL);
  80.     tv_usec_used = time_usec_diff(&tv, &prev_tv);
  81.     printf("[WRITE]\ttv_usec_used = %ldus\n", tv_usec_used);
  82.    

  83.     gettimeofday(&prev_tv, NULL);
  84.     read_data((char*)rd_buffer, TEST_COUNT*4);
  85.     gettimeofday(&tv, NULL);
  86.     tv_usec_used = time_usec_diff(&tv, &prev_tv);
  87.     printf("[READ]\ttv_usec_used = %ldus\n", tv_usec_used);
  88.    
  89.     unsigned int error_count = 0;
  90.     for(i = 0; i < TEST_COUNT; i++) {
  91.       printf("[addr] 0x%4x - 0x%4x: \t put: 0x%8x, \tget: 0x%8x", i*4, (i+1)*4-1, *(wr_buffer+i), *(rd_buffer+i));
  92.       if(*(rd_buffer+i) != *(wr_buffer+i)) {
  93.         printf("\t[UNMATCH]\n");
  94.         error_count += 1;
  95.       }
  96.       else
  97.         printf("\n");
  98.     }
  99.    
  100.     if(error_count != 0) {
  101.       printf("Failed!\n");
  102.     } else {
  103.       printf("PASS! ^_^\n");
  104.     }
  105.   }

  106.   printf("\n");

  107.   write2file(rd_buffer, TEST_COUNT*4);
  108.   
  109.   
  110.   free(rd_buffer);
  111.   free(wr_buffer);

  112.   return 0;
  113. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP