drv_sdram.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-24 CDT first version
  9. * 2024-02-20 CDT modify exclk clock max frequency to 40MHz for HC32F4A0
  10. * add t_rcd_p/t_rfc_p/t_rp_p configuration
  11. * 2024-12-24 CDT modify sample clock to EXMC_DMC_SAMPLE_CLK_EXTCLK for HC32F4A0
  12. */
  13. /*******************************************************************************
  14. * Include files
  15. ******************************************************************************/
  16. #include <rtthread.h>
  17. #if defined(BSP_USING_EXMC)
  18. #if defined(BSP_USING_SDRAM)
  19. #include "drv_sdram.h"
  20. #include "board_config.h"
  21. #include "sdram_port.h"
  22. /*******************************************************************************
  23. * Local type definitions ('typedef')
  24. ******************************************************************************/
  25. /*******************************************************************************
  26. * Local pre-processor symbols/macros ('#define')
  27. ******************************************************************************/
  28. //#define DRV_DEBUG
  29. #define LOG_TAG "drv.sdram"
  30. #include <drv_log.h>
  31. /*******************************************************************************
  32. * Global variable definitions (declared in header file with 'extern')
  33. ******************************************************************************/
  34. #if defined (BSP_USING_SDRAM)
  35. rt_err_t rt_hw_board_sdram_init(void);
  36. #endif
  37. /*******************************************************************************
  38. * Local function prototypes ('static')
  39. ******************************************************************************/
  40. /*******************************************************************************
  41. * Local variable definitions ('static')
  42. ******************************************************************************/
  43. #ifdef RT_USING_MEMHEAP_AS_HEAP
  44. static struct rt_memheap _system_heap;
  45. #endif
  46. /*******************************************************************************
  47. * Function implementation - global ('extern') and local ('static')
  48. ******************************************************************************/
  49. /**
  50. * @brief SDRAM initialization sequence.
  51. * @param [in] chip The command chip number.
  52. * @param [in] md_reg_value The SDRAM mode register value
  53. * @retval None
  54. */
  55. static void _sdram_initialization_sequence(rt_uint32_t chip, rt_uint32_t md_reg_value)
  56. {
  57. /* SDRAM initialization sequence:
  58. CMD NOP->PrechargeAll->AutoRefresh->AutoRefresh->MdRegConfig->NOP */
  59. (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_NOP, 0UL);
  60. (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_PRECHARGE_ALL, 0UL);
  61. (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_AUTO_REFRESH, 0UL);
  62. (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_AUTO_REFRESH, 0UL);
  63. (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_MDREG_CONFIG, md_reg_value);
  64. (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_NOP, 0UL);
  65. }
  66. /**
  67. * @brief verify clock frequency.
  68. * @retval result
  69. */
  70. static rt_int32_t _sdram_verify_clock_frequency(void)
  71. {
  72. rt_int32_t ret = RT_EOK;
  73. #if defined (HC32F4A0) || defined (HC32F4A8)
  74. /* EXCLK max frequency for SDRAM */
  75. if (CLK_GetBusClockFreq(CLK_BUS_EXCLK) > EXMC_EXCLK_DMC_MAX_FREQ)
  76. {
  77. ret = -RT_ERROR;
  78. }
  79. #endif
  80. return ret;
  81. }
  82. /**
  83. * @brief SDRAM initialization.
  84. * @param None
  85. * @retval result
  86. */
  87. static rt_int32_t _sdram_init(void)
  88. {
  89. rt_uint32_t md_reg_value;
  90. stc_exmc_dmc_init_t stcDmcInit;
  91. stc_exmc_dmc_chip_config_t stcCsConfig;
  92. /* verify SDRAM clock frequency */
  93. if (_sdram_verify_clock_frequency() != RT_EOK)
  94. {
  95. LOG_E("EXMC clock frequency is over limit for SDRAM!");
  96. return -RT_ERROR;
  97. }
  98. /* initialization SDRAM port.*/
  99. rt_hw_board_sdram_init();
  100. /* enable DMC clock */
  101. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DMC, ENABLE);
  102. /* enable DMC. */
  103. EXMC_DMC_Cmd(ENABLE);
  104. /* configure DMC width && refresh period & chip & timing. */
  105. (void)EXMC_DMC_StructInit(&stcDmcInit);
  106. #if defined (HC32F4A0)
  107. stcDmcInit.u32SampleClock = EXMC_DMC_SAMPLE_CLK_EXTCLK;
  108. #endif
  109. stcDmcInit.u32RefreshPeriod = SDRAM_REFRESH_COUNT;
  110. stcDmcInit.u32ColumnBitsNumber = SDRAM_COLUMN_BITS;
  111. stcDmcInit.u32RowBitsNumber = SDRAM_ROW_BITS;
  112. stcDmcInit.u32MemBurst = SDRAM_BURST_LENGTH;
  113. stcDmcInit.u32AutoRefreshChips = EXMC_DMC_AUTO_REFRESH_4CHIPS;
  114. stcDmcInit.stcTimingConfig.u8CASL = SDRAM_CAS_LATENCY;
  115. stcDmcInit.stcTimingConfig.u8DQSS = 0U;
  116. stcDmcInit.stcTimingConfig.u8MRD = SDRAM_TMDR;
  117. stcDmcInit.stcTimingConfig.u8RAS = SDRAM_TRAS;
  118. stcDmcInit.stcTimingConfig.u8RC = SDRAM_TRC;
  119. stcDmcInit.stcTimingConfig.u8RCD_B = SDRAM_TRCD_B;
  120. stcDmcInit.stcTimingConfig.u8RCD_P = SDRAM_TRCD_P;
  121. stcDmcInit.stcTimingConfig.u8RFC_B = SDRAM_TRFC_B;
  122. stcDmcInit.stcTimingConfig.u8RFC_P = SDRAM_TRFC_P;
  123. stcDmcInit.stcTimingConfig.u8RP_B = SDRAM_TRP_B;
  124. stcDmcInit.stcTimingConfig.u8RP_P = SDRAM_TRP_P;
  125. stcDmcInit.stcTimingConfig.u8RRD = SDRAM_TRRD;
  126. stcDmcInit.stcTimingConfig.u8WR = SDRAM_TWR;
  127. stcDmcInit.stcTimingConfig.u8WTR = SDRAM_TWTR;
  128. stcDmcInit.stcTimingConfig.u8XP = SDRAM_TXP;
  129. stcDmcInit.stcTimingConfig.u8XSR = SDRAM_TXSR;
  130. stcDmcInit.stcTimingConfig.u8ESR = SDRAM_TESR;
  131. (void)EXMC_DMC_Init(&stcDmcInit);
  132. /* configure DMC address space. */
  133. stcCsConfig.u32AddrMatch = (SDRAM_BANK_ADDR >> 24);
  134. stcCsConfig.u32AddrMask = EXMC_DMC_ADDR_MASK_128MB;
  135. stcCsConfig.u32AddrDecodeMode = EXMC_DMC_CS_DECODE_ROWBANKCOL;
  136. (void)EXMC_DMC_ChipConfig(SDRAM_CHIP, &stcCsConfig);
  137. /* SDRAM initialization sequence. */
  138. md_reg_value = (SDRAM_MODEREG_BURST_TYPE | SDRAM_MODEREG_WRITEBURST_MODE | SDRAM_MODEREG_OPERATING_MODE);
  139. if (2U == stcDmcInit.stcTimingConfig.u8CASL)
  140. {
  141. md_reg_value |= SDRAM_MODEREG_CAS_LATENCY_2;
  142. }
  143. else
  144. {
  145. md_reg_value |= SDRAM_MODEREG_CAS_LATENCY_3;
  146. }
  147. if (EXMC_DMC_BURST_1BEAT == stcDmcInit.u32MemBurst)
  148. {
  149. md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_1;
  150. }
  151. else if (EXMC_DMC_BURST_2BEAT == stcDmcInit.u32MemBurst)
  152. {
  153. md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_2;
  154. }
  155. else if (EXMC_DMC_BURST_4BEAT == stcDmcInit.u32MemBurst)
  156. {
  157. md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_4;
  158. }
  159. else
  160. {
  161. md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_8;
  162. }
  163. _sdram_initialization_sequence(SDRAM_CHIP, md_reg_value);
  164. /* switch state from configure to ready */
  165. EXMC_DMC_SetState(EXMC_DMC_CTRL_STATE_GO);
  166. EXMC_DMC_SetState(EXMC_DMC_CTRL_STATE_WAKEUP);
  167. EXMC_DMC_SetState(EXMC_DMC_CTRL_STATE_GO);
  168. return RT_EOK;
  169. }
  170. int rt_hw_sdram_init(void)
  171. {
  172. rt_int32_t ret;
  173. ret = _sdram_init();
  174. if (RT_EOK != ret)
  175. {
  176. LOG_E("SDRAM init failed!");
  177. return -RT_ERROR;
  178. }
  179. #ifdef RT_USING_MEMHEAP_AS_HEAP
  180. /* If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap */
  181. rt_memheap_init(&_system_heap, "sdram", (void *)SDRAM_BANK_ADDR, SDRAM_SIZE);
  182. #endif
  183. return ret;
  184. }
  185. INIT_BOARD_EXPORT(rt_hw_sdram_init);
  186. #ifdef DRV_DEBUG
  187. #ifdef FINSH_USING_MSH
  188. static int _sdram_test(void)
  189. {
  190. rt_uint32_t i;
  191. rt_uint32_t start_time;
  192. rt_uint32_t time_cast;
  193. #if SDRAM_DATA_WIDTH == EXMC_DMC_MEMORY_WIDTH_16BIT
  194. const char data_width = 2;
  195. rt_uint16_t data = 0;
  196. #else
  197. char data_width = 4;
  198. rt_uint32_t data = 0;
  199. #endif
  200. /* write data */
  201. LOG_D("writing the %ld bytes data, waiting....", SDRAM_SIZE);
  202. start_time = rt_tick_get();
  203. for (i = 0; i < SDRAM_SIZE / data_width; i++)
  204. {
  205. #if SDRAM_DATA_WIDTH == EXMC_DMC_MEMORY_WIDTH_16BIT
  206. *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)(i % 1000);
  207. #else
  208. *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint32_t)(i % 1000);
  209. #endif
  210. }
  211. time_cast = rt_tick_get() - start_time;
  212. LOG_D("write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND,
  213. time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
  214. /* read data */
  215. LOG_D("start reading and verifying data, waiting....");
  216. for (i = 0; i < SDRAM_SIZE / data_width; i++)
  217. {
  218. #if SDRAM_DATA_WIDTH == EXMC_DMC_MEMORY_WIDTH_16BIT
  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. if (i >= SDRAM_SIZE / data_width)
  235. {
  236. LOG_D("SDRAM test success!");
  237. }
  238. return RT_EOK;
  239. }
  240. MSH_CMD_EXPORT(_sdram_test, sdram test)
  241. #endif /* FINSH_USING_MSH */
  242. #endif /* DRV_DEBUG */
  243. #endif /* BSP_USING_SDRAM */
  244. #endif /* BSP_USING_EXMC */