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 ++++++++++++++++++++++--- 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 Date: Mon, 16 Jul 2018 15:00:16 -0400 Subject: Whack various bits of sw/stm32 test code to compile on fmc_clk branch. --- projects/board-test/fmc-perf.c | 20 ++++---------------- projects/board-test/fmc-probe.c | 5 +---- projects/board-test/fmc-test.c | 16 ++++++---------- projects/cli-test/test-fmc.c | 12 ++---------- 4 files changed, 13 insertions(+), 40 deletions(-) diff --git a/projects/board-test/fmc-perf.c b/projects/board-test/fmc-perf.c index 71d0149..5af0946 100644 --- a/projects/board-test/fmc-perf.c +++ b/projects/board-test/fmc-perf.c @@ -31,14 +31,8 @@ static void sanity(void) uint32_t rnd, data; rnd = random(); - if (fmc_write_32(0, rnd) != 0) { - uart_send_string("fmc_write_32 failed\r\n"); - Error_Handler(); - } - if (fmc_read_32(0, &data) != 0) { - uart_send_string("fmc_read_32 failed\r\n"); - Error_Handler(); - } + fmc_write_32(0, rnd); + fmc_read_32(0, &data); if (data != rnd) { uart_send_string("Data bus fail: expected "); uart_send_hex(rnd, 8); @@ -76,10 +70,7 @@ static void test_read(void) uint32_t i, data; for (i = 0; i < TEST_NUM_ROUNDS; ++i) { - if (fmc_read_32(0, &data) != 0) { - uart_send_string("fmc_read_32 failed\r\n"); - Error_Handler(); - } + fmc_read_32(0, &data); } } @@ -88,10 +79,7 @@ static void test_write(void) uint32_t i; for (i = 0; i < TEST_NUM_ROUNDS; ++i) { - if (fmc_write_32(0, i) != 0) { - uart_send_string("fmc_write_32 failed\r\n"); - Error_Handler(); - } + fmc_write_32(0, i); } } diff --git a/projects/board-test/fmc-probe.c b/projects/board-test/fmc-probe.c index 5f7fdb5..38897ab 100644 --- a/projects/board-test/fmc-probe.c +++ b/projects/board-test/fmc-probe.c @@ -21,10 +21,7 @@ static uint32_t read0(uint32_t addr) { uint32_t data; - if (fmc_read_32(addr, &data) != 0) { - uart_send_string("fmc_read_32 failed\r\n"); - Error_Handler(); - } + fmc_read_32(addr, &data); return data; } diff --git a/projects/board-test/fmc-test.c b/projects/board-test/fmc-test.c index 1421db0..bd30dd5 100644 --- a/projects/board-test/fmc-test.c +++ b/projects/board-test/fmc-test.c @@ -158,7 +158,7 @@ int main(void) int test_fpga_data_bus(void) //------------------------------------------------------------------------------ { - int c, ok; + int c; uint32_t rnd, buf; HAL_StatusTypeDef hal_result; @@ -171,12 +171,10 @@ int test_fpga_data_bus(void) if (hal_result != HAL_OK) break; // write value to fpga at address 0 - ok = fmc_write_32(0, rnd); - if (ok != 0) break; + fmc_write_32(0, rnd); // read value from fpga - ok = fmc_read_32(0, &buf); - if (ok != 0) break; + fmc_read_32(0, &buf); // compare (abort testing in case of error) if (buf != rnd) @@ -218,7 +216,7 @@ int test_fpga_data_bus(void) int test_fpga_address_bus(void) //------------------------------------------------------------------------------ { - int c, ok; + int c; uint32_t rnd, buf; HAL_StatusTypeDef hal_result; @@ -239,12 +237,10 @@ int test_fpga_address_bus(void) if (rnd == 0) continue; // write dummy value to fpga at some non-zero address - ok = fmc_write_32(rnd, buf); - if (ok != 0) break; + fmc_write_32(rnd, buf); // read value from fpga - ok = fmc_read_32(0, &buf); - if (ok != 0) break; + fmc_read_32(0, &buf); // fpga receives address of 32-bit word, while we need // byte address here to compare diff --git a/projects/cli-test/test-fmc.c b/projects/cli-test/test-fmc.c index 6773cfc..d9b0c9b 100644 --- a/projects/cli-test/test-fmc.c +++ b/projects/cli-test/test-fmc.c @@ -80,16 +80,8 @@ static int _write_then_read(struct cli_def *cli, uint32_t addr, uint32_t write_b { int ok; - ok = fmc_write_32(addr, write_buf); - if (ok != 0) { - cli_print(cli, "FMC write failed: 0x%x", ok); - return 0; - } - ok = fmc_read_32(0, read_buf); - if (ok != 0) { - cli_print(cli, "FMC read failed: 0x%x", ok); - return 0; - } + fmc_write_32(addr, write_buf); + fmc_read_32(0, read_buf); return 1; } -- 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(-) 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