diff options
author | Paul Selkirk <paul@psgd.org> | 2016-05-24 18:13:26 -0400 |
---|---|---|
committer | Paul Selkirk <paul@psgd.org> | 2016-05-24 18:15:07 -0400 |
commit | ebe70741a4771698423e4c61939e88d6db66460d (patch) | |
tree | bf78c5e845c809e6dff113e0b2e46c94972317f4 | |
parent | 9bb798876768f702c5940dcf67feffc6d0e9a0a4 (diff) | |
parent | 6265025f7cd7f606b6da62c7add13a6008500cf7 (diff) |
Merge branch 'master' of git.cryptech.is:sw/stm32
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h | 2 | ||||
-rw-r--r-- | libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c | 9 | ||||
-rw-r--r-- | libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c | 98 | ||||
-rw-r--r-- | projects/cli-test/Makefile | 2 | ||||
-rw-r--r-- | projects/cli-test/cli-test.c | 98 | ||||
-rw-r--r-- | projects/cli-test/mgmt-cli.c | 4 | ||||
-rw-r--r-- | projects/cli-test/mgmt-cli.h | 33 | ||||
-rw-r--r-- | projects/cli-test/test_sdram.c | 274 | ||||
-rw-r--r-- | projects/cli-test/test_sdram.h | 42 | ||||
-rw-r--r-- | stm-fmc.c | 398 | ||||
-rw-r--r-- | stm-fmc.h | 22 | ||||
-rw-r--r-- | stm-init.c | 21 | ||||
-rw-r--r-- | stm-init.h | 19 | ||||
-rw-r--r-- | stm-sdram.c | 267 | ||||
-rw-r--r-- | stm-sdram.h | 66 |
16 files changed, 1013 insertions, 343 deletions
@@ -57,6 +57,7 @@ export BOARD_OBJS = \ $(TOPLEVEL)/spiflash_n25q128.o \ $(TOPLEVEL)/stm-fpgacfg.o \ $(TOPLEVEL)/stm-keystore.o \ + $(TOPLEVEL)/stm-sdram.o \ $(TOPLEVEL)/syscalls.o \ $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.o \ $(BOARD_DIR)/system_stm32f4xx.o \ diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h index 3844481..8a11b8b 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h @@ -65,7 +65,7 @@ //#define HAL_NOR_MODULE_ENABLED //#define HAL_PCCARD_MODULE_ENABLED #define HAL_SRAM_MODULE_ENABLED -//#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED //#define HAL_HASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c index 6d1d029..2a207b6 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c @@ -107,6 +107,15 @@ void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef* hsram) { } +void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram) +{ +} + +void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef* hsdram) +{ +} + + void HAL_UART_MspInit(UART_HandleTypeDef* huart) { GPIO_InitTypeDef GPIO_InitStruct; diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c index bf28b4b..bdf38fc 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c @@ -1413,23 +1413,31 @@ HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDe } else /* FMC_Bank2_SDRAM */ { - tmpr1 = Device->SDCR[FMC_SDRAM_BANK1]; - - /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */ - tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \ - FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \ - FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE)); - - tmpr1 |= (uint32_t)(Init->SDClockPeriod |\ - Init->ReadBurst |\ - Init->ReadPipeDelay); - - tmpr2 = Device->SDCR[FMC_SDRAM_BANK2]; +/////////////////////////////// +// BEGIN PIECE OF WEIRD CODE // +/////////////////////////////// +// +// tmpr1 = Device->SDCR[FMC_SDRAM_BANK1]; +// +// /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */ +// tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \ +// FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \ +// FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE)); +// +// tmpr1 |= (uint32_t)(Init->SDClockPeriod |\ +// Init->ReadBurst |\ +// Init->ReadPipeDelay); +// +/////////////////////////////// +// END PIECE OF WEIRD CODE // +/////////////////////////////// + + tmpr2 = Device->SDCR[FMC_SDRAM_BANK1]; /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */ - tmpr2 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \ - FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \ - FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE)); + tmpr2 &= ((uint32_t)~(FMC_SDCR2_NC | FMC_SDCR2_NR | FMC_SDCR2_MWID | \ + FMC_SDCR2_NB | FMC_SDCR2_CAS | FMC_SDCR2_WP | \ + FMC_SDCR2_SDCLK | FMC_SDCR2_RBURST | FMC_SDCR2_RPIPE)); tmpr2 |= (uint32_t)(Init->ColumnBitsNumber |\ Init->RowBitsNumber |\ @@ -1438,7 +1446,9 @@ HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDe Init->CASLatency |\ Init->WriteProtection); - Device->SDCR[FMC_SDRAM_BANK1] = tmpr1; +// +// Device->SDCR[FMC_SDRAM_BANK1] = tmpr1; +// Device->SDCR[FMC_SDRAM_BANK2] = tmpr2; } @@ -1490,30 +1500,44 @@ HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_Tim } else /* FMC_Bank2_SDRAM */ { - tmpr1 = Device->SDTR[FMC_SDRAM_BANK2]; - - /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */ - tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \ - FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \ - FMC_SDTR1_TRCD)); - - tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1) |\ - (((Timing->ExitSelfRefreshDelay)-1) << 4) |\ - (((Timing->SelfRefreshTime)-1) << 8) |\ - (((Timing->WriteRecoveryTime)-1) <<16) |\ - (((Timing->RCDDelay)-1) << 24)); - +/////////////////////////////// +// BEGIN PIECE OF WEIRD CODE // +/////////////////////////////// +// +// tmpr1 = Device->SDTR[FMC_SDRAM_BANK2]; +// +// /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */ +// tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \ +// FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \ +// FMC_SDTR1_TRCD)); +// +// tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1) |\ +// (((Timing->ExitSelfRefreshDelay)-1) << 4) |\ +// (((Timing->SelfRefreshTime)-1) << 8) |\ +// (((Timing->WriteRecoveryTime)-1) <<16) |\ +// (((Timing->RCDDelay)-1) << 24)); +// +/////////////////////////////// +// END PIECE OF WEIRD CODE // +/////////////////////////////// + tmpr2 = Device->SDTR[FMC_SDRAM_BANK1]; /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */ - tmpr2 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \ - FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \ - FMC_SDTR1_TRCD)); - tmpr2 |= (uint32_t)((((Timing->RowCycleDelay)-1) << 12) |\ - (((Timing->RPDelay)-1) << 20)); - - Device->SDTR[FMC_SDRAM_BANK2] = tmpr1; - Device->SDTR[FMC_SDRAM_BANK1] = tmpr2; + tmpr2 &= ((uint32_t)~(FMC_SDTR2_TMRD | FMC_SDTR2_TXSR | FMC_SDTR2_TRAS | \ + FMC_SDTR2_TRC | FMC_SDTR2_TWR | FMC_SDTR2_TRP | \ + FMC_SDTR2_TRCD)); + + tmpr2 |= (uint32_t)(((Timing->LoadToActiveDelay)-1U) |\ + (((Timing->ExitSelfRefreshDelay)-1U) << 4U) |\ + (((Timing->SelfRefreshTime)-1U) << 8U) |\ + (((Timing->WriteRecoveryTime)-1U) <<16U) |\ + (((Timing->RCDDelay)-1U) << 24U)); + +// +// Device->SDTR[FMC_SDRAM_BANK2] = tmpr1; +// + Device->SDTR[FMC_SDRAM_BANK2] = tmpr2; } return HAL_OK; diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index f3976e4..7737e13 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -1,6 +1,6 @@ TEST = cli-test -OBJS = crc32.o mgmt-cli.o +OBJS = crc32.o mgmt-cli.o test_sdram.o CFLAGS += -I$(LIBCLI_DIR) LIBS += $(LIBCLI_DIR)/libcli.a diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index 152c121..dfcf856 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -37,38 +37,12 @@ #include "stm-uart.h" #include "stm-fpgacfg.h" #include "stm-keystore.h" +#include "stm-sdram.h" #include "mgmt-cli.h" +#include "test_sdram.h" #include <string.h> -/* A bunch of defines to make it easier to add/maintain the CLI commands. - * - */ -#define _cli_cmd_struct(name, fullname, func, help) \ - static struct cli_command cmd_##fullname##_s = \ - {(char *) #name, func, 0, help, \ - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL} - -/* ROOT is a top-level label with no command */ -#define cli_command_root(name) \ - _cli_cmd_struct(name, name, NULL, NULL); \ - cli_register_command2(cli, &cmd_##name##_s, NULL) - -/* BRANCH is a label with a parent, but no command */ -#define cli_command_branch(parent, name) \ - _cli_cmd_struct(name, parent##_##name, NULL, NULL); \ - cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) - -/* NODE is a label with a parent and with a command associated with it */ -#define cli_command_node(parent, name, help) \ - _cli_cmd_struct(name, parent##_##name, cmd_##parent##_##name, (char *) help); \ - cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) - -/* ROOT NODE is a label without a parent, but with a command associated with it */ -#define cli_command_root_node(name, help) \ - _cli_cmd_struct(name, name, NULL, (char *) help); \ - cli_register_command2(cli, &cmd_##name##_s, NULL) - extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); @@ -306,6 +280,64 @@ int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc) while (1) {}; } +int cmd_test_sdram(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + // run external memory initialization sequence + HAL_StatusTypeDef status; + int ok, n = 1, test_completed; + + cli_print(cli, "Initializing SDRAM"); + status = sdram_init(); + if (status != HAL_OK) { + cli_print(cli, "Failed initializing SDRAM: %i", (int) status); + return CLI_OK; + } + + /* XXX support number of iterations given as argument like 'test sdram 5' */ + while (n--) { + cli_print(cli, "Starting SDRAM test (n = %i)", n); + test_completed = 0; + // set LFSRs to some initial value, LFSRs will produce + // pseudo-random 32-bit patterns to test our memories + lfsr1 = 0xCCAA5533; + lfsr2 = 0xCCAA5533; + + cli_print(cli, "Run sequential write-then-read test for the first chip"); + ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP1); + if (!ok) break; + + cli_print(cli, "Run random write-then-read test for the first chip"); + ok = test_sdram_random(SDRAM_BASEADDR_CHIP1); + if (!ok) break; + + cli_print(cli, "Run sequential write-then-read test for the second chip"); + ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP2); + if (!ok) break; + + cli_print(cli, "Run random write-then-read test for the second chip"); + ok = test_sdram_random(SDRAM_BASEADDR_CHIP2); + if (!ok) break; + + // turn blue led on (testing two chips at the same time) + led_on(LED_BLUE); + + cli_print(cli, "Run interleaved write-then-read test for both chips at once"); + ok = test_sdrams_interleaved(SDRAM_BASEADDR_CHIP1, SDRAM_BASEADDR_CHIP2); + + led_off(LED_BLUE); + test_completed = 1; + cli_print(cli, "SDRAM test (n = %i) completed", n); + } + + if (! test_completed) { + cli_print(cli, "SDRAM test failed (n = %i)", n); + } else { + cli_print(cli, "SDRAM test completed successfully"); + } + + return CLI_OK; +} + int check_auth(const char *username, const char *password) { if (strcasecmp(username, "ct") != 0) @@ -349,6 +381,15 @@ void configure_cli_fpga(struct cli_def *cli) cli_command_node(fpga_bitstream, erase, "Erase FPGA config memory"); } +void configure_cli_test(struct cli_def *cli) +{ + /* test */ + cli_command_root(test); + + /* test sdram */ + cli_command_node(test, sdram, "Run SDRAM tests"); +} + void configure_cli_misc(struct cli_def *cli) { /* filetransfer */ @@ -371,6 +412,7 @@ main() configure_cli_show(&cli); configure_cli_fpga(&cli); + configure_cli_test(&cli); configure_cli_misc(&cli); led_off(LED_RED); diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c index 8d53515..faaafda 100644 --- a/projects/cli-test/mgmt-cli.c +++ b/projects/cli-test/mgmt-cli.c @@ -33,7 +33,6 @@ */ #include "stm32f4xx_hal.h" #include "stm-init.h" -#include "stm-led.h" #include "stm-uart.h" #include "mgmt-cli.h" @@ -79,11 +78,8 @@ int embedded_cli_loop(struct cli_def *cli) while (1) { cli_loop_start_new_command(cli, &ctx); - HAL_GPIO_TogglePin(LED_PORT, LED_YELLOW); while (1) { - HAL_GPIO_TogglePin(LED_PORT, LED_BLUE); - cli_loop_show_prompt(cli, &ctx); n = cli_loop_read_next_char(cli, &ctx, &c); diff --git a/projects/cli-test/mgmt-cli.h b/projects/cli-test/mgmt-cli.h index 2f1f139..e6780a3 100644 --- a/projects/cli-test/mgmt-cli.h +++ b/projects/cli-test/mgmt-cli.h @@ -38,13 +38,40 @@ #include "stm32f4xx_hal.h" #include <libcli.h> + +/* A bunch of defines to make it easier to add/maintain the CLI commands. + * + */ +#define _cli_cmd_struct(name, fullname, func, help) \ + static struct cli_command cmd_##fullname##_s = \ + {(char *) #name, func, 0, help, \ + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL} + +/* ROOT is a top-level label with no command */ +#define cli_command_root(name) \ + _cli_cmd_struct(name, name, NULL, NULL); \ + cli_register_command2(cli, &cmd_##name##_s, NULL) + +/* BRANCH is a label with a parent, but no command */ +#define cli_command_branch(parent, name) \ + _cli_cmd_struct(name, parent##_##name, NULL, NULL); \ + cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) + +/* NODE is a label with a parent and with a command associated with it */ +#define cli_command_node(parent, name, help) \ + _cli_cmd_struct(name, parent##_##name, cmd_##parent##_##name, (char *) help); \ + cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) + +/* ROOT NODE is a label without a parent, but with a command associated with it */ +#define cli_command_root_node(name, help) \ + _cli_cmd_struct(name, name, NULL, (char *) help); \ + cli_register_command2(cli, &cmd_##name##_s, NULL) + + extern void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf); extern int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count); extern int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count); extern int embedded_cli_loop(struct cli_def *cli); extern void mgmt_cli_init(struct cli_def *cli); -extern __IO ITStatus MgmtUartDataReceived; -extern __IO ITStatus MgmtUartShouldCli; - #endif /* __STM32_MGMT_CLI_H */ diff --git a/projects/cli-test/test_sdram.c b/projects/cli-test/test_sdram.c new file mode 100644 index 0000000..e720667 --- /dev/null +++ b/projects/cli-test/test_sdram.c @@ -0,0 +1,274 @@ +/*
+ * test_sdram.c
+ * ------------
+ * Test code for the 2x512 MBit SDRAM working memory.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stm32f4xx_hal.h"
+#include "stm-led.h"
+#include "stm-sdram.h"
+#include "test_sdram.h"
+
+
+uint32_t lfsr1;
+uint32_t lfsr2;
+
+
+int test_sdram_sequential(uint32_t *base_addr)
+{
+ // memory offset
+ int offset;
+
+ // readback value
+ uint32_t sdram_readback;
+
+
+ /* This test fills entire memory chip with some pseudo-random pattern
+ starting from the very first cell and going in linear fashion. It then
+ reads entire memory and compares read values with what was written. */
+
+
+ // turn on yellow led to indicate, that we're writing
+ led_on(LED_YELLOW);
+
+
+ //
+ // Note, that SDRAM_SIZE is in BYTES, and since we write using
+ // 32-bit words, total number of words is SDRAM_SIZE / 4.
+ //
+
+ // fill entire memory with "random" values
+ for (offset=0; offset<(SDRAM_SIZE >> 2); offset++) {
+ // generate next "random" value to write
+ lfsr1 = lfsr_next_32(lfsr1);
+
+ // write to memory
+ base_addr[offset] = lfsr1;
+ }
+
+
+ // turn off yellow led to indicate, that we're going to read
+ led_off(LED_YELLOW);
+
+
+ // read entire memory and compare values
+ for (offset=0; offset<(SDRAM_SIZE >> 2); offset++) {
+ // generate next "random" value (we use the second LFSR to catch up)
+ lfsr2 = lfsr_next_32(lfsr2);
+
+ // read from memory
+ sdram_readback = base_addr[offset];
+
+ // compare and abort test in case of mismatch
+ if (sdram_readback != lfsr2) return 0;
+ }
+
+ // done
+ return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+int test_sdram_random(uint32_t *base_addr)
+//-----------------------------------------------------------------------------
+{
+ // cell counter, memory offset
+ int counter, offset;
+
+ // readback value
+ uint32_t sdram_readback;
+
+
+ /* This test fills entire memory chip with some pseudo-random pattern
+ starting from the very first cell, but then jumping around in pseudo-
+ random fashion to make sure, that SDRAM controller in STM32 handles
+ bank, row and column switching correctly. It then reads entire memory
+ and compares read values with what was written. */
+
+
+ // turn on yellow led to indicate, that we're writing
+ led_on(LED_YELLOW);
+
+
+ //
+ // Note, that SDRAM_SIZE is in BYTES, and since we write using
+ // 32-bit words, total number of words is SDRAM_SIZE / 4.
+ //
+
+ // start with the first cell
+ for (counter=0, offset=0; counter<(SDRAM_SIZE >> 2); counter++) {
+ // generate next "random" value to write
+ lfsr1 = lfsr_next_32(lfsr1);
+
+ // write to memory
+ base_addr[offset] = lfsr1;
+
+ // generate next "random" address
+
+ //
+ // Note, that for 64 MB memory with 32-bit data bus we need 24 bits
+ // of address, so we use 24-bit LFSR here. Since LFSR has only 2^^24-1
+ // states, i.e. all possible 24-bit values excluding 0, we have to
+ // manually kick it into some arbitrary state during the first iteration.
+ //
+
+ offset = offset ? lfsr_next_24(offset) : 0x00DEC0DE;
+ }
+
+
+ // turn off yellow led to indicate, that we're going to read
+ led_off(LED_YELLOW);
+
+
+ // read entire memory and compare values
+ for (counter=0, offset=0; counter<(SDRAM_SIZE >> 2); counter++) {
+ // generate next "random" value (we use the second LFSR to catch up)
+ lfsr2 = lfsr_next_32(lfsr2);
+
+ // read from memory
+ sdram_readback = base_addr[offset];
+
+ // compare and abort test in case of mismatch
+ if (sdram_readback != lfsr2) return 0;
+
+ // generate next "random" address
+ offset = offset ? lfsr_next_24(offset) : 0x00DEC0DE;
+ }
+
+ //
+ // we should have walked exactly 2**24 iterations and returned
+ // back to the arbitrary starting address...
+ //
+
+ if (offset != 0x00DEC0DE) return 0;
+
+
+ // done
+ return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+int test_sdrams_interleaved(uint32_t *base_addr1, uint32_t *base_addr2)
+//-----------------------------------------------------------------------------
+{
+ // cell counter, memory offsets
+ int counter, offset1, offset2;
+
+ // readback value
+ uint32_t sdram_readback;
+
+
+ /* Basically this is the same as test_sdram_random() except that it
+ tests both memory chips at the same time. */
+
+
+ // turn on yellow led to indicate, that we're writing
+ led_on(LED_YELLOW);
+
+
+ //
+ // Note, that SDRAM_SIZE is in BYTES, and since we write using
+ // 32-bit words, total number of words is SDRAM_SIZE / 4.
+ //
+
+ // start with the first cell
+ for (counter=0, offset1=0, offset2=0; counter<(SDRAM_SIZE >> 2); counter++) {
+ // generate next "random" value to write
+ lfsr1 = lfsr_next_32(lfsr1);
+
+ // write to memory
+ base_addr1[offset1] = lfsr1;
+ base_addr2[offset2] = lfsr1;
+
+ // generate next "random" addresses (use different starting states!)
+
+ offset1 = offset1 ? lfsr_next_24(offset1) : 0x00ABCDEF;
+ offset2 = offset2 ? lfsr_next_24(offset2) : 0x00FEDCBA;
+ }
+
+
+ // turn off yellow led to indicate, that we're going to read
+ led_off(LED_YELLOW);
+
+
+ // read entire memory and compare values
+ for (counter=0, offset1=0, offset2=0; counter<(SDRAM_SIZE >> 2); counter++) {
+ // generate next "random" value (we use the second LFSR to catch up)
+ lfsr2 = lfsr_next_32(lfsr2);
+
+ // read from the first memory and compare
+ sdram_readback = base_addr1[offset1];
+ if (sdram_readback != lfsr2) return 0;
+
+ // read from the second memory and compare
+ sdram_readback = base_addr2[offset2];
+ if (sdram_readback != lfsr2) return 0;
+
+ // generate next "random" addresses
+ offset1 = offset1 ? lfsr_next_24(offset1) : 0x00ABCDEF;
+ offset2 = offset2 ? lfsr_next_24(offset2) : 0x00FEDCBA;
+ }
+
+ //
+ // we should have walked exactly 2**24 iterations and returned
+ // back to the arbitrary starting address...
+ //
+
+ if (offset1 != 0x00ABCDEF) return 0;
+ if (offset2 != 0x00FEDCBA) return 0;
+
+ // done
+ return 1;
+}
+
+uint32_t lfsr_next_32(uint32_t lfsr)
+{
+ uint32_t tap = 0;
+
+ tap ^= (lfsr >> 31);
+ tap ^= (lfsr >> 30);
+ tap ^= (lfsr >> 29);
+ tap ^= (lfsr >> 9);
+
+ return (lfsr << 1) | (tap & 1);
+}
+
+uint32_t lfsr_next_24(uint32_t lfsr)
+{
+ unsigned int tap = 0;
+
+ tap ^= (lfsr >> 23);
+ tap ^= (lfsr >> 22);
+ tap ^= (lfsr >> 21);
+ tap ^= (lfsr >> 16);
+
+ return ((lfsr << 1) | (tap & 1)) & 0x00FFFFFF;
+}
diff --git a/projects/cli-test/test_sdram.h b/projects/cli-test/test_sdram.h new file mode 100644 index 0000000..b848d18 --- /dev/null +++ b/projects/cli-test/test_sdram.h @@ -0,0 +1,42 @@ +/* + * test_sdram.h + * ------------ + * Prototypes and defines for testing the 2x512 MBit SDRAM working memory. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +extern uint32_t lfsr1; +extern uint32_t lfsr2; + +extern int test_sdram_sequential(uint32_t *base_addr); +extern int test_sdram_random(uint32_t *base_addr); +extern int test_sdrams_interleaved(uint32_t *base_addr1, uint32_t *base_addr2); + +extern uint32_t lfsr_next_32(uint32_t lfsr); +extern uint32_t lfsr_next_24(uint32_t lfsr); @@ -31,325 +31,231 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - - -//------------------------------------------------------------------------------ -// Headers -//------------------------------------------------------------------------------ -#include "stm-fmc.h" #include "stm32f4xx_hal.h" +#include "stm-init.h" +#include "stm-fmc.h" -//------------------------------------------------------------------------------ -// Defined Values -//------------------------------------------------------------------------------ -#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 - - -//------------------------------------------------------------------------------ -// Variables -//------------------------------------------------------------------------------ static SRAM_HandleTypeDef _fmc_fpga_inst; - -//------------------------------------------------------------------------------ -// Prototypes -//------------------------------------------------------------------------------ -static void _fmc_init_gpio(void); -static void _fmc_init_params(void); +static HAL_StatusTypeDef _fmc_init_params(void); static int _fmc_nwait_idle(void); -//------------------------------------------------------------------------------ -void fmc_init(void) -//------------------------------------------------------------------------------ +HAL_StatusTypeDef fmc_init(void) { - // configure fmc pins - _fmc_init_gpio(); + static int initialized = 0; + + if (initialized) { + return HAL_OK; + } + initialized = 1; + + // configure fmc pins + fmc_init_gpio(); - // configure fmc registers - _fmc_init_params(); + // configure fmc registers + return _fmc_init_params(); } -//------------------------------------------------------------------------------ int fmc_write_32(uint32_t addr, uint32_t *data) -//------------------------------------------------------------------------------ { - // calculate target fpga address - uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); + // calculate target fpga address + uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); - // write data to fpga - HAL_StatusTypeDef ok = HAL_SRAM_Write_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); + // write data to fpga + HAL_StatusTypeDef ok = HAL_SRAM_Write_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); - // check for error - if (ok != HAL_OK) return -1; + // check for error + if (ok != HAL_OK) return -1; - // wait for transaction to complete - int wait = _fmc_nwait_idle(); + // wait for transaction to complete + int wait = _fmc_nwait_idle(); - // check for timeout - if (wait != 0) return -1; + // check for timeout + if (wait != 0) return -1; - // everything went ok - return 0; + // everything went ok + return 0; } -//------------------------------------------------------------------------------ int fmc_read_32(uint32_t addr, uint32_t *data) -//------------------------------------------------------------------------------ { - // calculate target fpga address - uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); + // calculate target fpga address + uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); - // perform dummy read transaction - HAL_StatusTypeDef ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); + // perform dummy read transaction + HAL_StatusTypeDef ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); - // check for error - if (ok != HAL_OK) return -1; + // check for error + if (ok != HAL_OK) return -1; - // wait for dummy transaction to complete - int wait = _fmc_nwait_idle(); + // wait for dummy transaction to complete + int wait = _fmc_nwait_idle(); - // check for timeout - if (wait != 0) return -1; + // check for timeout + if (wait != 0) return -1; - // read data from fpga - ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); + // read data from fpga + ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); - // check for error - if (ok != HAL_OK) return -1; + // check for error + if (ok != HAL_OK) return -1; - // wait for read transaction to complete - wait = _fmc_nwait_idle(); + // wait for read transaction to complete + wait = _fmc_nwait_idle(); - // check for timeout - if (wait != 0) return -1; + // check for timeout + if (wait != 0) return -1; - // everything went ok - return 0; + // everything went ok + return 0; } -//------------------------------------------------------------------------------ static int _fmc_nwait_idle() -//------------------------------------------------------------------------------ { - int cnt; // counter + int cnt; // counter - // poll NWAIT (number of iterations is limited) - for (cnt=0; cnt<FMC_FPGA_NWAIT_MAX_POLL_TICKS; cnt++) - { - // read pin state - GPIO_PinState nwait = HAL_GPIO_ReadPin(FMC_GPIO_PORT_NWAIT, FMC_GPIO_PIN_NWAIT); + // poll NWAIT (number of iterations is limited) + for (cnt=0; cnt<FMC_FPGA_NWAIT_MAX_POLL_TICKS; cnt++) + { + // read pin state + GPIO_PinState nwait = HAL_GPIO_ReadPin(FMC_GPIO_PORT_NWAIT, FMC_GPIO_PIN_NWAIT); - // stop waiting if fpga is ready - if (nwait == FMC_NWAIT_IDLE) break; - } + // stop waiting if fpga is ready + if (nwait == FMC_NWAIT_IDLE) break; + } - // check for timeout - if (cnt >= FMC_FPGA_NWAIT_MAX_POLL_TICKS) return -1; + // check for timeout + if (cnt >= FMC_FPGA_NWAIT_MAX_POLL_TICKS) return -1; - // ok - return 0; + // ok + return 0; } -//------------------------------------------------------------------------------ -static void _fmc_init_gpio(void) -//------------------------------------------------------------------------------ +void fmc_init_gpio(void) { - // enable gpio clocks - __GPIOA_CLK_ENABLE(); - __GPIOB_CLK_ENABLE(); - __GPIOD_CLK_ENABLE(); - __GPIOE_CLK_ENABLE(); - __GPIOF_CLK_ENABLE(); - __GPIOG_CLK_ENABLE(); - __GPIOH_CLK_ENABLE(); - __GPIOI_CLK_ENABLE(); - - // enable fmc clock - __FMC_CLK_ENABLE(); - - // structure - GPIO_InitTypeDef GPIO_InitStruct; - - // Port B - GPIO_InitStruct.Pin = GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - // Port D - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 - |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15 - |GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_4 - |GPIO_PIN_5|GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - - /* - * When FMC is working with fixed latency, NWAIT pin must not be - * configured in AF mode, according to STM32F429 errata. - */ - - // Port D (GPIO!) - GPIO_InitStruct.Pin = GPIO_PIN_6; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLUP; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - - // Port E - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 - |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 - |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - - // Port F - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 - |GPIO_PIN_14|GPIO_PIN_15; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - - // Port G - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - - // Port H - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 - |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - - // Port I - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 - |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_6|GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + GPIO_InitTypeDef GPIO_InitStruct; + + // enable fmc clock + __HAL_RCC_FMC_CLK_ENABLE(); + + fmc_af_gpio(GPIOB, GPIO_PIN_7); + fmc_af_gpio(GPIOD, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4 + | GPIO_PIN_5 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 + | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 + | GPIO_PIN_14 | GPIO_PIN_15); + + /* + * When FMC is working with fixed latency, NWAIT pin (PD6) must not be + * configured in AF mode, according to STM32F429 errata. + */ + GPIO_InitStruct.Pin = GPIO_PIN_6; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + fmc_af_gpio(GPIOE, GPIO_PIN_2 + | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 + | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 + | GPIO_PIN_12 | GPIO_PIN_13 |GPIO_PIN_14 | GPIO_PIN_15); + fmc_af_gpio(GPIOF, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 + | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 + | GPIO_PIN_14 | GPIO_PIN_15); + fmc_af_gpio(GPIOG, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 + | GPIO_PIN_4 | GPIO_PIN_5); + fmc_af_gpio(GPIOH, GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 + | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + fmc_af_gpio(GPIOI, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 + | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_9 | GPIO_PIN_10); } -//------------------------------------------------------------------------------ -static void _fmc_init_params(void) -//------------------------------------------------------------------------------ +static HAL_StatusTypeDef _fmc_init_params(void) { - /* - * fill internal fields - */ - _fmc_fpga_inst.Instance = FMC_NORSRAM_DEVICE; - _fmc_fpga_inst.Extended = FMC_NORSRAM_EXTENDED_DEVICE; + /* + * fill internal fields + */ + _fmc_fpga_inst.Instance = FMC_NORSRAM_DEVICE; + _fmc_fpga_inst.Extended = FMC_NORSRAM_EXTENDED_DEVICE; - /* - * configure fmc interface settings - */ + /* + * configure fmc interface settings + */ - // use the first bank and corresponding chip select - _fmc_fpga_inst.Init.NSBank = FMC_NORSRAM_BANK1; + // use the first bank and corresponding chip select + _fmc_fpga_inst.Init.NSBank = FMC_NORSRAM_BANK1; - // data and address buses are separate - _fmc_fpga_inst.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; + // data and address buses are separate + _fmc_fpga_inst.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; - // fpga mimics psram-type memory - _fmc_fpga_inst.Init.MemoryType = FMC_MEMORY_TYPE_PSRAM; + // fpga mimics psram-type memory + _fmc_fpga_inst.Init.MemoryType = FMC_MEMORY_TYPE_PSRAM; - // data bus is 32-bit - _fmc_fpga_inst.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_32; + // data bus is 32-bit + _fmc_fpga_inst.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_32; - // read transaction is sync - _fmc_fpga_inst.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE; + // read transaction is sync + _fmc_fpga_inst.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE; - // this _must_ be configured to high, according to errata, otherwise - // the processor may hang after trying to access fpga via fmc - _fmc_fpga_inst.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_HIGH; + // this _must_ be configured to high, according to errata, otherwise + // the processor may hang after trying to access fpga via fmc + _fmc_fpga_inst.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_HIGH; - // wrap mode is not supported - _fmc_fpga_inst.Init.WrapMode = FMC_WRAP_MODE_DISABLE; + // wrap mode is not supported + _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; + // don't care in fixed latency mode + _fmc_fpga_inst.Init.WaitSignalActive = FMC_WAIT_TIMING_DURING_WS; - // allow write access to fpga - _fmc_fpga_inst.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; + // allow write access to fpga + _fmc_fpga_inst.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; - // use fixed latency mode (ignore wait signal) - _fmc_fpga_inst.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; + // use fixed latency mode (ignore wait signal) + _fmc_fpga_inst.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; - // write and read have same timing - _fmc_fpga_inst.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; + // write and read have same timing + _fmc_fpga_inst.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; - // don't care in sync mode - _fmc_fpga_inst.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE; + // don't care in sync mode + _fmc_fpga_inst.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE; - // write transaction is sync - _fmc_fpga_inst.Init.WriteBurst = FMC_WRITE_BURST_ENABLE; + // write transaction is sync + _fmc_fpga_inst.Init.WriteBurst = FMC_WRITE_BURST_ENABLE; - // keep clock always active - _fmc_fpga_inst.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC; + // keep clock always active + _fmc_fpga_inst.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC; - /* - * configure fmc timing parameters - */ - FMC_NORSRAM_TimingTypeDef fmc_timing; + /* + * configure fmc timing parameters + */ + FMC_NORSRAM_TimingTypeDef fmc_timing; - // don't care in sync mode - fmc_timing.AddressSetupTime = 15; + // don't care in sync mode + fmc_timing.AddressSetupTime = 15; - // don't care in sync mode - fmc_timing.AddressHoldTime = 15; + // don't care in sync mode + fmc_timing.AddressHoldTime = 15; - // don't care in sync mode - fmc_timing.DataSetupTime = 255; + // don't care in sync mode + fmc_timing.DataSetupTime = 255; - // not needed, since nwait will be polled manually - fmc_timing.BusTurnAroundDuration = 0; + // not needed, since nwait will be polled manually + fmc_timing.BusTurnAroundDuration = 0; - // use smallest allowed divisor for best performance - fmc_timing.CLKDivision = 2; + // 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; + // stm is too slow to work with min allowed 2-cycle latency + fmc_timing.DataLatency = 3; - // don't care in sync mode - fmc_timing.AccessMode = FMC_ACCESS_MODE_A; + // don't care in sync mode + fmc_timing.AccessMode = FMC_ACCESS_MODE_A; - // initialize fmc - HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); + // initialize fmc + return HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); } - - -//------------------------------------------------------------------------------ -// EOF -//------------------------------------------------------------------------------ @@ -35,9 +35,27 @@ #ifndef __STM_FMC_H #define __STM_FMC_H -#include <stdint.h> +#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 -extern void fmc_init(void); +#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; \ + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; \ + GPIO_InitStruct.Pull = GPIO_NOPULL; \ + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; \ + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; \ + __HAL_RCC_##port##_CLK_ENABLE(); \ + HAL_GPIO_Init(port, &GPIO_InitStruct) + + +extern HAL_StatusTypeDef fmc_init(void); +extern void fmc_init_gpio(void); extern int fmc_write_32(uint32_t addr, uint32_t *data); extern int fmc_read_32(uint32_t addr, uint32_t *data); @@ -38,9 +38,6 @@ #ifdef HAL_GPIO_MODULE_ENABLED #include "stm-led.h" #endif -#ifdef HAL_SRAM_MODULE_ENABLED -#include "stm-fmc.h" -#endif #ifdef HAL_UART_MODULE_ENABLED #include "stm-uart.h" #endif @@ -143,24 +140,6 @@ static void MX_USART2_UART_Init(void) #ifdef HAL_GPIO_MODULE_ENABLED -#define gpio_output(output_port, output_pins, output_level) \ - /* Configure GPIO pin Output Level */ \ - HAL_GPIO_WritePin(output_port, output_pins, output_level); \ - /* Configure pin as output */ \ - GPIO_InitStruct.Pin = output_pins; \ - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \ - GPIO_InitStruct.Pull = GPIO_NOPULL; \ - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ - HAL_GPIO_Init(output_port, &GPIO_InitStruct) - -#define gpio_input(input_port, input_pin, input_pull) \ - GPIO_InitStruct.Pin = input_pin; \ - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \ - GPIO_InitStruct.Pull = input_pull; \ - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ - HAL_GPIO_Init(input_port, &GPIO_InitStruct) - - /* Configure General Purpose Input/Output pins */ static void MX_GPIO_Init(void) { @@ -38,6 +38,25 @@ #include "cmsis_os.h" #include "stm32f4xx_hal.h" +/* Macros used to make GPIO pin setup (in stm-init.c) easier */ +#define gpio_output(output_port, output_pins, output_level) \ + /* Configure GPIO pin Output Level */ \ + HAL_GPIO_WritePin(output_port, output_pins, output_level); \ + /* Configure pin as output */ \ + GPIO_InitStruct.Pin = output_pins; \ + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \ + GPIO_InitStruct.Pull = GPIO_NOPULL; \ + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ + HAL_GPIO_Init(output_port, &GPIO_InitStruct) + +#define gpio_input(input_port, input_pin, input_pull) \ + GPIO_InitStruct.Pin = input_pin; \ + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \ + GPIO_InitStruct.Pull = input_pull; \ + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ + HAL_GPIO_Init(input_port, &GPIO_InitStruct) + + extern void stm_init(void); extern void Error_Handler(void); diff --git a/stm-sdram.c b/stm-sdram.c new file mode 100644 index 0000000..0ec8065 --- /dev/null +++ b/stm-sdram.c @@ -0,0 +1,267 @@ +/*
+ * stm-sdram.c
+ * -----------
+ * Functions concerning the 2x512 Mbit SDRAM working memory.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stm32f4xx_hal.h"
+#include "stm-init.h"
+#include "stm-sdram.h"
+#include "stm-fmc.h"
+#include "stm-led.h"
+
+SDRAM_HandleTypeDef hsdram1;
+SDRAM_HandleTypeDef hsdram2;
+
+void _sdram_init_gpio(void);
+HAL_StatusTypeDef _sdram_init_fmc(void);
+HAL_StatusTypeDef _sdram_init_params(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2);
+
+
+HAL_StatusTypeDef sdram_init(void)
+{
+ HAL_StatusTypeDef status;
+ static int initialized = 0;
+
+ if (initialized) {
+ return;
+ }
+ initialized = 1;
+
+ /* We rely on several things being set up by fmc_init() instead of duplicating all
+ * that code here for independent FPGA/SDRAM FMC setup. This means the FPGA<->STM32
+ * FMC bus can be used without the SDRAMs initialized, but the SDRAMs can't be
+ * initialized withouth the FPGA<->STM32 FMC bus being set up too.
+ */
+ fmc_init();
+
+ // configure FMC
+ _sdram_init_gpio();
+ status = _sdram_init_fmc();
+ if (status != HAL_OK) return status;
+
+ // configure SDRAM registers
+ status = _sdram_init_params(&hsdram1, &hsdram2);
+ if (status != HAL_OK) return status;
+
+ return HAL_OK;
+}
+
+void _sdram_init_gpio(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ /* The bulk of the FMC GPIO pins are set up in fmc_init_gpio().
+ * This function just needs to enable the additional ones used
+ * with the SDRAMs.
+ */
+ fmc_af_gpio(GPIOB, GPIO_PIN_5 | GPIO_PIN_6);
+ fmc_af_gpio(GPIOC, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
+ fmc_af_gpio(GPIOE, GPIO_PIN_0 | GPIO_PIN_1);
+ fmc_af_gpio(GPIOF, GPIO_PIN_11);
+ fmc_af_gpio(GPIOG, GPIO_PIN_8 | GPIO_PIN_15);
+ fmc_af_gpio(GPIOI, GPIO_PIN_4 | GPIO_PIN_5);
+}
+
+HAL_StatusTypeDef _sdram_init_fmc()
+{
+ HAL_StatusTypeDef status;
+ FMC_SDRAM_TimingTypeDef SdramTiming;
+
+ /*
+ * following settings are for -75E speed grade memory chip
+ * clocked at only 90 MHz instead of the rated 133 MHz
+ *
+ * ExitSelfRefreshDelay: 67 ns @ 90 MHz is 6.03 cycles, so in theory
+ * 6 can be used here, but let's be on the safe side
+ *
+ * WriteRecoveryTime: must be >= tRAS - tRCD (5 - 2 = 3 cycles),
+ * and >= tRC - tRCD - tRP (8 - 2 - 2 = 4 cycles)
+ */
+ SdramTiming.LoadToActiveDelay = 2; // tMRD
+ SdramTiming.ExitSelfRefreshDelay = 7; // (see above)
+ SdramTiming.SelfRefreshTime = 5; // should be >= tRAS (5 cycles)
+ SdramTiming.RowCycleDelay = 8; // tRC
+ SdramTiming.WriteRecoveryTime = 4; // (see above)
+ SdramTiming.RPDelay = 2; // tRP
+ SdramTiming.RCDDelay = 2; // tRCD
+
+ /*
+ * configure the first bank
+ */
+
+ // memory type
+ hsdram1.Instance = FMC_SDRAM_DEVICE;
+
+ // bank
+ hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
+
+ // settings for IS42S32160F
+ hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
+ hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
+ hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
+ hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
+ hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
+
+ // write protection not needed
+ hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+
+ // memory clock is 90 MHz (HCLK / 2)
+ hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
+
+ // read burst not needed
+ hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
+
+ // additional pipeline stages not neeed
+ hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
+
+ // call HAL layer
+ status = HAL_SDRAM_Init(&hsdram1, &SdramTiming);
+ if (status != HAL_OK) return status;
+
+ /*
+ * configure the second bank
+ */
+
+ // memory type
+ hsdram2.Instance = FMC_SDRAM_DEVICE;
+
+ // bank number
+ hsdram2.Init.SDBank = FMC_SDRAM_BANK2;
+
+ // settings for IS42S32160F
+ hsdram2.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
+ hsdram2.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
+ hsdram2.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
+ hsdram2.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
+ hsdram2.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
+
+ // write protection not needed
+ hsdram2.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+
+ // memory clock is 90 MHz (HCLK / 2)
+ hsdram2.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
+
+ // read burst not needed
+ hsdram2.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
+
+ // additional pipeline stages not neeed
+ hsdram2.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
+
+ // call HAL layer
+ return HAL_SDRAM_Init(&hsdram2, &SdramTiming);
+}
+
+HAL_StatusTypeDef _sdram_init_params(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2)
+{
+ HAL_StatusTypeDef ok; // status
+ FMC_SDRAM_CommandTypeDef cmd; // command
+
+ /*
+ * enable clocking
+ */
+ cmd.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition = 0;
+
+ HAL_Delay(1);
+ ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+ if (ok != HAL_OK) return ok;
+
+ /*
+ * precharge all banks
+ */
+ cmd.CommandMode = FMC_SDRAM_CMD_PALL;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition = 0;
+
+ HAL_Delay(1);
+ ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+ if (ok != HAL_OK) return ok;
+
+
+ /*
+ * send two auto-refresh commands in a row
+ */
+ cmd.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition = 0;
+
+ ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+ if (ok != HAL_OK) return ok;
+
+ ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+ if (ok != HAL_OK) return ok;
+
+
+ /*
+ * load mode register
+ */
+ cmd.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition =
+ SDRAM_MODEREG_BURST_LENGTH_1 |
+ SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
+ SDRAM_MODEREG_CAS_LATENCY_2 |
+ SDRAM_MODEREG_OPERATING_MODE_STANDARD |
+ SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ;
+
+ ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+ if (ok != HAL_OK) return ok;
+
+
+ /*
+ * set number of consequtive auto-refresh commands
+ * and program refresh rate
+ *
+ * RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc
+ *
+ * RefreshCycles = 7.8125 us * 90 MHz = 703
+ *
+ * According to the formula on p.1665 of the reference manual,
+ * we also need to subtract 20 from the value, so the target
+ * refresh rate is 703 - 20 = 683.
+ */
+
+ ok = HAL_SDRAM_SetAutoRefreshNumber(sdram1, 8);
+ if (ok != HAL_OK) return ok;
+
+ HAL_SDRAM_ProgramRefreshRate(sdram1, 683);
+ if (ok != HAL_OK) return ok;
+
+ /*
+ * done
+ */
+ return HAL_OK;
+}
diff --git a/stm-sdram.h b/stm-sdram.h new file mode 100644 index 0000000..8f58b34 --- /dev/null +++ b/stm-sdram.h @@ -0,0 +1,66 @@ +/*
+ * stm-sdram.h
+ * -----------
+ * Functions and defines concerning the 2x512 Mbit SDRAM working memory.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __STM32_SDRAM_H
+#define __STM32_SDRAM_H
+
+/* Base Addresses */
+#define SDRAM_BASEADDR_CHIP1 ((uint32_t *)0xC0000000)
+#define SDRAM_BASEADDR_CHIP2 ((uint32_t *)0xD0000000)
+
+/* Memory Size, 64 MBytes (512 Mbits) */
+#define SDRAM_SIZE 0x4000000
+
+/* Mode Register Bits */
+#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
+#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
+#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
+
+#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
+
+#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
+#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
+
+#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
+
+#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
+#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
+
+extern SDRAM_HandleTypeDef hsdram1;
+extern SDRAM_HandleTypeDef hsdram2;
+
+extern HAL_StatusTypeDef sdram_init(void);
+
+#endif
|