热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

zynq-7000学习笔记(十一)——Linux下VDMA的使用

PC平台:WINDOWS1064位+虚拟机Ubuntu14.04Xilinx设计开发套件:Xilinx_vivado_sdk_2015.4开发板:ZedBoardUSB摄

PC平台:WINDOWS 10 64位 + 虚拟机Ubuntu 14.04

Xilinx设计开发套件:Xilinx_vivado_sdk_2015.4

开发板:Zed Board

USB摄像头:罗技 C270(720P)

Linux源码:2016_R1

Linaro文件系统:linaro-vivid-developer-20150618-705.tar.gz


      在zynq平台做视频应用,VDMA是一定会用到的,在linux下如何使用呢?我在网上找到了一个例子,稍微做了一下修改,代码没怎么整理,将就着先用

#include 
#include
#include
#include
#include

/* 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 char* fb1VirtualAddress;
unsigned char* fb1PhysicalAddress;
unsigned char* fb2VirtualAddress;
unsigned char* fb2PhysicalAddress;
unsigned char* fb3VirtualAddress;
unsigned char* 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) {
handle->baseAddr=baseAddr;
handle->/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);
if(handle->vdmaVirtualAddress == MAP_FAILED) {
perror("vdmaVirtualAddress mapping for absolute memory access failed.\n");
return -1;
}

handle->fb1PhysicalAddress = fb1Addr;
handle->fb1VirtualAddress = (unsigned char*)mmap(NULL, handle->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, handle->vdmaHandler, (off_t)fb1Addr);
if(handle->fb1VirtualAddress == MAP_FAILED) {
perror("fb1VirtualAddress mapping for absolute memory access failed.\n");
return -2;
}

handle->fb2PhysicalAddress = fb2Addr;
handle->fb2VirtualAddress = (unsigned char*)mmap(NULL, handle->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, handle->vdmaHandler, (off_t)fb2Addr);
if(handle->fb2VirtualAddress == MAP_FAILED) {
perror("fb2VirtualAddress mapping for absolute memory access failed.\n");
return -3;
}

handle->fb3PhysicalAddress = fb3Addr;
handle->fb3VirtualAddress = (unsigned char*)mmap(NULL, handle->fbLength, PROT_READ | PROT_WRITE, MAP_SHARED, handle->vdmaHandler, (off_t)fb3Addr);
if(handle->fb3VirtualAddress == MAP_FAILED)
{
perror("fb3VirtualAddress mapping for absolute memory access failed.\n");
return -3;
}

memset(handle->fb1VirtualAddress, 255, handle->width*handle->height*handle->pixelLength);
memset(handle->fb2VirtualAddress, 255, handle->width*handle->height*handle->pixelLength);
memset(handle->fb3VirtualAddress, 255, handle->width*handle->height*handle->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, handle->fb1PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_S2MM_FRAMEBUFFER2, handle->fb1PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_S2MM_FRAMEBUFFER3, handle->fb1PhysicalAddress);

vdma_set(handle, OFFSET_VDMA_MM2S_FRAMEBUFFER1, handle->fb2PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_MM2S_FRAMEBUFFER2, handle->fb2PhysicalAddress);
vdma_set(handle, OFFSET_VDMA_MM2S_FRAMEBUFFER3, 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->width*handle->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;
}

int main() {
int j, i;
vdma_handle handle;

// Setup VDMA handle and memory-mapped ranges
vdma_setup(&handle, 0x43010000, 640, 480, 4, 0x1f400000, 0x1f500000, 0x1f600000);

// 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);

memset(handle.fb2VirtualAddress, 0xCC+i, 640*480*4);

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);
}

      main函数测试方法很简单,就是往MM2S写数据,然后把S2MM的数据打印出来看看是不是对的;不过先要把vivado工程里的VDMA stream端的MM2S和S2MM直接连起来,形成一个回环才能测试;还要把VDMA加到设备树里面去,下面是个例子,要注意地址是否与vivado分配的地址一致

		axi_vdma_2: fast_corner_vdma@43020000 {
compatible = "xlnx,axi-vdma-1.00.a";
#dma-cells = <1>;
reg = <0x43020000 0x10000>;
xlnx,num-fstores = <0x8>;
xlnx,flush-fsync = <0x1>;
interrupt-parent = <&intc>;
dma-channel@43020000 {
compatible = "xlnx,axi-vdma-mm2s-channel";
interrupts = <0 52 0x4>;
xlnx,datawidth = <0x40>;
};
dma-channel@43020030 {
compatible = "xlnx,axi-vdma-s2mm-channel";
interrupts = <0 51 0x4>;
xlnx,datawidth = <0x40>;
};
};




推荐阅读
  • 如何搭建Java开发环境并开发WinCE项目
    本文介绍了如何搭建Java开发环境并开发WinCE项目,包括搭建开发环境的步骤和获取SDK的几种方式。同时还解答了一些关于WinCE开发的常见问题。通过阅读本文,您将了解如何使用Java进行嵌入式开发,并能够顺利开发WinCE应用程序。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • ShiftLeft:将静态防护与运行时防护结合的持续性安全防护解决方案
    ShiftLeft公司是一家致力于将应用的静态防护和运行时防护与应用开发自动化工作流相结合以提升软件开发生命周期中的安全性的公司。传统的安全防护方式存在误报率高、人工成本高、耗时长等问题,而ShiftLeft提供的持续性安全防护解决方案能够解决这些问题。通过将下一代静态代码分析与应用开发自动化工作流中涉及的安全工具相结合,ShiftLeft帮助企业实现DevSecOps的安全部分,提供高效、准确的安全能力。 ... [详细]
  • 本文总结和分析了JDK核心源码(2)中lang包下的基础知识,包括常用的对象类型包和异常类型包。在对象类型包中,介绍了Object类、String类、StringBuilder类、StringBuffer类和基本元素的包装类。在异常类型包中,介绍了Throwable类、Error类型和Exception类型。这些基础知识对于理解和使用JDK核心源码具有重要意义。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • 本文介绍了使用数据库管理员用户执行onstat -l命令来监控GBase8s数据库的物理日志和逻辑日志的使用情况,并强调了对已使用的逻辑日志是否及时备份的重要性。同时提供了监控方法和注意事项。 ... [详细]
author-avatar
汽车时尚宠
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有