From: Michael McMaster Date: Wed, 31 Jan 2018 11:25:50 +0000 (+1000) Subject: Fix sync timings to split read and write period times X-Git-Tag: v6.1.3 X-Git-Url: http://git.codesrc.com/gitweb.cgi?a=commitdiff_plain;h=7b4f3365c64f4f96cce8da9106445ee924c15657;p=SCSI2SD-V6.git Fix sync timings to split read and write period times --- diff --git a/CHANGELOG b/CHANGELOG index 57009708..19c4ab24 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +20180131 6.1.3 + - Fix bug that caused stability issues with 10MB/s transfers. + 20171128 6.1.2 - Fix synchronous negotiation bugs diff --git a/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c b/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c index 1e200f7c..5261aa92 100755 --- a/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c +++ b/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c @@ -81,10 +81,10 @@ void MX_FSMC_Init(void) // 1 to write back to fsmc bus. Timing.DataSetupTime = 4; - // Allow a clock for us to release signals, plus 3 for the synchroniser to - // realise the cycle has ended. Need to avoid both devices acting as outputs + // Allow a clock for us to release signals + // Need to avoid both devices acting as outputs // on the multiplexed lines at the same time. - Timing.BusTurnAroundDuration = 4; + Timing.BusTurnAroundDuration = 1; Timing.CLKDivision = 16; // Ignored for async Timing.DataLatency = 17; // Ignored for async diff --git a/rtl/fpga_bitmap.o b/rtl/fpga_bitmap.o index aa8447bf..046632ca 100644 Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ diff --git a/src/firmware/config.c b/src/firmware/config.c index 06baee27..dc2fe1a3 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -38,7 +38,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0612; +static const uint16_t FIRMWARE_VERSION = 0x0613; // 1 flash row static const uint8_t DEFAULT_CONFIG[128] = diff --git a/src/firmware/disk.c b/src/firmware/disk.c index e7c097fc..5b114009 100755 --- a/src/firmware/disk.c +++ b/src/firmware/disk.c @@ -718,8 +718,11 @@ void scsiDiskPoll() process_MessageIn(); // Will go to BUS_FREE state // Try and prevent anyone else using the SCSI bus while we're not ready. - *SCSI_CTRL_BSY = 1; - clearBSY = 1; + if (*SCSI_CTRL_BSY == 0) // Could be busy for a linked command + { + *SCSI_CTRL_BSY = 1; + clearBSY = 1; + } } diff --git a/src/firmware/scsi.c b/src/firmware/scsi.c index e5528bfc..81af617f 100755 --- a/src/firmware/scsi.c +++ b/src/firmware/scsi.c @@ -815,13 +815,14 @@ static void process_MessageOut() // After 80 we start to run out of bits in the fpga timing // register. (transferPeriod == 0) || + (offset == 0) || ((scsiDev.boardCfg.scsiSpeed != S2S_CFG_SPEED_NoLimit) && (scsiDev.boardCfg.scsiSpeed <= S2S_CFG_SPEED_ASYNC_50))) { scsiDev.target->syncOffset = 0; scsiDev.target->syncPeriod = 0; } else { - scsiDev.target->syncOffset = offset < 63 ? offset : 63; + scsiDev.target->syncOffset = offset <= 15 ? offset : 15; // FAST20 / 50ns / 20MHz is disabled for now due to // data corruption while reading data. We can count the // ACK's correctly, but can't save the data to a register diff --git a/src/firmware/scsiPhy.c b/src/firmware/scsiPhy.c index fadddcb3..b2bb258f 100755 --- a/src/firmware/scsiPhy.c +++ b/src/firmware/scsiPhy.c @@ -31,7 +31,7 @@ static uint8_t asyncTimings[][4] = { /* Speed, Assert, Deskew, Hold, Glitch */ -{/*1.5MB/s*/ 28, 18, 13, 13}, +{/*1.5MB/s*/ 28, 18, 13, 15}, {/*3.3MB/s*/ 13, 6, 6, 13}, {/*5MB/s*/ 9, 6, 6, 6}, // 80ns {/*safe*/ 3, 6, 6, 6}, // Probably safe @@ -58,7 +58,13 @@ static uint8_t asyncTimings[][4] = #define SCSI_FAST10_DESKEW 2 // 25ns #define SCSI_FAST10_HOLD 3 // 33ns -#define SCSI_FAST10_ASSERT 3 // 30ns +#define SCSI_FAST10_WRITE_ASSERT 3 // 30ns. Overall clocks only works if fpga overhead is 3. + +// Slow down the cycle to be valid. 2x assert period is TOO FAST when +// reading data. It's ok when writing due to the deskew. +// 50ns. ie. 100ns / 2. Rounded down because there's likely a few extra cycles +// here and there. +#define SCSI_FAST10_READ_ASSERT 5 // Fastest possible timing, probably not 20MB/s #define SCSI_FAST20_DESKEW 1 @@ -74,12 +80,17 @@ static uint8_t asyncTimings[][4] = : SCSI_FAST5_HOLD) +// Number of overhead cycles per period. +#define FPGA_OVERHEAD 2 +#define FPGA_CYCLES_PER_NS 9 +#define SCSI_PERIOD_CLKS(period) ((((int)period * 4) + (FPGA_CYCLES_PER_NS/2)) / FPGA_CYCLES_PER_NS) + // 3.125MB/s (80 period) to < 10MB/s sync // Assumes a 108MHz fpga clock. (9 ns) -// (((period * 4) / 2) * 0.8) / 9 -// Done using 3 fixed point math. // 3:0 Assertion count, variable -#define syncAssertion(period) ((((((int)period) * 177) + 750)/1000) & 0xF) +#define syncAssertionWrite(period,deskew) ((SCSI_PERIOD_CLKS(period) - deskew - FPGA_OVERHEAD + 1) / 2) +#define syncAssertionRead(period) syncAssertionWrite(period,0) + // Time until we consider ourselves selected // 400ns at 108MHz @@ -481,13 +492,12 @@ scsiSetDefaultTiming() asyncTiming[3]); } -void scsiEnterPhase(int phase) +void scsiEnterPhase(int newPhase) { // ANSI INCITS 362-2002 SPI-3 10.7.1: // Phase changes are not allowed while REQ or ACK is asserted. while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {} - int newPhase = phase > 0 ? phase : 0; int oldPhase = *SCSI_CTRL_PHASE; if (!scsiDev.resetFlag && (!scsiPhyFifoEmpty() || !scsiPhyFifoAltEmpty())) { @@ -505,7 +515,14 @@ void scsiEnterPhase(int phase) } else if (scsiDev.target->syncPeriod <= 25) { - scsiSetTiming(SCSI_FAST10_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1); + if (newPhase == DATA_IN) + { + scsiSetTiming(SCSI_FAST10_WRITE_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1); + } + else + { + scsiSetTiming(SCSI_FAST10_READ_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1); + } } else { @@ -514,26 +531,26 @@ void scsiEnterPhase(int phase) int glitch = scsiDev.target->syncPeriod < 35 ? 1 : (scsiDev.target->syncPeriod < 45 ? 2 : 5); + int deskew = syncDeskew(scsiDev.target->syncPeriod); + int assertion; + if (newPhase == DATA_IN) + { + assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew); + } + else + { + assertion = syncAssertionRead(scsiDev.target->syncPeriod); + } scsiSetTiming( - syncAssertion(scsiDev.target->syncPeriod), - syncDeskew(scsiDev.target->syncPeriod), + assertion, + deskew, syncHold(scsiDev.target->syncPeriod), glitch); } - // See note 26 in SCSI 2 standard: SCSI 1 implementations may assume - // "leading edge of the first REQ pulse beyond the REQ/ACK offset - // agreement would not occur until after the trailing edge of the - // last ACK pulse within the agreement." - // We simply subtract 1 from the offset to meet this requirement. - if (scsiDev.target->syncOffset >= 2) - { - *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset - 1; - } else { - *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset; - } + *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset; } - else + else if (newPhase >= 0) { *SCSI_CTRL_SYNC_OFFSET = 0; @@ -564,14 +581,20 @@ void scsiEnterPhase(int phase) asyncTiming[3]); } - *SCSI_CTRL_PHASE = newPhase; - busSettleDelay(); + if (newPhase >= 0) + { + *SCSI_CTRL_PHASE = newPhase; + busSettleDelay(); - if (scsiDev.compatMode < COMPAT_SCSI2) + if (scsiDev.compatMode < COMPAT_SCSI2) + { + s2s_delay_us(100); + } + } + else { - s2s_delay_us(100); + *SCSI_CTRL_PHASE = 0; } - } } @@ -587,10 +610,10 @@ void scsiPhyReset() dmaInProgress = 0; } - *SCSI_CTRL_PHASE = 0x00; - *SCSI_CTRL_BSY = 0x00; s2s_fpgaReset(); // Clears fifos etc. + *SCSI_CTRL_PHASE = 0x00; + *SCSI_CTRL_BSY = 0x00; scsiPhyFifoSel = 0; *SCSI_FIFO_SEL = 0; *SCSI_CTRL_DBX = 0;