当前位置:   article > 正文

PCIE的AXI LITE MASTER端使用_7系列pcie ip核 使用master

7系列pcie ip核 使用master

参考文章:

https://blog.csdn.net/mcupro/article/details/121668833?spm=1001.2014.3001.5501

近期计划设计一个PCIE接口的使用AD9361芯片的SDR前端外设。思路就是用XILINX提供的XDMA的PCIE核,用AXIS_MASTER和AXIS_SLAVE 接口实现数据流接驳AD9361的数据口,使用PCIE核提供的AXI_LITE_MASTER控制若干需要的AXI_LITE外设。有了这个AXI_LITE外设其实就可以将之前在ZYNQ里面运行的裸奔的C代码移植到PC机上运行。

大约1年前我就打通了数据流的的交互试验,这篇文章我主要记录一下AXI_LITE控制接口的打通。也就是实现用PC编程使用AXI_LITE接口实现对AXI_LITE_SLAVE的寄存器的读写。

 图中看到XDMA的PCIE核通过AXI 交换器接了5个外设,其实还可以接更多。

设置PCIE:BARs时候默认如图:

 我们看到这其实相当于给AXI_LITE_MASTER 留了1M的寻址空间。其中VALUE我觉得可能是MASK的意思,正好有20个比特0,对应1M空间,挂在此AXI_LITE_MASTER下的外设最高地址必须小于1M。

我们看一下AXI_LITE外设的地址空间设置:

 我每个外设给分配了64K字节的空间,偏移地址64K递增。这个TOOLS的IP是我写的具有SPI接口和GPIO接口等,其中第一个寄存器也就是REG0我设置了是一个可读写寄存器,能读出上次写入的数值,下列试验代码用到。

这里列出访问的代码:

  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4. #include <assert.h>
  5. #include <fcntl.h>
  6. #include <getopt.h>
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <time.h>
  13. #include <pthread.h>
  14. #include <semaphore.h>
  15. #include <stdarg.h>
  16. #include <syslog.h>
  17. #include <sys/mman.h>
  18. #include <sys/stat.h>
  19. #include <sys/time.h>
  20. #include <sys/types.h>
  21. #include <sys/sysinfo.h>
  22. #include <unistd.h>
  23. #include <dirent.h>
  24. #include <string.h>
  25. /* ltoh: little to host */
  26. /* htol: little to host */
  27. #if __BYTE_ORDER == __LITTLE_ENDIAN
  28. # define ltohl(x) (x)
  29. # define ltohs(x) (x)
  30. # define htoll(x) (x)
  31. # define htols(x) (x)
  32. #elif __BYTE_ORDER == __BIG_ENDIAN
  33. # define ltohl(x) __bswap_32(x)
  34. # define ltohs(x) __bswap_16(x)
  35. # define htoll(x) __bswap_32(x)
  36. # define htols(x) __bswap_16(x)
  37. #endif
  38. #define MAP_SIZE (1024*1024UL)
  39. #define MAP_MASK (MAP_SIZE - 1)
  40. #define LED_BASE 0x30000
  41. #define BTN_BASE 0x40000
  42. #define TOOLS_BASE 0x10000
  43. void *control_base;
  44. int control_fd;
  45. static int open_control(char *filename)
  46. {
  47. int fd;
  48. fd = open(filename, O_RDWR | O_SYNC);
  49. if(fd == -1)
  50. {
  51. printf("open control error\n");
  52. return -1;
  53. }
  54. return fd;
  55. }
  56. static void *mmap_control(int fd,long mapsize)
  57. {
  58. void *vir_addr;
  59. vir_addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  60. return vir_addr;
  61. }
  62. void write_io(int offset,uint32_t val)
  63. {
  64. uint32_t writeval = htoll(val);
  65. *((uint32_t *)(control_base+offset)) = writeval;
  66. }
  67. uint32_t read_io(int offset)
  68. {
  69. uint32_t read_result = *((uint32_t *)(control_base+offset));
  70. read_result = ltohl(read_result);
  71. return read_result;
  72. }
  73. int pcie_init()
  74. {
  75. control_fd = open_control("/dev/xdma0_user");
  76. if(control_fd < 0)
  77. return -5;
  78. control_base = mmap_control(control_fd,MAP_SIZE);
  79. return 1;
  80. }
  81. void pcie_deinit()
  82. {
  83. close(control_fd);
  84. }
  85. void main( void ){
  86. unsigned int i , t ;
  87. pcie_init() ;
  88. for(i=0;i<10;++i){
  89. write_io ( TOOLS_BASE,i );
  90. t = read_io(TOOLS_BASE ) ;
  91. if (i==t) printf("OK\n");else printf("ERROR\n");
  92. }
  93. }
  94. #ifdef __cplusplus
  95. }
  96. #endif

这里我们看到使用了mmap函数,首先获取_user文件的基本虚拟地址,之后再加上图ADDERESS EDITER里面列的偏移地址,就是AXI_LITE_SALVE的REG0地址,当然REGn的话只需要在这个偏移量基础上加4*n就可以。

运行后显示OK,试验成功。

{{aAxvOXMOIvVUoXMxvoxiowMwWV8xxWTxoxOIOVIUUOvwVOUiIoUvvTMMVMwovWHWX8vOUOvwVVTxwOTHUHiv8IUiIvMMxTiwMUmvTTIHMUXIHMvvHOMoiHIoVU8VvmvIWXTvvOvv8xvMovOWMMOxxTMi8UiUZz}}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/738537
推荐阅读
相关标签
  

闽ICP备14008679号