From 0f8c20fe0658082c044443d0c8a51b773c457191 Mon Sep 17 00:00:00 2001 From: "Pavel V. Shatov (Meister)" Date: Sat, 7 Jul 2018 00:40:13 +0300 Subject: Changed FMC initialization code to match the new sync FMC arbiter. Removed unnecessary code (no more double read, yay!) --- stm-fmc.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'stm-fmc.c') 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; + } } -- cgit v1.2.3 From 624527539a83dbfd0dc2f03fda1cff14a1669811 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 7 Sep 2018 12:13:37 -0400 Subject: Tweak for 60MHz FMC clock. --- stm-fmc.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'stm-fmc.c') diff --git a/stm-fmc.c b/stm-fmc.c index 58df6fe..1019531 100644 --- a/stm-fmc.c +++ b/stm-fmc.c @@ -153,7 +153,18 @@ void fmc_init(void) fmc_timing.BusTurnAroundDuration = 0; // use smallest allowed divisor for best performance - fmc_timing.CLKDivision = 2; + // + // FMC_CLK = HCLK / CLKDivision, HCLK is 180 MHz + // + // Allowed values for CLKDivision are integers >= 2. + // + // Division == 2: FMC_CLK = 180 / 2 = 90 MHz (highest allowed frequency) + // Division == 3: FMC_CLK = 180 / 3 = 60 MHz (one step below) + // ... + // + +// fmc_timing.CLKDivision = 2; // 90 MHz + fmc_timing.CLKDivision = 3; // 60 MHz // use min suitable for fastest transfer fmc_timing.DataLatency = 4; @@ -164,22 +175,21 @@ void fmc_init(void) // 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. + // 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; - } + // 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; + } } -- cgit v1.2.3