dd working

This commit is contained in:
Polprzewodnikowy 2021-12-15 21:23:40 +01:00
parent 71f134178a
commit b7b1d1990a
18 changed files with 1147 additions and 63 deletions

View File

@ -54,6 +54,7 @@ set_global_assignment -name SDC_FILE SummerCart64.sdc
set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dd.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv

View File

@ -46,6 +46,8 @@ module SummerCart64 (
logic [7:0] gpio_i;
logic [7:0] gpio_oe;
logic dd_interrupt;
if_system sys (
.in_clk(i_clk),
.n64_reset(i_n64_reset),
@ -64,6 +66,10 @@ module SummerCart64 (
if_flash flash ();
if_dd dd (
.dd_interrupt(dd_interrupt)
);
system system_inst (
.sys(sys)
);
@ -82,6 +88,7 @@ module SummerCart64 (
.flashram(flashram),
.si(si),
.flash(flash),
.dd(dd),
.n64_pi_alel(i_n64_pi_alel),
.n64_pi_aleh(i_n64_pi_aleh),
@ -109,6 +116,7 @@ module SummerCart64 (
.flashram(flashram),
.si(si),
.flash(flash),
.dd(dd),
.gpio_o(gpio_o),
.gpio_i(gpio_i),
@ -131,9 +139,12 @@ module SummerCart64 (
.sd_dat(io_sd_dat)
);
always_comb begin
o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ;
end
always_comb begin
o_led = gpio_oe[0] ? gpio_o[0] : 1'bZ;
o_n64_irq = gpio_oe[1] ? gpio_o[1] : 1'bZ;
end
always_ff @(posedge sys.clk) begin

124
fw/rtl/cpu/cpu_dd.sv Normal file
View File

@ -0,0 +1,124 @@
module cpu_dd (
if_system.sys sys,
if_cpu_bus bus,
if_dd.cpu dd
);
const bit [8:0] M_SECTOR_BUFFER = 9'h100;
logic bm_ack;
typedef enum bit [2:0] {
R_SCR,
R_CMD_DATA,
R_HEAD_TRACK,
R_SECTOR_INFO,
R_DRIVE_ID
} e_reg_id;
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
if (bus.address[8] == M_SECTOR_BUFFER[8]) begin
bus.rdata = dd.sector_rdata;
end else begin
case (bus.address[5:2])
R_SCR: bus.rdata = {
14'd0,
bm_ack,
dd.bm_micro_error,
dd.bm_transfer_c2,
dd.bm_transfer_data,
dd.bm_transfer_blocks,
dd.bm_transfer_mode,
1'b0,
dd.bm_stop_pending,
1'b0,
dd.bm_start_pending,
dd.disk_changed,
dd.disk_inserted,
1'b0,
dd.bm_pending,
1'b0,
dd.cmd_pending,
1'b0,
dd.hard_reset
};
R_CMD_DATA: bus.rdata = {8'd0, dd.cmd, dd.data};
R_HEAD_TRACK: bus.rdata = {18'd0, dd.index_lock, dd.head_track};
R_SECTOR_INFO: bus.rdata = {
dd.sectors_in_block,
dd.sector_size_full,
dd.sector_size,
dd.sector_num
};
R_DRIVE_ID: bus.rdata = {dd.drive_id};
default: bus.rdata = 32'd0;
endcase
end
end
end
always_comb begin
dd.sector_address = bus.address[7:2];
dd.sector_address_valid = bus.request && bus.address[8] == M_SECTOR_BUFFER[8];
dd.sector_write = (&bus.wmask) && dd.sector_address_valid;
dd.sector_wdata = {bus.wdata[7:0], bus.wdata[15:8], bus.wdata[23:16], bus.wdata[31:24]};
end
always_ff @(posedge sys.clk) begin
dd.hard_reset_clear <= 1'b0;
dd.cmd_ready <= 1'b0;
dd.bm_ready <= 1'b0;
dd.bm_start_clear <= 1'b0;
dd.bm_stop_clear <= 1'b0;
if (dd.bm_interrupt_ack) begin
bm_ack <= 1'b1;
end
if (sys.reset) begin
bm_ack <= 1'b0;
end else begin
if (bus.request && (!bus.address[8])) begin
case (bus.address[4:2])
R_SCR: if (&bus.wmask) begin
if (bus.wdata[18]) begin
bm_ack <= 1'b0;
end
dd.bm_micro_error <= bus.wdata[16];
dd.bm_transfer_c2 <= bus.wdata[15];
dd.bm_transfer_data <= bus.wdata[14];
dd.bm_stop_clear <= bus.wdata[11];
dd.bm_start_clear <= bus.wdata[9];
dd.disk_changed <= bus.wdata[7];
dd.disk_inserted <= bus.wdata[6];
dd.bm_ready <= bus.wdata[5];
dd.cmd_ready <= bus.wdata[3];
dd.hard_reset_clear <= bus.wdata[1];
end
R_CMD_DATA: if (&bus.wmask[1:0]) begin
dd.cmd_data <= bus.wdata[15:0];
end
R_HEAD_TRACK: if (&bus.wmask[1:0]) begin
{dd.index_lock, dd.head_track} <= bus.wdata[13:0];
end
R_DRIVE_ID: if (&bus.wmask[0]) begin
dd.drive_id <= bus.wdata[2:0];
end
endcase
end
end
end
endmodule

View File

@ -6,6 +6,7 @@ module cpu_soc (
if_flashram.cpu flashram,
if_si.cpu si,
if_flash.cpu flash,
if_dd.cpu dd,
input [7:0] gpio_i,
output [7:0] gpio_o,
@ -113,6 +114,12 @@ module cpu_soc (
.si(si)
);
cpu_dd cpu_dd_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_DD].device),
.dd(dd)
);
assign sd_clk = 1'bZ;
assign sd_cmd = 1'bZ;
assign sd_dat = 4'bZZZZ;

View File

@ -9,6 +9,9 @@ interface if_n64_bus ();
logic [31:0] address;
logic [15:0] wdata;
logic [15:0] rdata;
logic [31:0] real_address;
logic read_op;
logic write_op;
logic device_ack [(NUM_DEVICES - 1):0];
logic [15:0] device_rdata [(NUM_DEVICES - 1):0];
@ -30,7 +33,11 @@ interface if_n64_bus ();
output write,
output address,
output wdata,
input rdata
input rdata,
output real_address,
output read_op,
output write_op
);
genvar n;
@ -48,7 +55,11 @@ interface if_n64_bus ();
input .write(write),
input .address(address),
input .wdata(wdata),
output .rdata(device_rdata[n])
output .rdata(device_rdata[n]),
input .real_address(real_address),
input .read_op(read_op),
input .write_op(write_op)
);
end
endgenerate

View File

@ -1,40 +1,154 @@
interface if_dd();
interface if_dd (
output dd_interrupt
);
// Sector buffer regs
logic [6:0] n64_sector_address;
logic n64_sector_address_valid;
logic n64_sector_write;
logic [15:0] n64_sector_wdata;
logic [5:0] cpu_sector_address;
logic cpu_sector_address_valid;
logic cpu_sector_write;
logic [31:0] cpu_sector_wdata;
logic [31:0] sector_rdata;
// N64 controlled regs
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;
logic [15:0] data;
logic [7:0] cmd;
logic cmd_pending;
logic cmd_interrupt;
logic bm_start_pending;
logic bm_stop_pending;
logic bm_transfer_mode;
logic bm_transfer_blocks;
logic bm_pending;
logic bm_interrupt;
logic bm_interrupt_ack;
logic [7:0] sector_num;
logic [7:0] sector_size;
logic [7:0] sector_size_full;
logic [7:0] sectors_in_block;
modport n64 (
// CPU controlled regs
logic hard_reset_clear;
logic [15:0] cmd_data;
logic cmd_ready;
logic bm_start_clear;
logic bm_stop_clear;
logic bm_transfer_c2;
logic bm_transfer_data;
logic bm_micro_error;
logic bm_ready;
logic disk_inserted;
logic disk_changed;
logic index_lock;
logic [12:0] head_track;
logic [2:0] drive_id;
always_comb begin
dd_interrupt = cmd_interrupt || bm_interrupt;
end
modport dd (
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
output data,
output cmd,
output cmd_pending,
output cmd_interrupt,
output bm_start_pending,
output bm_stop_pending,
output bm_transfer_mode,
output bm_transfer_blocks,
output bm_pending,
output bm_interrupt,
output bm_interrupt_ack,
output sector_num,
output sector_size,
output sector_size_full,
output sectors_in_block,
input hard_reset_clear,
input cmd_data,
input cmd_ready,
input bm_start_clear,
input bm_stop_clear,
input bm_transfer_c2,
input bm_transfer_data,
input bm_micro_error,
input bm_ready,
input disk_inserted,
input disk_changed,
input index_lock,
input head_track,
input drive_id,
output .sector_address(n64_sector_address),
output .sector_address_valid(n64_sector_address_valid),
output .sector_write(n64_sector_write),
output .sector_wdata(n64_sector_wdata),
input sector_rdata
);
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
input data,
input cmd,
input cmd_pending,
input bm_start_pending,
input bm_stop_pending,
input bm_transfer_mode,
input bm_transfer_blocks,
input bm_pending,
input bm_interrupt_ack,
input sector_num,
input sector_size,
input sector_size_full,
input sectors_in_block,
output hard_reset_clear,
output cmd_data,
output cmd_ready,
output bm_start_clear,
output bm_stop_clear,
output bm_transfer_c2,
output bm_transfer_data,
output bm_micro_error,
output bm_ready,
output disk_inserted,
output disk_changed,
output index_lock,
output head_track,
output drive_id,
output .sector_address(cpu_sector_address),
output .sector_address_valid(cpu_sector_address_valid),
output .sector_write(cpu_sector_write),
output .sector_wdata(cpu_sector_wdata),
input sector_rdata
);
modport sector_buffer (
input n64_sector_address,
input n64_sector_address_valid,
input n64_sector_write,
input n64_sector_wdata,
input cpu_sector_address,
input cpu_sector_address_valid,
input cpu_sector_write,
input cpu_sector_wdata,
output sector_rdata
);
endinterface
@ -42,9 +156,33 @@ endinterface
module n64_dd (
if_system.sys sys,
if_n64_bus bus
if_n64_bus bus,
if_dd.dd dd
);
const bit [31:0] M_BASE = 32'h0500_0000;
const bit [31:0] M_C2_BUFFER = M_BASE + 11'h000;
const bit [31:0] M_SECTOR_BUFFER = M_BASE + 11'h400;
typedef enum bit [10:0] {
R_DATA = 11'h500,
R_CMD_SR = 11'h508,
R_TRK_CUR = 11'h50C,
R_BM_SCR = 11'h510,
R_RESET = 11'h520,
R_SEC_SIZ = 11'h528,
R_SEC_INFO = 11'h530,
R_ID = 11'h540
} e_reg_id;
typedef enum bit [3:0] {
BM_CONTROL_START_BUFFER_MANAGER = 4'd15,
BM_CONTROL_BUFFER_MANAGER_MODE = 4'd14,
BM_CONTROL_BUFFER_MANAGER_RESET = 4'd12,
BM_CONTROL_BLOCK_TRANSFER = 4'd9,
BM_CONTROL_MECHANIC_INTERRUPT_RESET = 4'd8
} e_bm_control_id;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
@ -53,23 +191,153 @@ module n64_dd (
e_state state;
always_comb begin
bus.rdata = 16'h0000;
dd.sector_address = bus.address[7:1];
dd.sector_address_valid = bus.request && bus.address[11:8] == M_SECTOR_BUFFER[11:8];
dd.sector_write = bus.write && dd.sector_address_valid;
dd.sector_wdata = bus.wdata;
end
always_comb begin
bus.rdata = 16'd0;
if (bus.ack) begin
bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000;
if (bus.address[10:8] == M_SECTOR_BUFFER[10:8]) begin
if (bus.address[1]) begin
bus.rdata = dd.sector_rdata[15:0];
end else begin
bus.rdata = dd.sector_rdata[31:16];
end
end else begin
case (bus.address[10:0])
R_DATA: bus.rdata = dd.data;
R_CMD_SR: bus.rdata = {
1'b0,
dd.bm_transfer_data,
1'b0,
dd.bm_transfer_c2,
1'b0,
dd.bm_interrupt,
dd.cmd_interrupt,
dd.disk_inserted,
dd.cmd_pending,
dd.hard_reset,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
dd.disk_changed
};
R_TRK_CUR: bus.rdata = {1'd0, {2{dd.index_lock}}, dd.head_track};
R_BM_SCR: bus.rdata = {6'd0, dd.bm_micro_error, 9'd0};
R_ID: bus.rdata = {13'd0, dd.drive_id};
default: bus.rdata = 16'd0;
endcase
end
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
dd.bm_interrupt_ack <= 1'b0;
if (dd.hard_reset_clear) begin
dd.hard_reset <= 1'b0;
end
if (dd.cmd_ready) begin
dd.data <= dd.cmd_data;
dd.cmd_pending <= 1'b0;
dd.cmd_interrupt <= 1'b1;
end
if (dd.bm_start_clear) begin
dd.bm_start_pending <= 1'b0;
end
if (dd.bm_stop_clear) begin
dd.bm_stop_pending <= 1'b0;
end
if (dd.bm_ready) begin
dd.bm_pending <= 1'b0;
dd.bm_interrupt <= 1'b1;
end
if (bus.real_address == (M_C2_BUFFER + ({dd.sector_size[7:1], 1'b0} * 3'd4)) && bus.read_op) begin
dd.bm_pending <= 1'b1;
end
if (bus.real_address == (M_SECTOR_BUFFER + {dd.sector_size[7:1], 1'b0}) && (bus.read_op || bus.write_op)) begin
dd.bm_pending <= 1'b1;
end
if (bus.real_address == (M_BASE + R_CMD_SR) && bus.read_op) begin
dd.bm_interrupt <= 1'b0;
dd.bm_interrupt_ack <= 1'b1;
end
if (sys.reset) begin
dd.hard_reset <= 1'b1;
dd.cmd_pending <= 1'b0;
dd.cmd_interrupt <= 1'b0;
dd.bm_start_pending <= 1'b0;
dd.bm_stop_pending <= 1'b0;
dd.bm_pending <= 1'b0;
dd.bm_interrupt <= 1'b0;
state <= S_IDLE;
end else begin
end else begin
case (state)
S_IDLE: begin
if (bus.request) begin
state <= S_WAIT;
bus.ack <= 1'b1;
if (bus.write) begin
case (bus.address[10:0])
R_DATA: begin
dd.data <= bus.wdata;
end
R_CMD_SR: begin
dd.cmd <= bus.wdata[7:0];
dd.cmd_pending <= 1'b1;
end
R_BM_SCR: begin
dd.sector_num <= bus.wdata[7:0];
if (bus.wdata[BM_CONTROL_START_BUFFER_MANAGER]) begin
dd.bm_start_pending <= 1'b1;
dd.bm_stop_pending <= 1'b0;
dd.bm_transfer_mode <= bus.wdata[BM_CONTROL_BUFFER_MANAGER_MODE];
dd.bm_transfer_blocks <= bus.wdata[BM_CONTROL_BLOCK_TRANSFER];
end
if (bus.wdata[BM_CONTROL_BUFFER_MANAGER_RESET]) begin
dd.bm_start_pending <= 1'b0;
dd.bm_stop_pending <= 1'b1;
dd.bm_transfer_mode <= 1'b0;
dd.bm_transfer_blocks <= 1'b0;
dd.bm_pending <= 1'b0;
dd.bm_interrupt <= 1'b0;
end
if (bus.wdata[BM_CONTROL_MECHANIC_INTERRUPT_RESET]) begin
dd.cmd_interrupt <= 1'b0;
end
end
R_RESET: begin
if (bus.wdata == 16'hAAAA) begin
dd.hard_reset <= 1'b1;
dd.cmd_pending <= 1'b0;
dd.cmd_interrupt <= 1'b0;
dd.bm_start_pending <= 1'b0;
dd.bm_stop_pending <= 1'b0;
dd.bm_pending <= 1'b0;
dd.bm_interrupt <= 1'b0;
end
end
R_SEC_SIZ: begin
dd.sector_size <= bus.wdata[7:0];
end
R_SEC_INFO: begin
dd.sectors_in_block <= bus.wdata[15:8];
dd.sector_size_full <= bus.wdata[7:0];
end
endcase
end
end
end
@ -81,3 +349,50 @@ module n64_dd (
end
endmodule
module n64_dd_sector_buffer (
if_system.sys sys,
if_dd.sector_buffer dd
);
logic [5:0] sector_address;
logic [31:0] sector_buffer [0:63];
logic [15:0] sector_high_buffer;
logic sector_write;
logic [31:0] sector_wdata;
always_comb begin
sector_address = 6'd0;
sector_write = 1'b0;
sector_wdata = 32'd0;
if (dd.n64_sector_address_valid) begin
sector_address = dd.n64_sector_address[6:1];
end else if (dd.cpu_sector_address_valid) begin
sector_address = dd.cpu_sector_address;
end
if (dd.n64_sector_write && dd.n64_sector_address[0]) begin
sector_write = 1'b1;
sector_wdata = {sector_high_buffer, dd.n64_sector_wdata};
end else if (dd.cpu_sector_write) begin
sector_write = 1'b1;
sector_wdata = dd.cpu_sector_wdata;
end
end
always_ff @(posedge sys.clk) begin
if (dd.n64_sector_write && !dd.n64_sector_address[0]) begin
sector_high_buffer <= dd.n64_sector_wdata;
end
end
always_ff @(posedge sys.clk) begin
dd.sector_rdata <= sector_buffer[sector_address];
if (sector_write) begin
sector_buffer[sector_address] <= sector_wdata;
end
end
endmodule

View File

@ -190,6 +190,23 @@ module n64_pi (
end
end
always_comb begin
bus.read_op = read_op;
bus.write_op = write_op;
end
always_ff @(posedge sys.clk) begin
if (aleh_op) begin
bus.real_address[31:16] <= n64_pi_ad_input;
end
if (alel_op) begin
bus.real_address[15:0] <= {n64_pi_ad_input[15:1], 1'b0};
end
if (read_op || write_op) begin
bus.real_address <= bus.real_address + 2'd2;
end
end
// Address decoding
@ -253,6 +270,11 @@ module n64_pi (
end
end
if (alel_op) begin
if (next_id == sc64::ID_N64_DD) begin
if (|n64_pi_ad_input[15:11]) begin
n64_pi_address_valid <= 1'b0;
end
end
if (sram_selected) begin
if (n64_pi_ad_input[15]) begin
n64_pi_address_valid <= 1'b0;

View File

@ -6,6 +6,7 @@ module n64_soc (
if_flashram.flashram flashram,
if_si.si si,
if_flash.memory flash,
if_dd dd,
input n64_pi_alel,
input n64_pi_aleh,
@ -77,7 +78,13 @@ module n64_soc (
n64_dd n64_dd_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_DD].device)
.bus(bus.at[sc64::ID_N64_DD].device),
.dd(dd)
);
n64_dd_sector_buffer n64_dd_sector_buffer_inst (
.sys(sys),
.dd(dd)
);
n64_cfg n64_cfg_inst (

View File

@ -21,6 +21,7 @@ package sc64;
ID_CPU_SDRAM,
ID_CPU_FLASHRAM,
ID_CPU_SI,
ID_CPU_DD,
__ID_CPU_END
} e_cpu_id;

View File

@ -14,13 +14,13 @@ typedef struct {
} ipl3_crc32_t;
static const ipl3_crc32_t ipl3_crc32[] = {
{ .crc32 = 0x587BD543, .seed = 0xAC, .version = 0 }, // CIC5101
{ .crc32 = 0x6170A4A1, .seed = 0x3F, .version = 1 }, // CIC6101
{ .crc32 = 0x009E9EA3, .seed = 0x3F, .version = 1 }, // CIC7102
{ .crc32 = 0x90BB6CB5, .seed = 0x3F, .version = 0 }, // CICx102
{ .crc32 = 0x0B050EE0, .seed = 0x78, .version = 0 }, // CICx103
{ .crc32 = 0x98BC2C86, .seed = 0x91, .version = 0 }, // CICx105
{ .crc32 = 0xACC8580A, .seed = 0x85, .version = 0 }, // CICx106
{ .crc32 = 0x587BD543, .seed = 0xAC, .version = 0 }, // 5101
{ .crc32 = 0x6170A4A1, .seed = 0x3F, .version = 1 }, // 6101
{ .crc32 = 0x009E9EA3, .seed = 0x3F, .version = 1 }, // 7102
{ .crc32 = 0x90BB6CB5, .seed = 0x3F, .version = 0 }, // x102
{ .crc32 = 0x0B050EE0, .seed = 0x78, .version = 0 }, // x103
{ .crc32 = 0x98BC2C86, .seed = 0x91, .version = 0 }, // x105
{ .crc32 = 0xACC8580A, .seed = 0x85, .version = 0 }, // x106
{ .crc32 = 0x10C68B18, .seed = 0xDD, .version = 0 }, // NDXJ0
{ .crc32 = 0xBC605D0A, .seed = 0xDD, .version = 0 }, // NDDJ0
{ .crc32 = 0x502C4466, .seed = 0xDD, .version = 0 }, // NDDJ1
@ -43,26 +43,13 @@ bool boot_get_tv_type (boot_info_t *info) {
char region = ((pi_io_read(&base[15]) >> 8) & 0xFF);
switch (region) {
case 'D':
case 'F':
case 'H':
case 'I':
case 'P':
case 'S':
case 'W':
case 'X':
case 'Y':
case 'U':
info->tv_type = BOOT_TV_TYPE_PAL;
break;
case '7':
case 'A':
case 'C':
case 'E':
case 'J':
case 'K':
case 'N':
case 'U':
info->tv_type = BOOT_TV_TYPE_NTSC;
break;

View File

@ -46,6 +46,7 @@ class SC64:
__DEBUG_ID_FSD_READ = 0xF1
__DEBUG_ID_FSD_WRITE = 0xF2
__DEBUG_ID_FSD_SECTOR = 0xF3
__DEBUG_ID_DD_BLOCK = 0xF5
def __init__(self) -> None:
@ -54,6 +55,7 @@ class SC64:
self.__progress_value = None
self.__progress_finish = None
self.__fsd_file = None
self.__disk_file = None
self.__find_sc64()
@ -379,7 +381,77 @@ class SC64:
self.__fsd_file.write(data)
def debug_loop(self, file: str = None) -> None:
def __dd_track_offset(self, head_track: int) -> int:
head = (head_track & 0x1000) >> 9
track = head_track & 0xFFF
dd_zone = 0
tr_off = 0
if (track >= 0x425):
dd_zone = 7 + head
tr_off = track - 0x425
elif (track >= 0x390):
dd_zone = 6 + head
tr_off = track - 0x390
elif (track >= 0x2FB):
dd_zone = 5 + head
tr_off = track - 0x2FB
elif (track >= 0x266):
dd_zone = 4 + head
tr_off = track - 0x266
elif (track >= 0x1D1):
dd_zone = 3 + head
tr_off = track - 0x1D1
elif (track >= 0x13C):
dd_zone = 2 + head
tr_off = track - 0x13C
elif (track >= 0x9E):
dd_zone = 1 + head
tr_off = track - 0x9E
else:
dd_zone = 0 + head
tr_off = track
ddStartOffset = [0x0,0x5F15E0,0xB79D00,0x10801A0,0x1523720,0x1963D80,0x1D414C0,0x20BBCE0,
0x23196E0,0x28A1E00,0x2DF5DC0,0x3299340,0x36D99A0,0x3AB70E0,0x3E31900,0x4149200]
ddZoneSecSize = [232,216,208,192,176,160,144,128,
216,208,192,176,160,144,128,112]
return (dd_zone, ddStartOffset[dd_zone] + tr_off * ddZoneSecSize[dd_zone] * 85 * 2)
# def __dd_zone_track_size(self, i) -> int:
# # ddZoneTrackSize = [158,158,149,149,149,149,149,114,158,158,149,149,149,149,149,114]
# ddZoneSecSize = [232,216,208,192,176,160,144,128,
# 216,208,192,176,160,144,128,112]
# return ddZoneSecSize[i]
def __debug_process_dd_block(self, data: bytes) -> None:
# scr = int.from_bytes(data[0:4], byteorder='big')
current_sector = int.from_bytes(data[4:8], byteorder='little')
head_track = int.from_bytes(data[8:12], byteorder='little')
sector_num = int.from_bytes(data[12:16], byteorder='little')
sector_size = int.from_bytes(data[16:20], byteorder='little')
# sector_size_full = int.from_bytes(data[20:24], byteorder='little')
# sectors_in_block = int.from_bytes(data[24:28], byteorder='little')
# print(f"info: {hex(scr)}, {current_sector}, {head_track}, {sector_num}, {sector_size}, {sector_size_full}, {sectors_in_block}")
if (self.__disk_file):
(zone, track_offset) = self.__dd_track_offset(head_track)
sector = 0
sector += track_offset
sector += (int(sector_num / 90) * 85 * (sector_size + 1)) # self.__dd_zone_track_size(zone)
sector += ((current_sector) * (sector_size + 1))
self.__disk_file.seek(sector)
data_dd = self.__disk_file.read(0x100 * 85)
if (current_sector == 0x00 or current_sector == 0x5A):
print(f"getting sect {hex(sector)}, {hex(int.from_bytes(data_dd[0:4], byteorder='big'))}")
self.__debug_write(self.__DEBUG_ID_DD_BLOCK, data_dd)
else:
self.__debug_write(self.__DEBUG_ID_DD_BLOCK, bytes(0x100))
def debug_loop(self, file: str = None, disk_file: str = None) -> None:
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
self.__serial.timeout = 0.01
@ -388,6 +460,9 @@ class SC64:
if (file):
self.__fsd_file = open(file, "rb+")
if (disk_file):
self.__disk_file = open(disk_file, "rb+")
start_indicator = bytearray()
dropped_bytes = 0
@ -418,6 +493,8 @@ class SC64:
self.__debug_process_fsd_write(data)
elif (id == self.__DEBUG_ID_FSD_SECTOR):
self.__debug_process_fsd_set_sector(data)
elif (id == self.__DEBUG_ID_DD_BLOCK):
self.__debug_process_dd_block(data)
else:
print(f"\033[35mGot unknown id: {id}, length: {length}\033[0m", file=sys.stderr)
@ -499,6 +576,7 @@ if __name__ == "__main__":
parser.add_argument("-i", metavar="ddipl_path", default=None, required=False, help="path to DDIPL file")
parser.add_argument("-q", default=None, action="store_true", required=False, help="start debug server")
parser.add_argument("-f", metavar="sd_path", default=None, required=False, help="path to disk or file for fake SD card emulation")
parser.add_argument("-k", metavar="disk_path", default=None, required=False, help="path to 64DD disk file")
parser.add_argument("rom", metavar="rom_path", default=None, help="path to ROM file", nargs="?")
if (len(sys.argv) <= 1):
@ -523,6 +601,7 @@ if __name__ == "__main__":
rom_file = args.rom
debug_server = args.q
sd_file = args.f
disk_file = args.k
firmware_backup_file = "sc64firmware.bin.bak"
@ -582,7 +661,7 @@ if __name__ == "__main__":
sc64.upload_save(save_file)
if (debug_server):
sc64.debug_loop(sd_file)
sc64.debug_loop(sd_file, disk_file)
except SC64Exception as e:
print(f"Error: {e}")

View File

@ -12,7 +12,7 @@ LDFLAGS = -nostartfiles -Wl,--gc-sections
SRC_DIR = src
BUILD_DIR = build
SRC_FILES = startup.S process.c usb.c cfg.c dma.c joybus.c rtc.c i2c.c flashram.c uart.c flash.c
SRC_FILES = startup.S process.c usb.c cfg.c dma.c joybus.c rtc.c i2c.c flashram.c uart.c flash.c dd.c
SRCS = $(addprefix $(SRC_DIR)/, $(SRC_FILES))
OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(patsubst %,%.o,$(SRCS))))

View File

@ -159,7 +159,7 @@ void cfg_update (uint32_t *args) {
case CFG_ID_RECONFIGURE:
if (args[1] == CFG->RECONFIGURE) {
CFG->RECONFIGURE = args[1];
__asm__ volatile (
asm volatile (
"ebreak \n"
);
}

459
sw/riscv/src/dd.c Normal file
View File

@ -0,0 +1,459 @@
#include "dd.h"
#include "uart.h"
#include "rtc.h"
#include "usb.h"
#define DD_DRIVE_ID_RETAIL (0x03)
#define DD_VERSION_RETAIL (0x0114)
typedef enum {
DD_CMD_SEEK_READ = 0x01,
DD_CMD_SEEK_WRITE = 0x02,
DD_CMD_CLEAR_DISK_CHANGE = 0x08,
DD_CMD_CLEAR_RESET_STATE = 0x09,
DD_CMD_READ_VERSION = 0x0A,
DD_CMD_SET_DISK_TYPE = 0x0B,
DD_CMD_REQUEST_STATUS = 0x0C,
DD_CMD_SET_RTC_YEAR_MONTH = 0x0F,
DD_CMD_SET_RTC_DAY_HOUR = 0x10,
DD_CMD_SET_RTC_MINUTE_SECOND = 0x11,
DD_CMD_GET_RTC_YEAR_MONTH = 0x12,
DD_CMD_GET_RTC_DAY_HOUR = 0x13,
DD_CMD_GET_RTC_MINUTE_SECOND = 0x14,
DD_CMD_READ_PROGRAM_VERSION = 0x1B,
} dd_cmd_t;
static rtc_time_t time;
static uint8_t current_sector;
static bool continued_transfer;
static void log_bm_op (uint32_t scr) {
if (scr & DD_SCR_BM_STOP) {
uart_print("Got BM stop [0x");
uart_print_02hex(current_sector); uart_print("]\r\n");
}
if (scr & DD_SCR_BM_START) {
uart_print("Got BM start [0x");
// uart_print_02hex((DD->HEAD_TRACK >> 8) & 0xFF);
// uart_print_02hex((DD->HEAD_TRACK >> 0) & 0xFF); uart_print(", ");
// uart_print_02hex(DD->SECTOR_NUM); uart_print(", ");
// uart_print_02hex(DD->SECTOR_SIZE); uart_print(", ");
// uart_print_02hex(DD->SECTOR_SIZE_FULL); uart_print(", ");
// uart_print_02hex(DD->SECTORS_IN_BLOCK); uart_print("]\r\n");
// uart_print("DD Info [0x");
uart_print_08hex(DD->SCR); uart_print(", ");
uart_print_02hex((DD->DATA >> 8) & 0xFF);
uart_print_02hex((DD->DATA >> 0) & 0xFF); uart_print(", ");
uart_print_02hex(DD->CMD); uart_print(", ");
uart_print_02hex((DD->HEAD_TRACK >> 8) & 0xFF);
uart_print_02hex((DD->HEAD_TRACK >> 0) & 0xFF); uart_print(", ");
uart_print_02hex(DD->SECTOR_NUM); uart_print(", ");
uart_print_02hex(DD->SECTOR_SIZE); uart_print(", ");
uart_print_02hex(DD->SECTOR_SIZE_FULL); uart_print(", ");
uart_print_02hex(DD->SECTORS_IN_BLOCK); uart_print(", ");
uart_print_02hex(DD->DRIVE_ID); uart_print("]\r\n");
// uart_print("Requesting data sector [0x00]\r\n");
}
if (scr & DD_SCR_BM_PENDING) {
if (current_sector < 85) {
// uart_print("Requesting data sector [0x");
// uart_print_02hex(current_sector); uart_print("]\r\n");
} else if (current_sector < 85 + 4) {
uart_print("Read C2 sector [0x");
uart_print_02hex(current_sector); uart_print("]\r\n");
} else if (current_sector == 85 + 4 - 1) {
uart_print("Gap sector??\r\n");
} else {
uart_print("Unknown BM pending [0x");
uart_print_02hex(current_sector); uart_print("]\r\n");
}
}
}
enum state {
STATE_IDLE,
STATE_START,
STATE_FETCH,
STATE_WAIT,
STATE_WAIT_2,
STATE_TRANSFER,
STATE_STOP,
};
static enum state state;
void dd_init (void) {
DD->SCR &= DD_SCR_DISK_INSERTED;
DD->HEAD_TRACK = 0;
DD->DRIVE_ID = DD_DRIVE_ID_RETAIL;
state = STATE_IDLE;
}
void process_dd (void) {
uint32_t scr = DD->SCR;
if (scr & DD_SCR_HARD_RESET) {
dd_init();
}
if (scr & DD_SCR_CMD_PENDING) {
dd_cmd_t cmd = (dd_cmd_t) (DD->CMD);
uint16_t data = DD->DATA;
if (cmd < DD_CMD_GET_RTC_YEAR_MONTH || cmd > DD_CMD_GET_RTC_MINUTE_SECOND) {
uart_print("Got DD command: [0x");
uart_print_02hex(cmd); uart_print("], data: [0x");
uart_print_02hex((data >> 8) & 0xFF); uart_print_02hex((data >> 0) & 0xFF); uart_print("]\r\n");
}
switch (cmd) {
case DD_CMD_SEEK_READ:
DD->HEAD_TRACK = DD_HEAD_TRACK_INDEX_LOCK | data;
break;
case DD_CMD_SEEK_WRITE:
DD->HEAD_TRACK = DD_HEAD_TRACK_INDEX_LOCK | data;
break;
case DD_CMD_CLEAR_DISK_CHANGE:
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
break;
case DD_CMD_CLEAR_RESET_STATE:
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
DD->SCR |= DD_SCR_HARD_RESET_CLEAR;
break;
case DD_CMD_READ_VERSION:
DD->DATA = DD_VERSION_RETAIL;
break;
case DD_CMD_SET_DISK_TYPE:
// TODO
break;
case DD_CMD_REQUEST_STATUS:
DD->DATA = 0;
break;
case DD_CMD_SET_RTC_YEAR_MONTH:
time.year = ((data >> 8) & 0xFF);
time.month = (data & 0xFF);
break;
case DD_CMD_SET_RTC_DAY_HOUR:
time.day = ((data >> 8) & 0xFF);
time.hour = (data & 0xFF);
break;
case DD_CMD_SET_RTC_MINUTE_SECOND:
time.minute = ((data >> 8) & 0xFF);
time.second = (data & 0xFF);
rtc_set_time(&time);
break;
case DD_CMD_GET_RTC_YEAR_MONTH:
DD->DATA = (time.year << 8) | time.month;
break;
case DD_CMD_GET_RTC_DAY_HOUR:
DD->DATA = (time.day << 8) | time.hour;
break;
case DD_CMD_GET_RTC_MINUTE_SECOND:
time = *rtc_get_time();
DD->DATA = (time.minute << 8) | time.second;
break;
case DD_CMD_READ_PROGRAM_VERSION:
DD->DATA = 0;
break;
}
DD->SCR |= DD_SCR_CMD_READY;
}
// log_bm_op (scr);
uint16_t track = (DD->HEAD_TRACK & DD_HEAD_TRACK_MASK);
uint8_t starting_sector = DD->SECTOR_NUM;
bool forbidden_block = (track == 6) && (starting_sector == 0);
if (scr & DD_SCR_BM_ACK) {
DD->SCR |= DD_SCR_BM_ACK_CLEAR;
if (current_sector <= 85) {
// if (state == STATE_TRANSFER) {
// state = STATE_FETCH;
// current_sector += 1;
// }
} else if (current_sector < 85 + 3) {
// for (volatile int i = 0; i < 100000; i++) {
// UART->SCR = 0;
// }
uart_print("issuing no C2 in freely [0x");
uart_print_08hex(scr);
uart_print("]\r\n");
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
DD->SCR |= DD_SCR_BM_READY;
current_sector += 1;
} else if (current_sector < 85 + 4) {
// for (volatile int i = 0; i < 100000; i++) {
// UART->SCR = 0;
// }
uart_print("issuing C2 freely [0x");
uart_print_08hex(scr);
uart_print("]\r\n");
DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
DD->SCR |= DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_READY;
current_sector += 1;
} else {
uart_print("gap sector imaginary [0x");
uart_print_08hex(scr);
uart_print("]\r\n");
current_sector = 0;
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
if (continued_transfer) {
state = STATE_STOP;
} else {
if (DD->SCR & DD_SCR_BM_TRANSFER_BLOCKS) {
continued_transfer = true;
state = STATE_FETCH;
} else {
state = STATE_STOP;
}
}
}
}
if (scr & DD_SCR_BM_STOP) {
DD->SCR |= DD_SCR_BM_STOP_CLEAR;
DD->SCR &= ~(DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
state = STATE_STOP;
} else if (scr & DD_SCR_BM_START) {
DD->SCR |= DD_SCR_BM_START_CLEAR;
DD->SCR &= ~(DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
if (forbidden_block) {
DD->SCR |= DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_READY;
} else {
// kick off transfer here
// DD->SCR |= DD_SCR_BM_TRANSFER_DATA;
state = STATE_START;
}
continued_transfer = false;
current_sector = 0;
// current_sector = 1;
} else if (scr & DD_SCR_BM_PENDING) {
if (forbidden_block) {
DD->SCR |= DD_SCR_BM_READY;
} else {
if (current_sector < 85) {
if (state == STATE_TRANSFER) {
state = STATE_FETCH;
// current_sector += 1;
}
} else if (current_sector == 85) {
// uart_print("issuing no C2 in bm_pending\r\n");
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
DD->SCR |= DD_SCR_BM_READY;
current_sector += 1;
} else if (current_sector < 85 + 4) {
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
// DD->SCR |= DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_READY;
// current_sector += 1;
} else {
uart_print("gap sector read\r\n");
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
// DD->SCR |= DD_SCR_BM_READY;
current_sector = 0;
state = STATE_STOP;
}
// else {
// DD->SCR |= DD_SCR_BM_READY;
// state = STATE_STOP;
// current_sector = 0;
// }
}
// if (current_sector < 85) {
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
// DD->SCR |= DD_SCR_BM_TRANSFER_DATA;
// } else if (current_sector < 85 + 4) {
// } else if (current_sector == 88) {
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
// DD->SCR |= DD_SCR_BM_TRANSFER_C2;
// } else {
// return;
// }
// current_sector += 1;
// DD->SCR |= DD_SCR_BM_READY;
// else {
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
// }
// if (forbidden_block) {
// DD->SCR |= DD_SCR_BM_READY;
// } else {
// // request more data here
// DD->SCR |= DD_SCR_BM_READY;
// }
}
// else if (current_sector < 85 + 4) {
// }
io32_t *sdram = (io32_t *) (SDRAM_BASE + (32 * 1024 * 1024));
io32_t *dst = sdram;
const char *dma = "DMA@";
const char *cmp = "CMPH";
io32_t *buf = DD->SEC_BUF;
switch (state) {
case STATE_IDLE:
break;
case STATE_START:
usb_debug_reset();
// if (usb_debug_tx_ready()) {
// uart_print("state start\r\n");
// current_sector = 0;
state = STATE_FETCH;
// }
break;
case STATE_FETCH:
if (current_sector != 0) {
state = STATE_WAIT_2;
} else if (usb_debug_tx_ready()) {
// uart_print("state fetch\r\n");
*dst++ = *((uint32_t *) (dma));
*dst++ = 0xF5 | (7 * 4) << 24;
*dst++ = (uint32_t) DD->SCR;
*dst++ = (uint32_t) current_sector;
*dst++ = (uint32_t) DD->HEAD_TRACK;
if (continued_transfer) {
*dst++ = DD->SECTOR_NUM == 0x5A ? 0 : 0x5A;
} else {
*dst++ = (uint32_t) DD->SECTOR_NUM;
}
*dst++ = (uint32_t) DD->SECTOR_SIZE;
*dst++ = (uint32_t) DD->SECTOR_SIZE_FULL;
*dst++ = (uint32_t) DD->SECTORS_IN_BLOCK;
*dst++ = *((uint32_t *) (cmp));
usb_debug_tx_data((uint32_t) (sdram), 10 * 4);
state = STATE_WAIT;
}
break;
case STATE_WAIT: {
uint32_t type;
size_t length;
// if (current_sector != 0) {}
if (usb_debug_rx_ready(&type, &length)) {
usb_debug_rx_data((uint32_t) (sdram), length);
state = STATE_WAIT_2;
}
}
break;
case STATE_WAIT_2:
if (current_sector != 0) {
uint8_t sector_size = DD->SECTOR_SIZE + 1;
dst += ((sector_size * current_sector) / sizeof(io32_t));
for (int i = 0; i < sector_size; i += 4) {
*buf++ = *dst++;
}
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY;
state = STATE_TRANSFER;
current_sector += 1;
} else if (!usb_debug_rx_busy()) {
// uart_print("state wait 2\r\n");
uint8_t sector_size = DD->SECTOR_SIZE + 1;
for (int i = 0; i < sector_size; i += 4) {
// uint32_t datat = *dst++;
// *buf++ = ((datat>>24)&0xff) | // move byte 3 to byte 0
// ((datat<<8)&0xff0000) | // move byte 1 to byte 2
// ((datat>>8)&0xff00) | // move byte 2 to byte 1
// ((datat<<24)&0xff000000); // byte 0 to byte 3
*buf++ = *dst++;
}
// if (current_sector < 85) {
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY;
// } else {
// uart_print("shouldn't be here");
// }
state = STATE_TRANSFER;
current_sector += 1;
}
break;
// case STATE_TRANSFER:
// break;
case STATE_STOP:
// uart_print("state stop\r\n");
state = STATE_IDLE;
break;
}
}
// current_sector = 0;
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
// DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY;
// if (current_sector < 85) {
// } else if (current_sector == 85) {
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
// DD->SCR |= DD_SCR_BM_TRANSFER_C2;
// } else if (current_sector == 85 + 4) {
// } else {
// }
// current_sector += 1;
// DD->SCR |= DD_SCR_BM_READY;
void usb_print (const char *text) {
char *mmm = text;
int length = 0;
while (*mmm++ != 0) {
++length;
}
const char *dma = "DMA@";
const char *cmp = "CMPH";
io32_t *dst = &SDRAM;
uint32_t *src = (uint32_t *) (text);
*dst++ = *((uint32_t *)dma);
*dst++ = 0x01 | (length & 0xFF) << 24;
int i = 0;
for (; i < length; i += 4) {
*dst++ = *src++;
}
*dst++ = *((uint32_t *)cmp);
usb_debug_tx_data(0, i + 12);
}

12
sw/riscv/src/dd.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef DD_H__
#define DD_H__
#include "sys.h"
void dd_init (void);
void process_dd (void);
#endif

View File

@ -6,6 +6,7 @@
#include "rtc.h"
#include "i2c.h"
#include "flashram.h"
#include "dd.h"
#include "uart.h"
@ -15,6 +16,7 @@ static const void (*process_table[])(void) = {
process_rtc,
process_i2c,
process_flashram,
process_dd,
process_uart,
NULL,
};
@ -30,6 +32,7 @@ __attribute__((naked)) void process_loop (void) {
rtc_init();
i2c_init();
flashram_init();
dd_init();
uart_init();
while (1) {

View File

@ -8,6 +8,7 @@
typedef volatile uint8_t io8_t;
typedef volatile uint16_t io16_t;
typedef volatile uint32_t io32_t;
@ -189,6 +190,50 @@ typedef volatile struct joybus_regs {
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
typedef volatile struct dd_regs {
io32_t SCR;
io16_t DATA;
io8_t CMD;
io8_t __padding_1;
io16_t HEAD_TRACK;
io16_t __padding_2;
io8_t SECTOR_NUM;
io8_t SECTOR_SIZE;
io8_t SECTOR_SIZE_FULL;
io8_t SECTORS_IN_BLOCK;
io8_t DRIVE_ID;
io8_t __padding_3[3];
io32_t __padding_4[59];
io32_t SEC_BUF[64];
} dd_regs_t;
#define DD_BASE (0xB0000000UL)
#define DD ((dd_regs_t *) DD_BASE)
#define DD_SCR_HARD_RESET (1 << 0)
#define DD_SCR_HARD_RESET_CLEAR (1 << 1)
#define DD_SCR_CMD_PENDING (1 << 2)
#define DD_SCR_CMD_READY (1 << 3)
#define DD_SCR_BM_PENDING (1 << 4)
#define DD_SCR_BM_READY (1 << 5)
#define DD_SCR_DISK_INSERTED (1 << 6)
#define DD_SCR_DISK_CHANGED (1 << 7)
#define DD_SCR_BM_START (1 << 8)
#define DD_SCR_BM_START_CLEAR (1 << 9)
#define DD_SCR_BM_STOP (1 << 10)
#define DD_SCR_BM_STOP_CLEAR (1 << 11)
#define DD_SCR_BM_TRANSFER_MODE (1 << 12)
#define DD_SCR_BM_TRANSFER_BLOCKS (1 << 13)
#define DD_SCR_BM_TRANSFER_DATA (1 << 14)
#define DD_SCR_BM_TRANSFER_C2 (1 << 15)
#define DD_SCR_BM_MICRO_ERROR (1 << 16)
#define DD_SCR_BM_ACK (1 << 17)
#define DD_SCR_BM_ACK_CLEAR (1 << 18)
#define DD_HEAD_TRACK_MASK (0x1FFF)
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
void reset_handler(void);

View File

@ -151,7 +151,7 @@ void usb_debug_reset (void) {
p.debug_rx_busy = false;
p.debug_tx_busy = false;
USB->SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
USB->SCR = USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
}
static uint8_t rx_cmd_current_byte = 0;