diff options
author | Fredrik Thulin <fredrik@thulin.net> | 2016-05-23 21:59:17 +0200 |
---|---|---|
committer | Fredrik Thulin <fredrik@thulin.net> | 2016-05-23 21:59:17 +0200 |
commit | 6265025f7cd7f606b6da62c7add13a6008500cf7 (patch) | |
tree | 7761c2a2136ed59fab776c6e2c78427a3082fd10 | |
parent | 50f9d40503e5f9cb24241c4c584db3cb94af07aa (diff) |
SDRAM initialization and test code from Pavel.
Integrated into the cli-test program as such:
cryptech> test sdram
Initializing SDRAM
Starting SDRAM test (n = 0)
Run sequential write-then-read test for the first chip
Run random write-then-read test for the first chip
Run sequential write-then-read test for the second chip
Run random write-then-read test for the second chip
Run interleaved write-then-read test for both chips at once
SDRAM test (n = 0) completed
SDRAM test completed successfully
cryptech>
-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-- | 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 | 124 | ||||
-rw-r--r-- | stm-fmc.h | 14 | ||||
-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 |
15 files changed, 828 insertions, 148 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/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); @@ -32,23 +32,30 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "stm32f4xx_hal.h" +#include "stm-init.h" #include "stm-fmc.h" static SRAM_HandleTypeDef _fmc_fpga_inst; -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) { + static int initialized = 0; + + if (initialized) { + return HAL_OK; + } + initialized = 1; + // configure fmc pins - _fmc_init_gpio(); + fmc_init_gpio(); // configure fmc registers - _fmc_init_params(); + return _fmc_init_params(); } @@ -129,104 +136,45 @@ static int _fmc_nwait_idle() 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(); + GPIO_InitTypeDef GPIO_InitStruct; // enable fmc clock - __FMC_CLK_ENABLE(); + __HAL_RCC_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); + 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 must not be + * When FMC is working with fixed latency, NWAIT pin (PD6) 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); + 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 @@ -309,5 +257,5 @@ static void _fmc_init_params(void) fmc_timing.AccessMode = FMC_ACCESS_MODE_A; // initialize fmc - HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); + return HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); } @@ -44,8 +44,18 @@ #define FMC_NWAIT_IDLE GPIO_PIN_SET - -extern void fmc_init(void); +#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
|