ZYNQ linux下AXI4从机接口的使用
vivado版本:2017.4
petalinux版本:2017.4
1、vivado硬件设计
vivado中并没有自带的AXI4接口可以使用,所以我们需要自己创建
选择创建一个新的AXI4外设
更改名字然后next,IP核的位置会放在你工程项目目录下
选择接口类型为Full,选择接口存储大小,我这里选择的是1024字节。
点击finish
将自定义的核添加到 block design 中
添加 smart_connect IP核
添加处理器,处理器相关设置根据自己的板子来进行设计。
想要使用AXI4从机接口,就必须打开GP0 主机接口
添加完成后,启动自动连接自动连接
最终完成的硬件图(不同ZYNQ芯片设计效果图不同,但一定要开启GP0接口):
查看XI4从机接口的地址,地址是0x7aa00000,这个地址我们之后会用到
然后生成创建顶层文件,生成bit流这些我就不赘述了,如有疑惑可以看我的这篇博客:
https://blog.csdn.net/yohe12/article/details/104789041
2、使用petalinux生成系统并导入开发板
将硬件资源导入ubuntu
使用 petalinux-create -t project --template zynq --name axi4_test
命令创建项目
使用petalinux-config --get-hw-description=./axi_slave_wrapper_hw_platform_0
命令来使用硬件资源生成系统
选择默认配置,然后选择 Exit 就会自动配置系统
使用 petalinux-build
命令编译系统
编译完成后,使用 petalinux-package --boot --fsbl zynq_fsbl.elf --fpga axi4_test_wrapper.bit --u-boot
生成BOOT.BIN
将BOOT.BIN 和 uimage.ub放入TF卡中,再启动开发板。
3、编写应用程序
现在我们要在应用程序中使用axi4的接口,使用mmap函数就可以将AXI4接口映射为一个地址,我们读写这个地址就相当于读写AXI4接口。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <fcntl.h>
#define PORT 3333
#define AXI4_INTERFACE 0x7aa00000
#define DATA_LEN 1024
unsigned int *map_base0;
void udp_server(void)
{
int sockfd;
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("create socket false\n");
exit(1);
}
socklen_t len;
struct sockaddr_in server_addr;
int n;
int opt = 1;
len = sizeof(server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
printf("can not bind\n");
exit(1);
}
while (1) {
printf("\n========wait for client's request========\n");
n = recvfrom(sockfd, map_base0, DATA_LEN, 0, (struct sockaddr *)&server_addr, &len);
char buf[DATA_LEN];
memcpy(buf, map_base0, n);
printf("\n%x receive client's data: %s\n", map_base0, buf);
sendto(sockfd, map_base0, n, 0, (struct sockaddr *)&server_addr, len);
printf("\n%x send data to client: %s\n", map_base0, buf);
memset(map_base0, 0, n);
}
close(sockfd);
}
void pl_peripheral(void)
{
int devfd;
if ((devfd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
printf("can not open /dev/mem \n");
exit(1);
}
printf("\n open /dev/mem successful\n");
map_base0 = mmap(NULL, DATA_LEN * 4, PROT_READ | PROT_WRITE, MAP_SHARED, devfd, AXI4_INTERFACE);
if (map_base0 ==0) {
printf("NULL pointer \n");
}
else {
printf("mmap successful\n");
}
}
int main(int argc, char **argv)
{
pl_peripheral();
udp_server();
exit(0);
}
使用交叉编译命令编译程序 :arm-linux-gnueabihf-gcc -o arm_server udp_server.c
最终效果
网口数据通过AXI4的接口进行了环回实验,但这个接口有1024字节的限制,当网络调试助手中发送的数据超过1024字节的时候,数据就会出错
这个AXI4接口是vivado中默认的接口,如果想解除1024字节的限制,那么必须自己编写AXI4的接口
还没有评论,来说两句吧...