summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Leech <andrew.leech@planetinnovation.com.au>2018-07-10 17:30:27 +1000
committerDamien George <damien.p.george@gmail.com>2018-07-23 23:13:24 +1000
commit7ae053abfd3368cea5377e992d0f1ccc2cd2d9be (patch)
tree6fd71729fa5fe54051d926d5df1f65b3ec7a43ee
parent7067ac3573de38b0070d4086fa5ff4de5e47f9ee (diff)
stm32/sdram: Add SDRAM driver from OpenMV project.
Taken from https://github.com/openmv/openmv/blob/7fbe54ad4e9dc1c527d9297a3f4c69c365dc9b2c/src/omv/sdram.c Code is is MIT licensed.
-rw-r--r--ports/stm32/sdram.c183
-rw-r--r--ports/stm32/sdram.h13
2 files changed, 196 insertions, 0 deletions
diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c
new file mode 100644
index 000000000..181a34cad
--- /dev/null
+++ b/ports/stm32/sdram.c
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the OpenMV project.
+ * Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
+ * This work is licensed under the MIT license, see the file LICENSE for details.
+ *
+ * SDRAM Driver.
+ *
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <stm32f4xx_hal.h>
+#include "mdefs.h"
+#include "pincfg.h"
+#include "systick.h"
+#include "sdram.h"
+
+#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
+#define REFRESH_COUNT ((uint32_t)0x0569) /* SDRAM refresh counter (90Mhz SD clock) */
+#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)
+
+static SDRAM_HandleTypeDef hsdram;
+static FMC_SDRAM_TimingTypeDef SDRAM_Timing;
+static FMC_SDRAM_CommandTypeDef command;
+static void sdram_init_seq(SDRAM_HandleTypeDef
+ *hsdram, FMC_SDRAM_CommandTypeDef *command);
+extern void __fatal_error(const char *msg);
+
+bool sdram_init()
+{
+ /* SDRAM device configuration */
+ hsdram.Instance = FMC_SDRAM_DEVICE;
+ /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */
+ /* TMRD: 2 Clock cycles */
+ SDRAM_Timing.LoadToActiveDelay = 2;
+ /* TXSR: min=70ns (6x11.90ns) */
+ SDRAM_Timing.ExitSelfRefreshDelay = 7;
+ /* TRAS: min=45ns (4x11.90ns) max=120k (ns) */
+ SDRAM_Timing.SelfRefreshTime = 7;
+ /* TRC: min=67ns (6x11.90ns) */
+ SDRAM_Timing.RowCycleDelay = 10;
+ /* TWR: 2 Clock cycles */
+ SDRAM_Timing.WriteRecoveryTime = 2;
+ /* TRP: 20ns => 2x11.90ns */
+ SDRAM_Timing.RPDelay = 3;
+ /* TRCD: 20ns => 2x11.90ns */
+ SDRAM_Timing.RCDDelay = 3;
+
+ hsdram.Init.SDBank = FMC_SDRAM_BANK1;
+ hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
+ hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_10;
+ hsdram.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_8;
+ hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
+ hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
+ hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+ hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_3;
+ hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
+ hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
+
+ /* Initialize the SDRAM controller */
+ if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK) {
+ return false;
+ }
+
+ sdram_init_seq(&hsdram, &command);
+ return true;
+}
+
+static void sdram_init_seq(SDRAM_HandleTypeDef
+ *hsdram, FMC_SDRAM_CommandTypeDef *command)
+{
+ /* Program the SDRAM external device */
+ __IO uint32_t tmpmrd =0;
+
+ /* Step 3: Configure a clock configuration enable command */
+ command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
+ command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ command->AutoRefreshNumber = 1;
+ command->ModeRegisterDefinition = 0;
+
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, command, 0x1000);
+
+ /* Step 4: Insert 100 ms delay */
+ HAL_Delay(100);
+
+ /* Step 5: Configure a PALL (precharge all) command */
+ command->CommandMode = FMC_SDRAM_CMD_PALL;
+ command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ command->AutoRefreshNumber = 1;
+ command->ModeRegisterDefinition = 0;
+
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, command, 0x1000);
+
+ /* Step 6 : Configure a Auto-Refresh command */
+ command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
+ command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ command->AutoRefreshNumber = 4;
+ command->ModeRegisterDefinition = 0;
+
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, command, 0x1000);
+
+ /* Step 7: Program the external memory mode register */
+ tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
+ SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
+ SDRAM_MODEREG_CAS_LATENCY_3 |
+ SDRAM_MODEREG_OPERATING_MODE_STANDARD |
+ SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
+
+ command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
+ command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ command->AutoRefreshNumber = 1;
+ command->ModeRegisterDefinition = tmpmrd;
+
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, command, 0x1000);
+
+ /* Step 8: Set the refresh rate counter */
+ /* (15.62 us x Freq) - 20 */
+ /* Set the device refresh counter */
+ HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
+}
+
+
+bool DISABLE_OPT sdram_test()
+{
+ uint8_t pattern = 0xAA;
+ uint8_t antipattern = 0x55;
+ uint32_t mem_size = (16*1024*1024);
+ uint8_t * const mem_base = (uint8_t*)0xC0000000;
+
+ printf("sdram test...\n");
+ /* test data bus */
+ for (uint8_t i=1; i; i<<=1) {
+ *mem_base = i;
+ if (*mem_base != i) {
+ printf("data bus lines test failed! data (%d)\n", i);
+ BREAK();
+ }
+ }
+
+ /* test address bus */
+ /* Check individual address lines */
+ for (uint32_t i=1; i<mem_size; i<<=1) {
+ mem_base[i] = pattern;
+ if (mem_base[i] != pattern) {
+ printf("address bus lines test failed! address (%p)\n", &mem_base[i]);
+ BREAK();
+ }
+ }
+
+ /* Check for aliasing (overlaping addresses) */
+ mem_base[0] = antipattern;
+ for (uint32_t i=1; i<mem_size; i<<=1) {
+ if (mem_base[i] != pattern) {
+ printf("address bus overlap %p\n", &mem_base[i]);
+ BREAK();
+ }
+ }
+
+ /* test all ram cells */
+ for (uint32_t i=0; i<mem_size; i++) {
+ mem_base[i] = pattern;
+ if (mem_base[i] != pattern) {
+ printf("address bus test failed! address (%p)\n", &mem_base[i]);
+ BREAK();
+ }
+ }
+
+ printf("sdram test passed\n");
+ return true;
+}
diff --git a/ports/stm32/sdram.h b/ports/stm32/sdram.h
new file mode 100644
index 000000000..f4e7915ad
--- /dev/null
+++ b/ports/stm32/sdram.h
@@ -0,0 +1,13 @@
+/*
+ * This file is part of the OpenMV project.
+ * Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
+ * This work is licensed under the MIT license, see the file LICENSE for details.
+ *
+ * SDRAM Driver.
+ *
+ */
+#ifndef __SDRAM_H__
+#define __SDRAM_H__
+bool sdram_init();
+bool sdram_test();
+#endif // __SDRAM_H__