drv_sdram.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. */
  10. #include <board.h>
  11. #include <rtthread.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 SDRAM_HandleTypeDef hsdram1;
  18. static FMC_SDRAM_CommandTypeDef command;
  19. #ifdef RT_USING_MEMHEAP_AS_HEAP
  20. static struct rt_memheap system_heap;
  21. #endif
  22. /**
  23. * @brief
  24. * @param hsdram: SDRAM handle
  25. * @param Command: Pointer to SDRAM command structure
  26. * @retval None
  27. */
  28. static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
  29. {
  30. __IO uint32_t tmpmrd = 0;
  31. uint32_t target_bank = 0;
  32. #if SDRAM_TARGET_BANK == 1
  33. target_bank = FMC_SDRAM_CMD_TARGET_BANK1;
  34. #else
  35. target_bank = FMC_SDRAM_CMD_TARGET_BANK2;
  36. #endif
  37. /* Configure a clock configuration enable command */
  38. Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
  39. Command->CommandTarget = target_bank;
  40. Command->AutoRefreshNumber = 1;
  41. Command->ModeRegisterDefinition = 0;
  42. /* Send the command */
  43. HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
  44. /* Insert 100 ms delay */
  45. /* interrupt is not enable, just to delay some time. */
  46. for (tmpmrd = 0; tmpmrd < 0xffff; tmpmrd ++)
  47. ;
  48. /* Configure a PALL (precharge all) command */
  49. Command->CommandMode = FMC_SDRAM_CMD_PALL;
  50. Command->CommandTarget = target_bank;
  51. Command->AutoRefreshNumber = 1;
  52. Command->ModeRegisterDefinition = 0;
  53. /* Send the command */
  54. HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
  55. /* Configure a Auto-Refresh command */
  56. Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  57. Command->CommandTarget = target_bank;
  58. Command->AutoRefreshNumber = 8;
  59. Command->ModeRegisterDefinition = 0;
  60. /* Send the command */
  61. HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
  62. /* Program the external memory mode register */
  63. #if SDRAM_DATA_WIDTH == 8
  64. tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
  65. #elif SDRAM_DATA_WIDTH == 16
  66. tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
  67. #else
  68. tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_4 |
  69. #endif
  70. SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
  71. #if SDRAM_CAS_LATENCY == 3
  72. SDRAM_MODEREG_CAS_LATENCY_3 |
  73. #else
  74. SDRAM_MODEREG_CAS_LATENCY_2 |
  75. #endif
  76. SDRAM_MODEREG_OPERATING_MODE_STANDARD |
  77. SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  78. Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
  79. Command->CommandTarget = target_bank;
  80. Command->AutoRefreshNumber = 1;
  81. Command->ModeRegisterDefinition = tmpmrd;
  82. /* Send the command */
  83. HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
  84. /* Set the device refresh counter */
  85. HAL_SDRAM_ProgramRefreshRate(hsdram, SDRAM_REFRESH_COUNT);
  86. }
  87. static int SDRAM_Init(void)
  88. {
  89. int result = RT_EOK;
  90. FMC_SDRAM_TimingTypeDef SDRAM_Timing;
  91. /* SDRAM device configuration */
  92. hsdram1.Instance = FMC_SDRAM_DEVICE;
  93. SDRAM_Timing.LoadToActiveDelay = LOADTOACTIVEDELAY;
  94. SDRAM_Timing.ExitSelfRefreshDelay = EXITSELFREFRESHDELAY;
  95. SDRAM_Timing.SelfRefreshTime = SELFREFRESHTIME;
  96. SDRAM_Timing.RowCycleDelay = ROWCYCLEDELAY;
  97. SDRAM_Timing.WriteRecoveryTime = WRITERECOVERYTIME;
  98. SDRAM_Timing.RPDelay = RPDELAY;
  99. SDRAM_Timing.RCDDelay = RCDDELAY;
  100. #if SDRAM_TARGET_BANK == 1
  101. hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
  102. #else
  103. hsdram1.Init.SDBank = FMC_SDRAM_BANK2;
  104. #endif
  105. #if SDRAM_COLUMN_BITS == 8
  106. hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
  107. #elif SDRAM_COLUMN_BITS == 9
  108. hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
  109. #elif SDRAM_COLUMN_BITS == 10
  110. hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_10;
  111. #else
  112. hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_11;
  113. #endif
  114. #if SDRAM_ROW_BITS == 11
  115. hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_11;
  116. #elif SDRAM_ROW_BITS == 12
  117. hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
  118. #else
  119. hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
  120. #endif
  121. #if SDRAM_DATA_WIDTH == 8
  122. hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_8;
  123. #elif SDRAM_DATA_WIDTH == 16
  124. hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
  125. #else
  126. hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
  127. #endif
  128. hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  129. #if SDRAM_CAS_LATENCY == 1
  130. hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_1;
  131. #elif SDRAM_CAS_LATENCY == 2
  132. hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
  133. #else
  134. hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
  135. #endif
  136. hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  137. #if SDCLOCK_PERIOD == 2
  138. hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
  139. #else
  140. hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_3;
  141. #endif
  142. hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
  143. #if SDRAM_RPIPE_DELAY == 0
  144. hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
  145. #elif SDRAM_RPIPE_DELAY == 1
  146. hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
  147. #else
  148. hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_2;
  149. #endif
  150. /* Initialize the SDRAM controller */
  151. if (HAL_SDRAM_Init(&hsdram1, &SDRAM_Timing) != HAL_OK)
  152. {
  153. LOG_E("SDRAM init failed!");
  154. result = -RT_ERROR;
  155. }
  156. else
  157. {
  158. /* Program the SDRAM external device */
  159. SDRAM_Initialization_Sequence(&hsdram1, &command);
  160. 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);
  161. #ifdef RT_USING_MEMHEAP_AS_HEAP
  162. /* If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap */
  163. rt_memheap_init(&system_heap, "sdram", (void *)SDRAM_BANK_ADDR, SDRAM_SIZE);
  164. #endif
  165. }
  166. return result;
  167. }
  168. INIT_BOARD_EXPORT(SDRAM_Init);
  169. #ifdef DRV_DEBUG
  170. #ifdef FINSH_USING_MSH
  171. int sdram_test(void)
  172. {
  173. int i = 0;
  174. uint32_t start_time = 0, time_cast = 0;
  175. #if SDRAM_DATA_WIDTH == 8
  176. char data_width = 1;
  177. uint8_t data = 0;
  178. #elif SDRAM_DATA_WIDTH == 16
  179. char data_width = 2;
  180. uint16_t data = 0;
  181. #else
  182. char data_width = 4;
  183. uint32_t data = 0;
  184. #endif
  185. /* write data */
  186. LOG_D("Writing the %ld bytes data, waiting....", SDRAM_SIZE);
  187. start_time = rt_tick_get();
  188. for (i = 0; i < SDRAM_SIZE / data_width; i++)
  189. {
  190. #if SDRAM_DATA_WIDTH == 8
  191. *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint8_t)(i % 100);
  192. #elif SDRAM_DATA_WIDTH == 16
  193. *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)(i % 1000);
  194. #else
  195. *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint32_t)(i % 1000);
  196. #endif
  197. }
  198. time_cast = rt_tick_get() - start_time;
  199. LOG_D("Write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND,
  200. time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
  201. /* read data */
  202. LOG_D("start Reading and verifying data, waiting....");
  203. for (i = 0; i < SDRAM_SIZE / data_width; i++)
  204. {
  205. #if SDRAM_DATA_WIDTH == 8
  206. data = *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width);
  207. if (data != i % 100)
  208. {
  209. LOG_E("SDRAM test failed!");
  210. break;
  211. }
  212. #elif SDRAM_DATA_WIDTH == 16
  213. data = *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width);
  214. if (data != i % 1000)
  215. {
  216. LOG_E("SDRAM test failed!");
  217. break;
  218. }
  219. #else
  220. data = *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width);
  221. if (data != i % 1000)
  222. {
  223. LOG_E("SDRAM test failed!");
  224. break;
  225. }
  226. #endif
  227. }
  228. if (i >= SDRAM_SIZE / data_width)
  229. {
  230. LOG_D("SDRAM test success!");
  231. }
  232. return RT_EOK;
  233. }
  234. MSH_CMD_EXPORT(sdram_test, sdram test)
  235. #endif /* FINSH_USING_MSH */
  236. #endif /* DRV_DEBUG */
  237. #endif /* BSP_USING_SDRAM */