6
6
//
7
7
// SPDX-License-Identifier: MIT
8
8
9
+ #include <stdint.h>
9
10
#include <stdio.h>
10
11
#include <stdbool.h>
11
12
#include <string.h>
35
36
#define DEBUG_OP_printf (...) (void)0
36
37
#endif
37
38
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)
70
41
71
42
static uint8_t FMC_Initialized = 0 ;
72
43
static SDRAM_HandleTypeDef hsdram = {0 };
44
+ static uint32_t sdram_start_address = 0 ;
73
45
74
46
75
- static void sdram_init_seq (void );
47
+ static void sdram_init_seq (const struct stm32_sdram_config * config );
76
48
77
- bool sdram_init (void ) {
49
+ void sdram_init (const struct stm32_sdram_config * config ) {
78
50
FMC_SDRAM_TimingTypeDef SDRAM_Timing = {0 };
79
51
80
52
if (!FMC_Initialized ) {
@@ -91,65 +63,37 @@ bool sdram_init(void) {
91
63
/* Peripheral clock enable */
92
64
__HAL_RCC_FMC_CLK_ENABLE ();
93
65
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
+ }
94
76
}
95
77
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
- }
110
78
/* 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
+ }
146
92
}
147
93
148
- sdram_init_seq ();
94
+ sdram_init_seq (config );
149
95
150
- return true;
151
96
}
152
-
153
97
void sdram_deinit (void ) {
154
98
FMC_SDRAM_CommandTypeDef command = {0 };
155
99
if (FMC_Initialized ) {
@@ -167,78 +111,55 @@ void sdram_deinit(void) {
167
111
}
168
112
169
113
void * sdram_start (void ) {
170
- return (void * )SDRAM_START_ADDRESS ;
114
+ return (void * )sdram_start_address ;
171
115
}
172
116
173
117
void * sdram_end (void ) {
174
- return (void * )(SDRAM_START_ADDRESS + CIRCUITPY_HW_SDRAM_SIZE );
118
+ return (void * )(sdram_start_address + CIRCUITPY_HW_SDRAM_SIZE );
175
119
}
176
120
177
121
uint32_t sdram_size (void ) {
178
122
return CIRCUITPY_HW_SDRAM_SIZE ;
179
123
}
180
124
181
- static void sdram_init_seq (void ) {
125
+ static void sdram_init_seq (const struct stm32_sdram_config * config ) {
182
126
FMC_SDRAM_CommandTypeDef command = {0 };
183
127
/* 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
+ }
185
142
186
143
/* Configure a clock configuration enable command */
187
144
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 */
193
145
HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
194
146
195
- /* Insert 100 ms delay */
196
147
HAL_Delay (100 );
197
148
198
149
/* Configure a PALL (precharge all) command */
199
150
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 */
205
151
HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
206
152
207
153
/* Configure a Auto-Refresh command */
208
154
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 */
214
155
HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
215
156
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
-
222
157
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 */
228
159
HAL_SDRAM_SendCommand (& hsdram , & command , HAL_MAX_DELAY );
229
160
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 );
242
163
243
164
#if defined(STM32F7 ) || defined(STM32H7 )
244
165
__disable_irq ();
@@ -247,7 +168,7 @@ static void sdram_init_seq(void) {
247
168
*/
248
169
MPU_InitStruct .Enable = MPU_REGION_ENABLE ;
249
170
MPU_InitStruct .Number = CPY_SDRAM_REGION ;
250
- MPU_InitStruct .BaseAddress = SDRAM_START_ADDRESS ;
171
+ MPU_InitStruct .BaseAddress = sdram_start_address ;
251
172
MPU_InitStruct .Size = CPY_SDRAM_REGION_SIZE ;
252
173
MPU_InitStruct .SubRegionDisable = 0x0 ;
253
174
MPU_InitStruct .TypeExtField = MPU_TEX_LEVEL1 ;
@@ -267,6 +188,8 @@ static void sdram_init_seq(void) {
267
188
268
189
}
269
190
191
+ #if defined(CIRCUITPY_HW_SDRAM_STARTUP_TEST ) && (CIRCUITPY_HW_SDRAM_STARTUP_TEST == 1 )
192
+
270
193
bool __attribute__((optimize ("Os" ))) sdram_test (bool exhaustive ) {
271
194
uint8_t const pattern = 0xaa ;
272
195
uint8_t const antipattern = 0x55 ;
@@ -293,7 +216,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
293
216
#endif
294
217
295
218
// 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 ++ ) {
297
220
* ((volatile uint32_t * )mem_base ) = (1u << i );
298
221
__DSB ();
299
222
if (* ((volatile uint32_t * )mem_base ) != (1u << i )) {
@@ -367,5 +290,4 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
367
290
return true;
368
291
}
369
292
370
-
371
- #endif // FMC_SDRAM_BANK
293
+ #endif // sdram_test
0 commit comments