Petalinux201902-zynqMP write and read VDMA

本文介绍了在Ultra96平台上配置视频直接内存访问(VDMA)的过程。包括创建Vivado项目、导出XSA文件、建立PetaLinux项目、设置Qt X11环境等步骤。此外,还详细说明了如何在设备树中为用户保留DMA空间,并通过代码示例展示了VDMA的初始化和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,create vivado project like
在这里插入图片描述
在这里插入图片描述
2,export xsa
3,create petalinux project
4,add qt x11 mali to rootfs. then petalinux-build.
5,vmda needs to reserve ddr space,ultra96 v1 has 2GB space,let addr 0x50000000 size 0x10000000 256MB space to user as dma space.so in (device tree) system-user.dtsi

/include/ “system-conf.dtsi”
/ {
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
reserved: buffer@70000000 {
compatible = “shared-dma-pool”;
no-map;
reg = <0x0 0x50000000 0x0 0x10000000>;
};
};
reserved-driver@70000000 {
compatible = “xlnx,reserved-memory”;
memory-region = <&reserved>;
};
};

&axi_vdma_0 {
status = “disabled”;
};

5,#address-cells means using several cells to represent the address,
#size-cells means using several cells to represent the address length,
eg1:
#address-cells = <1>;
#size-cells = <1>;
reg = <0x50000000 0x10000000>;
eg2:
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x50000000 0x0 0x10000000>;
6,redo petalinux-build cp BOOT.bin image.ub to SD FAT space.
7,petalinux-build --sdk then petalinux-package --sysroot.
8,configure qt environment.
9,source environment-setup-aarch64-xilinx-linux,create qt project
maiwindow.cpp
#include “mainwindow.h”
#include “ui_mainwindow.h”
#include “vdma.h”

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
int j, i;
vdma_handle handle;
// Setup VDMA handle and memory-mapped ranges
vdma_setup(&handle, 0xa0000000, 640, 480, 4, 0x50000000, 0x51000000, 0x52000000);
// Start triple buffering
vdma_start_triple_buffering(&handle);
// Run for 10 seconds, just monitor status registers
for(i=0; i<10; i++) {
vdma_s2mm_status_dump(&handle);
vdma_mm2s_status_dump(&handle);
printf(“FB1:\n”);
for (j = 0; j < 256; j++) printf(" %02x", handle.fb1VirtualAddress[j]); printf("\n");
sleep(1);
}
// Halt VDMA and unmap memory ranges
vdma_halt(&handle);
}

MainWindow::~MainWindow()
{
delete ui;
}

vdma.cpp
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include “vdma.h”
#include
#include

int vdma_setup(vdma_handle handle, unsigned int baseAddr, int width, int height, int pixelLength, unsigned int fb1Addr, unsigned int fb2Addr, unsigned int fb3Addr) {
handle->baseAddr=baseAddr;
handle->width=width;
handle->height=height;
handle->pixelLength=pixelLength;
handle->fbLength=pixelLength
widthheight;
handle->vdmaHandler = open("/dev/mem", O_RDWR | O_SYNC);
handle->vdmaVirtualAddress = (unsigned int
)mmap(NULL, 65535, PROT_READ | PROT_WRITE, MAP_SHARED, handle->vdmaHandler, (off_t)handle->baseAddr);
// debug
// unsigned char p_map;
// int fd;
// p_map=(unsigned char )mmap(NULL,65536,PROT_READ | PROT_WRITE, MAP_SHARED,handle->vdmaHandler,off_t(0xf0000000));
// if(handle->fb1VirtualAddress == MAP_FAILED){
// perror(“failed”);
// }
// qDebug() << handle->fb1VirtualAddress;
//debug
qDebug() << handle->baseAddr;
qDebug() << handle->vdmaVirtualAddress;
if(handle->vdmaVirtualAddress == MAP_FAILED) {
perror(“vdmaVirtualAddress mapping for absolute memory access failed.\n”);
return -1;
}
handle->fb1PhysicalAddress = (unsigned int
)fb1Addr;
handle->fb1VirtualAddress = (unsigned int
)mmap(NULL, handle->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, handle->vdmaHandler, (off_t)fb1Addr);
qDebug() << handle->fb1PhysicalAddress;
qDebug() << handle->fb1VirtualAddress;
if(handle->fb1VirtualAddress == MAP_FAILED) {
perror(“fb1VirtualAddress mapping for absolute memory access failed.\n”);
return -2;
}
handle->fb2PhysicalAddress = (unsigned int*)fb2Addr;
handle->fb2VirtualAddress = (unsigned int*)mmap(NULL, handle->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, handle->vdmaHandler, (off_t)fb2Addr);
qDebug() << handle->fb2PhysicalAddress;
qDebug() << handle->fb2VirtualAddress;
if(handle->fb2VirtualAddress == MAP_FAILED) {
perror(“fb2VirtualAddress mapping for absolute memory access failed.\n”);
return -3;
}
handle->fb3PhysicalAddress = (unsigned int*)fb3Addr;
handle->fb3VirtualAddress = (unsigned int*)mmap(NULL, handle->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, handle->vdmaHandler, (off_t)fb3Addr);
qDebug() << handle->fb3PhysicalAddress;
qDebug() << handle->fb3VirtualAddress;
if(handle->fb3VirtualAddress == MAP_FAILED)
{
perror(“fb3VirtualAddress mapping for absolute memory access failed.\n”);
return -3;
}
memset(handle->fb1VirtualAddress, 255, handle->widthhandle->heighthandle->pixelLength);
memset(handle->fb2VirtualAddress, 255, handle->widthhandle->heighthandle->pixelLength);
memset(handle->fb3VirtualAddress, 255, handle->widthhandle->heighthandle->pixelLength);
return 0;
}

void vdma_halt(vdma_handle *handle) {
vdma_set(handle, OFFSET_VDMA_S2MM_CONTROL_REGISTER, VDMA_CONTROL_REGISTER_RESET);
vdma_set(handle, OFFSET_VDMA_MM2S_CONTROL_REGISTER, VDMA_CONTROL_REGISTER_RESET);
munmap((void *)handle->vdmaVirtualAddress, 65535);
munmap((void *)handle->fb1VirtualAddress, handle->fbLength);
munmap((void *)handle->fb2VirtualAddress, handle->fbLength);
munmap((void *)handle->fb3VirtualAddress, handle->fbLength);
close(handle->vdmaHandler);
}

unsigned int vdma_get(vdma_handle *handle, int num) {
return handle->vdmaVirtualAddress[num>>2];
}

void vdma_set(vdma_handle *handle, int num, unsigned int val) {
handle->vdmaVirtualAddress[num>>2]=val;
}

void vdma_status_dump(int status) {
if (status & VDMA_STATUS_REGISTER_HALTED) printf(" halted"); else printf(“running”);
if (status & VDMA_STATUS_REGISTER_VDMAInternalError) printf(" vdma-internal-error");
if (status & VDMA_STATUS_REGISTER_VDMASlaveError) printf(" vdma-slave-error");
if (status & VDMA_STATUS_REGISTER_VDMADecodeError) printf(" vdma-decode-error");
if (status & VDMA_STATUS_REGISTER_StartOfFrameEarlyError) printf(" start-of-frame-early-error");
if (status & VDMA_STATUS_REGISTER_EndOfLineEarlyError) printf(" end-of-line-early-error");
if (status & VDMA_STATUS_REGISTER_StartOfFrameLateError) printf(" start-of-frame-late-error");
if (status & VDMA_STATUS_REGISTER_FrameCountInterrupt) printf(" frame-count-interrupt");
if (status & VDMA_STATUS_REGISTER_DelayCountInterrupt) printf(" delay-count-interrupt");
if (status & VDMA_STATUS_REGISTER_ErrorInterrupt) printf(" error-interrupt");
if (status & VDMA_STATUS_REGISTER_EndOfLineLateError) printf(" end-of-line-late-error");
printf(" frame-count:%d", (status & VDMA_STATUS_REGISTER_FrameCount) >> 16);
printf(" delay-count:%d", (status & VDMA_STATUS_REGISTER_DelayCount) >> 24);
printf("\n");
}

void vdma_s2mm_status_dump(vdma_handle *handle) {
int status = vdma_get(handle, OFFSET_VDMA_S2MM_STATUS_REGISTER);
printf(“S2MM status register (%08x):”, status);
vdma_status_dump(status);
}

void vdma_mm2s_status_dump(vdma_handle *handle) {
int status = vdma_get(handle, OFFSET_VDMA_MM2S_STATUS_REGISTER);
printf(“MM2S status register (%08x):”, status);
vdma_status_dump(status);
}

void vdma_start_triple_buffering(vdma_handle handle) {
// Reset VDMA
vdma_set(handle, OFFSET_VDMA_S2MM_CONTROL_REGISTER, VDMA_CONTROL_REGISTER_RESET);
vdma_set(handle, OFFSET_VDMA_MM2S_CONTROL_REGISTER, VDMA_CONTROL_REGISTER_RESET);
// Wait for reset to finish
while((vdma_get(handle, OFFSET_VDMA_S2MM_CONTROL_REGISTER) & VDMA_CONTROL_REGISTER_RESET)==4);
while((vdma_get(handle, OFFSET_VDMA_MM2S_CONTROL_REGISTER) & VDMA_CONTROL_REGISTER_RESET)==4);
// Clear all error bits in status register
vdma_set(handle, OFFSET_VDMA_S2MM_STATUS_REGISTER, 0);
vdma_set(handle, OFFSET_VDMA_MM2S_STATUS_REGISTER, 0);
// Do not mask interrupts
vdma_set(handle, OFFSET_VDMA_S2MM_IRQ_MASK, 0xf);
int interrupt_frame_count = 3;
// Start both S2MM and MM2S in triple buffering mode
vdma_set(handle, OFFSET_VDMA_S2MM_CONTROL_REGISTER,
(interrupt_frame_count << 16) |
VDMA_CONTROL_REGISTER_START |
VDMA_CONTROL_REGISTER_GENLOCK_ENABLE |
VDMA_CONTROL_REGISTER_INTERNAL_GENLOCK |
VDMA_CONTROL_REGISTER_CIRCULAR_PARK);
vdma_set(handle, OFFSET_VDMA_MM2S_CONTROL_REGISTER,
(interrupt_frame_count << 16) |
VDMA_CONTROL_REGISTER_START |
VDMA_CONTROL_REGISTER_GENLOCK_ENABLE |
VDMA_CONTROL_REGISTER_INTERNAL_GENLOCK |
VDMA_CONTROL_REGISTER_CIRCULAR_PARK);
while((vdma_get(handle, 0x30)&1)==0 || (vdma_get(handle, 0x34)&1)==1) {
printf(“Waiting for VDMA to start running…\n”);
sleep(1);
}
// Extra register index, use first 16 frame pointer registers
vdma_set(handle, OFFSET_VDMA_S2MM_REG_INDEX, 0);
// Write physical addresses to control register
vdma_set(handle, OFFSET_VDMA_S2MM_FRAMEBUFFER1, (off64_t)handle->fb1PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_S2MM_FRAMEBUFFER2, (off64_t)handle->fb1PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_S2MM_FRAMEBUFFER3, (off64_t)handle->fb1PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_MM2S_FRAMEBUFFER1, (off64_t)handle->fb2PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_MM2S_FRAMEBUFFER2, (off64_t)handle->fb2PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_MM2S_FRAMEBUFFER3, (off64_t)handle->fb2PhysicalAddress);
// Write Park pointer register
vdma_set(handle, OFFSET_PARK_PTR_REG, 0);
// Frame delay and stride (bytes)
vdma_set(handle, OFFSET_VDMA_S2MM_FRMDLY_STRIDE, handle->width
handle->pixelLength);
vdma_set(handle, OFFSET_VDMA_MM2S_FRMDLY_STRIDE, handle->widthhandle->pixelLength);
// Write horizontal size (bytes)
vdma_set(handle, OFFSET_VDMA_S2MM_HSIZE, handle->width
handle->pixelLength);
vdma_set(handle, OFFSET_VDMA_MM2S_HSIZE, handle->width*handle->pixelLength);
// Write vertical size (lines), this actually starts the transfer
vdma_set(handle, OFFSET_VDMA_S2MM_VSIZE, handle->height);
vdma_set(handle, OFFSET_VDMA_MM2S_VSIZE, handle->height);
}

int vdma_running(vdma_handle *handle) {
// Check whether VDMA is running, that is ready to start transfers
return (vdma_get(handle, 0x34)&1)==1;
}

int vdma_idle(vdma_handle *handle) {
// Check whtether VDMA is transferring
return (vdma_get(handle, OFFSET_VDMA_S2MM_STATUS_REGISTER) & VDMA_STATUS_REGISTER_FrameCountInterrupt)!=0;
}

vdma.h

#ifndef VDMA_H
#define VDMA_H

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>

/* Register offsets */
#define OFFSET_PARK_PTR_REG 0x28
#define OFFSET_VERSION 0x2c

#define OFFSET_VDMA_MM2S_CONTROL_REGISTER 0x00
#define OFFSET_VDMA_MM2S_STATUS_REGISTER 0x04
#define OFFSET_VDMA_MM2S_VSIZE 0x50
#define OFFSET_VDMA_MM2S_HSIZE 0x54
#define OFFSET_VDMA_MM2S_FRMDLY_STRIDE 0x58
#define OFFSET_VDMA_MM2S_FRAMEBUFFER1 0x5c
#define OFFSET_VDMA_MM2S_FRAMEBUFFER2 0x60
#define OFFSET_VDMA_MM2S_FRAMEBUFFER3 0x64
#define OFFSET_VDMA_MM2S_FRAMEBUFFER4 0x68

#define OFFSET_VDMA_S2MM_CONTROL_REGISTER 0x30
#define OFFSET_VDMA_S2MM_STATUS_REGISTER 0x34
#define OFFSET_VDMA_S2MM_IRQ_MASK 0x3c
#define OFFSET_VDMA_S2MM_REG_INDEX 0x44
#define OFFSET_VDMA_S2MM_VSIZE 0xa0
#define OFFSET_VDMA_S2MM_HSIZE 0xa4
#define OFFSET_VDMA_S2MM_FRMDLY_STRIDE 0xa8
#define OFFSET_VDMA_S2MM_FRAMEBUFFER1 0xac
#define OFFSET_VDMA_S2MM_FRAMEBUFFER2 0xb0
#define OFFSET_VDMA_S2MM_FRAMEBUFFER3 0xb4
#define OFFSET_VDMA_S2MM_FRAMEBUFFER4 0xb8

/* S2MM and MM2S control register flags */
#define VDMA_CONTROL_REGISTER_START 0x00000001
#define VDMA_CONTROL_REGISTER_CIRCULAR_PARK 0x00000002
#define VDMA_CONTROL_REGISTER_RESET 0x00000004
#define VDMA_CONTROL_REGISTER_GENLOCK_ENABLE 0x00000008
#define VDMA_CONTROL_REGISTER_FrameCntEn 0x00000010
#define VDMA_CONTROL_REGISTER_INTERNAL_GENLOCK 0x00000080
#define VDMA_CONTROL_REGISTER_WrPntr 0x00000f00
#define VDMA_CONTROL_REGISTER_FrmCtn_IrqEn 0x00001000
#define VDMA_CONTROL_REGISTER_DlyCnt_IrqEn 0x00002000
#define VDMA_CONTROL_REGISTER_ERR_IrqEn 0x00004000
#define VDMA_CONTROL_REGISTER_Repeat_En 0x00008000
#define VDMA_CONTROL_REGISTER_InterruptFrameCount 0x00ff0000
#define VDMA_CONTROL_REGISTER_IRQDelayCount 0xff000000

/* S2MM status register */
#define VDMA_STATUS_REGISTER_HALTED 0x00000001 // Read-only
#define VDMA_STATUS_REGISTER_VDMAInternalError 0x00000010 // Read or write-clear
#define VDMA_STATUS_REGISTER_VDMASlaveError 0x00000020 // Read-only
#define VDMA_STATUS_REGISTER_VDMADecodeError 0x00000040 // Read-only
#define VDMA_STATUS_REGISTER_StartOfFrameEarlyError 0x00000080 // Read-only
#define VDMA_STATUS_REGISTER_EndOfLineEarlyError 0x00000100 // Read-only
#define VDMA_STATUS_REGISTER_StartOfFrameLateError 0x00000800 // Read-only
#define VDMA_STATUS_REGISTER_FrameCountInterrupt 0x00001000 // Read-only
#define VDMA_STATUS_REGISTER_DelayCountInterrupt 0x00002000 // Read-only
#define VDMA_STATUS_REGISTER_ErrorInterrupt 0x00004000 // Read-only
#define VDMA_STATUS_REGISTER_EndOfLineLateError 0x00008000 // Read-only
#define VDMA_STATUS_REGISTER_FrameCount 0x00ff0000 // Read-only
#define VDMA_STATUS_REGISTER_DelayCount 0xff000000 // Read-only

typedef struct {
unsigned int baseAddr;
int vdmaHandler;
int width;
int height;
int pixelLength;
int fbLength;
unsigned int* vdmaVirtualAddress;
unsigned int* fb1VirtualAddress;
unsigned int* fb1PhysicalAddress;
unsigned int* fb2VirtualAddress;
unsigned int* fb2PhysicalAddress;
unsigned int* fb3VirtualAddress;
unsigned int* fb3PhysicalAddress;
pthread_mutex_t lock;
} vdma_handle;

int vdma_setup(vdma_handle *handle, unsigned int baseAddr, int width, int height, int pixelLength, unsigned int fb1Addr, unsigned int fb2Addr, unsigned int fb3Addr);
void vdma_halt(vdma_handle *handle);
unsigned int vdma_get(vdma_handle *handle, int num);
void vdma_set(vdma_handle *handle, int num, unsigned int val);
void vdma_status_dump(int status);
void vdma_s2mm_status_dump(vdma_handle *handle);
void vdma_mm2s_status_dump(vdma_handle *handle);
void vdma_start_triple_buffering(vdma_handle *handle);
int vdma_running(vdma_handle *handle);
int vdma_idle(vdma_handle *handle);

#endif // VDMA_H

8,cp u3_d8 to u disk
9,power on the board,we can see

reserved memory:created DMA memory pool at 0x0000000050000000,size 256MiB

10,cat /proc/iomem
50000000-5ffffffff we can not see the space,it means we do right.
11,yes,it work well.
在这里插入图片描述
12,it is so hard for me do write in english,my linux system is english.fuck!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值