From c02494855e36f692998570d9d0d607df8d523735 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Sat, 23 Oct 2021 21:55:52 +0200 Subject: [PATCH] [SC64][SW] Added USB debug feature (#8) --- sw/riscv/build.sh | 2 +- sw/riscv/src/cfg.c | 32 ++++++++++++++ sw/riscv/src/usb.c | 106 ++++++++++++++++++++++++++++++++++++++++++++- sw/riscv/src/usb.h | 6 +++ 4 files changed, 144 insertions(+), 2 deletions(-) diff --git a/sw/riscv/build.sh b/sw/riscv/build.sh index faeb3d6..1c0ceb8 100755 --- a/sw/riscv/build.sh +++ b/sw/riscv/build.sh @@ -1,3 +1,3 @@ #!/bin/bash -docker run --mount type=bind,src="$(pwd)",target="/workdir" ghcr.io/polprzewodnikowy/sc64env:v1.0 /bin/bash -c "make clean all" +docker run --mount type=bind,src="$(pwd)",target="/workdir" ghcr.io/polprzewodnikowy/sc64env:v1.0 /bin/bash -c "USER_FLAGS=\"-DDEBUG\" make clean all" diff --git a/sw/riscv/src/cfg.c b/sw/riscv/src/cfg.c index 3740008..3b405da 100644 --- a/sw/riscv/src/cfg.c +++ b/sw/riscv/src/cfg.c @@ -1,5 +1,6 @@ #include "cfg.h" #include "joybus.h" +#include "usb.h" #define SAVE_SIZE_EEPROM_4K (512) @@ -199,6 +200,37 @@ void process_cfg (void) { cfg_query(args); break; + case 'S': + args[0] = usb_debug_tx_ready(); + break; + + case 'D': + if (!usb_debug_tx_data(args[0], (size_t) args[1])) { + change_scr_bits(CFG_SCR_CMD_ERROR, true); + } + break; + + case 'A': + if (!usb_debug_rx_ready(&args[0], (size_t *) (&args[1]))) { + args[0] = 0; + args[1] = 0; + } + break; + + case 'F': + args[0] = usb_debug_rx_busy(); + break; + + case 'E': + if (!usb_debug_rx_data(args[0], (size_t) args[1])) { + change_scr_bits(CFG_SCR_CMD_ERROR, true); + } + break; + + case 'B': + usb_debug_reset(); + break; + default: change_scr_bits(CFG_SCR_CMD_ERROR, true); break; diff --git a/sw/riscv/src/usb.c b/sw/riscv/src/usb.c index ab1582c..4bf8f8d 100644 --- a/sw/riscv/src/usb.c +++ b/sw/riscv/src/usb.c @@ -67,6 +67,7 @@ enum state { STATE_ARGS, STATE_DATA, STATE_RESPONSE, + STATE_DEBUG_TX, }; struct process { @@ -76,22 +77,97 @@ struct process { uint32_t args[2]; bool error; bool dma_in_progress; + + bool debug_rx_busy; + uint32_t debug_rx_address; + size_t debug_rx_length; + + bool debug_tx_busy; + uint32_t debug_tx_address; + size_t debug_tx_length; }; static struct process p; +bool usb_debug_rx_ready (uint32_t *type, size_t *length) { + if (p.state != STATE_DATA || p.cmd != 'D' || p.debug_rx_busy) { + return false; + } + + *type = p.args[0]; + *length = (size_t) p.args[1]; + + return true; +} + +bool usb_debug_rx_busy (void) { + return p.debug_rx_busy; +} + +bool usb_debug_rx_data (uint32_t address, size_t length) { + if (p.debug_rx_busy) { + return false; + } + + p.debug_rx_busy = true; + p.debug_rx_address = address; + p.debug_rx_length = length; + + return true; +} + +bool usb_debug_tx_ready (void) { + return !p.debug_tx_busy; +} + +bool usb_debug_tx_data (uint32_t address, size_t length) { + if (p.debug_tx_busy) { + return false; + } + + p.debug_tx_busy = true; + p.debug_tx_address = address; + p.debug_tx_length = length; + + return true; +} + +void usb_debug_reset (void) { + uint8_t tmp; + + if (p.state == STATE_DATA && p.cmd == 'D') { + for (size_t i = 0; i < p.args[1]; i++) { + rx_byte(&tmp); + } + p.args[1] = 0; + } + if (p.state == STATE_DEBUG_TX) { + p.state = STATE_IDLE; + } + p.debug_rx_busy = false; + p.debug_tx_busy = false; + + USB->SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX; +} + + void usb_init (void) { USB->SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX; p.state = STATE_IDLE; + p.debug_rx_busy = false; + p.debug_tx_busy = false; } void process_usb (void) { switch (p.state) { case STATE_IDLE: - if (rx_word(&p.args[0])) { + if (p.debug_tx_busy) { + p.state = STATE_DEBUG_TX; + p.dma_in_progress = false; + } else if (rx_word(&p.args[0])) { if ((p.args[0] & 0xFFFFFF00) == USB_CMD_TOKEN) { p.cmd = p.args[0] & 0xFF; p.counter = 0; @@ -142,6 +218,22 @@ void process_usb (void) { } break; + case 'D': + if (!dma_busy() && p.debug_rx_busy && p.args[1] > 0) { + if (!p.dma_in_progress) { + dma_start(p.debug_rx_address, p.debug_rx_length, DMA_ID_USB, DMA_DIR_TO_SDRAM); + p.dma_in_progress = true; + } else { + p.args[1] -= p.debug_rx_length > p.args[1] ? p.args[1] : p.debug_rx_length; + p.dma_in_progress = false; + p.debug_rx_busy = false; + } + } + if (p.args[1] == 0) { + p.state = STATE_IDLE; + } + break; + default: p.error = true; p.state = STATE_RESPONSE; @@ -154,5 +246,17 @@ void process_usb (void) { p.state = STATE_IDLE; } break; + + case STATE_DEBUG_TX: + if (!dma_busy()) { + if (!p.dma_in_progress) { + dma_start(p.debug_tx_address, p.debug_tx_length, DMA_ID_USB, DMA_DIR_FROM_SDRAM); + p.dma_in_progress = true; + } else { + p.debug_tx_busy = false; + p.state = STATE_IDLE; + } + } + break; } } diff --git a/sw/riscv/src/usb.h b/sw/riscv/src/usb.h index 3b4f5e4..28f3298 100644 --- a/sw/riscv/src/usb.h +++ b/sw/riscv/src/usb.h @@ -5,6 +5,12 @@ #include "sys.h" +bool usb_debug_rx_ready (uint32_t *type, size_t *length); +bool usb_debug_rx_busy (void); +bool usb_debug_rx_data (uint32_t address, size_t length); +bool usb_debug_tx_ready (void); +bool usb_debug_tx_data (uint32_t address, size_t length); +void usb_debug_reset (void); void usb_init (void); void process_usb (void);