当前位置: 首页 > news >正文

zynq7000- linux平台 PS读写PL测试

ZYNQ PL使用自定义AXI slave 模块 :
BD如下:
FPGA代码简单,可在vivado 自定义 AXI slave ip上的代码更改即可
在这里插入图片描述

系统制作完,直接在虚拟机上编译好可执行文件,在板子上运行即可:

./axilite -l 100

运行结果

linux上运行程序。代码可以自行改善。下面代码功能有:
1、遍历 PL寄存器,自定义测试寄存器个数
2、自定义测试轮数,指定对某寄存器读写
等等

注意:
vivado上BD分配的物理地址要和下面代码上能够对上。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <time.h>#define AXI_BASE_ADDRESS 0x40000000  // 根据实际情况修改
#define MAP_SIZE 0x1000              // 4KB 映射空间
#define REGISTER_COUNT 34             // 测试的寄存器数量static volatile uint32_t *axi_base = NULL;
static int mem_fd = -1;
static int running = 1;// 信号处理函数,用于优雅退出
void signal_handler(int sig)
{printf("\n收到信号 %d,正在退出...\n", sig);running = 0;
}// 映射物理内存到用户空间
int map_axi_memory(void)
{// 打开 /dev/mem 设备mem_fd = open("/dev/mem", O_RDWR | O_SYNC);if (mem_fd < 0) {perror("打开 /dev/mem 失败");return -1;}// 映射物理内存axi_base = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, AXI_BASE_ADDRESS);if (axi_base == MAP_FAILED) {perror("内存映射失败");close(mem_fd);return -1;}printf("成功映射物理内存:\n");printf("  物理地址: 0x%08X\n", AXI_BASE_ADDRESS);printf("  虚拟地址: %p\n", axi_base);printf("  映射大小: 0x%X (%d KB)\n", MAP_SIZE, MAP_SIZE / 1024);return 0;
}// 取消内存映射
void unmap_axi_memory(void)
{if (axi_base != NULL && axi_base != MAP_FAILED) {munmap((void*)axi_base, MAP_SIZE);axi_base = NULL;}if (mem_fd >= 0) {close(mem_fd);mem_fd = -1;}
}// 读取寄存器值
uint32_t read_register(int reg_index)
{if (axi_base == NULL || reg_index >= MAP_SIZE / 4) {printf("错误: 无效的寄存器索引 %d\n", reg_index);return 0;}uint32_t value = axi_base[reg_index];printf("读取 寄存器[%d]: 地址=%p, 值=0x%08X\n", reg_index, &axi_base[reg_index], value);return value;
}// 写入寄存器值
void write_register(int reg_index, uint32_t value)
{if (axi_base == NULL || reg_index >= MAP_SIZE / 4) {printf("错误: 无效的寄存器索引 %d\n", reg_index);return;}axi_base[reg_index] = value;printf("写入 寄存器[%d]: 地址=%p, 值=0x%08X\n", reg_index, &axi_base[reg_index], value);
}// 循环读写测试
void read_write_loop_test(int test_count)
{printf("\n=== 开始循环读写测试,共 %d 轮 ===\n", test_count);int error_count ;int error_flag  ;error_flag = 0;for (int i = 0; i < test_count && running; i++) {error_count = 0;printf("\n--- 第 %d 轮测试 ---\n", i + 1);// 写入测试数据for (int reg = 1; reg < REGISTER_COUNT; reg++) {uint32_t write_value = 0x1000 * (i + 1) + 0x100 * reg + 0xAB;write_register(reg, write_value);usleep(1000); // 1ms 延迟}// 读取验证for (int reg = 1; reg < REGISTER_COUNT; reg++) {uint32_t read_value = read_register(reg);uint32_t expected = 0x1000 * (i + 1) + 0x100 * reg + 0xAB;if (read_value == expected) {printf("寄存器[%d] ✅ 验证成功\n", reg);} else {error_count = error_count + 1;printf("寄存器[%d] ❌ 验证失败: 读取=0x%08X, 期望=0x%08X\n", reg, read_value, expected);}usleep(1000); // 1ms 延迟}// 每10轮显示进度if ((i + 1) % 10 == 0) {printf("已完成 %d/%d 轮测试\n", i + 1, test_count);}sleep(1); // 每秒一轮printf ("读写错误数量 是: %d\n" ,error_count);if (error_count > 0) {error_flag = 1;printf("=== AXI SLave 读写在第 %d轮出现问题 推出测试 ===\n",test_count);break;}}printf("=== 数据错误标志 error_flag = %d ===\n",error_flag);printf("=== 循环读写测试完成 ===\n");
}// 递增模式测试
void incremental_pattern_test(void)
{printf("\n=== 开始递增模式测试 ===\n");for (int i = 0; i < 16 && running; i++) {uint32_t pattern = 0x11111111 * i;printf("\n模式 %2d:\n", i);// 写入不同模式的数据write_register(0, pattern);write_register(1, ~pattern);write_register(2, pattern >> 16);write_register(3, pattern << 16);// 读取显示printf("读取结果: ");for (int reg = 0; reg < REGISTER_COUNT; reg++) {printf("0x%08X ", read_register(reg));}printf("\n");sleep(1);}printf("=== 递增模式测试完成 ===\n");
}// 交互式测试模式
void interactive_test(void)
{printf("\n=== 进入交互式测试模式 ===\n");printf("命令说明:\n");printf("  r <索引>    - 读取寄存器\n");printf("  w <索引> <值> - 写入寄存器\n");printf("  s          - 显示所有寄存器状态\n");printf("  q          - 退出\n");char command[256];while (running) {printf("\n> ");fflush(stdout);if (fgets(command, sizeof(command), stdin) == NULL) {break;}// 解析命令if (strncmp(command, "r", 1) == 0) {int reg_index;if (sscanf(command + 1, "%d", &reg_index) == 1) {read_register(reg_index);} else {printf("用法: r <寄存器索引>\n");}}else if (strncmp(command, "w", 1) == 0) {int reg_index;uint32_t value;if (sscanf(command + 1, "%d %x", &reg_index, &value) == 2) {write_register(reg_index, value);} else {printf("用法: w <寄存器索引> <十六进制值>\n");}}else if (strncmp(command, "s", 1) == 0) {printf("当前寄存器状态:\n");for (int i = 0; i < REGISTER_COUNT; i++) {uint32_t value = axi_base[i];printf("  寄存器[%d]: 0x%08X\n", i, value);}}else if (strncmp(command, "q", 1) == 0) {break;}else {printf("未知命令。使用 r, w, s, 或 q\n");}}
}// 显示使用说明
void print_usage(const char *program_name)
{printf("用法: %s [选项]\n", program_name);printf("选项:\n");printf("  -l <次数>   循环测试次数 (默认: 50)\n");printf("  -i          交互式模式\n");printf("  -p          递增模式测试\n");printf("  -a <地址>   AXI基地址 (十六进制, 默认: 0x%08X)\n", AXI_BASE_ADDRESS);printf("  -s <大小>   映射大小 (十六进制, 默认: 0x%X)\n", MAP_SIZE);printf("  -h          显示此帮助信息\n");printf("\n示例:\n");printf("  %s -l 100          # 循环测试100次\n", program_name);printf("  %s -i              # 交互式模式\n", program_name);printf("  %s -a 0xA0000000   # 指定基地址\n", program_name);
}int main(int argc, char *argv[])
{int test_count = 10;int interactive_mode = 0;int pattern_mode = 0;uint32_t base_addr = AXI_BASE_ADDRESS;size_t map_size = MAP_SIZE;// 解析命令行参数int opt;while ((opt = getopt(argc, argv, "l:ipa:s:h")) != -1) {switch (opt) {case 'l':test_count = atoi(optarg);break;case 'i':interactive_mode = 1;break;case 'p':pattern_mode = 1;break;case 'a':base_addr = strtoul(optarg, NULL, 16);break;case 's':map_size = strtoul(optarg, NULL, 16);break;case 'h':print_usage(argv[0]);return 0;default:print_usage(argv[0]);return 1;}}// 注册信号处理signal(SIGINT, signal_handler);signal(SIGTERM, signal_handler);printf("AXI Lite PL寄存器测试应用程序\n");printf("基地址: 0x%08X, 映射大小: 0x%zX\n", base_addr, map_size);// 映射内存if (map_axi_memory() < 0) {return 1;}// 根据模式执行测试if (interactive_mode) {interactive_test();} else if (pattern_mode) {incremental_pattern_test();} else {read_write_loop_test(test_count);}// 清理资源unmap_axi_memory();printf("应用程序退出\n");return 0;
}
http://www.dtcms.com/a/549762.html

相关文章:

  • 【JavaScript性能优化实战】
  • React Hook为什么这么“严格“?链表内部机制大揭秘
  • 爬虫进阶 JS逆向基础超详细,解锁加密数据
  • GF框架直接使用SQL语句查询数据库的指南
  • 美食网站素材怎么在网上卖产品
  • 网站建设综合实训设计报告怎么做单位网站
  • JavaWeb后端-JDBC、MyBatis
  • 网站访问流程改变WordPress界面
  • 聚合API平台如何重构AI开发效率?
  • 设计模式之单例模式:一个类就只有一个实例
  • 分布式数据库选型指南 (深入对比TiDB与OceanBase)
  • 模板方法模式:优雅地封装算法骨架
  • 有哪些做ppt用图片的网站有哪些免费咨询皮肤科医生在线
  • 理解 MySQL 架构:从连接到存储的全景视图
  • 电商网站 服务器易派客网站是谁做的
  • 大型语言模型(LLM)架构大比拼
  • 爱派(AiPy):一个让大语言模型直接操作Python完成任务
  • 【一加手机Bootloader解锁政策更新通知】
  • 什么是政企工作手机,有什么功能作用
  • 太原网站排名优化价格室内装修效果图网站有哪些
  • 深入探讨Python中三种核心数据结构:列表、字典和元组。
  • 建网站的几个公司通辽网站网站建设
  • 编辑 JAR 包内嵌套的 TXT 文件(Vim 操作)
  • 网站手机验证码如何做网站做链接代码
  • 无锡做网站6网站看不到预览图
  • Redis 限流最佳实践:令牌桶与滑动窗口全流程实现
  • *清理磁盘空间
  • 用什么软件做网站原型外贸退税流程及方法
  • 微软网站制作软件常见营销策略都有哪些
  • 全栈开源:一套源码快速构建电竞/体育直播平台(PC+H5+双端APP)