[Cryptech-Commits] [sw/stm32] 01/01: Changed FMC initialization code to match the new sync FMC arbiter. Removed unnecessary code (no more double read, yay!)

git at cryptech.is git at cryptech.is
Fri Jul 6 21:42:19 UTC 2018


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch fmc_clk
in repository sw/stm32.

commit 0f8c20fe0658082c044443d0c8a51b773c457191
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Sat Jul 7 00:40:13 2018 +0300

    Changed FMC initialization code to match the new sync FMC arbiter. Removed
    unnecessary code (no more double read, yay!)
---
 stm-fmc.c | 25 ++++++++++++++++++++++---
 stm-fmc.h | 52 ++++------------------------------------------------
 2 files changed, 26 insertions(+), 51 deletions(-)

diff --git a/stm-fmc.c b/stm-fmc.c
index c5086b4..58df6fe 100644
--- a/stm-fmc.c
+++ b/stm-fmc.c
@@ -115,7 +115,7 @@ void fmc_init(void)
     _fmc_fpga_inst.Init.WrapMode = FMC_WRAP_MODE_DISABLE;
 
     // don't care in fixed latency mode
-    _fmc_fpga_inst.Init.WaitSignalActive = FMC_WAIT_TIMING_DURING_WS;
+    _fmc_fpga_inst.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
 
     // allow write access to fpga
     _fmc_fpga_inst.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
@@ -155,12 +155,31 @@ void fmc_init(void)
     // use smallest allowed divisor for best performance
     fmc_timing.CLKDivision = 2;
 
-    // stm is too slow to work with min allowed 2-cycle latency
-    fmc_timing.DataLatency = 3;
+    // use min suitable for fastest transfer
+    fmc_timing.DataLatency = 4;
 
     // don't care in sync mode
     fmc_timing.AccessMode = FMC_ACCESS_MODE_A;
 
     // initialize fmc
     HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL);
+		
+		// STM32 only enables FMC clock right before the very first read/write
+		// access. FPGA takes certain time (<= 100 us) to lock its PLL to this frequency,
+		// so a certain number of initial FMC transactions may be missed. One read transaction
+		// takes ~0.1 us (9 ticks @ 90 MHz), so doing 1000 dummy reads will make sure, that FPGA
+		// has already locked its PLL and is ready. Another way around is to repeatedly read
+		// some register that is guaranteed to have known value until reading starts returning
+		// correct data.
+		
+		// to prevent compiler from optimizing this away, we pretent we're calculating sum
+		int cyc;
+		uint32_t sum;
+		volatile uint32_t part;
+		
+		for (cyc=0; cyc<1000; cyc++)
+		{
+			part = *(__IO uint32_t *)FMC_FPGA_BASE_ADDR;
+			sum += part;
+		}
 }
diff --git a/stm-fmc.h b/stm-fmc.h
index eab053d..92b261b 100644
--- a/stm-fmc.h
+++ b/stm-fmc.h
@@ -39,12 +39,6 @@
 
 #define FMC_FPGA_BASE_ADDR              0x60000000
 #define FMC_FPGA_ADDR_MASK              0x03FFFFFC  // there are 26 physical lines, but "only" 24 usable for now
-#define FMC_FPGA_NWAIT_MAX_POLL_TICKS   10
-
-#define FMC_GPIO_PORT_NWAIT             GPIOD
-#define FMC_GPIO_PIN_NWAIT              GPIO_PIN_6
-
-#define FMC_NWAIT_IDLE                  GPIO_PIN_SET
 
 #define fmc_af_gpio(port, pins)			       \
     GPIO_InitStruct.Pin = pins;			       \
@@ -58,60 +52,22 @@
 
 extern void fmc_init(void);
 
-static inline HAL_StatusTypeDef _fmc_nwait_idle(void)
-{
-    int cnt;
-
-    // poll NWAIT (number of iterations is limited)
-    for (cnt=0; cnt<FMC_FPGA_NWAIT_MAX_POLL_TICKS; cnt++)
-    {
-        // read pin state
-        if (HAL_GPIO_ReadPin(FMC_GPIO_PORT_NWAIT, FMC_GPIO_PIN_NWAIT) == FMC_NWAIT_IDLE)
-            return HAL_OK;
-    }
-
-    return HAL_ERROR;
-}
-
-static inline HAL_StatusTypeDef fmc_write_32(const uint32_t addr, const uint32_t data)
+static inline void fmc_write_32(const uint32_t addr, const uint32_t data)
 {
     // calculate target fpga address
     uint32_t *ptr = (uint32_t *) (FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK));
 
     // write data to fpga
    *ptr = data;
-
-   // wait for transaction to complete
-    return _fmc_nwait_idle();
 }
 
-static inline HAL_StatusTypeDef fmc_read_32(const uint32_t addr, uint32_t * const data)
+static inline void fmc_read_32(const uint32_t addr, uint32_t * const data)
 {
     // calculate target fpga address
     uint32_t *ptr = (uint32_t *) (FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK));
 
-    /* Pavel says:
-     * The short story is like, on one hand STM32 has a dedicated FMC_NWAIT
-     * pin, that can be used in variable-latency data transfer mode. On the
-     * other hand STM32 also has a very nasty hardware bug associated with
-     * FMC_WAIT, that causes processor to freeze under certain conditions.
-     * Because of this FMC_NWAIT cannot be used and FPGA can't properly signal
-     * to STM32, when data transfer is done. Because of that we have to read
-     * two times.
-     */
-
-    HAL_StatusTypeDef status;
-
-    *data = *ptr;
-    status = _fmc_nwait_idle();
-
-    if (status != HAL_OK)
-        return status;
-
-    *data = *ptr;
-    status = _fmc_nwait_idle();
-
-    return status;
+		// read data from fpga
+    *data = *ptr; 
 }
 
 #endif /* __STM_FMC_H */



More information about the Commits mailing list