diff --git a/fw/rtl/cpu/cpu_usb.sv b/fw/rtl/cpu/cpu_usb.sv index da439c2..76e86d2 100644 --- a/fw/rtl/cpu/cpu_usb.sv +++ b/fw/rtl/cpu/cpu_usb.sv @@ -28,6 +28,7 @@ module cpu_usb ( logic cpu_tx_write; logic usb_enabled; + logic tx_force; always_comb begin dma.rx_empty = rx_empty; @@ -66,6 +67,7 @@ module cpu_usb ( cpu_tx_write <= 1'b0; rx_escape_ack <= 1'b0; + tx_force <= 1'b0; if (sys.reset) begin usb_enabled <= 1'b0; @@ -73,6 +75,9 @@ module cpu_usb ( if (bus.request) begin case (bus.address[2:2]) 2'd0: begin + if (bus.wmask[1]) begin + tx_force <= bus.wdata[8]; + end if (bus.wmask[0]) begin rx_escape_ack <= bus.wdata[7]; {usb_enabled, tx_flush, rx_flush} <= bus.wdata[4:2]; @@ -95,6 +100,7 @@ module cpu_usb ( .sys(sys), .usb_enabled(usb_enabled), + .tx_force(tx_force), .usb_clk(usb_clk), .usb_cs(usb_cs), diff --git a/fw/rtl/usb/usb_ft1248.sv b/fw/rtl/usb/usb_ft1248.sv index 325991e..2426cd6 100644 --- a/fw/rtl/usb/usb_ft1248.sv +++ b/fw/rtl/usb/usb_ft1248.sv @@ -2,6 +2,7 @@ module usb_ft1248 ( if_system.sys sys, input usb_enabled, + input tx_force, output usb_clk, output usb_cs, @@ -111,7 +112,8 @@ module usb_ft1248 ( typedef enum bit [7:0] { C_WRITE = 8'h00, - C_READ = 8'h04 + C_READ = 8'h04, + C_FORCE = 8'h80 } e_command; typedef enum bit [1:0] { @@ -134,7 +136,9 @@ module usb_ft1248 ( logic usb_miosi_output_enable_data; logic usb_miso_input; + logic tx_force_pending; logic is_cmd_write; + logic is_cmd_tx_force; logic [1:0] nibble_counter; logic [7:0] tx_buffer; @@ -168,7 +172,9 @@ module usb_ft1248 ( S_COMMAND: begin usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING]; usb_cs_output = 1'b0; - if (is_cmd_write) begin + if (is_cmd_tx_force) begin + usb_miosi_output_data = nibble_counter[0] ? C_FORCE[3:0] : C_FORCE[7:4]; + end else if (is_cmd_write) begin usb_miosi_output_data = nibble_counter[0] ? C_WRITE[3:0] : C_WRITE[7:4]; end else begin usb_miosi_output_data = nibble_counter[0] ? C_READ[3:0] : C_READ[7:4]; @@ -202,12 +208,18 @@ module usb_ft1248 ( if (sys.reset || !usb_enabled) begin state <= S_TRY_RX; + tx_force_pending <= 1'b0; end else begin + if (tx_force) begin + tx_force_pending <= 1'b1; + end + case (state) S_TRY_RX: begin if (!rx_full && !rx_escape_valid) begin state <= S_COMMAND; is_cmd_write <= 1'b0; + is_cmd_tx_force <= 1'b0; nibble_counter <= 2'b11; end else begin state <= S_TRY_TX; @@ -218,6 +230,13 @@ module usb_ft1248 ( if (!tx_empty) begin state <= S_COMMAND; is_cmd_write <= 1'b1; + is_cmd_tx_force <= 1'b0; + nibble_counter <= 2'b11; + end else if (tx_force_pending) begin + state <= S_COMMAND; + tx_force_pending <= 1'b0; + is_cmd_write <= 1'b1; + is_cmd_tx_force <= 1'b1; nibble_counter <= 2'b11; end else begin state <= S_TRY_RX; @@ -227,7 +246,7 @@ module usb_ft1248 ( S_COMMAND: begin if (clock_phase[P_RISING]) begin if (nibble_counter == 2'd2) begin - if (usb_miso_input) begin + if (usb_miso_input || is_cmd_tx_force) begin state <= is_cmd_write ? S_TRY_RX : S_TRY_TX; end else begin state <= S_DATA; diff --git a/sw/n64/src/exception.S b/sw/n64/src/exception.S index 7474ba2..ab3d16e 100644 --- a/sw/n64/src/exception.S +++ b/sw/n64/src/exception.S @@ -1,7 +1,7 @@ #include "vr4300.h" -#define WATCHDOG_TIMEOUT (1 * (93750000UL / 2)) +#define WATCHDOG_TIMEOUT (5 * (93750000UL / 2)) #define VECTOR_LOCATION (0xA0000000UL) #define VECTOR_SIZE (0x80) diff --git a/sw/n64/src/exception.c b/sw/n64/src/exception.c index 3614c7d..d6331a4 100644 --- a/sw/n64/src/exception.c +++ b/sw/n64/src/exception.c @@ -276,7 +276,7 @@ void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, if (exception_code == EXCEPTION_INTERRUPT) { if (interrupt_mask & INTERRUPT_MASK_TIMER) { exception_disable_watchdog(); - exception_print("Still loading after 1 second limit...\n\n"); + exception_print("Still loading after 5 second limit...\n\n"); return; } } else if (exception_code == EXCEPTION_SYSCALL) { diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h index 0e227d0..4d84f9d 100644 --- a/sw/riscv/src/sys.h +++ b/sw/riscv/src/sys.h @@ -105,6 +105,7 @@ typedef volatile struct usb_regs { #define USB_SCR_PWREN (1 << 5) #define USB_SCR_ESCAPE_PENDING (1 << 6) #define USB_SCR_ESCAPE_ACK (1 << 7) +#define USB_SCR_FORCE_TX (1 << 8) typedef volatile struct uart_regs { diff --git a/sw/riscv/src/usb.c b/sw/riscv/src/usb.c index c7f140b..19014f7 100644 --- a/sw/riscv/src/usb.c +++ b/sw/riscv/src/usb.c @@ -252,6 +252,9 @@ void process_usb (void) { } } p.state = STATE_IDLE; + if (p.cmd == 'L') { + USB->SCR |= USB_SCR_FORCE_TX; + } } else { p.state = STATE_RESPONSE; } @@ -303,6 +306,7 @@ void process_usb (void) { case STATE_RESPONSE: if (tx_word((p.error ? USB_ERR_TOKEN : USB_CMP_TOKEN) | p.cmd)) { p.state = STATE_IDLE; + USB->SCR |= USB_SCR_FORCE_TX; } break; @@ -327,6 +331,7 @@ void process_usb (void) { } p.event_pending = false; p.state = STATE_IDLE; + USB->SCR |= USB_SCR_FORCE_TX; } break; }