Update test program
Add test register. Wait for 4k data blocks when possible.
This commit is contained in:
parent
4abc2ee165
commit
131fe91c67
|
@ -38,6 +38,7 @@
|
||||||
#define REG_DMA_ADDR_PTR 0x0210
|
#define REG_DMA_ADDR_PTR 0x0210
|
||||||
#define REG_DMA_CHANNEL_CTRL 0x0214
|
#define REG_DMA_CHANNEL_CTRL 0x0214
|
||||||
#define REG_DMA_INTR_CTRL 0x0218
|
#define REG_DMA_INTR_CTRL 0x0218
|
||||||
|
#define REG_TEST_DIVIDER 0x0408
|
||||||
|
|
||||||
|
|
||||||
struct puzzlefw_context {
|
struct puzzlefw_context {
|
||||||
|
@ -434,6 +435,9 @@ static void show_status(struct puzzlefw_context *ctx)
|
||||||
|
|
||||||
v = puzzlefw_read_reg(ctx, REG_DMA_INTR_CTRL);
|
v = puzzlefw_read_reg(ctx, REG_DMA_INTR_CTRL);
|
||||||
printf(" dma_intr_ctrl = 0x%08x\n", v);
|
printf(" dma_intr_ctrl = 0x%08x\n", v);
|
||||||
|
|
||||||
|
v = puzzlefw_read_reg(ctx, REG_TEST_DIVIDER);
|
||||||
|
printf(" test_divider = 0x%08x\n", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -494,8 +498,11 @@ static void blast_dma(struct puzzlefw_context *ctx)
|
||||||
// Set invalid limit to keep the writer blasting.
|
// Set invalid limit to keep the writer blasting.
|
||||||
puzzlefw_write_reg(ctx, REG_DMA_ADDR_LIMIT, 0xffffffff);
|
puzzlefw_write_reg(ctx, REG_DMA_ADDR_LIMIT, 0xffffffff);
|
||||||
|
|
||||||
// Initialize and enable DMA writer.
|
// Initialize DMA writer.
|
||||||
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 3);
|
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 2);
|
||||||
|
|
||||||
|
// Enable DMA writer.
|
||||||
|
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 1);
|
||||||
|
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
tp.tv_sec = 10;
|
tp.tv_sec = 10;
|
||||||
|
@ -646,15 +653,15 @@ int transmit_dma_data(struct puzzlefw_context *ctx, int conn)
|
||||||
// Maximum block size per TCP send() call.
|
// Maximum block size per TCP send() call.
|
||||||
const uint32_t send_max_block = 65536;
|
const uint32_t send_max_block = 65536;
|
||||||
|
|
||||||
// When buffer is empty, sleep until this amount becomes available.
|
// Sleep until this number of bytes is available in the buffer.
|
||||||
const uint32_t wait_block_size = 4096;
|
const uint32_t wait_block_size = 4096;
|
||||||
|
|
||||||
// Reserve this number of bytes in the buffer to avoid ambiguous pointers.
|
// Sleep at most this duration if there is insufficient data in the buffer.
|
||||||
const uint32_t pointer_margin = 1024;
|
|
||||||
|
|
||||||
// When buffer is empty, sleep at most this duration.
|
|
||||||
const int timeout_ms = 10;
|
const int timeout_ms = 10;
|
||||||
|
|
||||||
|
// Reserve this number of bytes in the buffer to avoid ambiguous pointers.
|
||||||
|
const uint32_t pointer_margin = 4096;
|
||||||
|
|
||||||
assert(ctx->dma_buf_size >= 2 * wait_block_size);
|
assert(ctx->dma_buf_size >= 2 * wait_block_size);
|
||||||
assert(send_max_block % ctx->dma_transfer_size == 0);
|
assert(send_max_block % ctx->dma_transfer_size == 0);
|
||||||
assert(wait_block_size % ctx->dma_transfer_size == 0);
|
assert(wait_block_size % ctx->dma_transfer_size == 0);
|
||||||
|
@ -681,8 +688,11 @@ int transmit_dma_data(struct puzzlefw_context *ctx, int conn)
|
||||||
// Enable AXI DMA.
|
// Enable AXI DMA.
|
||||||
puzzlefw_write_reg(ctx, REG_DMA_EN, 1);
|
puzzlefw_write_reg(ctx, REG_DMA_EN, 1);
|
||||||
|
|
||||||
// Initialize and enable DMA writer.
|
// Initialize DMA writer.
|
||||||
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 3);
|
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 2);
|
||||||
|
|
||||||
|
// Enable DMA writer.
|
||||||
|
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 1);
|
||||||
|
|
||||||
uint32_t read_pointer = 0;
|
uint32_t read_pointer = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -698,12 +708,14 @@ int transmit_dma_data(struct puzzlefw_context *ctx, int conn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for data in buffer.
|
// Determine number of bytes available.
|
||||||
uint32_t write_pointer = puzzlefw_read_reg(ctx, REG_DMA_ADDR_PTR);
|
uint32_t write_pointer = puzzlefw_read_reg(ctx, REG_DMA_ADDR_PTR);
|
||||||
|
uint32_t navail = (write_pointer >= read_pointer) ?
|
||||||
|
(write_pointer - read_pointer) :
|
||||||
|
(ctx->dma_buf_size + write_pointer - read_pointer);
|
||||||
|
|
||||||
if (write_pointer == read_pointer) {
|
// Wait for enough data in the buffer, or timeout.
|
||||||
|
if (navail < wait_block_size) {
|
||||||
// Wait for new data.
|
|
||||||
ret = wait_dma_data(ctx, conn,
|
ret = wait_dma_data(ctx, conn,
|
||||||
read_pointer,
|
read_pointer,
|
||||||
wait_block_size,
|
wait_block_size,
|
||||||
|
@ -717,56 +729,56 @@ int transmit_dma_data(struct puzzlefw_context *ctx, int conn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
write_pointer = puzzlefw_read_reg(ctx, REG_DMA_ADDR_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
// Determine number of bytes available.
|
// Determine number of bytes available.
|
||||||
// If the write pointer wrapped around the end of the buffer,
|
// If the write pointer wrapped around the end of the buffer,
|
||||||
// stop at the end of the buffer and process the rest in the next
|
// stop at the end of the buffer and process the rest in the next
|
||||||
// pass through the loop.
|
// pass through the loop.
|
||||||
uint32_t navail =
|
navail = (write_pointer >= read_pointer) ?
|
||||||
(write_pointer >= read_pointer) ?
|
(write_pointer - read_pointer) :
|
||||||
(write_pointer - read_pointer) :
|
(ctx->dma_buf_size - read_pointer);
|
||||||
(ctx->dma_buf_size - read_pointer);
|
|
||||||
|
|
||||||
// Make sure the CPU view of the DMA buffer is up to date
|
// Make sure the CPU view of the DMA buffer is up to date
|
||||||
// relative to the state previously reported via registers.
|
// relative to the state previously reported via registers.
|
||||||
puzzlefw_sync_dma();
|
puzzlefw_sync_dma();
|
||||||
|
|
||||||
// Transmit available data in blocks of 64 kB.
|
// Transmit available data in blocks of 64 kB.
|
||||||
while (navail > 0) {
|
while (navail > 0) {
|
||||||
uint32_t block_size =
|
uint32_t block_size =
|
||||||
(navail < send_max_block) ? navail : send_max_block;
|
(navail < send_max_block) ? navail : send_max_block;
|
||||||
|
|
||||||
// Send data to socket.
|
// Send data to socket.
|
||||||
ret = send_all(conn,
|
ret = send_all(conn,
|
||||||
(void*)ctx->dma_buf + read_pointer, block_size);
|
(void*)ctx->dma_buf + read_pointer, block_size);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update read pointer and update DMA writer limit.
|
|
||||||
read_pointer += block_size;
|
|
||||||
if (read_pointer > pointer_margin) {
|
|
||||||
puzzlefw_write_reg(ctx, REG_DMA_ADDR_LIMIT,
|
|
||||||
read_pointer - pointer_margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
navail -= block_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 2) {
|
// Update read pointer and update DMA writer limit.
|
||||||
// Connection closed.
|
read_pointer += block_size;
|
||||||
ret = 0;
|
if (read_pointer > pointer_margin) {
|
||||||
break;
|
puzzlefw_write_reg(ctx, REG_DMA_ADDR_LIMIT,
|
||||||
|
read_pointer - pointer_margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_pointer == ctx->dma_buf_size) {
|
navail -= block_size;
|
||||||
read_pointer = 0;
|
}
|
||||||
}
|
|
||||||
|
if (ret < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 2) {
|
||||||
|
// Connection closed.
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap read pointer at end of buffer.
|
||||||
|
if (read_pointer == ctx->dma_buf_size) {
|
||||||
|
read_pointer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,6 +860,8 @@ int main(int argc, char **argv)
|
||||||
int dmaclear = 0;
|
int dmaclear = 0;
|
||||||
int blastdma = 0;
|
int blastdma = 0;
|
||||||
int server = 0;
|
int server = 0;
|
||||||
|
int set_divider = 0;
|
||||||
|
int divider;
|
||||||
|
|
||||||
if (argc == 2 && strcmp(argv[1], "show") == 0) {
|
if (argc == 2 && strcmp(argv[1], "show") == 0) {
|
||||||
show = 1;
|
show = 1;
|
||||||
|
@ -863,6 +877,9 @@ int main(int argc, char **argv)
|
||||||
dmaclear = 1;
|
dmaclear = 1;
|
||||||
} else if (argc == 2 && strcmp(argv[1], "blastdma") == 0) {
|
} else if (argc == 2 && strcmp(argv[1], "blastdma") == 0) {
|
||||||
blastdma = 1;
|
blastdma = 1;
|
||||||
|
} else if (argc == 3 && strcmp(argv[1], "divider") == 0) {
|
||||||
|
set_divider = 1;
|
||||||
|
divider = atoi(argv[2]);
|
||||||
} else if (argc == 2 && strcmp(argv[1], "server") == 0) {
|
} else if (argc == 2 && strcmp(argv[1], "server") == 0) {
|
||||||
server = 1;
|
server = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -932,6 +949,10 @@ int main(int argc, char **argv)
|
||||||
blast_dma(&ctx);
|
blast_dma(&ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (set_divider) {
|
||||||
|
puzzlefw_write_reg(&ctx, REG_TEST_DIVIDER, divider);
|
||||||
|
}
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
run_server(&ctx);
|
run_server(&ctx);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue