drv_exmc_sdram.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*!
  2. \file main.c
  3. \brief exmc sdram(MICRON 48LC16M16A2) driver
  4. */
  5. /*
  6. Copyright (C) 2016 GigaDevice
  7. 2016-10-19, V1.0.0, demo for GD32F4xx
  8. */
  9. #include "gd32f4xx.h"
  10. #include "drv_exmc_sdram.h"
  11. #include <rtthread.h>
  12. /* define mode register content */
  13. /* burst length */
  14. #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
  15. #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
  16. #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
  17. #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0003)
  18. /* burst type */
  19. #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
  20. #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
  21. /* CAS latency */
  22. #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
  23. #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
  24. /* write mode */
  25. #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
  26. #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
  27. #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
  28. #define SDRAM_TIMEOUT ((uint32_t)0x0000FFFF)
  29. static void delay_1ms(volatile uint32_t count)
  30. {
  31. count *= 1000;
  32. while (count--)
  33. {
  34. count = count;
  35. }
  36. }
  37. /*!
  38. \brief sdram peripheral initialize
  39. \param[in] sdram_device: specifie the SDRAM device
  40. \param[out] none
  41. \retval none
  42. */
  43. void exmc_synchronous_dynamic_ram_init(uint32_t sdram_device)
  44. {
  45. exmc_sdram_parameter_struct sdram_init_struct;
  46. exmc_sdram_timing_parameter_struct sdram_timing_init_struct;
  47. exmc_sdram_command_parameter_struct sdram_command_init_struct;
  48. uint32_t command_content = 0, bank_select;
  49. uint32_t timeout = SDRAM_TIMEOUT;
  50. /* enable EXMC clock*/
  51. rcu_periph_clock_enable(RCU_EXMC);
  52. rcu_periph_clock_enable(RCU_GPIOB);
  53. rcu_periph_clock_enable(RCU_GPIOC);
  54. rcu_periph_clock_enable(RCU_GPIOD);
  55. rcu_periph_clock_enable(RCU_GPIOE);
  56. rcu_periph_clock_enable(RCU_GPIOF);
  57. rcu_periph_clock_enable(RCU_GPIOG);
  58. rcu_periph_clock_enable(RCU_GPIOH);
  59. /* common GPIO configuration */
  60. /* SDNWE(PC0),SDNE0(PC2),SDCKE0(PC3) pin configuration */
  61. gpio_af_set(GPIOC, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
  62. gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
  63. gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
  64. /* D2(PD0),D3(PD1),D13(PD8),D14(PD9),D15(PD10),D0(PD14),D1(PD15) pin configuration */
  65. gpio_af_set(GPIOD, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |
  66. GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
  67. gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |
  68. GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
  69. gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |
  70. GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
  71. /* NBL0(PE0),NBL1(PE1),D4(PE7),D5(PE8),D6(PE9),D7(PE10),D8(PE11),D9(PE12),D10(PE13),D11(PE14),D12(PE15) pin configuration */
  72. gpio_af_set(GPIOE, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |
  73. GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
  74. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  75. gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |
  76. GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
  77. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  78. gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |
  79. GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
  80. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  81. /* A0(PF0),A1(PF1),A2(PF2),A3(PF3),A4(PF4),A5(PF5),NRAS(PF11),A6(PF12),A7(PF13),A8(PF14),A9(PF15) pin configuration */
  82. gpio_af_set(GPIOF, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
  83. GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 |
  84. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  85. gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
  86. GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 |
  87. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  88. gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
  89. GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 |
  90. GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  91. /* A10(PG0),A11(PG1),A12(PG2),A14(PG4),A15(PG5),SDCLK(PG8),NCAS(PG15) pin configuration */
  92. gpio_af_set(GPIOG, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 |
  93. GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
  94. gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 |
  95. GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
  96. gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 |
  97. GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
  98. /* specify which SDRAM to read and write */
  99. if(EXMC_SDRAM_DEVICE0 == sdram_device){
  100. bank_select = EXMC_SDRAM_DEVICE0_SELECT;
  101. }else{
  102. bank_select = EXMC_SDRAM_DEVICE1_SELECT;
  103. }
  104. /* EXMC SDRAM device initialization sequence --------------------------------*/
  105. /* Step 1 : configure SDRAM timing registers --------------------------------*/
  106. /* LMRD: 2 clock cycles */
  107. sdram_timing_init_struct.load_mode_register_delay = 2;
  108. /* XSRD: min = 67ns */
  109. sdram_timing_init_struct.exit_selfrefresh_delay = 7;
  110. /* RASD: min=42ns , max=120k (ns) */
  111. sdram_timing_init_struct.row_address_select_delay = 5;
  112. /* ARFD: min=60ns */
  113. sdram_timing_init_struct.auto_refresh_delay = 6;
  114. /* WRD: min=1 Clock cycles +6ns */
  115. sdram_timing_init_struct.write_recovery_delay = 2;
  116. /* RPD: min=18ns */
  117. sdram_timing_init_struct.row_precharge_delay = 2;
  118. /* RCD: min=18ns */
  119. sdram_timing_init_struct.row_to_column_delay = 2;
  120. /* step 2 : configure SDRAM control registers ---------------------------------*/
  121. sdram_init_struct.sdram_device = sdram_device;
  122. sdram_init_struct.column_address_width = EXMC_SDRAM_COW_ADDRESS_9;
  123. sdram_init_struct.row_address_width = EXMC_SDRAM_ROW_ADDRESS_13;
  124. sdram_init_struct.data_width = EXMC_SDRAM_DATABUS_WIDTH_16B;
  125. sdram_init_struct.internal_bank_number = EXMC_SDRAM_4_INTER_BANK;
  126. sdram_init_struct.cas_latency = EXMC_CAS_LATENCY_3_SDCLK;
  127. sdram_init_struct.write_protection = DISABLE;
  128. sdram_init_struct.sdclock_config = EXMC_SDCLK_PERIODS_2_HCLK;
  129. sdram_init_struct.brust_read_switch = ENABLE;
  130. sdram_init_struct.pipeline_read_delay = EXMC_PIPELINE_DELAY_1_HCLK;
  131. sdram_init_struct.timing = &sdram_timing_init_struct;
  132. /* EXMC SDRAM bank initialization */
  133. exmc_sdram_init(&sdram_init_struct);
  134. /* step 3 : configure CKE high command---------------------------------------*/
  135. sdram_command_init_struct.command = EXMC_SDRAM_CLOCK_ENABLE;
  136. sdram_command_init_struct.bank_select = bank_select;
  137. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
  138. sdram_command_init_struct.mode_register_content = 0;
  139. /* wait until the SDRAM controller is ready */
  140. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
  141. timeout--;
  142. }
  143. /* send the command */
  144. exmc_sdram_command_config(&sdram_command_init_struct);
  145. /* step 4 : insert 10ms delay----------------------------------------------*/
  146. delay_1ms(10);
  147. /* step 5 : configure precharge all command----------------------------------*/
  148. sdram_command_init_struct.command = EXMC_SDRAM_PRECHARGE_ALL;
  149. sdram_command_init_struct.bank_select = bank_select;
  150. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
  151. sdram_command_init_struct.mode_register_content = 0;
  152. /* wait until the SDRAM controller is ready */
  153. timeout = SDRAM_TIMEOUT;
  154. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
  155. timeout--;
  156. }
  157. /* send the command */
  158. exmc_sdram_command_config(&sdram_command_init_struct);
  159. /* step 6 : configure Auto-Refresh command-----------------------------------*/
  160. sdram_command_init_struct.command = EXMC_SDRAM_AUTO_REFRESH;
  161. sdram_command_init_struct.bank_select = bank_select;
  162. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_8_SDCLK;
  163. sdram_command_init_struct.mode_register_content = 0;
  164. /* wait until the SDRAM controller is ready */
  165. timeout = SDRAM_TIMEOUT;
  166. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
  167. timeout--;
  168. }
  169. /* send the command */
  170. exmc_sdram_command_config(&sdram_command_init_struct);
  171. /* step 7 : configure load mode register command-----------------------------*/
  172. /* program mode register */
  173. command_content = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
  174. SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
  175. SDRAM_MODEREG_CAS_LATENCY_3 |
  176. SDRAM_MODEREG_OPERATING_MODE_STANDARD |
  177. SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  178. sdram_command_init_struct.command = EXMC_SDRAM_LOAD_MODE_REGISTER;
  179. sdram_command_init_struct.bank_select = bank_select;
  180. sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
  181. sdram_command_init_struct.mode_register_content = command_content;
  182. /* wait until the SDRAM controller is ready */
  183. timeout = SDRAM_TIMEOUT;
  184. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
  185. timeout--;
  186. }
  187. /* send the command */
  188. exmc_sdram_command_config(&sdram_command_init_struct);
  189. /* step 8 : set the auto-refresh rate counter--------------------------------*/
  190. /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */
  191. /* SDCLK_Freq = SYS_Freq/2 */
  192. /* (7.81 us * SDCLK_Freq) - 20 */
  193. exmc_sdram_refresh_count_set(761);
  194. /* wait until the SDRAM controller is ready */
  195. timeout = SDRAM_TIMEOUT;
  196. while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
  197. timeout--;
  198. }
  199. }
  200. /*!
  201. \brief fill the buffer with specified value
  202. \param[in] pbuffer: pointer on the buffer to fill
  203. \param[in] buffersize: size of the buffer to fill
  204. \param[in] value: value to fill on the buffer
  205. \param[out] none
  206. \retval none
  207. */
  208. void fill_buffer(uint8_t *pbuffer, uint16_t buffer_lengh, uint16_t offset)
  209. {
  210. uint16_t index = 0;
  211. /* put in global buffer same values */
  212. for (index = 0; index < buffer_lengh; index++ ){
  213. pbuffer[index] = index + offset;
  214. }
  215. }
  216. /*!
  217. \brief write a byte buffer(data is 8 bits) to the EXMC SDRAM memory
  218. \param[in] sdram_device: specify which a SDRAM memory block is written
  219. \param[in] pbuffer: pointer to buffer
  220. \param[in] writeaddr: SDRAM memory internal address from which the data will be written
  221. \param[in] numbytetowrite: number of bytes to write
  222. \param[out] none
  223. \retval none
  224. */
  225. void sdram_writebuffer_8(uint32_t sdram_device,uint8_t* pbuffer, uint32_t writeaddr, uint32_t numbytetowrite)
  226. {
  227. uint32_t temp_addr;
  228. /* Select the base address according to EXMC_Bank */
  229. if(sdram_device == EXMC_SDRAM_DEVICE0){
  230. temp_addr = SDRAM_DEVICE0_ADDR;
  231. }else{
  232. temp_addr = SDRAM_DEVICE1_ADDR;
  233. }
  234. /* While there is data to write */
  235. for(; numbytetowrite != 0; numbytetowrite--) {
  236. /* Transfer data to the memory */
  237. *(uint8_t *) (temp_addr + writeaddr) = *pbuffer++;
  238. /* Increment the address*/
  239. writeaddr += 1;
  240. }
  241. }
  242. /*!
  243. \brief read a block of 8-bit data from the EXMC SDRAM memory
  244. \param[in] sdram_device: specify which a SDRAM memory block is written
  245. \param[in] pbuffer: pointer to buffer
  246. \param[in] readaddr: SDRAM memory internal address to read from
  247. \param[in] numbytetoread: number of bytes to read
  248. \param[out] none
  249. \retval none
  250. */
  251. void sdram_readbuffer_8(uint32_t sdram_device,uint8_t* pbuffer, uint32_t readaddr, uint32_t numbytetoread)
  252. {
  253. uint32_t temp_addr;
  254. /* select the base address according to EXMC_Bank */
  255. if(sdram_device == EXMC_SDRAM_DEVICE0){
  256. temp_addr = SDRAM_DEVICE0_ADDR;
  257. }else{
  258. temp_addr = SDRAM_DEVICE1_ADDR;
  259. }
  260. /* while there is data to read */
  261. for(; numbytetoread != 0; numbytetoread--){
  262. /* read a byte from the memory */
  263. *pbuffer++ = *(uint8_t*) (temp_addr + readaddr);
  264. /* increment the address */
  265. readaddr += 1;
  266. }
  267. }
  268. int rt_hw_sdram_init(void)
  269. {
  270. exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0);
  271. return 0;
  272. }
  273. INIT_BOARD_EXPORT(rt_hw_sdram_init);