diff options
-rw-r--r-- | Makefile | 19 | ||||
-rw-r--r-- | libraries/libtfm/Makefile | 2 | ||||
-rw-r--r-- | projects/cli-test/Makefile | 19 | ||||
-rw-r--r-- | projects/cli-test/cli-test.c | 50 | ||||
-rw-r--r-- | projects/cli-test/mgmt-cli.c | 15 | ||||
-rw-r--r-- | projects/cli-test/mgmt-misc.c | 94 | ||||
-rw-r--r-- | projects/hsm/Makefile | 10 | ||||
-rw-r--r-- | projects/hsm/mgmt-cli.c | 14 | ||||
-rw-r--r-- | projects/hsm/mgmt-misc.c | 138 | ||||
-rw-r--r-- | stm-fmc.c | 61 |
10 files changed, 325 insertions, 97 deletions
@@ -1,5 +1,6 @@ -# Copyright (c) 2015-2017, NORDUnet A/S -# All rights reserved. +# Copyright (c) 2015-2017, NORDUnet A/S All rights reserved. +# Copyright: 2020, The Commons Conservancy Cryptech Project +# SPDX-License-Identifier: BSD-3-Clause # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -11,9 +12,9 @@ # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # -# - Neither the name of the NORDUnet nor the names of its contributors may -# be used to endorse or promote products derived from this software -# without specific prior written permission. +# - Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -130,6 +131,9 @@ CFLAGS += -I$(MBED_DIR)/targets/hal/TARGET_STM/TARGET_STM32F4/$(BOARD) ifdef DO_TASK_METRICS CFLAGS += -DDO_TASK_METRICS endif +ifdef DO_TIMING +CFLAGS += -DDO_TIMING +endif %.o : %.c $(CC) $(CFLAGS) -c -o $@ $< @@ -158,7 +162,7 @@ $(LIBTFM_BLD)/libtfm.a: .FORCE $(MAKE) -C $(LIBTFM_BLD) PREFIX=$(PREFIX) $(LIBHAL_BLD)/libhal.a: $(LIBTFM_BLD)/libtfm.a .FORCE - $(MAKE) -C $(LIBHAL_BLD) IO_BUS=fmc RPC_MODE=server RPC_TRANSPORT=serial KS=flash libhal.a + $(MAKE) -C $(LIBHAL_BLD) IO_BUS=fmc RPC_MODE=server RPC_TRANSPORT=serial KS=flash HASH_CORES=yes libhal.a $(LIBCLI_BLD)/libcli.a: .FORCE $(MAKE) -C $(LIBCLI_BLD) @@ -175,6 +179,9 @@ hsm: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a $(LIBCLI_BLD)/libcli.a .FORCE bootloader: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a .FORCE $(MAKE) -C projects/bootloader +modexpng-test: $(BOARD_OBJS) $(LIBS) .FORCE + $(MAKE) -C projects/modexpng-test + # don't automatically delete objects, to avoid a lot of unnecessary rebuilding .SECONDARY: $(BOARD_OBJS) diff --git a/libraries/libtfm/Makefile b/libraries/libtfm/Makefile index 359729b..34b9314 100644 --- a/libraries/libtfm/Makefile +++ b/libraries/libtfm/Makefile @@ -5,7 +5,7 @@ # vpath %.c ${LIBTFM_SRC} # vpath %.h ${LIBTFM_SRC} -BITS := 8192 +BITS := 4096 HDR := ${LIBTFM_SRC}/tomsfastmath/src/headers/tfm.h LIB := tomsfastmath/libtfm.a diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index fadf2cf..5971d13 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -1,5 +1,6 @@ -TEST = cli-test +PROJ = cli-test +# objs in addition to $(PROJ).o OBJS = \ mgmt-cli.o \ mgmt-dfu.o \ @@ -8,17 +9,21 @@ OBJS = \ mgmt-keywrap.o \ mgmt-masterkey.o \ mgmt-misc.o \ - mgmt-show.o \ - mgmt-test.o \ - test-fmc.o \ - test-mkmif.o \ - test_sdram.o + mgmt-show.o CFLAGS += -I$(LIBCLI_SRC) -I$(LIBHAL_SRC) +CFLAGS += -I$(LIBTFM_BLD) +CFLAGS += -Wno-missing-field-initializers + +ifdef DO_TIMING +CFLAGS += -DDO_TIMING +OBJS += mgmt-timing.o $(TOPLEVEL)/stm-dwt.o +LDFLAGS += -lm +endif LIBS += $(LIBCLI_BLD)/libcli.a $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a -all: $(TEST:=.elf) +all: $(PROJ:=.elf) %.elf: %.o $(BOARD_OBJS) $(OBJS) $(LIBS) $(CC) $(CFLAGS) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$*.map diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index c0fe57e..c50338b 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -57,9 +57,18 @@ int main() { stm_init(); - led_on(LED_GREEN); + /* For the hsm, the keystores are initialized in hal_rpc_server_init(), + * which is...less than optimal, but this is not the time or place to fix + * it, especially in light of all the terrible things I'm doing in this + * version of cli-test. + */ + extern void *hal_ks_token, *hal_ks_volatile; + extern int hal_ks_init(void *, int); + if (hal_ks_init(hal_ks_volatile, 1) != 0 || hal_ks_init(hal_ks_token, 1) != 0) + Error_Handler(); + while (1) { cli_main(); /* embedded_cli_loop returns when the user enters 'quit' or 'exit' */ @@ -70,23 +79,36 @@ main() } -/* - * Dummy to solve link problem. Not obvious to me that a program - * called "cli-test" should be duplicating all of the HSM keystore - * logic, let alone that it should be doing it badly, but, whatever. - * - * We could just copy the sdram_malloc() code from hsm.c, but since - * one of the other commands linked into cli-test goes merrily stomping - * all over the entire SDRAM chip, that might not work out so well. - * - * Issue deferred until somebody cares. - */ +/* end of variables declared with __attribute__((section(".sdram1"))) */ +extern uint8_t _esdram1 __asm ("_esdram1"); +/* end of SDRAM1 section */ +extern uint8_t __end_sdram1 __asm ("__end_sdram1"); +static uint8_t *sdram_heap = &_esdram1; -#warning hal_allocate_static_memory() stubbed out in cli-test, see source code +/* Allocate memory from SDRAM1. */ +static uint8_t *sdram_malloc(size_t size) +{ + uint8_t *p = sdram_heap; +#define pad(n) (((n) + 3) & ~3) + size = pad(size); + + if (p + size + sizeof(uint32_t) > &__end_sdram1) + return NULL; + + *(uint32_t *)p = (uint32_t)size; + p += sizeof(uint32_t); + + sdram_heap += size + sizeof(uint32_t); + return p; +} + +/* Implement static memory allocation for libhal over sdram_malloc(). + * Used in hal_ks_init. + */ void *hal_allocate_static_memory(const size_t size) { - return NULL; + return sdram_malloc(size); } int hal_free_static_memory(const void * const ptr) diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c index 416be77..fa63d50 100644 --- a/projects/cli-test/mgmt-cli.c +++ b/projects/cli-test/mgmt-cli.c @@ -4,6 +4,8 @@ * Management CLI code. * * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved. + * Copyright: 2020, The Commons Conservancy Cryptech Project + * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -15,9 +17,9 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -48,6 +50,9 @@ #include "mgmt-keystore.h" #include "mgmt-masterkey.h" #include "mgmt-keywrap.h" +#ifdef DO_TIMING +#include "mgmt-timing.h" +#endif #undef HAL_OK #define HAL_OK LIBHAL_OK @@ -173,10 +178,12 @@ int cli_main(void) configure_cli_show(cli); configure_cli_fpga(cli); configure_cli_misc(cli); - configure_cli_test(cli); configure_cli_keystore(cli); configure_cli_masterkey(cli); configure_cli_keywrap(cli); +#ifdef DO_TIMING + configure_cli_timing(cli); +#endif while (1) { control_mgmt_uart_dma_rx(DMA_RX_START); diff --git a/projects/cli-test/mgmt-misc.c b/projects/cli-test/mgmt-misc.c index db8dbd2..ca95c63 100644 --- a/projects/cli-test/mgmt-misc.c +++ b/projects/cli-test/mgmt-misc.c @@ -3,7 +3,9 @@ * ----------- * Miscellaneous CLI functions. * - * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved. + * Copyright: 2020, The Commons Conservancy Cryptech Project + * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -15,9 +17,9 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -144,11 +146,95 @@ static int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], in return CLI_OK; } +static int cmd_rsa_blinding(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + if (argc != 1) { + cli_print(cli, "Wrong number of arguments (%i).", argc); + cli_print(cli, "Syntax: %s <on|off|clear>", command); + return CLI_ERROR; + } + + if (strcmp(argv[0], "on") == 0) + hal_rsa_set_blinding(1); + else if (strcmp(argv[0], "off") == 0) + hal_rsa_set_blinding(0); + else if (strcmp(argv[0], "clear") == 0) + hal_rsa_clear_blinding_cache(); + else { + cli_print(cli, "Argument must be 'on', 'off', or 'clear' - not '%s'", argv[0]); + return CLI_ERROR; + } + + return CLI_OK; +} + +static int cmd_rsa_crt(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int onoff; + + if (argc != 1) { + cli_print(cli, "Wrong number of arguments (%i).", argc); + cli_print(cli, "Syntax: %s <on|off>", command); + return CLI_ERROR; + } + + if (strcmp(argv[0], "on") == 0) + onoff = 1; + else if (strcmp(argv[0], "off") == 0) + onoff = 0; + else { + cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]); + return CLI_ERROR; + } + + hal_rsa_set_crt(onoff); + + return CLI_OK; +} + +static int cmd_rsa_modexpng(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int onoff; + + if (argc != 1) { + cli_print(cli, "Wrong number of arguments (%i).", argc); + cli_print(cli, "Syntax: %s <on|off>", command); + return CLI_ERROR; + } + + if (strcmp(argv[0], "on") == 0) + onoff = 1; + else if (strcmp(argv[0], "off") == 0) + onoff = 0; + else { + cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]); + return CLI_ERROR; + } + + hal_error_t err; + if ((err = hal_modexp_use_modexpng(onoff)) == LIBHAL_OK) + return CLI_OK; + + cli_print(cli, hal_error_string(err)); + return CLI_ERROR; +} + void configure_cli_misc(struct cli_def *cli) { /* filetransfer */ cli_register_command(cli, NULL, "filetransfer", cmd_filetransfer, 0, 0, "Test file transfering"); + struct cli_command *c_rsa = cli_register_command(cli, NULL, "rsa", NULL, 0, 0, NULL); + + /* rsa blinding */ + cli_register_command(cli, c_rsa, "blinding", cmd_rsa_blinding, 0, 0, "Set use of RSA blinding"); + + /* rsa crt */ + cli_register_command(cli, c_rsa, "crt", cmd_rsa_crt, 0, 0, "Set use of RSA CRT"); + + /* rsa modexpng */ + cli_register_command(cli, c_rsa, "modexpng", cmd_rsa_modexpng, 0, 0, "Set use of ModExpNG"); + /* reboot */ cli_register_command(cli, NULL, "reboot", cmd_reboot, 0, 0, "Reboot the STM32"); } diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index 37c552d..a2b7c0d 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -16,6 +16,8 @@ CFLAGS += -DNUM_RPC_TASK=4 CFLAGS += -I$(LIBHAL_SRC) CFLAGS += -I$(LIBCLI_SRC) +CFLAGS += -I$(LIBTFM_BLD) +CFLAGS += -Wno-missing-field-initializers LIBS += $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a LIBS += $(LIBCLI_BLD)/libcli.a @@ -32,6 +34,14 @@ ifdef DO_TASK_METRICS CFLAGS += -DDO_TASK_METRICS endif +ifdef DO_TIMING +CFLAGS += -DDO_TIMING +CFLAGS += -I../cli-test +CFLAGS += -DCLI_STACK_SIZE=65536 +OBJS += ../cli-test/mgmt-timing.o $(TOPLEVEL)/stm-dwt.o +LDFLAGS += -lm +endif + all: $(PROJ:=.elf) %.elf: %.o $(BOARD_OBJS) $(OBJS) $(LIBS) diff --git a/projects/hsm/mgmt-cli.c b/projects/hsm/mgmt-cli.c index 2b5be1f..fd5c90a 100644 --- a/projects/hsm/mgmt-cli.c +++ b/projects/hsm/mgmt-cli.c @@ -4,6 +4,8 @@ * Management CLI code. * * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved. + * Copyright: 2020, The Commons Conservancy Cryptech Project + * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -15,9 +17,9 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -49,6 +51,9 @@ #include "mgmt-keystore.h" #include "mgmt-masterkey.h" #include "mgmt-task.h" +#ifdef DO_TIMING +#include "mgmt-timing.h" +#endif #undef HAL_OK #define HAL_OK LIBHAL_OK @@ -197,6 +202,9 @@ int cli_main(void) configure_cli_bootloader(cli); configure_cli_misc(cli); configure_cli_task(cli); +#ifdef DO_TIMING + configure_cli_timing(cli); +#endif while (1) { control_mgmt_uart_dma_rx(DMA_RX_START); diff --git a/projects/hsm/mgmt-misc.c b/projects/hsm/mgmt-misc.c index 72ee1f2..116197d 100644 --- a/projects/hsm/mgmt-misc.c +++ b/projects/hsm/mgmt-misc.c @@ -3,7 +3,9 @@ * ----------- * Miscellaneous CLI functions. * - * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * Copyright (c) 2016-2018, NORDUnet A/S All rights reserved. + * Copyright: 2020, The Commons Conservancy Cryptech Project + * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -15,9 +17,9 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -155,32 +157,108 @@ static int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], in return CLI_OK; } -static int cmd_keywrap_core(struct cli_def *cli, const char *command, char *argv[], int argc) +static int cmd_rsa_blinding(struct cli_def *cli, const char *command, char *argv[], int argc) { - command = command; + if (argc != 1) { + cli_print(cli, "Wrong number of arguments (%i).", argc); + cli_print(cli, "Syntax: %s <on|off|clear>", command); + return CLI_ERROR; + } + + if (strcmp(argv[0], "on") == 0) + hal_rsa_set_blinding(1); + else if (strcmp(argv[0], "off") == 0) + hal_rsa_set_blinding(0); + else if (strcmp(argv[0], "clear") == 0) + hal_rsa_clear_blinding_cache(); + else { + cli_print(cli, "Argument must be 'on', 'off', or 'clear' - not '%s'", argv[0]); + return CLI_ERROR; + } + + return CLI_OK; +} + +static int cmd_rsa_crt(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int onoff; + + if (argc != 1) { + cli_print(cli, "Wrong number of arguments (%i).", argc); + cli_print(cli, "Syntax: %s <on|off>", command); + return CLI_ERROR; + } + + if (strcmp(argv[0], "on") == 0) + onoff = 1; + else if (strcmp(argv[0], "off") == 0) + onoff = 0; + else { + cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]); + return CLI_ERROR; + } + + hal_rsa_set_crt(onoff); + + return CLI_OK; +} + +static int cmd_rsa_modexpng(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int onoff; - if (argc == 1) { - int onoff = -1; - if (strcmp(argv[0], "on") == 0) - onoff = 1; - else if (strcmp(argv[0], "off") == 0) - onoff = 0; - if (onoff >= 0) { - int ret = hal_aes_use_keywrap_core(onoff); - if (ret) - cli_print(cli, "keywrap core enabled"); - else if (onoff) - cli_print(cli, "keywrap core not found"); - else - cli_print(cli, "keywrap core disabled"); - return CLI_OK; - } + if (argc != 1) { + cli_print(cli, "Wrong number of arguments (%i).", argc); + cli_print(cli, "Syntax: %s <on|off>", command); + return CLI_ERROR; } - cli_print(cli, "Syntax: keywrap core <on|off>"); + if (strcmp(argv[0], "on") == 0) + onoff = 1; + else if (strcmp(argv[0], "off") == 0) + onoff = 0; + else { + cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]); + return CLI_ERROR; + } + + hal_error_t err; + if ((err = hal_modexp_use_modexpng(onoff)) == LIBHAL_OK) + return CLI_OK; + + cli_print(cli, hal_error_string(err)); return CLI_ERROR; } +static int cmd_keywrap_core(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int onoff; + + if (argc != 1) { + cli_print(cli, "Wrong number of arguments (%i).", argc); + cli_print(cli, "Syntax: %s <on|off>", command); + return CLI_ERROR; + } + + if (strcmp(argv[0], "on") == 0) + onoff = 1; + else if (strcmp(argv[0], "off") == 0) + onoff = 0; + else { + cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]); + return CLI_ERROR; + } + + int ret = hal_aes_use_keywrap_core(onoff); + if (ret) + cli_print(cli, "keywrap core enabled"); + else if (onoff) + cli_print(cli, "keywrap core not found"); + else + cli_print(cli, "keywrap core disabled"); + return CLI_OK; +} + void configure_cli_misc(struct cli_def *cli) { struct cli_command *c_keywrap = cli_register_command(cli, NULL, "keywrap", NULL, 0, 0, NULL); @@ -196,7 +274,19 @@ void configure_cli_misc(struct cli_def *cli) /* profile stop */ cli_register_command(cli, c_profile, "stop", cmd_profile_stop, 0, 0, "Stop collecting profiling data"); -#endif +#endif + + struct cli_command *c_rsa = cli_register_command(cli, NULL, "rsa", NULL, 0, 0, NULL); + + /* rsa blinding */ + cli_register_command(cli, c_rsa, "blinding", cmd_rsa_blinding, 0, 0, "Set use of RSA blinding"); + + /* rsa crt */ + cli_register_command(cli, c_rsa, "crt", cmd_rsa_crt, 0, 0, "Set use of RSA CRT"); + + /* rsa modexpng */ + cli_register_command(cli, c_rsa, "modexpng", cmd_rsa_modexpng, 0, 0, "Set use of ModExpNG"); + /* reboot */ cli_register_command(cli, NULL, "reboot", cmd_reboot, 0, 0, "Reboot the STM32"); } @@ -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; } |