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-28 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_APB2_PERIPH_AFIO | \
22 RCM_APB2_PERIPH_GPIOB | \
23 RCM_APB2_PERIPH_GPIOC | \
24 RCM_APB2_PERIPH_GPIOD | \
25 RCM_APB2_PERIPH_GPIOE | \
26 RCM_APB2_PERIPH_GPIOF | \
27 RCM_APB2_PERIPH_GPIOG)
28
29 /* SDRAM Peripheral Clock */
30 #define RCM_SDRAM_PERIPH (RCM_AHB_PERIPH_SMC)
31
32 #ifdef RT_USING_MEMHEAP_AS_HEAP
33 static struct rt_memheap system_heap;
34 #endif
35
36 /**
37 * @brief SDRAM divider Number
38 */
39 typedef enum
40 {
41 RCM_DMC_DIV_1,
42 RCM_DMC_DIV_2,
43 RCM_DMC_DIV_4 = 3
44 } RCM_DMC_DIV_T;
45
46 /**
47 * @brief Configs the SDRAM clock prescaler
48 * @param SDRAMDiv: Specifies the SDRAM clock prescaler from the DMC clock.
49 * @retval None
50 */
RCM_ConfigSDRAMCLK(RCM_DMC_DIV_T SDRAMDiv)51 static void RCM_ConfigSDRAMCLK(RCM_DMC_DIV_T SDRAMDiv)
52 {
53 RCM->CFG_B.SDRAMPSC = SDRAMDiv;
54 }
55
56 /**
57 * @brief sdram gpio init
58 * @param None
59 * @retval None
60 */
SDRAM_GPIO_Init(void)61 static void SDRAM_GPIO_Init(void)
62 {
63 GPIO_Config_T gpioConfig;
64
65 RCM_EnableAPB2PeriphClock(RCM_SDRAM_GPIO_PERIPH);
66
67 /** SDRAM pins assignment */
68 /**
69 +-------------------------+--------------------------+--------------------------+
70 | PB10 <-> MMC_SDRAM_UDQM | PC10 <-> MMC_SDRAM_D8 | PD2 <-> MMC_SDRAM_D10 |
71 | PB11 <-> MMC_SDRAM_CKE | PC11 <-> MMC_SDRAM_D9 | PD3 <-> MMC_SDRAM_D11 |
72 | | | PD4 <-> MMC_SDRAM_D12 |
73 | | | PD5 <-> MMC_SDRAM_D13 |
74 | | | PD6 <-> MMC_SDRAM_D14 |
75 +-------------------------+--------------------------+--------------------------+
76 | PE3 <-> MMC_SDRAM_D4 | PF0 <-> MMC_SDRAM_D7 | PG0 <-> MMC_SDRAM_A3 |
77 | PE5 <-> MMC_SDRAM_D5 | PF2 <-> MMC_SDRAM_NCS | PG9 <-> MMC_SDRAM_D15 |
78 | PE6 <-> MMC_SDRAM_D6 | PF4 <-> MMC_SDRAM_NRAS | PG12 <-> MMC_SDRAM_D0 |
79 | PE8 <-> MMC_SDRAM_A4 | PF5 <-> MMC_SDRAM_NCAS | PG13 <-> MMC_SDRAM_D1 |
80 | PE9 <-> MMC_SDRAM_A5 | PF6 <-> MMC_SDRAM_NWE | PG14 <-> MMC_SDRAM_D2 |
81 | PE10 <-> MMC_SDRAM_A6 | PF10 <-> MMC_SDRAM_LDQM | PG15 <-> MMC_SDRAM_D3 |
82 | PE11 <-> MMC_SDRAM_A7 | PF11 <-> MMC_SDRAM_Bank | |
83 | PE12 <-> MMC_SDRAM_A8 | PF12 <-> MMC_SDRAM_A10 | |
84 | PE13 <-> MMC_SDRAM_A9 | PF13 <-> MMC_SDRAM_A0 | |
85 | PE15 <-> MMC_SDRAM_CLK | PF14 <-> MMC_SDRAM_A1 | |
86 | | PF15 <-> MMC_SDRAM_A2 | |
87 +-------------------------+--------------------------+--------------------------+
88 */
89
90 gpioConfig.speed = GPIO_SPEED_50MHz;
91 gpioConfig.mode = GPIO_MODE_AF_PP;
92
93 gpioConfig.pin = GPIO_PIN_10 | GPIO_PIN_11;
94 GPIO_Config(GPIOB, &gpioConfig);
95
96 gpioConfig.pin = GPIO_PIN_10 | GPIO_PIN_11;
97 GPIO_Config(GPIOC, &gpioConfig);
98
99 gpioConfig.pin = GPIO_PIN_2 | GPIO_PIN_3 |
100 GPIO_PIN_4 | GPIO_PIN_5 |
101 GPIO_PIN_6;
102 GPIO_Config(GPIOD, &gpioConfig);
103
104 gpioConfig.pin = GPIO_PIN_3 | GPIO_PIN_5 |
105 GPIO_PIN_6 | GPIO_PIN_8 |
106 GPIO_PIN_9 | GPIO_PIN_10|
107 GPIO_PIN_11 | GPIO_PIN_12 |
108 GPIO_PIN_13 | GPIO_PIN_15 ;
109 GPIO_Config(GPIOE, &gpioConfig);
110
111 gpioConfig.pin = GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_4 |
112 GPIO_PIN_5 | GPIO_PIN_6 |
113 GPIO_PIN_10 |GPIO_PIN_11 |
114 GPIO_PIN_12 | GPIO_PIN_13|
115 GPIO_PIN_14 | GPIO_PIN_15;
116 GPIO_Config(GPIOF, &gpioConfig);
117
118 gpioConfig.pin = GPIO_PIN_0 | GPIO_PIN_9|
119 GPIO_PIN_12 | GPIO_PIN_13 |
120 GPIO_PIN_14 | GPIO_PIN_15;
121 GPIO_Config(GPIOG, &gpioConfig);
122 }
123
124 /**
125 * @brief sdram init
126 * @param None
127 * @retval None
128 */
SDRAM_Init(void)129 static int SDRAM_Init(void)
130 {
131 int result = RT_EOK;
132
133 DMC_Config_T dmc_init_config;
134 DMC_TimingConfig_T dmc_timing_config;
135
136 /* Config the SDRAM clock prescaler */
137 RCM_ConfigSDRAMCLK(RCM_DMC_DIV_2);
138
139 /* enable sdram clock */
140 RCM_EnableAHBPeriphClock(RCM_SDRAM_PERIPH);
141
142 /* sdram gpio init */
143 SDRAM_GPIO_Init();
144
145 /* dmc timing config */
146 dmc_timing_config.latencyCAS = DMC_CAS_LATENCY_3; //!< Configure CAS latency period
147 dmc_timing_config.tARP = DMC_AUTO_REFRESH_10; //!< Configure auto refresh period
148 dmc_timing_config.tRAS = DMC_RAS_MINIMUM_5; //!< Configure line activation and precharging minimum time
149 dmc_timing_config.tCMD = DMC_ATA_CMD_7; //!< Configure active to active period
150 dmc_timing_config.tRCD = DMC_DELAY_TIME_2; //!< Configure RAS To CAS delay Time
151 dmc_timing_config.tRP = DMC_PRECHARGE_2; //!< Configure precharge period
152 dmc_timing_config.tWR = DMC_NEXT_PRECHARGE_2; //!< Configure time between the Last Data and The Next Precharge for write
153 dmc_timing_config.tXSR = 6; //!< Configure XSR0
154 dmc_timing_config.tRFP = 0xC3; //!< Configure refresh Cycle
155
156 #if SDRAM_TARGET_BANK == 1
157 dmc_init_config.bankWidth = DMC_BANK_WIDTH_1; //!< Configure bank address width
158 #else
159 dmc_init_config.bankWidth = DMC_BANK_WIDTH_2; //!< Configure bank address width
160 #endif
161 dmc_init_config.clkPhase = DMC_CLK_PHASE_REVERSE; //!< Configure clock phase
162 dmc_init_config.rowWidth = SDRAM_ROW_BITS; //!< Configure row address width
163 dmc_init_config.colWidth = SDRAM_COLUMN_BITS; //!< Configure column address width
164 dmc_init_config.memorySize = SDRAM_MEMORY_SIZE;
165 dmc_init_config.timing = dmc_timing_config;
166
167 DMC_Config(&dmc_init_config);
168 DMC_ConfigOpenBank(DMC_BANK_NUMBER_2);
169 DMC_EnableAccelerateModule();
170
171 DMC_Enable();
172
173 LOG_D("sdram clock: %d MHz\r\n", RCM_ReadSYSCLKFreq()/1000000/(RCM->CFG_B.SDRAMPSC + 1));
174 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);
175
176 #ifdef RT_USING_MEMHEAP_AS_HEAP
177 /* If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap */
178 rt_memheap_init(&system_heap, "sdram", (void *)SDRAM_BANK_ADDR, SDRAM_SIZE);
179 #endif
180
181 return result;
182 }
183 INIT_BOARD_EXPORT(SDRAM_Init);
184
185 #ifdef DRV_DEBUG
186 #ifdef FINSH_USING_MSH
sdram_test(void)187 int sdram_test(void)
188 {
189 int i = 0;
190 uint32_t start_time = 0, time_cast = 0;
191 #if SDRAM_DATA_WIDTH == 8
192 char data_width = 1;
193 uint8_t data = 0;
194 #elif SDRAM_DATA_WIDTH == 16
195 char data_width = 2;
196 uint16_t data = 0;
197 #else
198 char data_width = 4;
199 uint32_t data = 0;
200 #endif
201
202 /* write data */
203 LOG_D("Writing the %ld bytes data, waiting....", SDRAM_SIZE);
204 start_time = rt_tick_get();
205 for (i = 0; i < SDRAM_SIZE / data_width; i++)
206 {
207 #if SDRAM_DATA_WIDTH == 8
208 *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint8_t)(i % 100);
209 #elif SDRAM_DATA_WIDTH == 16
210 *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)(i % 1000);
211 #else
212 *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint32_t)(i % 1000);
213 #endif
214 }
215 time_cast = rt_tick_get() - start_time;
216 LOG_D("Write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND,
217 time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
218
219 /* read data */
220 LOG_D("start Reading and verifying data, waiting....");
221 for (i = 0; i < SDRAM_SIZE / data_width; i++)
222 {
223 #if SDRAM_DATA_WIDTH == 8
224 data = *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width);
225 if (data != i % 100)
226 {
227 LOG_E("SDRAM test failed!");
228 break;
229 }
230 #elif SDRAM_DATA_WIDTH == 16
231 data = *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width);
232 if (data != i % 1000)
233 {
234 LOG_E("SDRAM test failed!");
235 break;
236 }
237 #else
238 data = *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width);
239 if (data != i % 1000)
240 {
241 LOG_E("SDRAM test failed!");
242 break;
243 }
244 #endif
245 }
246
247 if (i >= SDRAM_SIZE / data_width)
248 {
249 LOG_D("SDRAM test success!");
250 }
251
252 return RT_EOK;
253 }
254 MSH_CMD_EXPORT(sdram_test, sdram test)
255 #endif /* FINSH_USING_MSH */
256 #endif /* DRV_DEBUG */
257 #endif /* BSP_USING_SDRAM */
258