diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c new file mode 100644 index 0000000000..181a34cadb --- /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 + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * SDRAM Driver. + * + */ +#include +#include +#include +#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 + * 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__