/* * Copyright (C) EdgeTX * * Based on code named * opentx - https://github.com/opentx/opentx * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "hal/gpio.h" #include "stm32_gpio.h" #include "stm32_hal_ll.h" #include "board.h" #if defined(SDRAM_BANK1) #define SDRAM_BANK FMC_SDRAM_BANK1 #define COMMAND_TARGET FMC_SDRAM_CMD_TARGET_BANK1 #elif defined(SDRAM_BANK2) #define SDRAM_BANK FMC_SDRAM_BANK2 #define COMMAND_TARGET FMC_SDRAM_CMD_TARGET_BANK2 #else #error "No bank definition for SDRAM" #endif #define SDRAM_MEMORY_WIDTH FMC_SDRAM_MEM_BUS_WIDTH_16 #define SDRAM_CAS_LATENCY FMC_SDRAM_CAS_LATENCY_3 #define SDRAM_READBURST FMC_SDRAM_RBURST_ENABLE #define SDRAM_READPIPEDELAY FMC_SDRAM_RPIPE_DELAY_1 #define SDRAM_CLK_PERIOD FMC_SDRAM_CLOCK_PERIOD_2 #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_FULL_PAGE ((uint16_t)0x0007) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_1 ((uint16_t)0x0010) #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) #define GPIO_AF_FMC GPIO_AF12 extern "C" void SDRAM_GPIOConfig(void) { /*-- GPIOs Configuration -----------------------------------------------------*/ /* +-------------------+--------------------+--------------------+--------------------+ + SDRAM pins assignment + +-------------------+--------------------+--------------------+--------------------+ | PD0 <-> FMC_D2 | PE0 <-> FMC_NBL0 | PF0 <-> FMC_A0 | PG0 <-> FMC_A10 | | PD1 <-> FMC_D3 | PE1 <-> FMC_NBL1 | PF1 <-> FMC_A1 | PG1 <-> FMC_A11 | | PD8 <-> FMC_D13 | PE7 <-> FMC_D4 | PF2 <-> FMC_A2 | PG2 <-> FMC_A12 | | PD9 <-> FMC_D14 | PE8 <-> FMC_D5 | PF3 <-> FMC_A3 | PG8 <-> FMC_SDCLK | | PD10 <-> FMC_D15 | PE9 <-> FMC_D6 | PF4 <-> FMC_A4 | PG15 <-> FMC_NCAS | | PD14 <-> FMC_D0 | PE10 <-> FMC_D7 | PF5 <-> FMC_A5 |--------------------+ | PD15 <-> FMC_D1 | PE11 <-> FMC_D8 | PF11 <-> FMC_NRAS | +-------------------| PE12 <-> FMC_D9 | PF12 <-> FMC_A6 | | PE13 <-> FMC_D10 | PF13 <-> FMC_A7 | | PE14 <-> FMC_D11 | PF14 <-> FMC_A8 | | PE15 <-> FMC_D12 | PF15 <-> FMC_A9 | +-------------------+--------------------+--------------------+ | PC3 <-> FMC_SDCKE0| PB5 <-> FMC_SDCKE1 | | PH3 <-> FMC_SDNE0 | PH6 <-> FMC_SDNE1 | | PH5 <-> FMC_SDNWE | | +-------------------++-------------------+ */ #if defined(SDRAM_BANK1) /* GPIOC configuration */ gpio_init_af(GPIO_PIN(GPIOC, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); #else /* GPIOB configuration */ gpio_init_af(GPIO_PIN(GPIOB, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); #endif /* GPIOH configuration */ gpio_init_af(GPIO_PIN(GPIOH, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); #if defined(SDRAM_BANK1) gpio_init_af(GPIO_PIN(GPIOH, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); #else gpio_init_af(GPIO_PIN(GPIOH, 6), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); #endif /* GPIOD configuration */ gpio_init_af(GPIO_PIN(GPIOD, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOD, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOD, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOD, 9), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOD, 10), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOD, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOD, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); /* GPIOE configuration */ gpio_init_af(GPIO_PIN(GPIOE, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 7), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 9), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 10), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 11), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 12), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 13), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOE, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); /* GPIOF configuration */ gpio_init_af(GPIO_PIN(GPIOF, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 2), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 4), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 11), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 12), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 13), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOF, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); /* GPIOG configuration */ gpio_init_af(GPIO_PIN(GPIOG, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOG, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOG, 4), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOG, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOG, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(GPIO_PIN(GPIOG, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); #if defined(SDRAM_32MB) gpio_init_af(GPIO_PIN(GPIOG, 2), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); #endif } void SDRAM_InitSequence(void) { FMC_SDRAM_CommandTypeDef FMC_SDRAMCommandStructure; uint32_t tmpr = 0; /* Step 3 --------------------------------------------------------------------*/ /* Configure a clock configuration enable command */ FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; FMC_SDRAMCommandStructure.CommandTarget = COMMAND_TARGET; FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; /* Wait until the SDRAM controller is ready */ while((__FMC_SDRAM_GET_FLAG(FMC_SDRAM_DEVICE, FMC_SDRAM_FLAG_BUSY) != 0)); /* Send the command */ FMC_SDRAM_SendCommand(FMC_SDRAM_DEVICE, &FMC_SDRAMCommandStructure, 10); /* Step 4 --------------------------------------------------------------------*/ /* Insert 100 ms delay */ delay_ms(100); /* Step 5 --------------------------------------------------------------------*/ /* Configure a PALL (precharge all) command */ FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_PALL; FMC_SDRAMCommandStructure.CommandTarget = COMMAND_TARGET; FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; /* Wait until the SDRAM controller is ready */ while((__FMC_SDRAM_GET_FLAG(FMC_SDRAM_DEVICE, FMC_SDRAM_FLAG_BUSY) != 0)); /* Send the command */ FMC_SDRAM_SendCommand(FMC_SDRAM_DEVICE, &FMC_SDRAMCommandStructure, 10); /* Step 6 --------------------------------------------------------------------*/ /* Configure a Auto-Refresh command */ FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; FMC_SDRAMCommandStructure.CommandTarget = COMMAND_TARGET; FMC_SDRAMCommandStructure.AutoRefreshNumber = 4; FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; /* Wait until the SDRAM controller is ready */ while((__FMC_SDRAM_GET_FLAG(FMC_SDRAM_DEVICE, FMC_SDRAM_FLAG_BUSY) != 0)); /* Send the command */ FMC_SDRAM_SendCommand(FMC_SDRAM_DEVICE, &FMC_SDRAMCommandStructure, 10); /* Step 7 --------------------------------------------------------------------*/ /* Program the external memory mode register */ tmpr = (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; /* Configure a load Mode register command*/ FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_LOAD_MODE; FMC_SDRAMCommandStructure.CommandTarget = COMMAND_TARGET; FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; FMC_SDRAMCommandStructure.ModeRegisterDefinition = tmpr; /* Wait until the SDRAM controller is ready */ while((__FMC_SDRAM_GET_FLAG(FMC_SDRAM_DEVICE, FMC_SDRAM_FLAG_BUSY) != 0)); /* Send the command */ FMC_SDRAM_SendCommand(FMC_SDRAM_DEVICE, &FMC_SDRAMCommandStructure, 10); /* Step 8: Set the refresh rate counter - refer to section SDRAM refresh timer register in RM0455 */ #if defined(SDRAM_32MB) /* Set the device refresh rate * COUNT = [(SDRAM self refresh time / number of row) x SDRAM CLK] - 20 = [(64ms/8192) * 84MHz] - 20 = 656 - 20 ~ 636 */ FMC_SDRAM_ProgramRefreshRate(FMC_SDRAM_DEVICE, 636); #else /* Set the device refresh rate * COUNT = [(SDRAM self refresh time / number of row) x SDRAM CLK] - 20 = [(64ms/4096) * 84MHz] - 20 = 1312 - 20 ~ 1292 */ FMC_SDRAM_ProgramRefreshRate(FMC_SDRAM_DEVICE, 1292); #endif /* Wait until the SDRAM controller is ready */ while((__FMC_SDRAM_GET_FLAG(FMC_SDRAM_DEVICE, FMC_SDRAM_FLAG_BUSY) != 0)); } extern "C" void SDRAM_Init(void) { //delay funcion needed delaysInit(); // Clocks must be enabled here, because the sdramInit is called before main LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_FMC); /* GPIO configuration for FMC SDRAM bank */ SDRAM_GPIOConfig(); /* FMC Configuration ---------------------------------------------------------*/ FMC_SDRAM_InitTypeDef FMC_SDRAMInitStructure; FMC_SDRAM_TimingTypeDef FMC_SDRAMTimingInitStructure; /* FMC SDRAM Bank configuration */ /* Timing configuration for 84 Mhz of SD clock frequency (168Mhz/2) */ /* TMRD: 2 Clock cycles */ FMC_SDRAMTimingInitStructure.LoadToActiveDelay = 2; /* TXSR: min=72ns (7x11.9ns) */ FMC_SDRAMTimingInitStructure.ExitSelfRefreshDelay = 7; /* TRAS: min=42ns (4x11.9ns) max=120k (ns) */ FMC_SDRAMTimingInitStructure.SelfRefreshTime = 4; /* TRC: min=60 (6x11.9ns) */ FMC_SDRAMTimingInitStructure.RowCycleDelay = 6; /* TWR: 2 CLK */ FMC_SDRAMTimingInitStructure.WriteRecoveryTime = 2; /* TRP: 15ns => 2x11.9ns */ FMC_SDRAMTimingInitStructure.RPDelay = 2; /* TRCD: 15ns => 2x11.9ns */ FMC_SDRAMTimingInitStructure.RCDDelay = 2; /* FMC SDRAM control configuration */ FMC_SDRAMInitStructure.SDBank = SDRAM_BANK; #if defined(SDRAM_32MB) /* Column addressing: [8:0] */ FMC_SDRAMInitStructure.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9; /* Row addressing: [12:0] */ FMC_SDRAMInitStructure.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13; #else /* Column addressing: [7:0] */ FMC_SDRAMInitStructure.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8; /* Row addressing: [11:0] */ FMC_SDRAMInitStructure.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12; #endif FMC_SDRAMInitStructure.MemoryDataWidth = SDRAM_MEMORY_WIDTH; FMC_SDRAMInitStructure.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; FMC_SDRAMInitStructure.CASLatency = SDRAM_CAS_LATENCY; FMC_SDRAMInitStructure.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE; FMC_SDRAMInitStructure.SDClockPeriod = SDRAM_CLK_PERIOD; FMC_SDRAMInitStructure.ReadBurst = SDRAM_READBURST; FMC_SDRAMInitStructure.ReadPipeDelay = SDRAM_READPIPEDELAY; // FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure; /* FMC SDRAM bank initialization */ FMC_SDRAM_Init(FMC_SDRAM_DEVICE, &FMC_SDRAMInitStructure); FMC_SDRAM_Timing_Init(FMC_SDRAM_DEVICE, &FMC_SDRAMTimingInitStructure, SDRAM_BANK); /* FMC SDRAM device initialization sequence */ SDRAM_InitSequence(); FMC_SDRAM_WriteProtection_Disable(FMC_SDRAM_DEVICE, SDRAM_BANK); }