Update test program

Add test register.
Wait for 4k data blocks when possible.
This commit is contained in:
Joris van Rantwijk 2024-08-24 23:05:19 +02:00
parent 4abc2ee165
commit 131fe91c67
1 changed files with 75 additions and 54 deletions

View File

@ -38,6 +38,7 @@
#define REG_DMA_ADDR_PTR 0x0210
#define REG_DMA_CHANNEL_CTRL 0x0214
#define REG_DMA_INTR_CTRL 0x0218
#define REG_TEST_DIVIDER 0x0408
struct puzzlefw_context {
@ -434,6 +435,9 @@ static void show_status(struct puzzlefw_context *ctx)
v = puzzlefw_read_reg(ctx, REG_DMA_INTR_CTRL);
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.
puzzlefw_write_reg(ctx, REG_DMA_ADDR_LIMIT, 0xffffffff);
// Initialize and enable DMA writer.
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 3);
// Initialize DMA writer.
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 2);
// Enable DMA writer.
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 1);
struct timespec tp;
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.
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;
// Reserve this number of bytes in the buffer to avoid ambiguous pointers.
const uint32_t pointer_margin = 1024;
// When buffer is empty, sleep at most this duration.
// Sleep at most this duration if there is insufficient data in the buffer.
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(send_max_block % 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.
puzzlefw_write_reg(ctx, REG_DMA_EN, 1);
// Initialize and enable DMA writer.
puzzlefw_write_reg(ctx, REG_DMA_CHANNEL_CTRL, 3);
// Initialize DMA writer.
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;
int ret;
@ -698,12 +708,14 @@ int transmit_dma_data(struct puzzlefw_context *ctx, int conn)
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 navail = (write_pointer >= read_pointer) ?
(write_pointer - read_pointer) :
(ctx->dma_buf_size + write_pointer - read_pointer);
if (write_pointer == read_pointer) {
// Wait for new data.
// Wait for enough data in the buffer, or timeout.
if (navail < wait_block_size) {
ret = wait_dma_data(ctx, conn,
read_pointer,
wait_block_size,
@ -717,56 +729,56 @@ int transmit_dma_data(struct puzzlefw_context *ctx, int conn)
break;
}
} else {
write_pointer = puzzlefw_read_reg(ctx, REG_DMA_ADDR_PTR);
}
// Determine number of bytes available.
// 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
// pass through the loop.
uint32_t navail =
(write_pointer >= read_pointer) ?
(write_pointer - read_pointer) :
(ctx->dma_buf_size - read_pointer);
// Determine number of bytes available.
// 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
// pass through the loop.
navail = (write_pointer >= read_pointer) ?
(write_pointer - read_pointer) :
(ctx->dma_buf_size - read_pointer);
// Make sure the CPU view of the DMA buffer is up to date
// relative to the state previously reported via registers.
puzzlefw_sync_dma();
// Make sure the CPU view of the DMA buffer is up to date
// relative to the state previously reported via registers.
puzzlefw_sync_dma();
// Transmit available data in blocks of 64 kB.
while (navail > 0) {
uint32_t block_size =
(navail < send_max_block) ? navail : send_max_block;
// Transmit available data in blocks of 64 kB.
while (navail > 0) {
uint32_t block_size =
(navail < send_max_block) ? navail : send_max_block;
// Send data to socket.
ret = send_all(conn,
(void*)ctx->dma_buf + read_pointer, block_size);
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) {
// Send data to socket.
ret = send_all(conn,
(void*)ctx->dma_buf + read_pointer, block_size);
if (ret != 0) {
break;
}
if (ret == 2) {
// Connection closed.
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);
}
if (read_pointer == ctx->dma_buf_size) {
read_pointer = 0;
}
navail -= block_size;
}
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 blastdma = 0;
int server = 0;
int set_divider = 0;
int divider;
if (argc == 2 && strcmp(argv[1], "show") == 0) {
show = 1;
@ -863,6 +877,9 @@ int main(int argc, char **argv)
dmaclear = 1;
} else if (argc == 2 && strcmp(argv[1], "blastdma") == 0) {
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) {
server = 1;
} else {
@ -932,6 +949,10 @@ int main(int argc, char **argv)
blast_dma(&ctx);
}
if (set_divider) {
puzzlefw_write_reg(&ctx, REG_TEST_DIVIDER, divider);
}
if (server) {
run_server(&ctx);
}