1
0

drv_sdram.c 8.6 KB

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