当前位置:网站首页>如果是测试 axi dma抓数的话 看这里
如果是测试 axi dma抓数的话 看这里
2022-08-04 19:23:00 【洪大宇】
#include <algorithm>
#include <asm-generic/errno.h>
#include <cerrno>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <linux/ioctl.h>
#include <string>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <utility>
#include <vector>
struct dma_addr_t {
//最简化的结构 的使用
size_t size;
uint32_t phy_dma_addr; // dma 实际分配的 物理地址,将地址映射过来
};
#if defined(ZYNQ7035)
#define RX_AXI_DMAC_BASE 0x40400000
#define FPGA_CTR_BASE 0x43c10000
#elif defined(ZYNQMP)
#define RX_AXI_DMAC_BASE 0xa0030000
#define FPGA_CTR_BASE 0xa0020000
#endif
#define DMA_ALLOC_DEV "mem-dma"
#define DMA_MEM_CHAR 'M'
#define DMA_PHY_ADDR_GET _IOR(DMA_MEM_CHAR, 0, struct dma_addr_t)
#define __ALIGNED(x) __attribute__((aligned(x)))
#define BIT(x) (1 << (x))
#define COVER(x) ~(BIT(x))
#define XILINX_DMA_MM2S_CTRL_OFFSET 0x0000
#define XILINX_DMA_S2MM_CTRL_OFFSET 0x0030
#define XILINX_DMA_REG_DMACR 0x0000
#define XILINX_DMA_REG_DMASR 0x0004
#define XILINX_DMA_TRIGER_ENABLE BIT(2)
#define XILINX_DMA_TRIGER_DISABLE COVER(2)
#define XILINX_DMACR_RESET BIT(2)
#define XILINX_SAMPLE_DMA_MM2S_SA 0x18
#define XILINX_SAMPLE_DMA_MM2S_LENGTH 0x28
#define XILINX_SAMPLE_DMA_S2MM_SA 0x48
#define XILINX_SAMPLE_DMA_S2MM_LENGTH 0x58
#define DMAC_REGISTER_SET 0x17003
static uint32_t *FPGA_VIRTUAL;
static char *RX_AXI_DMAC_VIRTUAL;
static int32_t fpga_dev_fd;
static int32_t dmarx_dev_fd;
#define WFPGA(offset, val) \ *(volatile uint32_t *)(FPGA_VIRTUAL + (offset)) = (val)
#define RFPGA(offset) *(volatile uint32_t *)(FPGA_VIRTUAL + (offset))
#define RX_AXI_DMA_WRITE(offset, val) \ *(volatile uint32_t *)(RX_AXI_DMAC_VIRTUAL + (offset)) = (val)
#define RX_AXI_DMA_READ(offset) \ *(volatile uint32_t *)(RX_AXI_DMAC_VIRTUAL + (offset))
enum CAN_TYPE {
CAP_10MS, CAP_20MS };
#define FATAL \ do {
\ fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, \ __FILE__, errno, strerror(errno)); \ exit(1); \ } while (0)
template <class T> void mem_write(T address, T value) {
void *map_base, *virt_addr;
char dev_name[] = "/dev/mem";
int fd;
unsigned page_size, mapped_size, offset_in_page;
off_t target = address;
fd = open(dev_name, O_RDWR | O_SYNC);
if (fd < 0)
FATAL;
mapped_size = page_size = sysconf(_SC_PAGESIZE);
offset_in_page = (unsigned)target & (page_size - 1);
if ((offset_in_page + 32) > page_size) {
mapped_size *= 2;
}
map_base = mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
target & ~(off_t)(page_size - 1));
virt_addr = (char *)map_base + offset_in_page;
if (virt_addr == (void *)-1)
FATAL;
*(volatile T *)virt_addr = value;
if (munmap(map_base, mapped_size) == -1)
FATAL;
close(fd);
}
template <class T> void mem_read(T address, T &value) {
void *map_base, *virt_addr;
char dev_name[] = "/dev/mem";
int fd;
unsigned page_size, mapped_size, offset_in_page;
off_t target = address;
fd = open(dev_name, O_RDWR | O_SYNC);
if (fd < 0)
FATAL;
mapped_size = page_size = sysconf(_SC_PAGESIZE);
offset_in_page = (unsigned)target & (page_size - 1);
if ((offset_in_page + 32) > page_size) {
mapped_size *= 2;
}
map_base = mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
target & ~(off_t)(page_size - 1));
virt_addr = (char *)map_base + offset_in_page;
if (virt_addr == (void *)-1)
FATAL;
value = *(volatile T *)virt_addr;
if (munmap(map_base, mapped_size) == -1)
FATAL;
close(fd);
}
template <class T> void mem_write(std::vector<std::pair<T, T>> w) {
for (int i = 0; i < w.size(); i++) {
mem_write<T>(w[i].first, w[i].second);
}
}
template <class T> void mem_read(std::vector<std::pair<T, T &>> r) {
for (int i = 0; i < r.size(); i++) {
mem_read<T>(r[i].first, r[i].second);
}
}
template <class T>
T *phy_mem_alloc(int32_t &fd, uint32_t phyaddr, int32_t &size) {
void *map_base, *virt_addr;
char dev_name[] = "/dev/mem";
unsigned page_size, mapped_size, offset_in_page;
off_t target = phyaddr;
fd = open(dev_name, O_RDWR | O_SYNC);
if (fd < 0)
FATAL;
mapped_size = page_size = sysconf(_SC_PAGESIZE);
mapped_size += size; //允许访问的空间的大小,允许使用的内存空间的大小
offset_in_page = (unsigned)target & (page_size - 1);
if ((offset_in_page + 32) > page_size) {
mapped_size *= 2;
}
mapped_size = size; //将实际的长度同时进行返回使用
map_base = mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
target & ~(off_t)(page_size - 1));
virt_addr = (char *)map_base + offset_in_page;
if (virt_addr == (void *)-1)
FATAL;
return (T *)virt_addr;
}
template <class T> void phy_mem_free(T *mem, int32_t size, int fd) {
if (munmap(mem, size) == -1)
printf("phy mem free error: %s\n", strerror(errno));
close(fd);
}
void *dma_mem_alloc(int &fd, int32_t size) {
fd = open(DMA_ALLOC_DEV, O_RDWR); //返回操作使用的,文件描述符符号
if (fd < 0) {
std::cout << strerror(errno) << std::endl;
exit(1);
}
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
}
void dma_phy_addr_get(int32_t fd, uint32_t &phy, uint32_t &size) {
dma_addr_t dma_phy;
int32_t ret = ioctl(fd, DMA_PHY_ADDR_GET, &dma_phy);
if (ret < 0) {
printf("Can't get dma phy addr ... ...\n");
exit(1);
}
phy = dma_phy.phy_dma_addr;
size = dma_phy.size;
}
bool check_axidma_reset(void) {
return (RX_AXI_DMA_READ(XILINX_DMACR_RESET) & 0x4) ? false : true;
}
// nop = 0.1us
int32_t poll_read(uint32_t ms, bool (*func)(void)) {
for (int i = 0; i < ms * 10000; i++) {
if (func()) {
return 0;
}
asm("nop");
}
return -ETIMEDOUT;
}
bool check_dma_rx_done(void) {
return RX_AXI_DMA_READ(XILINX_DMA_S2MM_CTRL_OFFSET | XILINX_DMA_REG_DMASR)
? true
: false;
}
int32_t direct_dma_rx(uint32_t phy, uint32_t size,
void (*opt)(uint32_t, CAN_TYPE), uint32_t _opt,
CAN_TYPE _type) {
RX_AXI_DMA_WRITE(
XILINX_DMA_S2MM_CTRL_OFFSET,
0x4); //查看RESET 的模式是否成功,FIXME:辛亏是两个dma控制器,dma
//控制器的recvier 模式
if (poll_read(200, check_axidma_reset)) {
return -ETIMEDOUT;
}
RX_AXI_DMA_WRITE(XILINX_DMA_S2MM_CTRL_OFFSET, DMAC_REGISTER_SET); //使能中断
RX_AXI_DMA_WRITE(XILINX_SAMPLE_DMA_S2MM_SA, phy);
RX_AXI_DMA_WRITE(XILINX_SAMPLE_DMA_S2MM_LENGTH, size);
opt(_opt, _type);
int ret = poll_read(2000, check_dma_rx_done);
if (ret < 0) {
std::cout << "dma rx time out \n";
}
return RX_AXI_DMA_READ(XILINX_SAMPLE_DMA_S2MM_LENGTH);
}
int32_t init_dma(void) {
int32_t fpga_mmap_size = 0x1000;
int32_t dmarx_size = 0x1000;
FPGA_VIRTUAL =
phy_mem_alloc<uint32_t>(fpga_dev_fd, FPGA_CTR_BASE, fpga_mmap_size);
if (FPGA_VIRTUAL == (void *)-1) {
std::cout << "Fpga mem failed \n";
return 1;
}
RX_AXI_DMAC_VIRTUAL =
phy_mem_alloc<char>(dmarx_dev_fd, RX_AXI_DMAC_BASE, dmarx_size);
if (RX_AXI_DMAC_VIRTUAL == (void *)-1) {
std::cout << "Direct Dma Ctr Dev mem error\n";
return 1;
}
std::cout << "FPGA version: " << std::hex << RFPGA(0x0) << std::endl;
return 0;
}
int32_t dmarx(uint8_t **buf, uint32_t size, void (*opt)(uint32_t, CAN_TYPE),
uint32_t _opt, CAN_TYPE _type) {
uint32_t phy;
uint32_t _size;
*buf = (uint8_t *)dma_mem_alloc(dmarx_dev_fd, size);
dma_phy_addr_get(dmarx_dev_fd, phy, _size);
return direct_dma_rx(phy, size, opt, _opt, _type);
}
如果你没有在内核中使用 DMA 的内存分配方法,可以直接访问 mem , 避开使用的内存区域,你可以看到你抓到的数据
边栏推荐
猜你喜欢
随机推荐
基于YOLOV5行人跌倒检测实验
getBoundingClientRect
EuROC dataset format and related codes
PG网络传输安全SSL介绍及使用示例
Dragoma (DMA) Metaverse System Development
win10 uwp xaml 绑定接口
VQ Realization of Wavelet Extraction Features
Polygon zkEVM 基本概念
测试/开发程序员男都秃头?女都满脸痘痘?过好我们“短暂“的一生......
按需视觉识别:愿景和初步方案
How to add custom syntax to MySQL?
【着色器实现Glitch单项故障闪烁效果(与Television效果不同)_Shader效果第十四篇】
网络运维管理从基础到实战-自用笔记(1)构建综合园区网、接入互联网
Orthodontic MIA micro-implant anchorage technology China 10th anniversary exchange meeting was held in Shenyang
SAP UI5 视图控制器 View Controller 的生命周期方法 - Lifecycle methods
密码学系列之:PEM和PKCS7,PKCS8,PKCS12
visual studio 与 visual studio code
c语言进阶篇:自定义类型--结构体
当前最快的实例分割模型:YOLACT 和 YOLACT++
ELECTRA:Pre-training Text Encoders as Discriminators Rather Than Generators









