Fix sync timings to split read and write period times v6.1.3
authorMichael McMaster <michael@codesrc.com>
Wed, 31 Jan 2018 11:25:50 +0000 (21:25 +1000)
committerMichael McMaster <michael@codesrc.com>
Wed, 31 Jan 2018 11:25:50 +0000 (21:25 +1000)
CHANGELOG
STM32CubeMX/SCSI2SD-V6/Src/fsmc.c
rtl/fpga_bitmap.o
src/firmware/config.c
src/firmware/disk.c
src/firmware/scsi.c
src/firmware/scsiPhy.c

index 5700970..19c4ab2 100644 (file)
--- 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
 
index 1e200f7..5261aa9 100755 (executable)
@@ -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
index aa8447b..046632c 100644 (file)
Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ
index 06baee2..dc2fe1a 100755 (executable)
@@ -38,7 +38,7 @@
 \r
 #include <string.h>\r
 \r
-static const uint16_t FIRMWARE_VERSION = 0x0612;\r
+static const uint16_t FIRMWARE_VERSION = 0x0613;\r
 \r
 // 1 flash row\r
 static const uint8_t DEFAULT_CONFIG[128] =\r
index e7c097f..5b11400 100755 (executable)
@@ -718,8 +718,11 @@ void scsiDiskPoll()
                                process_MessageIn(); // Will go to BUS_FREE state\r
 \r
                                // Try and prevent anyone else using the SCSI bus while we're not ready.\r
-                               *SCSI_CTRL_BSY = 1;\r
-                               clearBSY = 1;\r
+                               if (*SCSI_CTRL_BSY == 0) // Could be busy for a linked command\r
+                               {\r
+                                       *SCSI_CTRL_BSY = 1;\r
+                                       clearBSY = 1;\r
+                               }\r
                        }\r
 \r
 \r
index e5528bf..81af617 100755 (executable)
@@ -815,13 +815,14 @@ static void process_MessageOut()
                                // After 80 we start to run out of bits in the fpga timing\r
                                // register.\r
                                (transferPeriod == 0) ||\r
+                               (offset == 0) ||\r
                                ((scsiDev.boardCfg.scsiSpeed != S2S_CFG_SPEED_NoLimit) &&\r
                                        (scsiDev.boardCfg.scsiSpeed <= S2S_CFG_SPEED_ASYNC_50)))\r
                        {\r
                                scsiDev.target->syncOffset = 0;\r
                                scsiDev.target->syncPeriod = 0;\r
                        } else {\r
-                               scsiDev.target->syncOffset = offset < 63 ? offset : 63;\r
+                               scsiDev.target->syncOffset = offset <= 15 ? offset : 15;\r
                                // FAST20 / 50ns / 20MHz is disabled for now due to\r
                                // data corruption while reading data. We can count the\r
                                // ACK's correctly, but can't save the data to a register\r
index fadddcb..b2bb258 100755 (executable)
@@ -31,7 +31,7 @@
 static uint8_t asyncTimings[][4] =\r
 {\r
 /* Speed,    Assert,    Deskew,    Hold,    Glitch */\r
-{/*1.5MB/s*/ 28,        18,        13,      13},\r
+{/*1.5MB/s*/ 28,        18,        13,      15},\r
 {/*3.3MB/s*/ 13,        6,         6,       13},\r
 {/*5MB/s*/   9,         6,         6,       6}, // 80ns\r
 {/*safe*/    3,         6,         6,       6}, // Probably safe\r
@@ -58,7 +58,13 @@ static uint8_t asyncTimings[][4] =
 \r
 #define SCSI_FAST10_DESKEW 2 // 25ns\r
 #define SCSI_FAST10_HOLD 3 // 33ns\r
-#define SCSI_FAST10_ASSERT 3 // 30ns\r
+#define SCSI_FAST10_WRITE_ASSERT 3 // 30ns. Overall clocks only works if fpga overhead is 3.\r
+\r
+// Slow down the cycle to be valid. 2x assert period is TOO FAST when\r
+// reading data. It's ok when writing due to the deskew.\r
+// 50ns. ie. 100ns / 2. Rounded down because there's likely a few extra cycles\r
+// here and there.\r
+#define SCSI_FAST10_READ_ASSERT 5\r
 \r
 // Fastest possible timing, probably not 20MB/s\r
 #define SCSI_FAST20_DESKEW 1\r
@@ -74,12 +80,17 @@ static uint8_t asyncTimings[][4] =
        : SCSI_FAST5_HOLD)\r
 \r
 \r
+// Number of overhead cycles per period.\r
+#define FPGA_OVERHEAD 2\r
+#define FPGA_CYCLES_PER_NS 9\r
+#define SCSI_PERIOD_CLKS(period) ((((int)period * 4) + (FPGA_CYCLES_PER_NS/2)) / FPGA_CYCLES_PER_NS)\r
+\r
 // 3.125MB/s (80 period) to < 10MB/s sync\r
 // Assumes a 108MHz fpga clock. (9 ns)\r
-// (((period * 4) / 2) * 0.8) / 9\r
-// Done using 3 fixed point math.\r
 // 3:0 Assertion count, variable\r
-#define syncAssertion(period) ((((((int)period) * 177) + 750)/1000) & 0xF)\r
+#define syncAssertionWrite(period,deskew) ((SCSI_PERIOD_CLKS(period) - deskew - FPGA_OVERHEAD + 1) / 2)\r
+#define syncAssertionRead(period) syncAssertionWrite(period,0)\r
+\r
 \r
 // Time until we consider ourselves selected\r
 // 400ns at 108MHz\r
@@ -481,13 +492,12 @@ scsiSetDefaultTiming()
                asyncTiming[3]);\r
 }\r
 \r
-void scsiEnterPhase(int phase)\r
+void scsiEnterPhase(int newPhase)\r
 {\r
        // ANSI INCITS 362-2002 SPI-3 10.7.1:\r
        // Phase changes are not allowed while REQ or ACK is asserted.\r
        while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {}\r
 \r
-       int newPhase = phase > 0 ? phase : 0;\r
        int oldPhase = *SCSI_CTRL_PHASE;\r
 \r
        if (!scsiDev.resetFlag && (!scsiPhyFifoEmpty() || !scsiPhyFifoAltEmpty())) {\r
@@ -505,7 +515,14 @@ void scsiEnterPhase(int phase)
                        }\r
                        else if (scsiDev.target->syncPeriod <= 25)\r
                        {\r
-                               scsiSetTiming(SCSI_FAST10_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
+                               if (newPhase == DATA_IN)\r
+                               {\r
+                                       scsiSetTiming(SCSI_FAST10_WRITE_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
+                               }\r
+                               else\r
+                               {\r
+                                       scsiSetTiming(SCSI_FAST10_READ_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
+                               }\r
                        }\r
                        else\r
                        {\r
@@ -514,26 +531,26 @@ void scsiEnterPhase(int phase)
                                int glitch =\r
                                        scsiDev.target->syncPeriod < 35 ? 1 :\r
                                                (scsiDev.target->syncPeriod < 45 ? 2 : 5);\r
+                               int deskew = syncDeskew(scsiDev.target->syncPeriod);\r
+                               int assertion;\r
+                               if (newPhase == DATA_IN)\r
+                               {\r
+                                       assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew);\r
+                               }\r
+                               else\r
+                               {\r
+                                       assertion = syncAssertionRead(scsiDev.target->syncPeriod);\r
+                               }\r
                                scsiSetTiming(\r
-                                       syncAssertion(scsiDev.target->syncPeriod),\r
-                                       syncDeskew(scsiDev.target->syncPeriod),\r
+                                       assertion,\r
+                                       deskew,\r
                                        syncHold(scsiDev.target->syncPeriod),\r
                                        glitch);\r
                        }\r
 \r
-                       // See note 26 in SCSI 2 standard: SCSI 1 implementations may assume\r
-                       // "leading edge of the first REQ pulse beyond the REQ/ACK offset\r
-                       // agreement would not occur until after the trailing edge of the\r
-                       // last ACK pulse within the agreement."\r
-                       // We simply subtract 1 from the offset to meet this requirement.\r
-                       if (scsiDev.target->syncOffset >= 2)\r
-                       {\r
-                               *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset - 1;\r
-                       } else {\r
-                               *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;\r
-                       }\r
+                       *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;\r
                }\r
-               else\r
+               else if (newPhase >= 0)\r
                {\r
 \r
                        *SCSI_CTRL_SYNC_OFFSET = 0;\r
@@ -564,14 +581,20 @@ void scsiEnterPhase(int phase)
                                asyncTiming[3]);\r
                }\r
 \r
-               *SCSI_CTRL_PHASE = newPhase;\r
-               busSettleDelay();\r
+               if (newPhase >= 0)\r
+               {\r
+                       *SCSI_CTRL_PHASE = newPhase;\r
+                       busSettleDelay();\r
 \r
-               if (scsiDev.compatMode < COMPAT_SCSI2)\r
+                       if (scsiDev.compatMode < COMPAT_SCSI2)\r
+                       {\r
+                               s2s_delay_us(100);\r
+                       }\r
+               }\r
+               else\r
                {\r
-                       s2s_delay_us(100);\r
+                       *SCSI_CTRL_PHASE = 0;\r
                }\r
-\r
        }\r
 }\r
 \r
@@ -587,10 +610,10 @@ void scsiPhyReset()
                dmaInProgress = 0;\r
        }\r
 \r
-       *SCSI_CTRL_PHASE = 0x00;\r
-       *SCSI_CTRL_BSY = 0x00;\r
        s2s_fpgaReset(); // Clears fifos etc.\r
 \r
+       *SCSI_CTRL_PHASE = 0x00;\r
+       *SCSI_CTRL_BSY = 0x00;\r
        scsiPhyFifoSel = 0;\r
        *SCSI_FIFO_SEL = 0;\r
        *SCSI_CTRL_DBX = 0;\r