diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 5cf8be79a..24e12d669 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -253,6 +253,7 @@ SRC_C = \ spibdev.c \ storage.c \ sdcard.c \ + sdram.c \ fatfs_port.c \ lcd.c \ accel.c \ @@ -305,10 +306,17 @@ ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l4)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_sd.c \ ll_sdmmc.c \ + ll_fmc.c \ ll_usb.c \ ) endif +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7)) +SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ + hal_sdram.c \ + ) +endif + ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c) else diff --git a/ports/stm32/main.c b/ports/stm32/main.c index a8600d975..eefb19b56 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -55,6 +55,7 @@ #include "rtc.h" #include "storage.h" #include "sdcard.h" +#include "sdram.h" #include "rng.h" #include "accel.h" #include "servo.h" @@ -555,7 +556,16 @@ soft_reset: mp_stack_set_limit((char*)&_estack - (char*)&_heap_end - 1024); // GC init + #if MICROPY_HW_SDRAM_SIZE + sdram_init(); + #if MICROPY_HW_SDRAM_STARTUP_TEST + sdram_test(true); + #endif + + gc_init(sdram_start(), sdram_end()); + #else gc_init(&_heap_start, &_heap_end); + #endif #if MICROPY_ENABLE_PYSTACK static mp_obj_t pystack[384]; diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index 181a34cad..323c66b1a 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -8,14 +8,15 @@ */ #include #include -#include -#include "mdefs.h" -#include "pincfg.h" +#include +#include "py/runtime.h" +#include "py/mphal.h" +#include "pin.h" +#include "pin_static_af.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_TIMEOUT ((uint32_t)0xFFFF) #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) @@ -28,43 +29,109 @@ #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; +#if defined(MICROPY_HW_FMC_SDCKE0) && defined(MICROPY_HW_FMC_SDNE0) +#define FMC_SDRAM_BANK FMC_SDRAM_BANK1 +#define FMC_SDRAM_CMD_TARGET_BANK FMC_SDRAM_CMD_TARGET_BANK1 +#define SDRAM_START_ADDRESS 0xC0000000 +#elif defined(MICROPY_HW_FMC_SDCKE1) && defined(MICROPY_HW_FMC_SDNE1) +#define FMC_SDRAM_BANK FMC_SDRAM_BANK2 +#define FMC_SDRAM_CMD_TARGET_BANK FMC_SDRAM_CMD_TARGET_BANK2 +#define SDRAM_START_ADDRESS 0xD0000000 +#endif + +#ifdef FMC_SDRAM_BANK + static void sdram_init_seq(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *command); extern void __fatal_error(const char *msg); -bool sdram_init() -{ +bool sdram_init(void) { + SDRAM_HandleTypeDef hsdram; + FMC_SDRAM_TimingTypeDef SDRAM_Timing; + FMC_SDRAM_CommandTypeDef command; + + __HAL_RCC_FMC_CLK_ENABLE(); + + #if defined(MICROPY_HW_FMC_SDCKE0) + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDCKE0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDCKE0); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDNE0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDNE0); + + #elif defined(MICROPY_HW_FMC_SDCKE1) + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDCKE1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDCKE1); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDNE1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDNE1); + #endif + + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDCLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDCLK); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDNCAS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDNCAS); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDNRAS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDNRAS); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_SDNWE, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_SDNWE); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_BA0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_BA0); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_BA1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_BA1); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_NBL0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_NBL0); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_NBL1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_NBL1); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A0); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A1); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A2); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A3); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A4, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A4); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A5); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A6); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A7); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A8); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A9); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A10); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A11); + #ifdef MICROPY_HW_FMC_A12 + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_A12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_A12); + #endif + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D0); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D1); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D2); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D3); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D4, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D4); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D5); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D6); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D7); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D8); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D9); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D10); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D11); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D12); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D13, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D13); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D14, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D14); + mp_hal_pin_config_alt_static(MICROPY_HW_FMC_D15, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_FMC_D15); + /* 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; + SDRAM_Timing.LoadToActiveDelay = MICROPY_HW_SDRAM_TIMING_TMRD; /* 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; + SDRAM_Timing.ExitSelfRefreshDelay = MICROPY_HW_SDRAM_TIMING_TXSR; + /* TRAS */ + SDRAM_Timing.SelfRefreshTime = MICROPY_HW_SDRAM_TIMING_TRAS; + /* TRC */ + SDRAM_Timing.RowCycleDelay = MICROPY_HW_SDRAM_TIMING_TRC; + /* TWR */ + SDRAM_Timing.WriteRecoveryTime = MICROPY_HW_SDRAM_TIMING_TWR; + /* TRP */ + SDRAM_Timing.RPDelay = MICROPY_HW_SDRAM_TIMING_TRP; + /* TRCD */ + SDRAM_Timing.RCDDelay = MICROPY_HW_SDRAM_TIMING_TRCD; - 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; + #define _FMC_INIT(x, n) x ## _ ## n + #define FMC_INIT(x, n) _FMC_INIT(x, n) + + hsdram.Init.SDBank = FMC_SDRAM_BANK; + hsdram.Init.ColumnBitsNumber = FMC_INIT(FMC_SDRAM_COLUMN_BITS_NUM, MICROPY_HW_SDRAM_COLUMN_BITS_NUM); + hsdram.Init.RowBitsNumber = FMC_INIT(FMC_SDRAM_ROW_BITS_NUM, MICROPY_HW_SDRAM_ROW_BITS_NUM); + hsdram.Init.MemoryDataWidth = FMC_INIT(FMC_SDRAM_MEM_BUS_WIDTH, MICROPY_HW_SDRAM_MEM_BUS_WIDTH); + hsdram.Init.InternalBankNumber = FMC_INIT(FMC_SDRAM_INTERN_BANKS_NUM, MICROPY_HW_SDRAM_INTERN_BANKS_NUM); + hsdram.Init.CASLatency = FMC_INIT(FMC_SDRAM_CAS_LATENCY, MICROPY_HW_SDRAM_CAS_LATENCY); + hsdram.Init.SDClockPeriod = FMC_INIT(FMC_SDRAM_CLOCK_PERIOD, MICROPY_HW_SDRAM_CLOCK_PERIOD); + hsdram.Init.ReadPipeDelay = FMC_INIT(FMC_SDRAM_RPIPE_DELAY, MICROPY_HW_SDRAM_RPIPE_DELAY); + hsdram.Init.ReadBurst = (MICROPY_HW_SDRAM_RBURST) ? FMC_SDRAM_RBURST_ENABLE : FMC_SDRAM_RBURST_DISABLE; + hsdram.Init.WriteProtection = (MICROPY_HW_SDRAM_WRITE_PROTECTION) ? FMC_SDRAM_WRITE_PROTECTION_ENABLE : FMC_SDRAM_WRITE_PROTECTION_DISABLE; /* Initialize the SDRAM controller */ if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK) { @@ -75,6 +142,14 @@ bool sdram_init() return true; } +void *sdram_start(void) { + return (void*)SDRAM_START_ADDRESS; +} + +void *sdram_end(void) { + return (void*)(SDRAM_START_ADDRESS + MICROPY_HW_SDRAM_SIZE); +} + static void sdram_init_seq(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *command) { @@ -83,7 +158,7 @@ static void sdram_init_seq(SDRAM_HandleTypeDef /* Step 3: Configure a clock configuration enable command */ command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; - command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; command->AutoRefreshNumber = 1; command->ModeRegisterDefinition = 0; @@ -95,7 +170,7 @@ static void sdram_init_seq(SDRAM_HandleTypeDef /* Step 5: Configure a PALL (precharge all) command */ command->CommandMode = FMC_SDRAM_CMD_PALL; - command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; command->AutoRefreshNumber = 1; command->ModeRegisterDefinition = 0; @@ -104,7 +179,7 @@ static void sdram_init_seq(SDRAM_HandleTypeDef /* Step 6 : Configure a Auto-Refresh command */ command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; - command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; command->AutoRefreshNumber = 4; command->ModeRegisterDefinition = 0; @@ -114,70 +189,77 @@ static void sdram_init_seq(SDRAM_HandleTypeDef /* 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 | + FMC_INIT(SDRAM_MODEREG_CAS_LATENCY, MICROPY_HW_SDRAM_CAS_LATENCY) | 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->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; 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 */ + /* Step 8: Set the refresh rate counter + 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. + */ + #define REFRESH_COUNT (MICROPY_HW_SDRAM_REFRESH_RATE * 90000 / 8192 - 20) HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT); } +bool __attribute__((optimize("O0"))) sdram_test(bool fast) { + uint8_t const pattern = 0xaa; + uint8_t const antipattern = 0x55; + uint8_t *const mem_base = (uint8_t*)sdram_start(); -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) { + 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(); + __asm__ volatile ("BKPT"); } } /* test address bus */ /* Check individual address lines */ - for (uint32_t i=1; i