赞
踩
参考文章:
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我设置了是一个可读写寄存器,能读出上次写入的数值,下列试验代码用到。
这里列出访问的代码:
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include <assert.h>
- #include <fcntl.h>
- #include <getopt.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <time.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <stdarg.h>
- #include <syslog.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/sysinfo.h>
- #include <unistd.h>
- #include <dirent.h>
- #include <string.h>
- /* ltoh: little to host */
- /* htol: little to host */
- #if __BYTE_ORDER == __LITTLE_ENDIAN
- # define ltohl(x) (x)
- # define ltohs(x) (x)
- # define htoll(x) (x)
- # define htols(x) (x)
- #elif __BYTE_ORDER == __BIG_ENDIAN
- # define ltohl(x) __bswap_32(x)
- # define ltohs(x) __bswap_16(x)
- # define htoll(x) __bswap_32(x)
- # define htols(x) __bswap_16(x)
- #endif
-
- #define MAP_SIZE (1024*1024UL)
- #define MAP_MASK (MAP_SIZE - 1)
-
- #define LED_BASE 0x30000
- #define BTN_BASE 0x40000
- #define TOOLS_BASE 0x10000
-
- void *control_base;
-
- int control_fd;
-
- static int open_control(char *filename)
- {
- int fd;
- fd = open(filename, O_RDWR | O_SYNC);
- if(fd == -1)
- {
- printf("open control error\n");
- return -1;
- }
- return fd;
- }
- static void *mmap_control(int fd,long mapsize)
- {
- void *vir_addr;
- vir_addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- return vir_addr;
- }
- void write_io(int offset,uint32_t val)
- {
- uint32_t writeval = htoll(val);
- *((uint32_t *)(control_base+offset)) = writeval;
- }
- uint32_t read_io(int offset)
- {
- uint32_t read_result = *((uint32_t *)(control_base+offset));
- read_result = ltohl(read_result);
- return read_result;
- }
-
-
-
- int pcie_init()
- {
- control_fd = open_control("/dev/xdma0_user");
- if(control_fd < 0)
- return -5;
- control_base = mmap_control(control_fd,MAP_SIZE);
- return 1;
- }
- void pcie_deinit()
- {
- close(control_fd);
- }
-
- void main( void ){
-
- unsigned int i , t ;
- pcie_init() ;
-
- for(i=0;i<10;++i){
-
- write_io ( TOOLS_BASE,i );
- t = read_io(TOOLS_BASE ) ;
- if (i==t) printf("OK\n");else printf("ERROR\n");
-
- }
-
-
- }
-
- #ifdef __cplusplus
- }
- #endif

这里我们看到使用了mmap函数,首先获取_user文件的基本虚拟地址,之后再加上图ADDERESS EDITER里面列的偏移地址,就是AXI_LITE_SALVE的REG0地址,当然REGn的话只需要在这个偏移量基础上加4*n就可以。
运行后显示OK,试验成功。
{{aAxvOXMOIvVUoXMxvoxiowMwWV8xxWTxoxOIOVIUUOvwVOUiIoUvvTMMVMwovWHWX8vOUOvwVVTxwOTHUHiv8IUiIvMMxTiwMUmvTTIHMUXIHMvvHOMoiHIoVU8VvmvIWXTvvOvv8xvMovOWMMOxxTMi8UiUZz}}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。