usb debug and si stuff

This commit is contained in:
Polprzewodnikowy 2021-09-06 12:59:37 +02:00
parent 5671e20c3f
commit 17311eed90
16 changed files with 790 additions and 172 deletions

View File

@ -63,6 +63,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_si.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_soc.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_soc.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
@ -72,10 +73,12 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_cfg.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_dd.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_flashram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi_fifo.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi_fifo.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_si.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_soc.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_soc.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/SummerCart64.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/SummerCart64.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/config.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/config.sv

View File

@ -62,6 +62,8 @@ module SummerCart64 (
if_flashram flashram (); if_flashram flashram ();
if_si si ();
system system_inst ( system system_inst (
.sys(sys) .sys(sys)
); );
@ -78,6 +80,7 @@ module SummerCart64 (
.dma(dma), .dma(dma),
.sdram(sdram), .sdram(sdram),
.flashram(flashram), .flashram(flashram),
.si(si),
.n64_pi_alel(i_n64_pi_alel), .n64_pi_alel(i_n64_pi_alel),
.n64_pi_aleh(i_n64_pi_aleh), .n64_pi_aleh(i_n64_pi_aleh),
@ -103,6 +106,7 @@ module SummerCart64 (
.dma(dma), .dma(dma),
.sdram(sdram), .sdram(sdram),
.flashram(flashram), .flashram(flashram),
.si(si),
.gpio_o(gpio_o), .gpio_o(gpio_o),
.gpio_i(gpio_i), .gpio_i(gpio_i),

59
fw/rtl/cpu/cpu_si.sv Normal file
View File

@ -0,0 +1,59 @@
module cpu_si (
if_system.sys sys,
if_cpu_bus bus,
if_si.cpu si
);
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
case (bus.address[3:2])
0: bus.rdata = {
20'd0,
si.rx_length[6:3],
4'd0,
si.tx_busy,
1'b0,
si.rx_data[0],
si.rx_ready
};
1: bus.rdata = {si.rx_data[56:49], si.rx_data[64:57], si.rx_data[72:65], si.rx_data[80:73]};
2: bus.rdata = {si.rx_data[24:17], si.rx_data[32:25], si.rx_data[40:33], si.rx_data[48:41]};
3: bus.rdata = {16'd0, si.rx_data[8:1], si.rx_data[16:9]};
default: bus.rdata = 32'd0;
endcase
end
end
always_comb begin
si.tx_data = {bus.wdata[7:0], bus.wdata[15:8], bus.wdata[23:16], bus.wdata[31:24]};
si.tx_length = bus.wdata[22:16];
end
always_ff @(posedge sys.clk) begin
si.tx_reset <= 1'b0;
si.rx_reset <= 1'b0;
si.tx_start <= 1'b0;
si.tx_wmask <= 3'b000;
if (bus.request && (&bus.wmask)) begin
case (bus.address[3:2])
0: begin
si.tx_reset <= bus.wdata[7];
si.rx_reset <= bus.wdata[6];
si.tx_start <= bus.wdata[2];
end
1: si.tx_wmask[0] <= 1'b1;
2: si.tx_wmask[1] <= 1'b1;
3: si.tx_wmask[2] <= 1'b1;
endcase
end
end
endmodule

View File

@ -4,6 +4,7 @@ module cpu_soc (
if_dma dma, if_dma dma,
if_sdram.cpu sdram, if_sdram.cpu sdram,
if_flashram.cpu flashram, if_flashram.cpu flashram,
if_si.cpu si,
input [7:0] gpio_i, input [7:0] gpio_i,
output [7:0] gpio_o, output [7:0] gpio_o,
@ -104,4 +105,10 @@ module cpu_soc (
.flashram(flashram) .flashram(flashram)
); );
cpu_si cpu_si_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_SI].device),
.si(si)
);
endmodule endmodule

83
fw/rtl/n64/n64_dd.sv Normal file
View File

@ -0,0 +1,83 @@
interface if_dd();
logic hard_reset;
logic cmd_request;
logic cmd_ack;
logic [7:0] command;
logic [15:0] status;
logic [15:0] data_input;
logic [15:0] data_output;
logic bm_request;
logic [15:0] bm_control;
logic [15:0] bm_status;
modport n64 (
output hard_reset,
output cmd_request,
input cmd_ack,
output command,
input status,
output data_input,
input data_output,
output bm_request,
output bm_control,
input bm_status
);
modport cpu (
input hard_reset,
input cmd_request,
output cmd_ack,
input command,
output status,
input data_input,
output data_output,
input bm_request,
input bm_control,
output bm_status
);
endinterface
module n64_dd (
if_system.sys sys,
if_n64_bus bus
);
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
always_comb begin
bus.rdata = 16'h0000;
if (bus.ack) begin
bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000;
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (sys.reset) begin
state <= S_IDLE;
end else begin
case (state)
S_IDLE: begin
if (bus.request) begin
state <= S_WAIT;
bus.ack <= 1'b1;
end
end
S_WAIT: begin
state <= S_IDLE;
end
endcase
end
end
endmodule

View File

@ -61,7 +61,7 @@ module n64_pi (
); );
// Control signals input synchronization // Control signals and input synchronization
logic [2:0] n64_pi_alel_ff; logic [2:0] n64_pi_alel_ff;
logic [2:0] n64_pi_aleh_ff; logic [2:0] n64_pi_aleh_ff;
@ -207,7 +207,7 @@ module n64_pi (
if (cfg.dd_enabled) begin if (cfg.dd_enabled) begin
if (n64_pi_ad_input == 16'h0500) begin if (n64_pi_ad_input == 16'h0500) begin
n64_pi_address_valid <= 1'b1; n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_DDREGS; next_id <= sc64::ID_N64_DD;
end end
if (n64_pi_ad_input >= 16'h0600 && n64_pi_ad_input < 16'h0640) begin if (n64_pi_ad_input >= 16'h0600 && n64_pi_ad_input < 16'h0640) begin
n64_pi_address_valid <= 1'b1; n64_pi_address_valid <= 1'b1;

222
fw/rtl/n64/n64_si.sv Normal file
View File

@ -0,0 +1,222 @@
interface if_si ();
logic rx_reset;
logic rx_ready;
logic [6:0] rx_length;
logic [80:0] rx_data;
logic tx_reset;
logic tx_start;
logic tx_busy;
logic [2:0] tx_wmask;
logic [6:0] tx_length;
logic [31:0] tx_data;
modport si (
input rx_reset,
output rx_ready,
output rx_length,
output rx_data,
input tx_reset,
input tx_start,
output tx_busy,
input tx_wmask,
input tx_length,
input tx_data
);
modport cpu (
output rx_reset,
input rx_ready,
input rx_length,
input rx_data,
output tx_reset,
output tx_start,
input tx_busy,
output tx_wmask,
output tx_length,
output tx_data
);
endinterface
module n64_si (
if_system.sys sys,
if_si.si si,
input n64_si_clk,
inout n64_si_dq
);
// Control signals and input synchronization
logic [1:0] n64_si_clk_ff;
always_ff @(posedge sys.clk) begin
n64_si_clk_ff <= {n64_si_clk_ff[0], n64_si_clk};
end
logic si_reset;
logic si_clk;
logic si_dq;
always_comb begin
si_reset = sys.n64_hard_reset;
si_clk = n64_si_clk_ff[1];
si_dq = n64_si_dq;
end
logic last_si_clk;
always_ff @(posedge sys.clk) begin
last_si_clk <= si_clk;
end
logic si_clk_rising_edge;
logic si_clk_falling_edge;
always_comb begin
si_clk_rising_edge = !si_reset && !last_si_clk && si_clk;
si_clk_falling_edge = !si_reset && last_si_clk && !si_clk;
end
logic si_dq_output_enable;
logic si_dq_output_enable_data;
always_ff @(posedge sys.clk) begin
si_dq_output_enable <= si_dq_output_enable_data;
end
always_comb begin
n64_si_dq = si_dq_output_enable ? 1'b0 : 1'bZ;
end
// Data register and shifter
logic [80:0] trx_data;
logic rx_shift;
logic tx_shift;
always_comb begin
si.rx_data = trx_data;
end
always_ff @(posedge sys.clk) begin
if (si.tx_wmask[0]) trx_data[80:49] <= si.tx_data;
if (si.tx_wmask[1]) trx_data[48:17] <= si.tx_data;
if (si.tx_wmask[2]) trx_data[16:0] <= si.tx_data[16:0];
if (rx_shift || tx_shift) begin
trx_data <= {trx_data[79:0], rx_sub_bit_counter < 2'd2};
end
end
// RX path
typedef enum bit [0:0] {
S_RX_IDLE,
S_RX_WAITING
} e_rx_state;
e_rx_state rx_state;
logic [1:0] rx_sub_bit_counter;
logic [3:0] rx_timeout_counter;
always_ff @(posedge sys.clk) begin
rx_shift <= 1'b0;
if (si_clk_rising_edge) begin
if (rx_timeout_counter < 4'd8) begin
rx_timeout_counter <= rx_timeout_counter + 1'd1;
end else if (si.rx_length > 7'd0) begin
si.rx_ready <= 1'b1;
end
end
if (sys.reset || si.rx_reset) begin
rx_state <= S_RX_IDLE;
si.rx_ready <= 1'b0;
si.rx_length <= 7'd0;
end else if (!si.tx_busy) begin
case (rx_state)
S_RX_IDLE: begin
if (si_clk_rising_edge && !si_dq) begin
rx_state <= S_RX_WAITING;
rx_sub_bit_counter <= 2'd0;
rx_timeout_counter <= 3'd0;
end
end
S_RX_WAITING: begin
if (si_clk_rising_edge) begin
if (si_dq) begin
rx_state <= S_RX_IDLE;
rx_shift <= 1'b1;
si.rx_length <= si.rx_length + 1'd1;
end else if (rx_sub_bit_counter < 2'd3) begin
rx_sub_bit_counter <= rx_sub_bit_counter + 1'd1;
end
end
end
endcase
end
end
// TX path
typedef enum bit [0:0] {
S_TX_IDLE,
S_TX_SENDING
} e_tx_state;
e_tx_state tx_state;
logic [2:0] tx_sub_bit_counter;
logic [6:0] tx_bit_counter;
always_ff @(posedge sys.clk) begin
tx_shift <= 1'b0;
if (sys.reset || si.tx_reset) begin
tx_state <= S_TX_IDLE;
si_dq_output_enable_data <= 1'b0;
si.tx_busy <= 1'b0;
end else begin
case (tx_state)
S_TX_IDLE: begin
if (si.tx_start) begin
tx_state <= S_TX_SENDING;
tx_sub_bit_counter <= 3'd0;
tx_bit_counter <= si.tx_length;
si.tx_busy <= 1'b1;
end
end
S_TX_SENDING: begin
if (si_clk_falling_edge) begin
tx_sub_bit_counter <= tx_sub_bit_counter + 1'd1;
if (tx_sub_bit_counter == 3'd7) begin
tx_shift <= 1'b1;
if (tx_bit_counter > 7'd1) begin
tx_bit_counter <= tx_bit_counter - 1'd1;
end else begin
tx_state <= S_TX_IDLE;
si.tx_busy <= 1'b0;
end
end
if (trx_data[80]) begin
si_dq_output_enable_data <= tx_sub_bit_counter < 3'd2;
end else begin
si_dq_output_enable_data <= tx_sub_bit_counter < 3'd6;
end
end
end
endcase
end
end
endmodule

View File

@ -4,6 +4,7 @@ module n64_soc (
if_dma.memory dma, if_dma.memory dma,
if_sdram.memory sdram, if_sdram.memory sdram,
if_flashram.flashram flashram, if_flashram.flashram flashram,
if_si.si si,
input n64_pi_alel, input n64_pi_alel,
input n64_pi_aleh, input n64_pi_aleh,
@ -37,6 +38,14 @@ module n64_soc (
.n64_pi_ad(n64_pi_ad) .n64_pi_ad(n64_pi_ad)
); );
n64_si n64_si_inst (
.sys(sys),
.si(si),
.n64_si_clk(n64_si_clk),
.n64_si_dq(n64_si_dq)
);
n64_sdram n64_sdram_inst ( n64_sdram n64_sdram_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_N64_SDRAM].device), .bus(bus.at[sc64::ID_N64_SDRAM].device),
@ -64,9 +73,9 @@ module n64_soc (
.flashram(flashram) .flashram(flashram)
); );
n64_dummy n64_ddregs_inst ( n64_dd n64_dd_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_N64_DDREGS].device) .bus(bus.at[sc64::ID_N64_DD].device)
); );
n64_cfg n64_cfg_inst ( n64_cfg n64_cfg_inst (
@ -76,46 +85,3 @@ module n64_soc (
); );
endmodule endmodule
module n64_dummy (
if_system.sys sys,
if_n64_bus bus
);
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
always_comb begin
bus.rdata = 16'h0000;
if (bus.ack) begin
bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000;
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (sys.reset) begin
state <= S_IDLE;
end else begin
case (state)
S_IDLE: begin
if (bus.request) begin
state <= S_WAIT;
bus.ack <= 1'b1;
end
end
S_WAIT: begin
state <= S_IDLE;
end
endcase
end
end
endmodule

View File

@ -1,40 +0,0 @@
interface if_dd();
logic hard_reset;
logic cmd_request;
logic cmd_ack;
logic [7:0] command;
logic [15:0] status;
logic [15:0] data_input;
logic [15:0] data_output;
logic bm_request;
logic [15:0] bm_control;
logic [15:0] bm_status;
modport n64 (
output hard_reset,
output cmd_request,
input cmd_ack,
output command,
input status,
output data_input,
input data_output,
output bm_request,
output bm_control,
input bm_status
);
modport cpu (
input hard_reset,
input cmd_request,
output cmd_ack,
input command,
output status,
input data_input,
output data_output,
input bm_request,
input bm_control,
output bm_status
);
endinterface

View File

@ -4,7 +4,7 @@ package sc64;
ID_N64_SDRAM, ID_N64_SDRAM,
ID_N64_BOOTLOADER, ID_N64_BOOTLOADER,
ID_N64_FLASHRAM, ID_N64_FLASHRAM,
ID_N64_DDREGS, ID_N64_DD,
ID_N64_CFG, ID_N64_CFG,
__ID_N64_END __ID_N64_END
} e_n64_id; } e_n64_id;
@ -20,6 +20,7 @@ package sc64;
ID_CPU_CFG, ID_CPU_CFG,
ID_CPU_SDRAM, ID_CPU_SDRAM,
ID_CPU_FLASHRAM, ID_CPU_FLASHRAM,
ID_CPU_SI,
__ID_CPU_END __ID_CPU_END
} e_cpu_id; } e_cpu_id;

View File

@ -3,7 +3,7 @@ MEMORY {
ROM (rx) : org = 0x10000000, len = 128 ROM (rx) : org = 0x10000000, len = 128
} }
__stack_pointer = ORIGIN(RAM) + LENGTH(RAM) - 4; __stack_pointer = ORIGIN(RAM) + LENGTH(RAM) - 16;
ENTRY(reset_handler) ENTRY(reset_handler)

View File

@ -1,16 +1,28 @@
#include "sys.h" #include "sys.h"
#include "driver.h" #include "driver.h"
#include "controller.h"
static e_cfg_save_type_t save_type = CFG_SAVE_TYPE_NONE; static e_cfg_save_type_t save_type = CFG_SAVE_TYPE_NONE;
static uint16_t cic_seed = 0xFFFF; static uint16_t cic_seed = 0xFFFF;
static uint8_t tv_type = 0xFF; static uint8_t tv_type = 0xFF;
static bool eeprom_enabled = false;
static bool n64_to_pc_pending = false;
static uint32_t n64_to_pc_address;
static uint32_t n64_to_pc_length;
static bool pc_to_n64_ready = false;
static uint32_t pc_to_n64_arg;
static uint32_t pc_to_n64_address;
static uint32_t pc_to_n64_length;
void process_usb (void); void process_usb (void);
void process_cfg (void); void process_cfg (void);
void process_flashram (void); void process_flashram (void);
void process_si (void);
bool debug_decide (uint32_t *args);
void config_update (uint32_t *args); void config_update (uint32_t *args);
void config_query (uint32_t *args); void config_query (uint32_t *args);
@ -23,6 +35,7 @@ void main (void) {
dma_abort(); dma_abort();
usb_flush_rx(); usb_flush_rx();
usb_flush_tx(); usb_flush_tx();
si_reset();
cfg_set_sdram_switch(true); cfg_set_sdram_switch(true);
cfg_set_save_type(CFG_SAVE_TYPE_NONE); cfg_set_save_type(CFG_SAVE_TYPE_NONE);
@ -33,21 +46,11 @@ void main (void) {
process_usb(); process_usb();
process_cfg(); process_cfg();
process_flashram(); process_flashram();
process_si();
} }
} }
typedef enum {
USB_STATE_IDLE,
USB_STATE_ARGS,
USB_STATE_DATA,
USB_STATE_RESPONSE,
} e_usb_state_t;
#define USB_CMD_TOKEN (0x434D4400)
#define USB_CMP_TOKEN (0x434D5000)
#define USB_ERR_TOKEN (0x45525200)
void process_usb (void) { void process_usb (void) {
static e_usb_state_t state = USB_STATE_IDLE; static e_usb_state_t state = USB_STATE_IDLE;
static uint8_t cmd; static uint8_t cmd;
@ -60,14 +63,20 @@ void process_usb (void) {
case USB_STATE_IDLE: case USB_STATE_IDLE:
if (usb_rx_word(&args[0])) { if (usb_rx_word(&args[0])) {
if ((args[0] & 0xFFFFFF00) == USB_CMD_TOKEN) { if ((args[0] & 0xFFFFFF00) == USB_CMD_TOKEN) {
state = USB_STATE_ARGS;
cmd = args[0] & 0xFF; cmd = args[0] & 0xFF;
error = false; error = false;
processing = false; processing = false;
current_word = 0; current_word = 0;
state = USB_STATE_ARGS;
} else { } else {
state = USB_STATE_RESPONSE; cmd = '!';
error = true; error = true;
state = USB_STATE_RESPONSE;
}
} else if (n64_to_pc_pending) {
if (!dma_busy()) {
dma_start(n64_to_pc_address, n64_to_pc_length, DMA_ID_USB, DMA_DIR_FROM_SDRAM);
state = USB_STATE_N64_TO_PC;
} }
} }
break; break;
@ -112,11 +121,15 @@ void process_usb (void) {
break; break;
case 'D': case 'D':
cfg_set_usb_waiting(true);
pc_to_n64_arg = args[0];
pc_to_n64_length = args[1];
state = USB_STATE_PC_TO_N64;
break; break;
default: default:
state = USB_STATE_RESPONSE;
error = true; error = true;
state = USB_STATE_RESPONSE;
break; break;
} }
break; break;
@ -127,6 +140,28 @@ void process_usb (void) {
} }
break; break;
case USB_STATE_N64_TO_PC:
if (!dma_busy()) {
n64_to_pc_pending = false;
state = USB_STATE_IDLE;
}
break;
case USB_STATE_PC_TO_N64:
if (!dma_busy()) {
if (!processing) {
if (pc_to_n64_ready) {
dma_start(pc_to_n64_address, pc_to_n64_length, DMA_ID_USB, DMA_DIR_TO_SDRAM);
processing = true;
}
} else {
pc_to_n64_ready = false;
processing = false;
state = USB_STATE_IDLE;
}
}
break;
default: default:
state = USB_STATE_IDLE; state = USB_STATE_IDLE;
break; break;
@ -136,6 +171,7 @@ void process_usb (void) {
void process_cfg (void) { void process_cfg (void) {
uint8_t cmd; uint8_t cmd;
uint32_t args[2]; uint32_t args[2];
bool error;
if (cfg_get_command(&cmd, args)) { if (cfg_get_command(&cmd, args)) {
switch (cmd) { switch (cmd) {
@ -150,6 +186,8 @@ void process_cfg (void) {
break; break;
case 'D': case 'D':
error = debug_decide(args);
cfg_set_response(args, error);
break; break;
default: default:
@ -181,15 +219,124 @@ void process_flashram (void) {
} }
} }
void process_si (void) {
uint8_t rx_data[10];
uint8_t tx_data[10];
uint32_t *save_data;
uint32_t *data_offset;
typedef enum { if (si_rx_ready()) {
CONFIG_UPDATE_SDRAM_SWITCH, if (si_rx_stop_bit()) {
CONFIG_UPDATE_SDRAM_WRITABLE, si_rx(rx_data);
CONFIG_UPDATE_DD_ENABLE,
CONFIG_UPDATE_SAVE_TYPE, if (eeprom_enabled) {
CONFIG_UPDATE_CIC_SEED, save_data = (uint32_t *) (SDRAM_BASE + cfg_get_save_offset() + (rx_data[1] * 8));
CONFIG_UPDATE_TV_TYPE
} e_config_update_t; switch (rx_data[0]) {
case SI_CMD_EEPROM_STATUS:
tx_data[0] = 0x00;
tx_data[1] = save_type == CFG_SAVE_TYPE_EEPROM_4K ? SI_EEPROM_ID_4K : SI_EEPROM_ID_16K;
tx_data[2] = 0x00;
si_tx(tx_data, 3);
break;
case SI_CMD_EEPROM_READ:
data_offset = (uint32_t *) (&tx_data[0]);
data_offset[0] = swapb(save_data[0]);
data_offset[1] = swapb(save_data[1]);
si_tx(tx_data, 8);
break;
case SI_CMD_EEPROM_WRITE:
data_offset = (uint32_t *) (&rx_data[2]);
save_data[0] = swapb(data_offset[0]);
save_data[1] = swapb(data_offset[1]);
tx_data[0] = 0x00;
si_tx(tx_data, 1);
break;
}
}
switch (rx_data[0]) {
case SI_CMD_RTC_STATUS:
tx_data[0] = 0x00;
tx_data[1] = 0x10;
tx_data[2] = 0x00;
si_tx(tx_data, 3);
break;
case SI_CMD_RTC_READ:
if (rx_data[1] == 0) {
tx_data[0] = 0x03;
tx_data[1] = 0x00;
tx_data[2] = 0x00;
tx_data[3] = 0x00;
tx_data[4] = 0x00;
tx_data[5] = 0x00;
tx_data[6] = 0x00;
tx_data[7] = 0x00;
} else {
tx_data[0] = 0x00;
tx_data[1] = 0x00;
tx_data[2] = 0x92;
tx_data[3] = 0x06;
tx_data[4] = 0x01;
tx_data[5] = 0x09;
tx_data[6] = 0x21;
tx_data[7] = 0x01;
}
tx_data[8] = 0x00;
si_tx(tx_data, 9);
break;
case SI_CMD_RTC_WRITE:
tx_data[0] = 0x00;
si_tx(tx_data, 1);
break;
}
}
si_rx_reset();
}
}
bool debug_decide (uint32_t *args) {
switch (args[0]) {
case DEBUG_WRITE_ADDRESS:
if (!n64_to_pc_pending) {
n64_to_pc_address = args[1];
} else {
return true;
}
break;
case DEBUG_WRITE_LENGTH_START:
if (!n64_to_pc_pending) {
n64_to_pc_length = args[1];
n64_to_pc_pending = true;
} else {
return true;
}
break;
case DEBUG_WRITE_STATUS:
args[1] = n64_to_pc_pending;
break;
case DEBUG_READ_ARG:
args[1] = pc_to_n64_arg;
break;
case DEBUG_READ_LENGTH:
args[1] = pc_to_n64_length;
break;
case DEBUG_READ_ADDRESS_START:
if (!pc_to_n64_ready) {
pc_to_n64_ready = true;
pc_to_n64_address = args[1];
cfg_set_usb_waiting(false);
} else {
return true;
}
break;
default:
return true;
}
return false;
}
void config_update (uint32_t *args) { void config_update (uint32_t *args) {
switch (args[0]) { switch (args[0]) {
@ -204,6 +351,10 @@ void config_update (uint32_t *args) {
break; break;
case CONFIG_UPDATE_SAVE_TYPE: case CONFIG_UPDATE_SAVE_TYPE:
save_type = args[1] & 0x07; save_type = args[1] & 0x07;
eeprom_enabled = (
save_type == CFG_SAVE_TYPE_EEPROM_4K ||
save_type == CFG_SAVE_TYPE_EEPROM_16K
);
cfg_set_save_type(save_type); cfg_set_save_type(save_type);
break; break;
case CONFIG_UPDATE_CIC_SEED: case CONFIG_UPDATE_CIC_SEED:
@ -215,15 +366,6 @@ void config_update (uint32_t *args) {
} }
} }
typedef enum {
CONFIG_QUERY_STATUS,
CONFIG_QUERY_SAVE_TYPE,
CONFIG_QUERY_CIC_SEED,
CONFIG_QUERY_TV_TYPE,
CONFIG_QUERY_SAVE_OFFSET,
CONFIG_QUERY_DD_OFFSET,
} e_config_query_t;
void config_query (uint32_t *args) { void config_query (uint32_t *args) {
switch (args[0]) { switch (args[0]) {
case CONFIG_QUERY_STATUS: case CONFIG_QUERY_STATUS:

47
sw/riscv/src/controller.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef CONTROLLER_H__
#define CONTROLLER_H__
#define USB_CMD_TOKEN (0x434D4400)
#define USB_CMP_TOKEN (0x434D5000)
#define USB_ERR_TOKEN (0x45525200)
typedef enum {
USB_STATE_IDLE,
USB_STATE_ARGS,
USB_STATE_DATA,
USB_STATE_RESPONSE,
USB_STATE_N64_TO_PC,
USB_STATE_PC_TO_N64,
} e_usb_state_t;
typedef enum {
DEBUG_WRITE_ADDRESS,
DEBUG_WRITE_LENGTH_START,
DEBUG_WRITE_STATUS,
DEBUG_READ_ARG,
DEBUG_READ_LENGTH,
DEBUG_READ_ADDRESS_START,
} e_debug_t;
typedef enum {
CONFIG_UPDATE_SDRAM_SWITCH,
CONFIG_UPDATE_SDRAM_WRITABLE,
CONFIG_UPDATE_DD_ENABLE,
CONFIG_UPDATE_SAVE_TYPE,
CONFIG_UPDATE_CIC_SEED,
CONFIG_UPDATE_TV_TYPE
} e_config_update_t;
typedef enum {
CONFIG_QUERY_STATUS,
CONFIG_QUERY_SAVE_TYPE,
CONFIG_QUERY_CIC_SEED,
CONFIG_QUERY_TV_TYPE,
CONFIG_QUERY_SAVE_OFFSET,
CONFIG_QUERY_DD_OFFSET,
} e_config_query_t;
#endif

View File

@ -255,3 +255,79 @@ void cfg_set_response (uint32_t *args, bool error) {
} }
CFG->SCR &= ~(CFG_SCR_CPU_BUSY); CFG->SCR &= ~(CFG_SCR_CPU_BUSY);
} }
// SI
bool si_rx_ready (void) {
return SI->SCR & SI_SCR_RX_READY;
}
bool si_rx_stop_bit (void) {
return SI->SCR & SI_SCR_RX_STOP_BIT;
}
bool si_tx_busy (void) {
return SI->SCR & SI_SCR_TX_BUSY;
}
void si_rx_reset (void) {
SI->SCR = SI_SCR_RX_RESET;
}
void si_reset (void) {
SI->SCR = SI_SCR_TX_RESET | SI_SCR_RX_RESET;
}
void si_rx (uint8_t *data) {
uint32_t rx_length = (SI->SCR & SI_SCR_RX_LENGTH_MASK) >> SI_SCR_RX_LENGTH_BIT;
for (size_t i = 0; i < rx_length; i++) {
data[i] = ((uint8_t *) SI->DATA)[(10 - rx_length) + i];
}
}
void si_tx (uint8_t *data, size_t length) {
for (size_t i = 0; i < ((length + 3) / 4); i++) {
SI->DATA[i] = ((uint32_t *) data)[i];
}
SI->DATA[length / 4] |= (0x80 << ((length % 4) * 8));
SI->SCR = (((length * 8) + 1) << SI_SCR_TX_LENGTH_BIT) | SI_SCR_TX_START;
}
// misc
const char hex_char_map[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
void print (const char *text) {
while (*text != '\0') {
while (!(UART->SCR & UART_SCR_TXE));
UART->DR = *text++;
}
}
void print_02hex (uint8_t number) {
char buffer[3];
buffer[0] = hex_char_map[(number >> 4) & 0x0F];
buffer[1] = hex_char_map[number & 0x0F];
buffer[2] = '\0';
print(buffer);
}
void print_08hex (uint32_t number) {
print_02hex((number >> 24) & 0xFF);
print_02hex((number >> 16) & 0xFF);
print_02hex((number >> 8) & 0xFF);
print_02hex((number >> 0) & 0xFF);
}
uint32_t swapb (uint32_t data) {
return (
(data << 24) |
((data << 8) & 0x00FF0000) |
((data >> 8) & 0x0000FF00) |
(data >> 24)
);
}

View File

@ -92,4 +92,33 @@ bool cfg_get_command (uint8_t *cmd, uint32_t *args);
void cfg_set_response (uint32_t *args, bool error); void cfg_set_response (uint32_t *args, bool error);
// SI
#define SI_CMD_EEPROM_STATUS (0x00)
#define SI_CMD_EEPROM_READ (0x04)
#define SI_CMD_EEPROM_WRITE (0x05)
#define SI_CMD_RTC_STATUS (0x06)
#define SI_CMD_RTC_READ (0x07)
#define SI_CMD_RTC_WRITE (0x08)
#define SI_EEPROM_ID_4K (0x80)
#define SI_EEPROM_ID_16K (0xC0)
bool si_rx_ready (void);
bool si_rx_stop_bit (void);
bool si_tx_busy (void);
void si_rx_reset (void);
void si_reset (void);
void si_rx (uint8_t *data);
void si_tx (uint8_t *data, size_t length);
// misc
void print (const char *text);
void print_02hex (uint8_t number);
void print_08hex (uint32_t number);
uint32_t swapb (uint32_t data);
#endif #endif

View File

@ -137,4 +137,23 @@ typedef volatile struct flashram_regs {
#define FLASHRAM_PAGE_BIT (8) #define FLASHRAM_PAGE_BIT (8)
typedef volatile struct si_regs {
io32_t SCR;
io32_t DATA[3];
} si_regs_t;
#define SI_BASE (0xA0000000UL)
#define SI ((si_regs_t *) SI_BASE)
#define SI_SCR_RX_READY (1 << 0)
#define SI_SCR_RX_STOP_BIT (1 << 1)
#define SI_SCR_TX_START (1 << 2)
#define SI_SCR_TX_BUSY (1 << 3)
#define SI_SCR_RX_RESET (1 << 6)
#define SI_SCR_TX_RESET (1 << 7)
#define SI_SCR_RX_LENGTH_BIT (8)
#define SI_SCR_RX_LENGTH_MASK (0x7F << SI_SCR_RX_LENGTH_BIT)
#define SI_SCR_TX_LENGTH_BIT (16)
#endif #endif