Selaa lähdekoodia

Improve stability of fpga async mem interface

Michael McMaster 4 vuotta sitten
vanhempi
sitoutus
5c9885c01b

+ 48 - 46
lib/SCSI2SD/STM32CubeMX/2020c.diff

@@ -1,49 +1,3 @@
-diff --git a/STM32CubeMX/2020c/Src/fsmc.c b/STM32CubeMX/2020c/Src/fsmc.c
-index 03a1b12..1b01446 100644
---- a/STM32CubeMX/2020c/Src/fsmc.c
-+++ b/STM32CubeMX/2020c/Src/fsmc.c
-@@ -50,12 +50,28 @@ void MX_FSMC_Init(void)
-   hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
-   hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
-   /* Timing */
-+
-+  // 1 clock to read the address, + 1 for synchroniser skew
-   Timing.AddressSetupTime = 2;
-   Timing.AddressHoldTime = 1;
-+
-+  // Writes to device:
-+  //   1 for synchroniser skew (dbx also delayed)
-+  //   1 to skip hold time
-+  //   1 to write data.
-+
-+  // Reads from device:
-+  //   3 for syncroniser
-+  //   1 to write back to fsmc bus.
-   Timing.DataSetupTime = 4;
-+
-+  // 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 = 1;
--  Timing.CLKDivision = 16;
--  Timing.DataLatency = 17;
-+
-+  Timing.CLKDivision = 16; // Ignored for async
-+  Timing.DataLatency = 17; // Ignored for async
-   Timing.AccessMode = FSMC_ACCESS_MODE_A;
-   /* ExtTiming */
- 
-@@ -105,6 +121,10 @@ static void HAL_FSMC_MspInit(void){
-   PE0   ------> FSMC_NBL0
-   PE1   ------> FSMC_NBL1
-   */
-+
-+  // MM: GPIO_SPEED_FREQ_MEDIUM is rated up to 50MHz, which is fine as all the
-+  // fsmc timings are > 1 (ie. so clock speed / 2 is around 50MHz).
-+
-   /* GPIO_InitStruct */
-   GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
-                           |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 
 diff --git a/STM32CubeMX/2020c/Src/sdio.c b/STM32CubeMX/2020c/Src/sdio.c
 index f2a0b7c..a00c6a8 100644
 --- a/STM32CubeMX/2020c/Src/sdio.c
@@ -441,3 +395,51 @@ index b060eae..de39f9d 100644
  /**
    * @brief  Send the Write Multi Block command and check the response
    * @param  SDIOx: Pointer to SDIO register base 
+diff --git a/STM32CubeMX/2020c/Src/fsmc.c b/STM32CubeMX/2020c/Src/fsmc.c
+index 03a1b12..52f03f4 100644
+--- a/STM32CubeMX/2020c/Src/fsmc.c
++++ b/STM32CubeMX/2020c/Src/fsmc.c
+@@ -50,12 +50,29 @@ void MX_FSMC_Init(void)
+   hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
+   hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
+   /* Timing */
+-  Timing.AddressSetupTime = 2;
++
++  // 1 clock to read the address, + 2 for synchroniser skew
++  Timing.AddressSetupTime = 3;
+   Timing.AddressHoldTime = 1;
++
++  // Writes to device:
++  //   2 for synchroniser skew (dbx also delayed)
++  //   1 to skip hold time
++  //   1 to write data.
++
++  // Reads from device:
++  //   1 to skip hold time
++  //   1 for synchroniser on OE
++  //   1 to write back to fsmc bus.
+   Timing.DataSetupTime = 4;
++
++  // 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 = 1;
+-  Timing.CLKDivision = 16;
+-  Timing.DataLatency = 17;
++
++  Timing.CLKDivision = 16; // Ignored for async
++  Timing.DataLatency = 17; // Ignored for async
+   Timing.AccessMode = FSMC_ACCESS_MODE_A;
+   /* ExtTiming */
+ 
+@@ -105,6 +122,10 @@ static void HAL_FSMC_MspInit(void){
+   PE0   ------> FSMC_NBL0
+   PE1   ------> FSMC_NBL1
+   */
++
++  // MM: GPIO_SPEED_FREQ_MEDIUM is rated up to 50MHz, which is fine as all the
++  // fsmc timings are > 1 (ie. so clock speed / 2 is around 50MHz).
++
+   /* GPIO_InitStruct */
+   GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
+                           |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 

+ 5 - 4
lib/SCSI2SD/STM32CubeMX/2020c/Src/fsmc.c

@@ -51,17 +51,18 @@ void MX_FSMC_Init(void)
   hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
   /* Timing */
 
-  // 1 clock to read the address, + 1 for synchroniser skew
-  Timing.AddressSetupTime = 2;
+  // 1 clock to read the address, + 2 for synchroniser skew
+  Timing.AddressSetupTime = 3;
   Timing.AddressHoldTime = 1;
 
   // Writes to device:
-  //   1 for synchroniser skew (dbx also delayed)
+  //   2 for synchroniser skew (dbx also delayed)
   //   1 to skip hold time
   //   1 to write data.
 
   // Reads from device:
-  //   3 for syncroniser
+  //   1 to skip hold time
+  //   1 for synchroniser on OE
   //   1 to write back to fsmc bus.
   Timing.DataSetupTime = 4;
 

+ 56 - 46
lib/SCSI2SD/STM32CubeMX/2021.diff

@@ -1,49 +1,3 @@
-diff --git a/STM32CubeMX/2021/Src/fmc.c b/STM32CubeMX/2021/Src/fmc.c
-index dae179a..995fd15 100644
---- a/STM32CubeMX/2021/Src/fmc.c
-+++ b/STM32CubeMX/2021/Src/fmc.c
-@@ -52,12 +52,28 @@ void MX_FMC_Init(void)
-   hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
-   hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
-   /* Timing */
-+
-+  // 1 clock to read the address, + 1 for synchroniser skew
-   Timing.AddressSetupTime = 2;
-   Timing.AddressHoldTime = 1;
-+
-+  // Writes to device:
-+  //   1 for synchroniser skew (dbx also delayed)
-+  //   1 to skip hold time
-+  //   1 to write data.
-+
-+  // Reads from device:
-+  //   3 for syncroniser
-+  //   1 to write back to fsmc bus.
-   Timing.DataSetupTime = 4;
-+
-+  // 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 = 1;
--  Timing.CLKDivision = 16;
--  Timing.DataLatency = 17;
-+
-+  Timing.CLKDivision = 16; // Ignored for async
-+  Timing.DataLatency = 17; // Ignored for async
-   Timing.AccessMode = FMC_ACCESS_MODE_A;
-   /* ExtTiming */
- 
-@@ -107,6 +123,10 @@ static void HAL_FMC_MspInit(void){
-   PE0   ------> FMC_NBL0
-   PE1   ------> FMC_NBL1
-   */
-+
-+  // MM: GPIO_SPEED_FREQ_MEDIUM is rated up to 50MHz, which is fine as all the
-+  // fsmc timings are > 1 (ie. so clock speed / 2 is around 50MHz).
-+
-   /* GPIO_InitStruct */
-   GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
-                           |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 
 diff --git a/STM32CubeMX/2021/Src/sdio.c b/STM32CubeMX/2021/Src/sdio.c
 index 01e3895..33fbae1 100644
 --- a/STM32CubeMX/2021/Src/sdio.c
@@ -447,3 +401,59 @@ index 4f23a45..614b6dc 100644
  /**
    * @brief  Send the Write Multi Block command and check the response
    * @param  SDIOx: Pointer to SDIO register base 
+diff --git a/STM32CubeMX/2021/Src/fmc.c b/STM32CubeMX/2021/Src/fmc.c
+index dae179a..a527167 100644
+--- a/STM32CubeMX/2021/Src/fmc.c
++++ b/STM32CubeMX/2021/Src/fmc.c
+@@ -49,15 +49,33 @@ void MX_FMC_Init(void)
+   hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
+   hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
+   hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
+-  hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
++  hsram1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;
++
+   hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
+   /* Timing */
+-  Timing.AddressSetupTime = 2;
+-  Timing.AddressHoldTime = 1;
+-  Timing.DataSetupTime = 4;
+-  Timing.BusTurnAroundDuration = 1;
+-  Timing.CLKDivision = 16;
+-  Timing.DataLatency = 17;
++
++  // 1 clock to read the address, + 2 for synchroniser skew
++  Timing.AddressSetupTime = 6;
++  Timing.AddressHoldTime = 2;
++
++  // Writes to device:
++  //   2 for synchroniser skew (dbx also delayed)
++  //   1 to skip hold time
++  //   1 to write data.
++
++  // Reads from device:
++  //   1 to skip hold time
++  //   2 for synchroniser skew on OE
++  //   1 to write back to fsmc bus.
++  Timing.DataSetupTime = 8;
++
++  // 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 = 2;
++
++  Timing.CLKDivision = 16; // Ignored for async
++  Timing.DataLatency = 17; // Ignored for async
+   Timing.AccessMode = FMC_ACCESS_MODE_A;
+   /* ExtTiming */
+ 
+@@ -107,6 +125,10 @@ static void HAL_FMC_MspInit(void){
+   PE0   ------> FMC_NBL0
+   PE1   ------> FMC_NBL1
+   */
++
++  // MM: GPIO_SPEED_FREQ_MEDIUM is rated up to 50MHz, which is fine as all the
++  // fsmc timings are > 1 (ie. so clock speed / 2 is around 50MHz).
++
+   /* GPIO_InitStruct */
+   GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
+                           |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 

+ 5 - 4
lib/SCSI2SD/STM32CubeMX/2021/Src/fmc.c

@@ -54,17 +54,18 @@ void MX_FMC_Init(void)
   hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
   /* Timing */
 
-  // 1 clock to read the address, + 1 for synchroniser skew
-  Timing.AddressSetupTime = 4;
+  // 1 clock to read the address, + 2 for synchroniser skew
+  Timing.AddressSetupTime = 6;
   Timing.AddressHoldTime = 2;
 
   // Writes to device:
-  //   1 for synchroniser skew (dbx also delayed)
+  //   2 for synchroniser skew (dbx also delayed)
   //   1 to skip hold time
   //   1 to write data.
 
   // Reads from device:
-  //   3 for syncroniser
+  //   1 to skip hold time
+  //   2 for synchroniser skew on OE
   //   1 to write back to fsmc bus.
   Timing.DataSetupTime = 8;
 

BIN
lib/SCSI2SD/rtl/fpga_bitmap.2020.o


+ 50 - 49
lib/SCSI2SD/src/firmware/bsp_driver_sd.c

@@ -66,8 +66,7 @@ uint8_t BSP_SD_Init(void)
       SD_state = MSD_OK;
 
 // Clock bypass mode is broken on STM32F205
-// This just corrupts data for now.
-//#ifdef STM32F4xx
+// #ifdef STM32F4xx
 #if 0
       uint8_t SD_hs[64]  = {0};
       //uint32_t SD_scr[2] = {0, 0};
@@ -75,7 +74,7 @@ uint8_t BSP_SD_Init(void)
       uint32_t count = 0;
       uint32_t *tempbuff = (uint32_t *)SD_hs;
 
-      // Prepare to read 64 bytes training data
+      // Prepare to read 64 bytes status data
       SDIO_DataInitTypeDef config;
       config.DataTimeOut   = SDMMC_DATATIMEOUT;
       config.DataLength    = 64;
@@ -90,61 +89,63 @@ uint8_t BSP_SD_Init(void)
       // Which is the max without going to 1.8v
       uint32_t errorstate = SDMMC_CmdSwitch(hsd.Instance, 0x80FFFF01);
 
-      // Low-level init for the bypass. Changes registers only
-      hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
-      SDIO_Init(hsd.Instance, hsd.Init); 
-
-      // Now we read some training data
+      // Now we read some status data
 
       if (errorstate == HAL_SD_ERROR_NONE)
       {
-        while(!__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND/* | SDIO_FLAG_STBITERR*/))
-        {
-          if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXFIFOHF))
+          while(!__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND/* | SDIO_FLAG_STBITERR*/))
           {
-            for (count = 0; count < 8; count++)
-            {
-              *(tempbuff + count) = SDIO_ReadFIFO(hsd.Instance);
-            }
+              if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXFIFOHF))
+              {
+                  for (count = 0; count < 8; count++)
+                  {
+                      *(tempbuff + count) = SDIO_ReadFIFO(hsd.Instance);
+                  }
+
+                  tempbuff += 8;
+              }
+          }
 
-            tempbuff += 8;
+          if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DTIMEOUT))
+          {
+              __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DTIMEOUT);
+              SD_state = MSD_ERROR;
+          }
+          else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DCRCFAIL))
+          {
+              __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DCRCFAIL);
+              SD_state = MSD_ERROR;
           }
-        }
-
-        if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DTIMEOUT))
-        {
-          __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DTIMEOUT);
-          SD_state = MSD_ERROR;
-        }
-        else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_DCRCFAIL))
-        {
-          __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_DCRCFAIL);
-          SD_state = MSD_ERROR;
-        }
-        else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR))
-        {
-          __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_RXOVERR);
-          SD_state = MSD_ERROR;
-        }
-        /*else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_STBITERR))
-        {
-          __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_STBITERR);
-          SD_state = MSD_ERROR;
-        }*/
-        else
-        {
-          count = SD_DATATIMEOUT;
-
-          while ((__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXDAVL)) && (count > 0))
+          else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXOVERR))
           {
-            *tempbuff = SDIO_ReadFIFO(hsd.Instance);
-            tempbuff++;
-            count--;
+              __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_RXOVERR);
+              SD_state = MSD_ERROR;
           }
+          /*else if (__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_STBITERR))
+            {
+            __HAL_SD_CLEAR_FLAG(&hsd, SDIO_FLAG_STBITERR);
+            SD_state = MSD_ERROR;
+            }*/
+          else
+          {
+              count = SD_DATATIMEOUT;
+
+              while ((__HAL_SD_GET_FLAG(&hsd, SDIO_FLAG_RXDAVL)) && (count > 0))
+              {
+                  *tempbuff = SDIO_ReadFIFO(hsd.Instance);
+                  tempbuff++;
+                  count--;
+              }
 
-          /* Clear all the static flags */
-          __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
-        }
+              /* Clear all the static flags */
+              __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
+
+              // After 8 "SD" clocks we can change speed
+              // Low-level init for the bypass. Changes registers only
+              hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
+              SDIO_Init(hsd.Instance, hsd.Init); 
+
+          }
       }
 #endif
     }

+ 1 - 1
lib/SCSI2SD/src/firmware/config.c

@@ -36,7 +36,7 @@
 
 #include <string.h>
 
-static const uint16_t FIRMWARE_VERSION = 0x0649;
+static const uint16_t FIRMWARE_VERSION = 0x064A;
 
 // Optional static config
 extern uint8_t* __fixed_config;

+ 8 - 15
lib/SCSI2SD/src/firmware/scsiPhy.c

@@ -19,12 +19,18 @@
 #include "stm32f2xx.h"
 #include "stm32f2xx_hal.h"
 #include "stm32f2xx_hal_dma.h"
+#include "fsmc.h"
+#define FMC_NORSRAM_TimingTypeDef FSMC_NORSRAM_TimingTypeDef
+#define FMC_ACCESS_MODE_A FSMC_ACCESS_MODE_A
+#define FMC_NORSRAM_Timing_Init FSMC_NORSRAM_Timing_Init
+#define FMC_NORSRAM_DEVICE FSMC_NORSRAM_DEVICE
 #endif
 
 #ifdef STM32F4xx
 #include "stm32f4xx.h"
 #include "stm32f4xx_hal.h"
 #include "stm32f4xx_hal_dma.h"
+#include "fmc.h"
 #endif
 
 #include "gpio.h"
@@ -442,16 +448,7 @@ scsiWritePIO(const uint8_t* data, uint32_t count)
                 scsiPhyTx32(fifoData[i + 120 + k], fifoData[i + k + 121]);
                 scsiPhyTx32(fifoData[i + 122 + k], fifoData[i + k + 123]);
                 scsiPhyTx32(fifoData[i + 124 + k], fifoData[i + k + 125]);
-
-                // Last write must be 16bit to avoid having data waiting in the AHB bus
-                // somewhere still waiting to be written while we're off checking
-                // for empty fifos
-                // Note also that the fmc fifo is disabled on stm32f446 because it's too big
-                // (64 bytes) and we may think the fpga fifo is empty even though
-                // there's pending writes
-                scsiPhyTx(fifoData[i + 126 + k]);
-                scsiPhyTx(fifoData[i + k + 127]);
-
+                scsiPhyTx32(fifoData[i + 126 + k], fifoData[i + k + 127]);
             }
 
             i += chunk16;
@@ -461,9 +458,7 @@ scsiWritePIO(const uint8_t* data, uint32_t count)
             uint32_t chunk16 = count16 - i;
 
             uint32_t k = 0;
-            // Note that last 4 bytes will fall through to next loop, which avoids
-            // ending on a 32bit write.
-            for (; k + 4 < chunk16; k += 4)
+            for (; k + 4 <= chunk16; k += 4)
             {
                 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);
                 scsiPhyTx32(fifoData[i + k + 2], fifoData[i + k + 3]);
@@ -853,7 +848,6 @@ void scsiPhyConfig()
         HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_SET);
     }
 
-
     uint8_t idMask = 0;
     for (int i = 0; i < 8; ++i)
     {
@@ -876,7 +870,6 @@ void scsiPhyConfig()
             SCSI_FAST_SELECTION : SCSI_DEFAULT_SELECTION;
 }
 
-
 // 1 = DBx error
 // 2 = Parity error
 // 4 = MSG error