From: Michael McMaster Date: Sun, 23 May 2021 09:49:43 +0000 (+1000) Subject: Improve stability of fpga async mem interface X-Git-Tag: v6.4.10 X-Git-Url: http://git.codesrc.com/gitweb.cgi?a=commitdiff_plain;h=1ed58adb1595d060fcd81db12d0bb1503c7d776f;p=SCSI2SD-V6.git Improve stability of fpga async mem interface --- 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 ccfcd0dd..f578e3df 100644 Binary files a/rtl/fpga_bitmap.2020.o and b/rtl/fpga_bitmap.2020.o differ 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