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