drv_sdram.c 8.8 KB

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