drv_sdram.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. * 2018-12-04 zylx first version
  9. * 2023-08-20 yuanzihao adapter gd32f4xx
  10. */
  11. #include <board.h>
  12. #ifdef BSP_USING_SDRAM
  13. #include <sdram_port.h>
  14. #define DRV_DEBUG
  15. #define LOG_TAG "drv.sdram"
  16. #include <drv_log.h>
  17. static exmc_sdram_parameter_struct sdram_init_struct;
  18. static exmc_sdram_command_parameter_struct sdram_command_init_struct;
  19. static exmc_sdram_timing_parameter_struct sdram_timing_init_struct;
  20. #ifdef RT_USING_MEMHEAP_AS_HEAP
  21. static struct rt_memheap system_heap;
  22. #endif
  23. static void SDRAM_Initialization_GPIO(void)
  24. {
  25. /* enable EXMC clock*/
  26. rcu_periph_clock_enable(RCU_EXMC);
  27. rcu_periph_clock_enable(RCU_GPIOB);
  28. rcu_periph_clock_enable(RCU_GPIOC);
  29. rcu_periph_clock_enable(RCU_GPIOD);
  30. rcu_periph_clock_enable(RCU_GPIOE);
  31. rcu_periph_clock_enable(RCU_GPIOF);
  32. rcu_periph_clock_enable(RCU_GPIOG);
  33. rcu_periph_clock_enable(RCU_GPIOH);
  34. /* common GPIO configuration */
  35. /* SDNWE(PC0),SDNE0(PC2),SDCKE0(PC3) pin configuration */
  36. gpio_af_set(GPIOC, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
  37. gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
  38. gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
  39. /* D2(PD0),D3(PD1),D13(PD8),D14(PD9),D15(PD10),D0(PD14),D1(PD15) pin configuration */
  40. gpio_af_set(GPIOD, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |
  41. GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
  42. gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |
  43. GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
  44. gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |
  45. GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
  46. /* NBL0(PE0),NBL1(PE1),D4(PE7),D5(PE8),D6(PE9),D7(PE10),D8(PE11),D9(PE12),D10(PE13),D11(PE14),D12(PE15) pin configuration */
  47. gpio_af_set(GPIOE, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |
  48. GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
  49. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  50. gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |
  51. GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
  52. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  53. gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |
  54. GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
  55. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  56. /* A0(PF0),A1(PF1),A2(PF2),A3(PF3),A4(PF4),A5(PF5),NRAS(PF11),A6(PF12),A7(PF13),A8(PF14),A9(PF15) pin configuration */
  57. gpio_af_set(GPIOF, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
  58. GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 |
  59. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  60. gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
  61. GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 |
  62. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  63. gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
  64. GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 |
  65. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  66. /* A10(PG0),A11(PG1),A12(PG2),A14(PG4),A15(PG5),SDCLK(PG8),NCAS(PG15) pin configuration */
  67. gpio_af_set(GPIOG, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 |
  68. GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
  69. gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 |
  70. GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
  71. gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 |
  72. GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
  73. }
  74. /**
  75. * @brief Perform the SDRAM exernal memory inialization sequence
  76. * @param hsdram: SDRAM handle
  77. * @param Command: Pointer to SDRAM command structure
  78. * @retval None
  79. */
  80. static rt_err_t SDRAM_Initialization_Sequence(exmc_sdram_parameter_struct *hsdram, exmc_sdram_command_parameter_struct *Command)
  81. {
  82. __IO uint32_t tmpmrd = 0;
  83. uint32_t target_bank = 0;
  84. uint32_t sdram_device = EXMC_SDRAM_DEVICE0;
  85. uint32_t command_content = 0;
  86. uint32_t timeout = SDRAM_TIMEOUT;
  87. #if SDRAM_TARGET_BANK == 1
  88. target_bank = EXMC_SDRAM_DEVICE0_SELECT;
  89. #else
  90. target_bank = EXMC_SDRAM_DEVICE1_SELECT;
  91. #endif
  92. SDRAM_Initialization_GPIO();
  93. /* EXMC SDRAM device initialization sequence --------------------------------*/
  94. /* Step 1 : configure SDRAM timing registers --------------------------------*/
  95. /* LMRD: 2 clock cycles */
  96. sdram_timing_init_struct.load_mode_register_delay = LOADTOACTIVEDELAY;
  97. /* XSRD: min = 75ns */
  98. sdram_timing_init_struct.exit_selfrefresh_delay = EXITSELFREFRESHDELAY;
  99. /* RASD: min=44ns , max=120k (ns) */
  100. sdram_timing_init_struct.row_address_select_delay = ROWCYCLEDELAY;
  101. /* ARFD: min=66ns */
  102. sdram_timing_init_struct.auto_refresh_delay = SELFREFRESHTIME;
  103. /* WRD: min=1 Clock cycles +7.5ns */
  104. sdram_timing_init_struct.write_recovery_delay = WRITERECOVERYTIME;
  105. /* RPD: min=20ns */
  106. sdram_timing_init_struct.row_precharge_delay = RPDELAY;
  107. /* RCD: min=20ns */
  108. sdram_timing_init_struct.row_to_column_delay = RCDDELAY;
  109. /* step 2 : configure SDRAM control registers ---------------------------------*/
  110. sdram_init_struct.sdram_device = sdram_device;
  111. sdram_init_struct.column_address_width = SDRAM_COLUMN_BITS;
  112. sdram_init_struct.row_address_width = SDRAM_ROW_BITS;
  113. sdram_init_struct.data_width = SDRAM_DATA_WIDTH;
  114. sdram_init_struct.internal_bank_number = EXMC_SDRAM_4_INTER_BANK;
  115. sdram_init_struct.cas_latency = SDRAM_CAS_LATENCY;
  116. sdram_init_struct.write_protection = DISABLE;
  117. sdram_init_struct.sdclock_config = SDCLOCK_PERIOD;
  118. sdram_init_struct.burst_read_switch = ENABLE;
  119. sdram_init_struct.pipeline_read_delay = SDRAM_RPIPE_DELAY;
  120. sdram_init_struct.timing = &sdram_timing_init_struct;
  121. /* EXMC SDRAM bank initialization */
  122. exmc_sdram_init(&sdram_init_struct);
  123. /* step 3 : configure CKE high command---------------------------------------*/
  124. sdram_command_init_struct.command = EXMC_SDRAM_CLOCK_ENABLE;
  125. sdram_command_init_struct.bank_select = target_bank;
  126. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
  127. sdram_command_init_struct.mode_register_content = 0;
  128. /* wait until the SDRAM controller is ready */
  129. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) {
  130. timeout--;
  131. }
  132. if(0 == timeout) {
  133. return RT_ERROR;
  134. }
  135. /* send the command */
  136. exmc_sdram_command_config(&sdram_command_init_struct);
  137. /* step 4 : insert 10ms delay----------------------------------------------*/
  138. // rt_thread_mdelay(10);
  139. /* step 5 : configure precharge all command----------------------------------*/
  140. sdram_command_init_struct.command = EXMC_SDRAM_PRECHARGE_ALL;
  141. sdram_command_init_struct.bank_select = target_bank;
  142. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
  143. sdram_command_init_struct.mode_register_content = 0;
  144. /* wait until the SDRAM controller is ready */
  145. timeout = SDRAM_TIMEOUT;
  146. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) {
  147. timeout--;
  148. }
  149. if(0 == timeout) {
  150. return RT_ERROR;
  151. }
  152. /* send the command */
  153. exmc_sdram_command_config(&sdram_command_init_struct);
  154. /* step 6 : configure Auto-Refresh command-----------------------------------*/
  155. sdram_command_init_struct.command = EXMC_SDRAM_AUTO_REFRESH;
  156. sdram_command_init_struct.bank_select = target_bank;
  157. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_9_SDCLK;
  158. sdram_command_init_struct.mode_register_content = 0;
  159. /* wait until the SDRAM controller is ready */
  160. timeout = SDRAM_TIMEOUT;
  161. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) {
  162. timeout--;
  163. }
  164. if(0 == timeout) {
  165. return RT_ERROR;
  166. }
  167. /* send the command */
  168. exmc_sdram_command_config(&sdram_command_init_struct);
  169. /* step 7 : configure load mode register command-----------------------------*/
  170. /* program mode register */
  171. command_content = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
  172. SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
  173. SDRAM_MODEREG_CAS_LATENCY_3 |
  174. SDRAM_MODEREG_OPERATING_MODE_STANDARD |
  175. SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  176. sdram_command_init_struct.command = EXMC_SDRAM_LOAD_MODE_REGISTER;
  177. sdram_command_init_struct.bank_select = target_bank;
  178. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
  179. sdram_command_init_struct.mode_register_content = command_content;
  180. /* wait until the SDRAM controller is ready */
  181. timeout = SDRAM_TIMEOUT;
  182. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) {
  183. timeout--;
  184. }
  185. if(0 == timeout) {
  186. return RT_ERROR;
  187. }
  188. /* send the command */
  189. exmc_sdram_command_config(&sdram_command_init_struct);
  190. /* step 8 : set the auto-refresh rate counter--------------------------------*/
  191. /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */
  192. /* SDCLK_Freq = SYS_Freq/2 */
  193. /* (7.81 us * SDCLK_Freq) - 20 */
  194. exmc_sdram_refresh_count_set(761);
  195. /* wait until the SDRAM controller is ready */
  196. timeout = SDRAM_TIMEOUT;
  197. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) {
  198. timeout--;
  199. }
  200. if(0 == timeout) {
  201. return RT_ERROR;
  202. }
  203. return RT_EOK;
  204. }
  205. static int SDRAM_Init(void)
  206. {
  207. int result = RT_EOK;
  208. /* Initialize the SDRAM controller */
  209. if (SDRAM_Initialization_Sequence(&sdram_init_struct, &sdram_command_init_struct) != RT_EOK)
  210. {
  211. LOG_E("SDRAM init failed!");
  212. result = -RT_ERROR;
  213. }
  214. else
  215. {
  216. rt_kprintf("sdram init success, mapped at 0x%X, size is %d bytes, data width is %d", SDRAM_BANK_ADDR, SDRAM_SIZE, SDRAM_DATA_WIDTH);
  217. #ifdef RT_USING_MEMHEAP_AS_HEAP
  218. /* If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap */
  219. rt_memheap_init(&system_heap, "sdram", (void *)SDRAM_BANK_ADDR, SDRAM_SIZE);
  220. #endif
  221. }
  222. return result;
  223. }
  224. INIT_BOARD_EXPORT(SDRAM_Init);
  225. #ifdef DRV_DEBUG
  226. #ifdef FINSH_USING_MSH
  227. int sdram_test(void)
  228. {
  229. int i = 0;
  230. uint32_t start_time = 0, time_cast = 0;
  231. #if SDRAM_DATA_WIDTH_IN_NUMBER == 8
  232. char data_width = 1;
  233. uint8_t data = 0;
  234. #elif SDRAM_DATA_WIDTH_IN_NUMBER == 16
  235. char data_width = 2;
  236. uint16_t data = 0;
  237. #else
  238. char data_width = 4;
  239. uint32_t data = 0;
  240. #endif
  241. /* write data */
  242. LOG_D("Writing the %ld bytes data, waiting....", SDRAM_SIZE);
  243. start_time = rt_tick_get();
  244. for (i = 0; i < SDRAM_SIZE / data_width; i++)
  245. {
  246. #if SDRAM_DATA_WIDTH_IN_NUMBER == 8
  247. *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint8_t)0x55;
  248. #elif SDRAM_DATA_WIDTH_IN_NUMBER == 16
  249. *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)0x5555;
  250. #else
  251. *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint32_t)0x55555555;
  252. #endif
  253. }
  254. time_cast = rt_tick_get() - start_time;
  255. LOG_D("Write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND,
  256. time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
  257. /* read data */
  258. LOG_D("start Reading and verifying data, waiting....");
  259. for (i = 0; i < SDRAM_SIZE / data_width; i++)
  260. {
  261. #if SDRAM_DATA_WIDTH_IN_NUMBER == 8
  262. data = *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width);
  263. if (data != 0x55)
  264. {
  265. LOG_E("SDRAM test failed!");
  266. break;
  267. }
  268. #elif SDRAM_DATA_WIDTH_IN_NUMBER == 16
  269. data = *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width);
  270. if (data != 0x5555)
  271. {
  272. LOG_E("SDRAM test failed!");
  273. break;
  274. }
  275. #else
  276. data = *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width);
  277. if (data != 0x55555555)
  278. {
  279. LOG_E("SDRAM test failed!");
  280. break;
  281. }
  282. #endif
  283. }
  284. if (i >= SDRAM_SIZE / data_width)
  285. {
  286. LOG_D("SDRAM test success!");
  287. }
  288. return RT_EOK;
  289. }
  290. MSH_CMD_EXPORT(sdram_test, sdram test)
  291. #endif /* FINSH_USING_MSH */
  292. #endif /* DRV_DEBUG */
  293. #endif /* BSP_USING_SDRAM */