You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.9 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/timeb.h>
// 函数:从设备读取数据到本地内存(缓冲区)
// 功能:实现设备到主机的数据传输
// 参数:
// dev_fd : 设备实例句柄
// addr : 设备中的源地址
// buffer : 缓冲区基指针
// size : 数据大小
// 返回值:
// 成功0失败-1
int dev_read (int dev_fd, uint64_t addr, void *buffer, uint64_t size) {
if ( addr != lseek(dev_fd, addr, SEEK_SET) ) // 调整文件偏移到指定地址
return -1; // 偏移失败
if ( size != read(dev_fd, buffer, size) ) // 从设备读取数据到缓冲区
return -1; // 读取失败
return 0;
}
// 函数:从本地内存(缓冲区)写数据到设备
// 功能:实现主机到设备的数据传输
// 参数:
// dev_fd : 设备实例句柄
// addr : 设备中的目标地址
// buffer : 缓冲区基指针
// size : 数据大小
// 返回值:
// 成功0失败-1
int dev_write (int dev_fd, uint64_t addr, void *buffer, uint64_t size) {
if ( addr != lseek(dev_fd, addr, SEEK_SET) )
return -1;
if ( size != write(dev_fd, buffer, size) )
return -1;
return 0;
}
// 函数:获取毫秒级别的时间
// 功能:返回当前时间的毫秒数
static uint64_t get_millisecond () {
struct timeb tb;
ftime(&tb);
return (uint64_t)tb.millitm + (uint64_t)tb.time * 1000UL;
// tb.time is the number of seconds since 00:00:00 January 1, 1970 UTC time;
// tb.millitm is the number of milliseconds in a second
}
// 函数:解析无符号整数
// 功能从字符串中解析出十六进制或十进制的无符号64位整数
// 参数:
// string : 输入的字符串
// pvalue : 解析后的值的指针
// 返回值:
// 成功解析的项数失败则为0
int parse_uint (char *string, uint64_t *pvalue) {
if ( string[0] == '0' && string[1] == 'x' ) // 十六进制格式"0xXXXXXXXX"
return sscanf( &(string[2]), "%lx", pvalue);
else // 十进制格式
return sscanf( string , "%lu", pvalue);
}
#define DMA_MAX_SIZE 0x10000000UL // DMA操作的最大尺寸定义 256kb
char USAGE[] =
"Usage: \n"
"\n"
" 写入设备(主机到设备):\n"
" %s <文件名> to <设备名> <设备内地址> <大小>\n"
" 示例:\n"
" %s data.bin to /dev/xdma0_h2c_0 0x100000 0x10000\n"
"\n"
" 读取设备(设备到主机):\n"
" %s <文件名> from <设备名> <设备内地址> <大小>\n"
" 示例:\n"
" %s data.bin from /dev/xdma0_c2h_0 0x100000 0x10000\n";
int main (int argc, char *argv[]) {
int ret = -1;
uint64_t millisecond;
char usage_string [1024];
char *dev_name, *file_name;
char direction;
uint64_t address, size;
int dev_fd = -1;
FILE *file_p = NULL;
void *buffer = NULL;
sprintf(usage_string, USAGE, argv[0], argv[0], argv[0], argv[0] );
if (argc < 6) { // not enough argument
puts(usage_string);
return -1;
}
file_name = argv[1];
direction = argv[2][0];
dev_name = argv[3];
if ( 0 == parse_uint(argv[4], &address) ) { // parse the address in the device
puts(usage_string);
return -1;
}
if ( 0 == parse_uint(argv[5], &size ) ) { // parse the size in the device
puts(usage_string);
return -1;
}
// print information:
if (direction == 't') { // to (write device, host-to-device)
printf("from : %s\n" , file_name);
printf("to : %s addr=0x%lx\n" , dev_name, address);
printf("size : 0x%lx\n\n" , size);
} else if (direction == 'f') { // from (read device, device-to-host)
printf("from : %s addr=0x%lx\n" , dev_name, address);
printf("to : %s\n" , file_name);
printf("size : 0x%lx\n\n" , size);
} else {
puts(usage_string);
return -1;
}
if (size > DMA_MAX_SIZE || size == 0) {
printf("*** ERROR: DMA size must larger than 0 and NOT be larger than %lu\n", DMA_MAX_SIZE);
return -1;
}
buffer = malloc(size); // allocate local memory (buffer)
if (buffer == NULL) {
printf("*** ERROR: failed to allocate buffer\n");
goto close_and_clear;
}
dev_fd = open(dev_name, O_RDWR); // open device
if (dev_fd < 0) {
printf("*** ERROR: failed to open device %s\n", dev_name);
goto close_and_clear;
}
file_p = fopen(file_name, direction == 't' ? "rb" : "wb"); // open file for read/write
if (file_p == NULL) {
printf("*** ERROR: failed to open file %s\n", file_name);
goto close_and_clear;
}
millisecond = get_millisecond(); // start time
if (direction == 't') {
if ( size != fread(buffer, 1, size, file_p) ) { // local file -> local buffer
printf("*** ERROR: failed to read %s\n", file_name);
goto close_and_clear;
}
if ( dev_write(dev_fd, address, buffer, size) ) { // local buffer -> device
printf("*** ERROR: failed to write %s\n", dev_name);
goto close_and_clear;
}
} else {
if ( dev_read(dev_fd, address, buffer, size) ) { // device -> local buffer
printf("*** ERROR: failed to read %s\n", dev_name);
goto close_and_clear;
}
if ( size != fwrite(buffer, 1, size, file_p) ) { // local buffer -> local file
printf("*** ERROR: failed to write %s\n", file_name);
goto close_and_clear;
}
}
millisecond = get_millisecond() - millisecond; // get time consumption
millisecond = (millisecond > 0) ? millisecond : 1; // avoid divide-by-zero
printf("time=%lu ms data rate=%.1lf KBps\n", millisecond, (double)size / millisecond );
ret = 0;
close_and_clear:
if (buffer != NULL)
free(buffer);
if (dev_fd >= 0)
close(dev_fd);
if (file_p != NULL)
fclose(file_p);
return ret;
}