当前位置:网站首页>If it is test axi dma catch a few words here
If it is test axi dma catch a few words here
2022-08-04 19:33:00 【Hong Dayu】
#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 , 避开使用的内存区域,你可以看到你抓到的数据
边栏推荐
猜你喜欢
随机推荐
重构指标之如何监控代码圈复杂度
正畸MIA微种植体支抗技术中国10周年交流会在沈举办
Query the published version records of the APP Store
really time ntp service start command
带你了解数据分布式存储原理
迪赛智慧数——其他图表(主题河流图):近年居民消费、储蓄、投资意愿
元国度链游系统开发
[Latest Information] 2 new regions will announce the registration time for the soft exam in the second half of 2022
入门:人脸专集1 | 级联卷积神经网络用于人脸检测(文末福利)
How to monitor code cyclomatic complexity by refactoring indicators
如何给MySQL添加自定义语法 ?
Client Side Cache 和 Server Side Cache 的区别
Highlights of some performance tests
Dragoma(DMA)元宇宙系统开发
蚂蚁集团时序数据库CeresDB正式开源
哈佛架构 VS 冯·诺依曼架构
Quantitative trading robot system development
awk statistical difference record
Openharmony first experience (1)
完善的交叉编译环境记录 peta 生成的shell 脚本









