DMA测试代码

#pragma once 
#include "DMACtrl.h"
class CLumDataCtrl //父类 通用类
{
public:
	// 构造函数
	CLumDataCtrl(const string & sDMADriverFile, int iType = 1);
	// 析构函数
	~CLumDataCtrl();
	// 初始化
	int iInitilize(int iDataLen);
public:
	// 采集亮度数据
	int iSampleLumData(unsigned char * &lumData, int &iLen);
private:
	// DMA控制
	CDMACtrl *m_pDmaCtrl;
};
#include <unistd.h>
#include "LumDataCtrl.h"
#include "DMAProxyCtrl.h"

// 最大轮询次数
const int cniLoopNum = 3;

// 构造函数
CLumDataCtrl::CLumDataCtrl(const string & sDMADriverFile, int iType)
{
	if (1 == iType)
	{
		m_pDmaCtrl = new CDMAProxyCtrl(sDMADriverFile);
	}
	else
	{
		m_pDmaCtrl = new CDMACtrl(sDMADriverFile);
	}
	return;
}

CLumDataCtrl::~CLumDataCtrl()
{
	if (nullptr != m_pDmaCtrl)
	{
		delete m_pDmaCtrl;
		m_pDmaCtrl = nullptr;
	}
	return;
}

// 初始化
int CLumDataCtrl::iInitilize(int iDataLen)
{
	return m_pDmaCtrl->iInitialize(iDataLen);
}

// 采集亮度数据
int CLumDataCtrl::iSampleLumData(unsigned char * &lumData, int &iLen)
{
	if (0 != m_pDmaCtrl->iStartSample())
	{
		return EXIT_FAILURE;
	}
	int iCounter = 0;
	while (m_pDmaCtrl->iGetSampleFinishedStatus() != 0 && iCounter < cniLoopNum)
	{
		usleep(1);
		iCounter++;
	}

	if (m_pDmaCtrl->iReadDMAData(lumData, iLen) < 0)
	{
		printf("iReadDMAData fail !");
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}

子类 read方式传输:

#pragma once
#include <string>
using namespace std;
const int cniRowDataSize = 2048;
const int cniRowDescSize = 128;
const int cniOnceSampleRowNum = 64;
const int cniOnceDMADataSize = (cniRowDataSize + cniRowDescSize) * cniOnceSampleRowNum;
class CDMACtrl
{
public:
	// 构造函数
	CDMACtrl(const string & sDriverFile);
	// 析构函数
	virtual ~CDMACtrl();
	// 初始化
	virtual int iInitialize(int iDataLen);
public:
	inline void SetDriverFile(const string &sDriverFile)
	{
		m_sDriverFile = sDriverFile;
		return;
	}
	inline string sGetDriverFile() const
	{
		return m_sDriverFile;
	}
	inline int iGetDriverHandle() const
	{
		return m_iDriverHandle;
	}
	// 开始采集
	virtual int iStartSample();
	// 采集完成标识
	virtual int iGetSampleFinishedStatus();
	// 读取DMA数据
	virtual int iReadDMAData(unsigned char * &rdBuf, int &iLen);
private:
	// 驱动文件句柄
	int m_iDriverHandle;
	// 驱动文件
	string m_sDriverFile;
	// 驱动文件映射内存
	//void * m_pMap;
};
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "DMACtrl.h"
#define IOCTL_ARG1                    0xFB
#define DMA_START_RD_COMMAND         _IO(IOCTL_ARG1,1)
#define DMA_START_WR_COMMAND         _IO(IOCTL_ARG1,2)
#define DMA_WAIT_WR_FINISH_COMMAND   _IO(IOCTL_ARG1,3)
#define DMA_WAIT_RD_FINISH_COMMAND   _IO(IOCTL_ARG1,4)
const unsigned int cnuiMapAddrSize = 0x22000;

// 构造函数
CDMACtrl::CDMACtrl(const string & sDriverFile)
{
	m_sDriverFile = sDriverFile;
	m_iDriverHandle = -1;
	//m_pMap = MAP_FAILED;
	return;
}
// 析构函数
CDMACtrl::~CDMACtrl()
{
	/*if (MAP_FAILED != m_pMap)
	{
		munmap(m_pMap, cnuiMapAddrSize);
	}*/
	if (-1 != m_iDriverHandle)
	{
		close(m_iDriverHandle);
		m_iDriverHandle = -1;
	}
	return;
}

// 初始化
int CDMACtrl::iInitialize(int iDataLen)
{
	m_iDriverHandle = open(m_sDriverFile.c_str(), O_RDWR);
	if (m_iDriverHandle < 0)
	{
		return EXIT_FAILURE;
	}
	else
	{
		/*m_pMap = mmap(nullptr, cnuiMapAddrSize, PROT_READ|PROT_WRITE, MAP_SHARED, m_iDriverHandle, 0);
		if (MAP_FAILED == m_pMap)
		{
			ostringstream os;
			os << "failed to mmap [" << m_sDriverFile << "]" << endl;
			CLog::GetInstance()->WriteLog(__FUNCTION__, __LINE__, os.str(), Log_Error);
		}*/
		return EXIT_SUCCESS;
	}
}

// 开始采集
int CDMACtrl::iStartSample()
{
	int iLen = cniOnceDMADataSize * 4;
	return ioctl(m_iDriverHandle, DMA_START_RD_COMMAND, &iLen);
}

// 采集完成标识
int CDMACtrl::iGetSampleFinishedStatus()
{
	int iLen = cniOnceDMADataSize * 4;
	return ioctl(m_iDriverHandle, DMA_WAIT_RD_FINISH_COMMAND, &iLen);
}

// 读取DMA数据
int CDMACtrl::iReadDMAData(unsigned char * &rdBuf, int &iLen)
{
	//iLen = cniOnceDMADataSize;
	rdBuf = new unsigned char[iLen];
	/*if (MAP_FAILED != m_pMap)
	{
		memcpy(rdBuf, m_pMap, cniOnceDMADataSize);
		return iLen;
	}
	else*/
	{
		int len = read(m_iDriverHandle, rdBuf, iLen);
		return len;
	}
}

子类mmap方式传输:

#pragma once
#include <string>
#include "DMACtrl.h"
#include "dma-proxy.h"
using namespace std;
class CDMAProxyCtrl:public CDMACtrl
{
public:
	// 构造函数
	CDMAProxyCtrl(const string & sDriverFile);
	// 析构函数
	~CDMAProxyCtrl();
	// 初始化
	int iInitialize(int iDataLen);
public:
	// 开始采集
	virtual int iStartSample();
	// 采集完成标识
	virtual int iGetSampleFinishedStatus();
	// 读取DMA数据
	virtual int iReadDMAData(unsigned char * &rdBuf, int &iLen);
private:
	// 驱动文件句柄
	channel_buffer *m_pChannelBuffer;
};

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "DMAProxyCtrl.h"
#include <string>
#include<iostream>
using namespace std;
// 构造函数
CDMAProxyCtrl::CDMAProxyCtrl(const string & sDriverFile)
	:CDMACtrl(sDriverFile)
{
	m_pChannelBuffer = (channel_buffer *)MAP_FAILED;
	return;
}
// 析构函数
CDMAProxyCtrl::~CDMAProxyCtrl()
{
	if (MAP_FAILED != m_pChannelBuffer)
	{
		munmap(m_pChannelBuffer, sizeof(struct channel_buffer));
		m_pChannelBuffer = nullptr;
	}
	return;
}

// 初始化
int CDMAProxyCtrl::iInitialize(int iDataLen)
{
	if (EXIT_FAILURE == CDMACtrl::iInitialize(iDataLen))
	{
		return EXIT_FAILURE;
	}
	m_pChannelBuffer = (struct channel_buffer *)mmap(NULL, sizeof(struct channel_buffer) * RX_BUFFER_COUNT,
		PROT_READ | PROT_WRITE, MAP_SHARED, iGetDriverHandle(), 0);

	m_pChannelBuffer[0].length = iDataLen; //m_pChannelBuffer->length = cniOnceDMADataSize; 
	return EXIT_SUCCESS;
}

// 开始采集
int CDMAProxyCtrl::iStartSample()
{
	int iChannelIndex = 0;
	return ioctl(iGetDriverHandle(), START_XFER, &iChannelIndex);
}

// 采集完成标识
int CDMAProxyCtrl::iGetSampleFinishedStatus()
{
	int iChannelIndex = 0;
	return ioctl(iGetDriverHandle(), FINISH_XFER, &iChannelIndex);
}

// 读取DMA数据
int CDMAProxyCtrl::iReadDMAData(unsigned char * &rdBuf, int &iLen)
{
	//iLen = cniOnceDMADataSize;
	rdBuf = new unsigned char[iLen];
	if (MAP_FAILED != m_pChannelBuffer)
	{
		//string *p = new string[iLen];
		//p = 9;
		//memcpy((void*)m_pChannelBuffer->buffer, p, sizeof(unsigned int));

		memcpy(rdBuf, (void*)m_pChannelBuffer->buffer, iLen);
		//memcpy(rdBuf, (void*)m_pChannelBuffer->buffer, cniOnceDMADataSize);
		return iLen;
	}
	else
	{
		printf("transport by read");
		return read(iGetDriverHandle(), rdBuf, iLen);
	}
}

主程序测试最佳带宽main:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include<iostream>
#include <iomanip>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string>
#include "LumDataCtrl.h"
#include <time.h>
#include <fstream>

#include<sys/stat.h>
#include<sys/types.h>



using namespace std;
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

#define BASE_ADDR 0x40000000
#define PAGE_SIZE ((size_t) getpagesize()) // 分配地址大小
#define PAGE_MASK ((uint32_t)(long)~(PAGE_SIZE-1)) // 分配地址掩码
#define DEV_MEM_SIZE (PAGE_SIZE*2)
#define DEV_MEM_MASK ((uint32_t)(long)~(DEV_MEM_SIZE-1)) // 分配地址掩码
#define WR_DMARDLEN_OFFSET 60 // 写DMA读长度寄存器偏移值 
#define CAPTURE_OFFSET 24
const int cniScanRowLowerLimit = 0;
const int cniScanRowUpperLimit = 1023;


int main(int argv, char ** args)
{
	if (argv < 2)
	{
		cout << "Please Enter DMAType(0 or 1)" << endl;
		return EXIT_FAILURE;
	}
	int iDMAType = 1;
	if ("0" == string(args[1]) || "1" == string(args[1]))
	{
		iDMAType = stoi(args[1]);
	}

	ofstream ofs;
	ofs.open("DMA_test_bind.txt", ios::out);

	unsigned char *m_bsRawLumData = nullptr;
	int m_iDataLen;// 原始亮度数据长度
	int cniRawLumRowDataSize = 2176*64;

	const string cnsDMADriverName = "/dev/axiDmaPoxy";
	CLumDataCtrl lumDataCtrl(cnsDMADriverName, iDMAType);

	//int iLen = cniOnceDMADataSize;
	int rowNum = 128; //初始row  开始的行数
	int DMAiLen = 2176 * rowNum;  //一次传输数据的大小
	unsigned char *bsData = nullptr;
	double ibandwidth = 0; //带宽 MB/S
	double ibandwidth_next = 0;

	while (1)        //外循环  退出循环条件是带宽发生下降或者大于了驱动的内存大小       
	{
	//********************************
		if (EXIT_FAILURE == lumDataCtrl.iInitilize(DMAiLen))
		{
			cout << "failed to initialize LumDataCtrl" << endl;
			return EXIT_FAILURE;
		}

		int fd = -1;
		volatile void *addr = NULL;
		volatile void * virt_addr = NULL;
		//打开文件
		fd = open("/dev/mem", O_RDWR | O_SYNC);
		if (-1 == fd)
		{
			printf("error:failed to open file[/dev/mem]\n");
			return 1;
		}

		//映射到内存
		addr = mmap(NULL, DEV_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDR);
		if (MAP_FAILED == addr)
		{
			close(fd);
			printf("failed to mmap phy-addr to virtual-addr\n");
			return 1;
		}
		virt_addr = (volatile void *)((uint32_t)addr & DEV_MEM_MASK);
		printf("PhyAddr:%x mamped to VirtAddr:%x, reg0:%x\n", BASE_ADDR, (uint32_t)virt_addr, *(volatile uint32_t *)(virt_addr));

		

		// 停止扫描
		unsigned int uiParam = (4 << 28) | (cniScanRowLowerLimit << 16) | cniScanRowUpperLimit;
		memcpy(((char*)virt_addr + CAPTURE_OFFSET), (void*)&uiParam, sizeof(unsigned int));  // 写方式一

		// 设置函数
		unsigned int uiLineNum = rowNum | (0x5a5a << 16);
		memcpy(((char*)virt_addr + WR_DMARDLEN_OFFSET), (void*)&uiLineNum, sizeof(unsigned int));  // 写方式一
		//(unsigned int *)(virt_addr+WR_DMARDLEN_OFFSET) = uiLineNum; // 写方式二

		//开始扫描
		uiParam = (5 << 28) | (cniScanRowLowerLimit << 16) | cniScanRowUpperLimit;
		memcpy(((char*)virt_addr + CAPTURE_OFFSET), (void*)&uiParam, sizeof(unsigned int));  // 写方式一

		  //断开映射
		munmap((void *)addr, BASE_ADDR);

		//关闭文件
		close(fd); 
		//********************************
		int i = 0;
		time_t tStartTime = time(NULL);
		int iInterval = 0;
		while (1)      //内循环, 退出循环条件达到十分钟                 
		{
			if (EXIT_FAILURE == lumDataCtrl.iSampleLumData(bsData, DMAiLen))
			{
				cout << "failed to sample lumData" << endl;
				return EXIT_FAILURE;
			}
			i++;                //记录次数
			if (nullptr != bsData)  //清空数据缓存
			{
				delete bsData;
				bsData = nullptr;
			}
			if ((iInterval = time(NULL) - tStartTime)> 10)      //更新时间     计算时间间隔
			{
				ofs << " 600s end! /n" << endl;
				break;
			}
		}
		ofs << " times = " << i << endl;             //记录结束次数*/
		long long Mbit = 1048576;
		long long j = i;
		long long size_MB = Mbit * 10;
		long long size_DMA = j * DMAiLen;
		long long ibandwidth = size_DMA / size_MB; //记录性能带宽
		
		if (ibandwidth < ibandwidth_next)   //判断这次计算的带宽和上次的带宽MB/S
		{
			ofs << " bind = " << ibandwidth << endl;
			ofs << " best_bind = " << ibandwidth_next << endl; //带宽开始下降,停止运行获取最优带宽, 最优带宽
			ofs << " row = " << rowNum << endl;
			ofs << " DMAiLen = " << DMAiLen << endl;
		//	break;
		}
		else
		{
			ofs << " bind = " << ibandwidth << endl; //当前带宽
			ofs << " row = " << rowNum << endl;
			ofs << " DMAiLen = " << DMAiLen << endl;
		}
		ibandwidth_next = ibandwidth;        //保存这次记录的带宽*/

	     // 一次循环后长度加倍 呈现2的指数上升
		rowNum = rowNum + 16; // 行数加倍*/
		DMAiLen = 2176 * rowNum;
	}
	ofs.close();
	return 0;
}

主程序验证正确性main:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include<iostream>
#include <iomanip>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string>
#include "LumDataCtrl.h"
#include <time.h>
#include <fstream>

#include<sys/types.h>
#include<sys/stat.h>

using namespace std;
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

#define BASE_ADDR 0x40000000
#define PAGE_SIZE ((size_t) getpagesize()) // 分配地址大小
#define PAGE_MASK ((uint32_t)(long)~(PAGE_SIZE-1)) // 分配地址掩码
#define DEV_MEM_SIZE (PAGE_SIZE*2)
#define DEV_MEM_MASK ((uint32_t)(long)~(DEV_MEM_SIZE-1)) // 分配地址掩码
#define WR_DMARDLEN_OFFSET 60 // 写DMA读长度寄存器偏移值 
#define CAPTURE_OFFSET 24
const int cniScanRowLowerLimit = 0;
const int cniScanRowUpperLimit = 1023;


int main(int argv, char ** args)
{
	if (argv < 2)
	{
		cout << "Please Enter DMAType(0 or 1)" << endl;
		return EXIT_FAILURE;
	}
	int iDMAType = 1;
	if ("0" == string(args[1]) || "1" == string(args[1]))
	{
		iDMAType = stoi(args[1]);
	}

	ofstream ofs;
	ofs.open("DMA_test_bind.txt", ios::out);

	int fd = -1;
	volatile void *addr = NULL;
	volatile void * virt_addr = NULL;
	unsigned char *bsData = nullptr;
	int rowNum = 1024; //初始row
	int iDMALen = 2176 * rowNum;

	const string cnsDMADriverName = "/dev/axiDmaPoxy";
	CLumDataCtrl lumDataCtrl(cnsDMADriverName, iDMAType);
	if (EXIT_FAILURE == lumDataCtrl.iInitilize(iDMALen))
	{
		cout << "failed to initialize LumDataCtrl" << endl;
		return EXIT_FAILURE;
	}
	
	

	//打开文件
	fd = open("/dev/mem", O_RDWR | O_SYNC);
		if (-1 == fd)
		{
			printf("error:failed to open file[/dev/mem]\n");
			return 1;
		}

		//映射到内存
		addr = mmap(NULL, DEV_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDR);
		if (MAP_FAILED == addr)
		{
			close(fd);
			printf("failed to mmap phy-addr to virtual-addr\n");
			return 1;
		}
		virt_addr = (volatile void *)((uint32_t)addr & DEV_MEM_MASK);
		printf("PhyAddr:%x mamped to VirtAddr:%x, reg0:%x\n", BASE_ADDR, (uint32_t)virt_addr, *(volatile uint32_t *)(virt_addr));

		

		// 停止扫描
		unsigned int uiParam = (4 << 28) | (cniScanRowLowerLimit << 16) | cniScanRowUpperLimit;
		memcpy(((char*)virt_addr + CAPTURE_OFFSET), (void*)&uiParam, sizeof(unsigned int));  // 写方式一

		// 设置函数
		unsigned int uiLineNum = rowNum | (0x5a5a << 16);
		memcpy(((char*)virt_addr + WR_DMARDLEN_OFFSET), (void*)&uiLineNum, sizeof(unsigned int));  // 写方式一
		//(unsigned int *)(virt_addr+WR_DMARDLEN_OFFSET) = uiLineNum; // 写方式二

		//开始扫描
		uiParam = (5 << 28) | (cniScanRowLowerLimit << 16) | cniScanRowUpperLimit;
		memcpy(((char*)virt_addr + CAPTURE_OFFSET), (void*)&uiParam, sizeof(unsigned int));  // 写方式一

		  //断开映射
		munmap((void *)addr, BASE_ADDR);

		//关闭文件
		close(fd); 
		unsigned int data_dma = 0;
		unsigned int data_dma2 = 0;
		while(1)
		{
			if (EXIT_FAILURE == lumDataCtrl.iSampleLumData(bsData, iDMALen))
			{
				cout << "failed to sample lumData" << endl;
				return EXIT_FAILURE;
			}
			data_dma = *(unsigned int*)(bsData+24);
			if ((data_dma-data_dma2) != rowNum)
			{
				cout << "failed to DMAData transform, preIndex:" << hex << setw(8) << setfill('0') << data_dma2;
				cout << ", CurIndex:" << hex << setw(8) << setfill('0') << data_dma << endl;
				
			}
			if (nullptr != bsData)  //清空数据缓存
			{
				delete bsData;
				bsData = nullptr;
			}
			data_dma2 = data_dma;
		}

	/*cout << " DMA data:" << endl;
	for (int i = 0; i < DMAiLen; i++)
	{
		if (i != 0 && 0 == i % 16)
		{
			cout << endl;
		}
		cout << hex << setw(2) << setfill('0') << (int)bsData[i];
		
	}*/
	ofs.close();
	return 0;
}

逻辑框图:

对应地址:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值