1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-03-18 luobeihai first version
9 */
10
11 #include <board.h>
12
13 #ifdef BSP_USING_SDRAM
14 #include "drv_sdram.h"
15
16 #define DRV_DEBUG
17 #define LOG_TAG "drv.sdram"
18 #include <drv_log.h>
19
20 /* SDRAM GPIO Clock */
21 #define RCM_SDRAM_GPIO_PERIPH (RCM_AHB1_PERIPH_GPIOA | \
22 RCM_AHB1_PERIPH_GPIOD | \
23 RCM_AHB1_PERIPH_GPIOF | \
24 RCM_AHB1_PERIPH_GPIOG | \
25 RCM_AHB1_PERIPH_GPIOH | \
26 RCM_AHB1_PERIPH_GPIOI )
27
28 #ifdef RT_USING_MEMHEAP_AS_HEAP
29 static struct rt_memheap system_heap;
30 #endif
31
32 /**
33 * @brief sdram gpio init
34 * @param None
35 * @retval None
36 */
SDRAM_GPIO_Init(void)37 static void SDRAM_GPIO_Init(void)
38 {
39 GPIO_Config_T gpioConfig;
40
41 RCM_EnableAHB1PeriphClock(RCM_SDRAM_GPIO_PERIPH);
42
43 gpioConfig.speed = GPIO_SPEED_50MHz;
44 gpioConfig.mode = GPIO_MODE_AF;
45 gpioConfig.otype = GPIO_OTYPE_PP;
46 gpioConfig.pupd = GPIO_PUPD_NOPULL;
47
48 gpioConfig.pin = GPIO_PIN_10 | GPIO_PIN_12 |
49 GPIO_PIN_13 | GPIO_PIN_14 |
50 GPIO_PIN_15;
51 GPIO_Config(GPIOD, &gpioConfig);
52
53 GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_10, GPIO_AF_FSMC);
54 GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_12, GPIO_AF_FSMC);
55 GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_13, GPIO_AF_FSMC);
56 GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_14, GPIO_AF_FSMC);
57 GPIO_ConfigPinAF(GPIOD, GPIO_PIN_SOURCE_15, GPIO_AF_FSMC);
58
59 gpioConfig.pin = GPIO_PIN_0 | GPIO_PIN_1 |
60 GPIO_PIN_2 | GPIO_PIN_3 |
61 GPIO_PIN_4 | GPIO_PIN_6 |
62 GPIO_PIN_7 | GPIO_PIN_8 |
63 GPIO_PIN_9 | GPIO_PIN_10 |
64 GPIO_PIN_11;
65 GPIO_Config(GPIOF, &gpioConfig);
66
67 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_0, GPIO_AF_FSMC);
68 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_1, GPIO_AF_FSMC);
69 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_2, GPIO_AF_FSMC);
70 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_3, GPIO_AF_FSMC);
71 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_4, GPIO_AF_FSMC);
72 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_6, GPIO_AF_FSMC);
73 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_7, GPIO_AF_FSMC);
74 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_8, GPIO_AF_FSMC);
75 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_9, GPIO_AF_FSMC);
76 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_10, GPIO_AF_FSMC);
77 GPIO_ConfigPinAF(GPIOF, GPIO_PIN_SOURCE_11, GPIO_AF_FSMC);
78
79 gpioConfig.pin = GPIO_PIN_1 | GPIO_PIN_2 |
80 GPIO_PIN_3 | GPIO_PIN_4 |
81 GPIO_PIN_5 | GPIO_PIN_6 |
82 GPIO_PIN_8 | GPIO_PIN_15;
83 GPIO_Config(GPIOG, &gpioConfig);
84
85 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_1, GPIO_AF_FSMC);
86 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_2, GPIO_AF_FSMC);
87 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_3, GPIO_AF_FSMC);
88 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_4, GPIO_AF_FSMC);
89 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_5, GPIO_AF_FSMC);
90 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_6, GPIO_AF_FSMC);
91 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_8, GPIO_AF_FSMC);
92 GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_15, GPIO_AF_FSMC);
93
94 gpioConfig.pin = GPIO_PIN_3 | GPIO_PIN_5 |
95 GPIO_PIN_8 | GPIO_PIN_10 |
96 GPIO_PIN_13 | GPIO_PIN_15;
97 GPIO_Config(GPIOH, &gpioConfig);
98
99 GPIO_ConfigPinAF(GPIOH, GPIO_PIN_SOURCE_3, GPIO_AF_FSMC);
100 GPIO_ConfigPinAF(GPIOH, GPIO_PIN_SOURCE_5, GPIO_AF_FSMC);
101 GPIO_ConfigPinAF(GPIOH, GPIO_PIN_SOURCE_8, GPIO_AF_FSMC);
102 GPIO_ConfigPinAF(GPIOH, GPIO_PIN_SOURCE_10, GPIO_AF_FSMC);
103 GPIO_ConfigPinAF(GPIOH, GPIO_PIN_SOURCE_13, GPIO_AF_FSMC);
104 GPIO_ConfigPinAF(GPIOH, GPIO_PIN_SOURCE_15, GPIO_AF_FSMC);
105
106 gpioConfig.pin = GPIO_PIN_3 | GPIO_PIN_7 |
107 GPIO_PIN_8 | GPIO_PIN_9 |
108 GPIO_PIN_10 | GPIO_PIN_11;
109 GPIO_Config(GPIOI, &gpioConfig);
110
111 GPIO_ConfigPinAF(GPIOI, GPIO_PIN_SOURCE_3, GPIO_AF_FSMC);
112 GPIO_ConfigPinAF(GPIOI, GPIO_PIN_SOURCE_7, GPIO_AF_FSMC);
113 GPIO_ConfigPinAF(GPIOI, GPIO_PIN_SOURCE_8, GPIO_AF_FSMC);
114 GPIO_ConfigPinAF(GPIOI, GPIO_PIN_SOURCE_9, GPIO_AF_FSMC);
115 GPIO_ConfigPinAF(GPIOI, GPIO_PIN_SOURCE_10, GPIO_AF_FSMC);
116 GPIO_ConfigPinAF(GPIOI, GPIO_PIN_SOURCE_11, GPIO_AF_FSMC);
117 }
118
SDRAM_Init(void)119 static int SDRAM_Init(void)
120 {
121 int result = RT_EOK;
122
123 DMC_Config_T dmc_init_config;
124 DMC_TimingConfig_T dmc_timing_config;
125
126 /* Config the SDRAM clock prescaler */
127 RCM_ConfigSDRAM(RCM_SDRAM_DIV_4);
128
129 /* enable sdram clock */
130 RCM->AHB3CLKEN |= BIT0;
131
132 /* sdram gpio init */
133 SDRAM_GPIO_Init();
134
135 /* dmc timing config */
136 dmc_timing_config.latencyCAS = DMC_CAS_LATENCY_3; //!< Configure CAS latency period
137 dmc_timing_config.tARP = DMC_AUTO_REFRESH_10; //!< Configure auto refresh period
138 dmc_timing_config.tRAS = DMC_RAS_MINIMUM_2; //!< Configure line activation and precharging minimum time
139 dmc_timing_config.tCMD = DMC_ATA_CMD_1; //!< Configure active to active period
140 dmc_timing_config.tRCD = DMC_DELAY_TIME_1; //!< Configure RAS To CAS delay Time
141 dmc_timing_config.tRP = DMC_PRECHARGE_1; //!< Configure precharge period
142 dmc_timing_config.tWR = DMC_NEXT_PRECHARGE_2; //!< Configure time between the Last Data and The Next Precharge for write
143 dmc_timing_config.tXSR = 3; //!< Configure XSR0
144 dmc_timing_config.tRFP = 0x2F9; //!< Configure refresh Cycle
145
146 #if SDRAM_TARGET_BANK == 1
147 dmc_init_config.bankWidth = DMC_BANK_WIDTH_1; //!< Configure bank address width
148 #else
149 dmc_init_config.bankWidth = DMC_BANK_WIDTH_2; //!< Configure bank address width
150 #endif
151 dmc_init_config.clkPhase = DMC_CLK_PHASE_REVERSE; //!< Configure clock phase
152 dmc_init_config.rowWidth = SDRAM_ROW_BITS; //!< Configure row address width
153 dmc_init_config.colWidth = SDRAM_COLUMN_BITS; //!< Configure column address width
154 dmc_init_config.timing = dmc_timing_config;
155
156 DMC_Config(&dmc_init_config);
157 DMC_ConfigOpenBank(DMC_BANK_NUMBER_2);
158 DMC_EnableAccelerateModule();
159
160 DMC_Enable();
161
162 LOG_D("sdram init success, mapped at 0x%X, size is %d bytes, data width is %d", SDRAM_BANK_ADDR, SDRAM_SIZE, SDRAM_DATA_WIDTH);
163
164 #ifdef RT_USING_MEMHEAP_AS_HEAP
165 /* If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap */
166 rt_memheap_init(&system_heap, "sdram", (void *)SDRAM_BANK_ADDR, SDRAM_SIZE);
167 #endif
168
169 return result;
170 }
171 INIT_BOARD_EXPORT(SDRAM_Init);
172
173 #ifdef DRV_DEBUG
174 #ifdef FINSH_USING_MSH
sdram_test(void)175 int sdram_test(void)
176 {
177 int i = 0;
178 uint32_t start_time = 0, time_cast = 0;
179 #if SDRAM_DATA_WIDTH == 8
180 char data_width = 1;
181 uint8_t data = 0;
182 #elif SDRAM_DATA_WIDTH == 16
183 char data_width = 2;
184 uint16_t data = 0;
185 #else
186 char data_width = 4;
187 uint32_t data = 0;
188 #endif
189
190 /* write data */
191 LOG_D("Writing the %ld bytes data, waiting....", SDRAM_SIZE);
192 start_time = rt_tick_get();
193 for (i = 0; i < SDRAM_SIZE / data_width; i++)
194 {
195 #if SDRAM_DATA_WIDTH == 8
196 *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint8_t)(i % 100);
197 #elif SDRAM_DATA_WIDTH == 16
198 *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)(i % 1000);
199 #else
200 *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint32_t)(i % 1000);
201 #endif
202 }
203 time_cast = rt_tick_get() - start_time;
204 LOG_D("Write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND,
205 time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
206
207 /* read data */
208 LOG_D("start Reading and verifying data, waiting....");
209 for (i = 0; i < SDRAM_SIZE / data_width; i++)
210 {
211 #if SDRAM_DATA_WIDTH == 8
212 data = *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width);
213 if (data != i % 100)
214 {
215 LOG_E("SDRAM test failed!");
216 break;
217 }
218 #elif SDRAM_DATA_WIDTH == 16
219 data = *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width);
220 if (data != i % 1000)
221 {
222 LOG_E("SDRAM test failed!");
223 break;
224 }
225 #else
226 data = *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width);
227 if (data != i % 1000)
228 {
229 LOG_E("SDRAM test failed!");
230 break;
231 }
232 #endif
233 }
234
235 if (i >= SDRAM_SIZE / data_width)
236 {
237 LOG_D("SDRAM test success!");
238 }
239
240 return RT_EOK;
241 }
242 MSH_CMD_EXPORT(sdram_test, sdram test)
243 #endif /* FINSH_USING_MSH */
244 #endif /* DRV_DEBUG */
245 #endif /* BSP_USING_SDRAM */
246