66//
77// SPDX-License-Identifier: MIT
88
9+ #include <stdint.h>
910#include <stdio.h>
1011#include <stdbool.h>
1112#include <string.h>
3536#define DEBUG_OP_printf (...) (void)0
3637#endif
3738
38- #define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
39- #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
40- #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
41- #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
42- #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
43- #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
44- #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
45- #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
46- #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
47- #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
48- #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
49- #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
50-
51- #if defined(CIRCUITPY_HW_FMC_SDCKE0 ) && defined(CIRCUITPY_HW_FMC_SDNE0 )
52- #define FMC_SDRAM_BANK FMC_SDRAM_BANK1
53- #define FMC_SDRAM_CMD_TARGET_BANK FMC_SDRAM_CMD_TARGET_BANK1
54- #if CIRCUITPY_HW_FMC_SWAP_BANKS
55- #define SDRAM_START_ADDRESS 0x60000000
56- #else
57- #define SDRAM_START_ADDRESS 0xC0000000
58- #endif
59- #elif defined(CIRCUITPY_HW_FMC_SDCKE1 ) && defined(CIRCUITPY_HW_FMC_SDNE1 )
60- #define FMC_SDRAM_BANK FMC_SDRAM_BANK2
61- #define FMC_SDRAM_CMD_TARGET_BANK FMC_SDRAM_CMD_TARGET_BANK2
62- #if CIRCUITPY_HW_FMC_SWAP_BANKS
63- #define SDRAM_START_ADDRESS 0x70000000
64- #else
65- #define SDRAM_START_ADDRESS 0xD0000000
66- #endif
67- #endif
68-
69- #ifdef FMC_SDRAM_BANK
39+ #define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
40+ #define CIRCUITPY_HW_SDRAM_STARTUP_TEST (0)
7041
7142static uint8_t FMC_Initialized = 0 ;
7243static SDRAM_HandleTypeDef hsdram = {0 };
44+ static uint32_t sdram_start_address = 0 ;
7345
7446
75- static void sdram_init_seq (void );
47+ static void sdram_init_seq (const struct stm32_sdram_config * config );
7648
77- bool sdram_init (void ) {
49+ void sdram_init (const struct stm32_sdram_config * config ) {
7850 FMC_SDRAM_TimingTypeDef SDRAM_Timing = {0 };
7951
8052 if (!FMC_Initialized ) {
@@ -91,65 +63,37 @@ bool sdram_init(void) {
9163 /* Peripheral clock enable */
9264 __HAL_RCC_FMC_CLK_ENABLE ();
9365 FMC_Initialized = 1 ;
66+ for (uint i = 0 ; i < MP_ARRAY_SIZE (sdram_pin_list ); i ++ ) {
67+ GPIO_InitTypeDef GPIO_InitStruct = {0 };
68+ GPIO_InitStruct .Pin = pin_mask (sdram_pin_list [i ].pin -> number );
69+ GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
70+ GPIO_InitStruct .Pull = GPIO_NOPULL ;
71+ GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
72+ GPIO_InitStruct .Alternate = GPIO_AF12_FMC ;
73+ HAL_GPIO_Init (pin_port (sdram_pin_list [i ].pin -> port ), & GPIO_InitStruct );
74+ never_reset_pin_number (sdram_pin_list [i ].pin -> port , sdram_pin_list [i ].pin -> number );
75+ }
9476 }
9577
96- #if CIRCUITPY_HW_FMC_SWAP_BANKS
97- HAL_SetFMCMemorySwappingConfig (FMC_SWAPBMAP_SDRAM_SRAM );
98- #endif
99-
100- for (uint i = 0 ; i < MP_ARRAY_SIZE (sdram_pin_list ); i ++ ) {
101- GPIO_InitTypeDef GPIO_InitStruct = {0 };
102- GPIO_InitStruct .Pin = pin_mask (sdram_pin_list [i ].pin -> number );
103- GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
104- GPIO_InitStruct .Pull = GPIO_NOPULL ;
105- GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
106- GPIO_InitStruct .Alternate = GPIO_AF12_FMC ;
107- HAL_GPIO_Init (pin_port (sdram_pin_list [i ].pin -> port ), & GPIO_InitStruct );
108- never_reset_pin_number (sdram_pin_list [i ].pin -> port , sdram_pin_list [i ].pin -> number );
109- }
11078 /* SDRAM device configuration */
111- hsdram .Instance = FMC_SDRAM_DEVICE ;
112- /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */
113- /* TMRD: 2 Clock cycles */
114- SDRAM_Timing .LoadToActiveDelay = CIRCUITPY_HW_SDRAM_TIMING_TMRD ;
115- /* TXSR: min=70ns (6x11.90ns) */
116- SDRAM_Timing .ExitSelfRefreshDelay = CIRCUITPY_HW_SDRAM_TIMING_TXSR ;
117- /* TRAS */
118- SDRAM_Timing .SelfRefreshTime = CIRCUITPY_HW_SDRAM_TIMING_TRAS ;
119- /* TRC */
120- SDRAM_Timing .RowCycleDelay = CIRCUITPY_HW_SDRAM_TIMING_TRC ;
121- /* TWR */
122- SDRAM_Timing .WriteRecoveryTime = CIRCUITPY_HW_SDRAM_TIMING_TWR ;
123- /* TRP */
124- SDRAM_Timing .RPDelay = CIRCUITPY_HW_SDRAM_TIMING_TRP ;
125- /* TRCD */
126- SDRAM_Timing .RCDDelay = CIRCUITPY_HW_SDRAM_TIMING_TRCD ;
127-
128- #define _FMC_INIT (x , n ) x##_##n
129- #define FMC_INIT (x , n ) _FMC_INIT(x, n)
130-
131- hsdram .Init .SDBank = FMC_SDRAM_BANK ;
132- hsdram .Init .ColumnBitsNumber = FMC_INIT (FMC_SDRAM_COLUMN_BITS_NUM , CIRCUITPY_HW_SDRAM_COLUMN_BITS_NUM );
133- hsdram .Init .RowBitsNumber = FMC_INIT (FMC_SDRAM_ROW_BITS_NUM , CIRCUITPY_HW_SDRAM_ROW_BITS_NUM );
134- hsdram .Init .MemoryDataWidth = FMC_INIT (FMC_SDRAM_MEM_BUS_WIDTH , CIRCUITPY_HW_SDRAM_MEM_BUS_WIDTH );
135- hsdram .Init .InternalBankNumber = FMC_INIT (FMC_SDRAM_INTERN_BANKS_NUM , CIRCUITPY_HW_SDRAM_INTERN_BANKS_NUM );
136- hsdram .Init .CASLatency = FMC_INIT (FMC_SDRAM_CAS_LATENCY , CIRCUITPY_HW_SDRAM_CAS_LATENCY );
137- hsdram .Init .SDClockPeriod = FMC_INIT (FMC_SDRAM_CLOCK_PERIOD , CIRCUITPY_HW_SDRAM_CLOCK_PERIOD );
138- hsdram .Init .ReadPipeDelay = FMC_INIT (FMC_SDRAM_RPIPE_DELAY , CIRCUITPY_HW_SDRAM_RPIPE_DELAY );
139- hsdram .Init .ReadBurst = (CIRCUITPY_HW_SDRAM_RBURST ) ? FMC_SDRAM_RBURST_ENABLE : FMC_SDRAM_RBURST_DISABLE ;
140- hsdram .Init .WriteProtection = (CIRCUITPY_HW_SDRAM_WRITE_PROTECTION ) ? FMC_SDRAM_WRITE_PROTECTION_ENABLE : FMC_SDRAM_WRITE_PROTECTION_DISABLE ;
141-
142- /* Initialize the SDRAM controller */
143- if (HAL_SDRAM_Init (& hsdram , & SDRAM_Timing ) != HAL_OK ) {
144- DEBUG_printf ("sdram: %s" , "init error" );
145- return false;
79+ hsdram .Instance = config -> sdram ;
80+
81+ for (size_t i = 0U ; i < config -> banks_len ; i ++ ) {
82+ hsdram .State = HAL_SDRAM_STATE_RESET ;
83+
84+ memcpy (& hsdram .Init , & config -> banks [i ].init , sizeof (hsdram .Init ));
85+
86+ memcpy (& SDRAM_Timing , & config -> banks [i ].timing , sizeof (SDRAM_Timing ));
87+
88+ /* Initialize the SDRAM controller */
89+ if (HAL_SDRAM_Init (& hsdram , & SDRAM_Timing ) != HAL_OK ) {
90+ DEBUG_printf ("sdram bank[%d]: %s" , i , "init error" );
91+ }
14692 }
14793
148- sdram_init_seq ();
94+ sdram_init_seq (config );
14995
150- return true;
15196}
152-
15397void sdram_deinit (void ) {
15498 FMC_SDRAM_CommandTypeDef command = {0 };
15599 if (FMC_Initialized ) {
@@ -167,78 +111,55 @@ void sdram_deinit(void) {
167111}
168112
169113void * sdram_start (void ) {
170- return (void * )SDRAM_START_ADDRESS ;
114+ return (void * )sdram_start_address ;
171115}
172116
173117void * sdram_end (void ) {
174- return (void * )(SDRAM_START_ADDRESS + CIRCUITPY_HW_SDRAM_SIZE );
118+ return (void * )(sdram_start_address + CIRCUITPY_HW_SDRAM_SIZE );
175119}
176120
177121uint32_t sdram_size (void ) {
178122 return CIRCUITPY_HW_SDRAM_SIZE ;
179123}
180124
181- static void sdram_init_seq (void ) {
125+ static void sdram_init_seq (const struct stm32_sdram_config * config ) {
182126 FMC_SDRAM_CommandTypeDef command = {0 };
183127 /* Program the SDRAM external device */
184- __IO uint32_t tmpmrd = 0 ;
128+
129+ command .AutoRefreshNumber = config -> num_auto_refresh ;
130+ command .ModeRegisterDefinition = config -> mode_register ;
131+ if (config -> banks_len == 2U ) {
132+ command .CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2 ;
133+ sdram_start_address = 0xC0000000 ;
134+ } else if (config -> banks [0 ].init .SDBank == FMC_SDRAM_BANK1 ) {
135+ command .CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1 ;
136+ sdram_start_address = 0xC0000000 ;
137+ } else {
138+ command .CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2 ;
139+ sdram_start_address = 0xD0000000 ;
140+
141+ }
185142
186143 /* Configure a clock configuration enable command */
187144 command .CommandMode = FMC_SDRAM_CMD_CLK_ENABLE ;
188- command .CommandTarget = FMC_SDRAM_CMD_TARGET_BANK ;
189- command .AutoRefreshNumber = 1 ;
190- command .ModeRegisterDefinition = 0 ;
191-
192- /* Send the command */
193145 HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
194146
195- /* Insert 100 ms delay */
196147 HAL_Delay (100 );
197148
198149 /* Configure a PALL (precharge all) command */
199150 command .CommandMode = FMC_SDRAM_CMD_PALL ;
200- command .CommandTarget = FMC_SDRAM_CMD_TARGET_BANK ;
201- command .AutoRefreshNumber = 1 ;
202- command .ModeRegisterDefinition = 0 ;
203-
204- /* Send the command */
205151 HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
206152
207153 /* Configure a Auto-Refresh command */
208154 command .CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE ;
209- command .CommandTarget = FMC_SDRAM_CMD_TARGET_BANK ;
210- command .AutoRefreshNumber = CIRCUITPY_HW_SDRAM_AUTOREFRESH_NUM ;
211- command .ModeRegisterDefinition = 0 ;
212-
213- /* Send the command */
214155 HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
215156
216- /* Program the external memory mode register */
217- tmpmrd = (uint32_t )0x0 | FMC_INIT (SDRAM_MODEREG_BURST_LENGTH , CIRCUITPY_HW_SDRAM_BURST_LENGTH ) |
218- SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
219- FMC_INIT (SDRAM_MODEREG_CAS_LATENCY , CIRCUITPY_HW_SDRAM_CAS_LATENCY ) |
220- SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ;
221-
222157 command .CommandMode = FMC_SDRAM_CMD_LOAD_MODE ;
223- command .CommandTarget = FMC_SDRAM_CMD_TARGET_BANK ;
224- command .AutoRefreshNumber = 1 ;
225- command .ModeRegisterDefinition = tmpmrd ;
226-
227- /* Send the command */
158+ /* load mode */
228159 HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
229160
230- /* Set the refresh rate counter.
231- Assuming 100MHz frequency, 8192 refresh cycles and 64ms refresh rate:
232- RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc
233- RefreshCycles = 7.8125 us * 100 MHz = 782
234- According to the formula on p.1665 of the reference manual,
235- we also need to subtract 20 from the value, so the target
236- refresh rate is 782 - 20 = 762
237- */
238-
239- #define REFRESH_COUNT (CIRCUITPY_HW_SDRAM_REFRESH_RATE * CIRCUITPY_HW_SDRAM_FREQUENCY_KHZ / CIRCUITPY_HW_SDRAM_REFRESH_CYCLES - 20)
240-
241- HAL_SDRAM_ProgramRefreshRate (& hsdram , REFRESH_COUNT );
161+ /* program refresh count */
162+ HAL_SDRAM_ProgramRefreshRate (& hsdram , config -> refresh_rate );
242163
243164 #if defined(STM32F7 ) || defined(STM32H7 )
244165 __disable_irq ();
@@ -247,7 +168,7 @@ static void sdram_init_seq(void) {
247168 */
248169 MPU_InitStruct .Enable = MPU_REGION_ENABLE ;
249170 MPU_InitStruct .Number = CPY_SDRAM_REGION ;
250- MPU_InitStruct .BaseAddress = SDRAM_START_ADDRESS ;
171+ MPU_InitStruct .BaseAddress = sdram_start_address ;
251172 MPU_InitStruct .Size = CPY_SDRAM_REGION_SIZE ;
252173 MPU_InitStruct .SubRegionDisable = 0x0 ;
253174 MPU_InitStruct .TypeExtField = MPU_TEX_LEVEL1 ;
@@ -267,6 +188,8 @@ static void sdram_init_seq(void) {
267188
268189}
269190
191+ #if defined(CIRCUITPY_HW_SDRAM_STARTUP_TEST ) && (CIRCUITPY_HW_SDRAM_STARTUP_TEST == 1 )
192+
270193bool __attribute__((optimize ("Os" ))) sdram_test (bool exhaustive ) {
271194 uint8_t const pattern = 0xaa ;
272195 uint8_t const antipattern = 0x55 ;
@@ -293,7 +216,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
293216 #endif
294217
295218 // Test data bus
296- for (uint32_t i = 0 ; i < CIRCUITPY_HW_SDRAM_MEM_BUS_WIDTH ; i ++ ) {
219+ for (uint32_t i = 0 ; i < hsdram . Init . MemoryDataWidth ; i ++ ) {
297220 * ((volatile uint32_t * )mem_base ) = (1u << i );
298221 __DSB ();
299222 if (* ((volatile uint32_t * )mem_base ) != (1u << i )) {
@@ -367,5 +290,4 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
367290 return true;
368291}
369292
370-
371- #endif // FMC_SDRAM_BANK
293+ #endif // sdram_test
0 commit comments