From f118ea7be8d112919ea4ea350745cc35b0a3ff78 Mon Sep 17 00:00:00 2001 From: Michael McMaster Date: Sun, 23 May 2021 19:49:43 +1000 Subject: [PATCH] Improve stability of fpga async mem interface --- STM32CubeMX/2020c.diff | 94 ++++++++++++++++---------------- STM32CubeMX/2020c/Src/fsmc.c | 9 ++-- STM32CubeMX/2021.diff | 102 +++++++++++++++++++---------------- STM32CubeMX/2021/Src/fmc.c | 9 ++-- rtl/fpga_bitmap.2020.o | Bin 32724 -> 32724 bytes src/firmware/bsp_driver_sd.c | 99 +++++++++++++++++----------------- src/firmware/config.c | 2 +- src/firmware/scsiPhy.c | 23 +++----- 8 files changed, 173 insertions(+), 165 deletions(-) diff --git a/STM32CubeMX/2020c.diff b/STM32CubeMX/2020c.diff index 7e740bae..63bce4b9 100644 --- a/STM32CubeMX/2020c.diff +++ b/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 diff --git a/STM32CubeMX/2020c/Src/fsmc.c b/STM32CubeMX/2020c/Src/fsmc.c index 1b01446f..52f03f4b 100644 --- a/STM32CubeMX/2020c/Src/fsmc.c +++ b/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; diff --git a/STM32CubeMX/2021.diff b/STM32CubeMX/2021.diff index 53f7cbf0..d237f6fb 100644 --- a/STM32CubeMX/2021.diff +++ b/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 diff --git a/STM32CubeMX/2021/Src/fmc.c b/STM32CubeMX/2021/Src/fmc.c index a5f765a4..a5271670 100644 --- a/STM32CubeMX/2021/Src/fmc.c +++ b/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; diff --git a/rtl/fpga_bitmap.2020.o b/rtl/fpga_bitmap.2020.o index ccfcd0dd19e229380b5d35ff7137c54ecb1f190b..f578e3df9802fd0ed403692d0b0742d8c1872542 100644 GIT binary patch literal 32724 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 EKiaF^G5`Po literal 32724 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 sa6881YZi==f7W?~7qYY-bf7x7p0A&t^xBvhE diff --git a/src/firmware/bsp_driver_sd.c b/src/firmware/bsp_driver_sd.c index 2ac26625..dc09fed1 100755 --- a/src/firmware/bsp_driver_sd.c +++ b/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 } diff --git a/src/firmware/config.c b/src/firmware/config.c index 9052d148..17ceab7d 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -36,7 +36,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0649; +static const uint16_t FIRMWARE_VERSION = 0x064A; // Optional static config extern uint8_t* __fixed_config; diff --git a/src/firmware/scsiPhy.c b/src/firmware/scsiPhy.c index 0c0c46c0..87c7beb7 100755 --- a/src/firmware/scsiPhy.c +++ b/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 -- 2.38.5