Improve stability of fpga async mem interface v6.4.10
authorMichael McMaster <michael@codesrc.com>
Sun, 23 May 2021 09:49:43 +0000 (19:49 +1000)
committerMichael McMaster <michael@codesrc.com>
Sun, 23 May 2021 12:45:18 +0000 (22:45 +1000)
STM32CubeMX/2020c.diff
STM32CubeMX/2020c/Src/fsmc.c
STM32CubeMX/2021.diff
STM32CubeMX/2021/Src/fmc.c
rtl/fpga_bitmap.2020.o
src/firmware/bsp_driver_sd.c
src/firmware/config.c
src/firmware/scsiPhy.c

index 7e740bae8d6ee355b146bd8be734469eb45a8342..63bce4b9ead656e5f4c8e32149e6867369b069cd 100644 (file)
@@ -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 
index 1b01446fc190bca91946f7a6ecd5170f9d0c89dc..52f03f4ba748c668a80492db17020165a0479e0a 100644 (file)
@@ -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;
 
index 53f7cbf06ba6c94ad51f4dc050571b09c342d223..d237f6fb412e2dcb8fc3b675176b5df3646eb21e 100644 (file)
@@ -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 
index a5f765a44617da40c25d9552edc048c8e3590392..a5271670deb218afba4ad1973f23df9d8c7f16dc 100644 (file)
@@ -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;
 
index ccfcd0dd19e229380b5d35ff7137c54ecb1f190b..f578e3df9802fd0ed403692d0b0742d8c1872542 100644 (file)
Binary files a/rtl/fpga_bitmap.2020.o and b/rtl/fpga_bitmap.2020.o differ
index 2ac26625994728a3957f0b036ca48701f251329d..dc09fed11a3cdc15849ca24d6559e5097484bb43 100755 (executable)
@@ -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
     }
index 9052d148b2e6e4f5cfc66be961691bee016358b6..17ceab7d9faced3cf3a5dd3bf5873e861f6ea0d0 100755 (executable)
@@ -36,7 +36,7 @@
 \r
 #include <string.h>\r
 \r
-static const uint16_t FIRMWARE_VERSION = 0x0649;\r
+static const uint16_t FIRMWARE_VERSION = 0x064A;\r
 \r
 // Optional static config\r
 extern uint8_t* __fixed_config;\r
index 0c0c46c0e8ff0cac258752f3b99bdfc7bde4da05..87c7beb7dc550a9925e1942f2a0c28fa9bebbc57 100755 (executable)
 #include "stm32f2xx.h"\r
 #include "stm32f2xx_hal.h"\r
 #include "stm32f2xx_hal_dma.h"\r
+#include "fsmc.h"\r
+#define FMC_NORSRAM_TimingTypeDef FSMC_NORSRAM_TimingTypeDef\r
+#define FMC_ACCESS_MODE_A FSMC_ACCESS_MODE_A\r
+#define FMC_NORSRAM_Timing_Init FSMC_NORSRAM_Timing_Init\r
+#define FMC_NORSRAM_DEVICE FSMC_NORSRAM_DEVICE\r
 #endif\r
 \r
 #ifdef STM32F4xx\r
 #include "stm32f4xx.h"\r
 #include "stm32f4xx_hal.h"\r
 #include "stm32f4xx_hal_dma.h"\r
+#include "fmc.h"\r
 #endif\r
 \r
 #include "gpio.h"\r
@@ -442,16 +448,7 @@ scsiWritePIO(const uint8_t* data, uint32_t count)
                 scsiPhyTx32(fifoData[i + 120 + k], fifoData[i + k + 121]);\r
                 scsiPhyTx32(fifoData[i + 122 + k], fifoData[i + k + 123]);\r
                 scsiPhyTx32(fifoData[i + 124 + k], fifoData[i + k + 125]);\r
-\r
-                // Last write must be 16bit to avoid having data waiting in the AHB bus\r
-                // somewhere still waiting to be written while we're off checking\r
-                // for empty fifos\r
-                // Note also that the fmc fifo is disabled on stm32f446 because it's too big\r
-                // (64 bytes) and we may think the fpga fifo is empty even though\r
-                // there's pending writes\r
-                scsiPhyTx(fifoData[i + 126 + k]);\r
-                scsiPhyTx(fifoData[i + k + 127]);\r
-\r
+                scsiPhyTx32(fifoData[i + 126 + k], fifoData[i + k + 127]);\r
             }\r
 \r
             i += chunk16;\r
@@ -461,9 +458,7 @@ scsiWritePIO(const uint8_t* data, uint32_t count)
             uint32_t chunk16 = count16 - i;\r
 \r
             uint32_t k = 0;\r
-            // Note that last 4 bytes will fall through to next loop, which avoids\r
-            // ending on a 32bit write.\r
-            for (; k + 4 < chunk16; k += 4)\r
+            for (; k + 4 <= chunk16; k += 4)\r
             {\r
                 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);\r
                 scsiPhyTx32(fifoData[i + k + 2], fifoData[i + k + 3]);\r
@@ -853,7 +848,6 @@ void scsiPhyConfig()
         HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_SET);\r
     }\r
 \r
-\r
     uint8_t idMask = 0;\r
     for (int i = 0; i < 8; ++i)\r
     {\r
@@ -876,7 +870,6 @@ void scsiPhyConfig()
             SCSI_FAST_SELECTION : SCSI_DEFAULT_SELECTION;\r
 }\r
 \r
-\r
 // 1 = DBx error\r
 // 2 = Parity error\r
 // 4 = MSG error\r