drv_sdram.c 8.2 KB

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