ZYNQ linux下AXI4从机接口的使用

桃扇骨 2023-07-25 08:42 236阅读 0赞

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接口。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <sys/mman.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <string.h>
  11. #include <fcntl.h>
  12. #define PORT 3333
  13. #define AXI4_INTERFACE 0x7aa00000
  14. #define DATA_LEN 1024
  15. unsigned int *map_base0;
  16. void udp_server(void)
  17. {
  18. int sockfd;
  19. if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
  20. printf("create socket false\n");
  21. exit(1);
  22. }
  23. socklen_t len;
  24. struct sockaddr_in server_addr;
  25. int n;
  26. int opt = 1;
  27. len = sizeof(server_addr);
  28. server_addr.sin_family = AF_INET;
  29. server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  30. server_addr.sin_port = htons(PORT);
  31. setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  32. if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
  33. printf("can not bind\n");
  34. exit(1);
  35. }
  36. while (1) {
  37. printf("\n========wait for client's request========\n");
  38. n = recvfrom(sockfd, map_base0, DATA_LEN, 0, (struct sockaddr *)&server_addr, &len);
  39. char buf[DATA_LEN];
  40. memcpy(buf, map_base0, n);
  41. printf("\n%x receive client's data: %s\n", map_base0, buf);
  42. sendto(sockfd, map_base0, n, 0, (struct sockaddr *)&server_addr, len);
  43. printf("\n%x send data to client: %s\n", map_base0, buf);
  44. memset(map_base0, 0, n);
  45. }
  46. close(sockfd);
  47. }
  48. void pl_peripheral(void)
  49. {
  50. int devfd;
  51. if ((devfd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
  52. printf("can not open /dev/mem \n");
  53. exit(1);
  54. }
  55. printf("\n open /dev/mem successful\n");
  56. map_base0 = mmap(NULL, DATA_LEN * 4, PROT_READ | PROT_WRITE, MAP_SHARED, devfd, AXI4_INTERFACE);
  57. if (map_base0 ==0) {
  58. printf("NULL pointer \n");
  59. }
  60. else {
  61. printf("mmap successful\n");
  62. }
  63. }
  64. int main(int argc, char **argv)
  65. {
  66. pl_peripheral();
  67. udp_server();
  68. exit(0);
  69. }

使用交叉编译命令编译程序arm-linux-gnueabihf-gcc -o arm_server udp_server.c

最终效果
在这里插入图片描述

网口数据通过AXI4的接口进行了环回实验,但这个接口有1024字节的限制,当网络调试助手中发送的数据超过1024字节的时候,数据就会出错

这个AXI4接口是vivado中默认的接口,如果想解除1024字节的限制,那么必须自己编写AXI4的接口

发表评论

表情:
评论列表 (有 0 条评论,236人围观)

还没有评论,来说两句吧...

相关阅读