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