diff --git a/os/src/userspace/testje.c b/os/src/userspace/testje.c index 244df15..f6db422 100644 --- a/os/src/userspace/testje.c +++ b/os/src/userspace/testje.c @@ -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); }