8000 SDRAM code refactoring · carlossless/circuitpython@6ac1e5b · GitHub
[go: up one dir, main page]

8000 Skip to content

Commit 6ac1e5b

Browse files
committed
SDRAM code refactoring
1 parent 71962eb commit 6ac1e5b

File tree

5 files changed

+151
-183
lines changed

5 files changed

+151
-183
lines changed

ports/stm/boards/daisy_seed_with_sdram/board.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,58 @@
33
// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct
44
//
55
// SPDX-License-Identifier: MIT
6+
#include STM32_HAL_H
67

78
#include "supervisor/board.h"
9+
#include "sdram.h"
810

9-
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.
11+
extern void port_add_sdram_to_heap(void);
12+
13+
/** SDRAM banks configuration. */
14+
static const struct stm32_sdram_bank_config bank_config[] = {
15+
{ .init = {
16+
.SDBank = FMC_SDRAM_BANK1,
17+
.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9,
18+
.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13,
19+
.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32,
20+
.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4,
21+
.CASLatency = FMC_SDRAM_CAS_LATENCY_3,
22+
.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE,
23+
.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2,
24+
.ReadBurst = FMC_SDRAM_RBURST_ENABLE,
25+
.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0
26+
},
27+
.timing = {
28+
.LoadToActiveDelay = 2,
29+
.ExitSelfRefreshDelay = 8,
30+
.SelfRefreshTime = 5,
31+
.RowCycleDelay = 6,
32+
.WriteRecoveryTime = 3,
33+
.RPDelay = 2,
34+
.RCDDelay = 2
35+
}}
36+
};
37+
38+
/* SDRAM configuration. */
39+
static const struct stm32_sdram_config config = {
40+
.sdram = FMC_SDRAM_DEVICE,
41+
.power_up_delay = 0,
42+
.num_auto_refresh = 8,
43+
.mode_register = SDRAM_MODEREG_BURST_LENGTH_4 |
44+
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
45+
SDRAM_MODEREG_CAS_LATENCY_3 |
46+
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE,
47+
/* Set the device refresh rate based on the RM0433 STM reference manual
48+
refresh_rate = [(SDRAM self refresh time / number of rows) x SDRAM CLK] – 20
49+
= [(64ms/8192) * 100MHz] - 20 = 781.25 - 20
50+
*/
51+
.refresh_rate = (64 * 100000 / 8192 - 20),
52+
.banks = bank_config,
53+
.banks_len = 1,
54+
};
55+
56+
void board_init(void) {
57+
sdram_init(&config);
58+
// sdram_test(true);
59+
port_add_sdram_to_heap();
60+
}

ports/stm/boards/daisy_seed_with_sdram/mpconfigboard.h

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,39 +32,9 @@
3232
// for RNG not audio
3333
#define CPY_CLK_USB_USES_AUDIOPLL (1)
3434

35-
// SDRAM -- on FMC controller
36-
37-
#define CPY_SDRAM_REGION MPU_REGION_NUMBER10
38-
#define CPY_SDRAM_REGION_SIZE MPU_REGION_SIZE_64MB
39-
40-
#define CIRCUITPY_HW_FMC_SDCKE0
41-
#define CIRCUITPY_HW_FMC_SDNE0
35+
// SDRAM and MPU region
4236

4337
#define CIRCUITPY_HW_SDRAM_SIZE (64 * 1024 * 1024) // 64 MByte
44-
#define CIRCUITPY_HW_SDRAM_STARTUP_TEST (1)
45-
#define CIRCUITPY_HW_FMC_SWAP_BANKS (0)
46-
47-
#define CIRCUITPY_HW_SDRAM_CLOCK_PERIOD 2
48-
#define CIRCUITPY_HW_SDRAM_CAS_LATENCY 3
49-
#define CIRCUITPY_HW_SDRAM_FREQUENCY_KHZ (100000) // 100 MHz
50-
#define CIRCUITPY_HW_SDRAM_TIMING_TMRD (2)
51-
#define CIRCUITPY_HW_SDRAM_TIMING_TXSR (8)
52-
#define CIRCUITPY_HW_SDRAM_TIMING_TRAS (5)
53-
#define CIRCUITPY_HW_SDRAM_TIMING_TRC (6)
54-
#define CIRCUITPY_HW_SDRAM_TIMING_TWR (3)
55-
#define CIRCUITPY_HW_SDRAM_TIMING_TRP (2)
56-
#define CIRCUITPY_HW_SDRAM_TIMING_TRCD (2)
5738

58-
#define CIRCUITPY_HW_SDRAM_ROW_BITS_NUM 13
59-
#define CIRCUITPY_HW_SDRAM_MEM_BUS_WIDTH 32
60-
#define CIRCUITPY_HW_SDRAM_REFRESH_CYCLES 8192
61-
62-
#define CIRCUITPY_HW_SDRAM_COLUMN_BITS_NUM 9
63-
#define CIRCUITPY_HW_SDRAM_INTERN_BANKS_NUM 4
64-
#define CIRCUITPY_HW_SDRAM_RPIPE_DELAY 0
65-
#define CIRCUITPY_HW_SDRAM_RBURST (1)
66-
#define CIRCUITPY_HW_SDRAM_WRITE_PROTECTION (0)
67-
68-
#define CIRCUITPY_HW_SDRAM_AUTOREFRESH_NUM (8)
69-
#define CIRCUITPY_HW_SDRAM_BURST_LENGTH 4
70-
#define CIRCUITPY_HW_SDRAM_REFRESH_RATE (64) // ms
39+
#define CPY_SDRAM_REGION MPU_REGION_NUMBER10
40+
#define CPY_SDRAM_REGION_SIZE MPU_REGION_SIZE_64MB

ports/stm/peripherals/sdram.c

< 10000 div class="d-flex flex-row flex-justify-end flex-1 flex-order-1 flex-sm-order-2 flex-items-center">
Lines changed: 55 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
// SPDX-License-Identifier: MIT
88

9+
#include <stdint.h>
910
#include <stdio.h>
1011
#include <stdbool.h>
1112
#include <string.h>
@@ -35,46 +36,17 @@
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

7142
static uint8_t FMC_Initialized = 0;
7243
static 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-
15397
void sdram_deinit(void) {
15498
FMC_SDRAM_CommandTypeDef command = {0};
15599
if (FMC_Initialized) {
@@ -167,78 +111,55 @@ void sdram_deinit(void) {
167111
}
168112

169113
void *sdram_start(void) {
170-
return (void *)SDRAM_START_ADDRESS;
114+
return (void *)sdram_start_address;
171115
}
172116

173117
void *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

177121
uint32_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+
270193
bool __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

Comments
 (0)
0