代码编织梦想

参考文章:

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}}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mcupro/article/details/129678835

二进值bin文件转mcs文件的小工具-爱代码爱编程

INTEL的.HEX文件只能表示小于64K字节的文件,XILINX 的.MCS文件在此基础上,每64K字节加入了一个起始地址,就能表示高达64K*64K的文件了。  下面代码是生成的代码: static void show_a_seg(){ unsigned char b[] = { 0x02,0x00,0x00,0x