aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2020-01-21 11:52:36 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2020-01-21 11:52:36 +0300
commit39f2d7ec4f35191884978db447bd97638b283d1d (patch)
tree93b519bf4e8b0e34016b60d7651bd6c198bd1b66
parente203f797dddfcd03419e7ac336a86a6186fce0c1 (diff)
parent723766c08127d3f489d90ea94bc090d9481bbebb (diff)
Merge branch 'fmc_clk'
-rw-r--r--stm-fmc.c61
1 files changed, 27 insertions, 34 deletions
diff --git a/stm-fmc.c b/stm-fmc.c
index 1019531..b5e79e8 100644
--- a/stm-fmc.c
+++ b/stm-fmc.c
@@ -62,7 +62,7 @@ void fmc_init(void)
*/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
fmc_af_gpio(GPIOE, GPIO_PIN_2
@@ -149,25 +149,14 @@ void fmc_init(void)
// don't care in sync mode
fmc_timing.DataSetupTime = 255;
- // not needed, since nwait will be polled manually
+ // not needed
fmc_timing.BusTurnAroundDuration = 0;
- // use smallest allowed divisor for best performance
- //
- // 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)
- // ...
- //
+ // use 45 MHz to match what FMC arbiter in the FPGA expects
+ fmc_timing.CLKDivision = 4; // 180/4
-// fmc_timing.CLKDivision = 2; // 90 MHz
- fmc_timing.CLKDivision = 3; // 60 MHz
-
- // use min suitable for fastest transfer
- fmc_timing.DataLatency = 4;
+ // use 6 to match what FMC arbiter in the FPGA expects
+ fmc_timing.DataLatency = 6;
// don't care in sync mode
fmc_timing.AccessMode = FMC_ACCESS_MODE_A;
@@ -175,21 +164,25 @@ 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.
-
- // 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;
- }
+ // 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.22 us (10 ticks @ 45 MHz), so doing ~500 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 = 0;
+ volatile uint32_t part;
+
+ for (cyc=0; cyc<500; cyc++)
+ {
+ part = *(__IO uint32_t *)FMC_FPGA_BASE_ADDR;
+ sum += part;
+ }
+
+ // dummy write to read-only address to not let the compiler remove the above loop
+ *(__IO uint32_t *)FMC_FPGA_BASE_ADDR = sum;
}