1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  */
9 #include <rtthread.h>
10 
11 #include <system_LPC177x_8x.h>
12 #include "LPC177x_8x.h"
13 #include "sdram.h"
14 
15 //LPC_EMC_TypeDef   * const g_pEMC = ((LPC_EMC_TypeDef*) LPC_EMC_BASE);
16 //LPC_IOCON_TypeDef * const LPC_IOCON = ((LPC_IOCON_TypeDef*) LPC_IOCON_BASE);
17 #define SDRAM_BASE               0xA0000000    /* CS0 */
18 #define EMC_NS2CLK(ns, nsPerClk)    ((ns + nsPerClk - 1) / nsPerClk)
19 
delayMs(int a,int b)20 static void delayMs(int a,int b)
21 {
22     volatile unsigned int i;
23     for(i=0;i<10000;i++);
24 }
25 
26 /*****************************************************************************
27 ** Function name:       delayMs
28 **
29 ** Descriptions:        Start the timer delay in milo seconds
30 **                      until elapsed
31 **
32 ** parameters:          timer number, Delay value in milo second
33 **
34 ** Returned value:      None
35 **
36 *****************************************************************************/
37 //void delayMs(uint8_t timer_num, uint32_t delayInMs)
38 //{
39 //  if ( timer_num == 0 )
40 //  {
41 //  LPC_TIM0->TCR = 0x02;       /* reset timer */
42 //  LPC_TIM0->PR  = 0x00;       /* set prescaler to zero */
43 //  LPC_TIM0->MR0 = delayInMs * (PeripheralClock / 1000 - 1);
44 //  LPC_TIM0->IR  = 0xff;       /* reset all interrrupts */
45 //  LPC_TIM0->MCR = 0x04;       /* stop timer on match */
46 //  LPC_TIM0->TCR = 0x01;       /* start timer */
47 //
48 //  /* wait until delay time has elapsed */
49 //  while (LPC_TIM0->TCR & 0x01);
50 //  }
51 //  else if ( timer_num == 1 )
52 //  {
53 //  LPC_TIM1->TCR = 0x02;       /* reset timer */
54 //  LPC_TIM1->PR  = 0x00;       /* set prescaler to zero */
55 //  LPC_TIM1->MR0 = delayInMs * (PeripheralClock / 1000 - 1);
56 //  LPC_TIM1->IR  = 0xff;       /* reset all interrrupts */
57 //  LPC_TIM1->MCR = 0x04;       /* stop timer on match */
58 //  LPC_TIM1->TCR = 0x01;       /* start timer */
59 //
60 //  /* wait until delay time has elapsed */
61 //  while (LPC_TIM1->TCR & 0x01);
62 //  }
63 //  else if ( timer_num == 2 )
64 //  {
65 //  LPC_TIM2->TCR = 0x02;       /* reset timer */
66 //  LPC_TIM2->PR  = 0x00;       /* set prescaler to zero */
67 //  LPC_TIM2->MR0 = delayInMs * (PeripheralClock / 1000 - 1);
68 //  LPC_TIM2->IR  = 0xff;       /* reset all interrrupts */
69 //  LPC_TIM2->MCR = 0x04;       /* stop timer on match */
70 //  LPC_TIM2->TCR = 0x01;       /* start timer */
71 //
72 //  /* wait until delay time has elapsed */
73 //  while (LPC_TIM2->TCR & 0x01);
74 //  }
75 //  else if ( timer_num == 3 )
76 //  {
77 //  LPC_TIM3->TCR = 0x02;       /* reset timer */
78 //  LPC_TIM3->PR  = 0x00;       /* set prescaler to zero */
79 //  LPC_TIM3->MR0 = delayInMs * (PeripheralClock / 1000 - 1);
80 //  LPC_TIM3->IR  = 0xff;       /* reset all interrrupts */
81 //  LPC_TIM3->MCR = 0x04;       /* stop timer on match */
82 //  LPC_TIM3->TCR = 0x01;       /* start timer */
83 //
84 //  /* wait until delay time has elapsed */
85 //  while (LPC_TIM3->TCR & 0x01);
86 //  }
87 //  return;
88 //}
89 
EMC_GPIO_Init(void)90 static void EMC_GPIO_Init (void)
91 {
92   LPC_IOCON->P3_0 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D0 @ P3.0 */
93   LPC_IOCON->P3_1 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D1 @ P3.1 */
94   LPC_IOCON->P3_2 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D2 @ P3.2 */
95   LPC_IOCON->P3_3 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D3 @ P3.3 */
96 
97   LPC_IOCON->P3_4 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D4 @ P3.4 */
98   LPC_IOCON->P3_5 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D5 @ P3.5 */
99   LPC_IOCON->P3_6 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D6 @ P3.6 */
100   LPC_IOCON->P3_7 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D7 @ P3.7 */
101 
102   LPC_IOCON->P3_8 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D8 @ P3.8 */
103   LPC_IOCON->P3_9 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D9 @ P3.9 */
104   LPC_IOCON->P3_10 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D10 @ P3.10 */
105   LPC_IOCON->P3_11 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D11 @ P3.11 */
106 
107   LPC_IOCON->P3_12 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D12 @ P3.12 */
108   LPC_IOCON->P3_13 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D13 @ P3.13 */
109   LPC_IOCON->P3_14 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D14 @ P3.14 */
110   LPC_IOCON->P3_15 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D15 @ P3.15 */
111 
112   LPC_IOCON->P3_16 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D16 @ P3.16 */
113   LPC_IOCON->P3_17 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D17 @ P3.17 */
114   LPC_IOCON->P3_18 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D18 @ P3.18 */
115   LPC_IOCON->P3_19 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D19 @ P3.19 */
116 
117   LPC_IOCON->P3_20 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D20 @ P3.20 */
118   LPC_IOCON->P3_21 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D21 @ P3.21 */
119   LPC_IOCON->P3_22 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D22 @ P3.22 */
120   LPC_IOCON->P3_23 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D23 @ P3.23 */
121 
122   LPC_IOCON->P3_24 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D24 @ P3.24 */
123   LPC_IOCON->P3_25 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D25 @ P3.25 */
124   LPC_IOCON->P3_26 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D26 @ P3.26 */
125   LPC_IOCON->P3_27 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D27 @ P3.27 */
126 
127   LPC_IOCON->P3_28 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D28 @ P3.28 */
128   LPC_IOCON->P3_29 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D29 @ P3.29 */
129   LPC_IOCON->P3_30 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D30 @ P3.30 */
130   LPC_IOCON->P3_31 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* D31 @ P3.31 */
131 
132   LPC_IOCON->P4_0 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A0 @ P4.0 */
133   LPC_IOCON->P4_1 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A1 @ P4.1 */
134   LPC_IOCON->P4_2 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A2 @ P4.2 */
135   LPC_IOCON->P4_3 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A3 @ P4.3 */
136 
137   LPC_IOCON->P4_4 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A4 @ P4.4 */
138   LPC_IOCON->P4_5 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A5 @ P4.5 */
139   LPC_IOCON->P4_6 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A6 @ P4.6 */
140   LPC_IOCON->P4_7 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A7 @ P4.7 */
141 
142   LPC_IOCON->P4_8 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A8 @ P4.8 */
143   LPC_IOCON->P4_9 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A9 @ P4.9 */
144   LPC_IOCON->P4_10 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A10 @ P4.10 */
145   LPC_IOCON->P4_11 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A11 @ P4.11 */
146 
147   LPC_IOCON->P4_12 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A12 @ P4.12 */
148   LPC_IOCON->P4_13 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A13 @ P4.13 */
149   LPC_IOCON->P4_14 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A14 @ P4.14 */
150   LPC_IOCON->P4_15 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A15 @ P4.15 */
151 
152   LPC_IOCON->P4_16 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A16 @ P4.16 */
153   LPC_IOCON->P4_17 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A17 @ P4.17 */
154   LPC_IOCON->P4_18 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A18 @ P4.18 */
155   LPC_IOCON->P4_19 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A19 @ P4.19 */
156 
157   LPC_IOCON->P4_20 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A20 @ P4.20 */
158   LPC_IOCON->P4_21 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A21 @ P4.21 */
159   LPC_IOCON->P4_22 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A22 @ P4.22 */
160   LPC_IOCON->P4_23 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* A23 @ P4.23 */
161 
162   LPC_IOCON->P4_25 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* WEN @ P4.25 */
163 
164 #if 1
165   LPC_IOCON->P4_24 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* OEN @ P4.24 */
166 
167   LPC_IOCON->P4_26 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* BLSN[0] @ P4.26 */
168   LPC_IOCON->P4_27 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* BLSN[1] @ P4.27 */
169 
170   LPC_IOCON->P4_28 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* BLSN[2] @ P4.28 */
171   LPC_IOCON->P4_29 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* BLSN[3] @ P4.29 */
172   LPC_IOCON->P4_30 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CSN[0] @ P4.30 */
173   LPC_IOCON->P4_31 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CSN[1] @ P4.31 */
174 
175   LPC_IOCON->P2_14 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CSN[2] @ P2.14 */
176   LPC_IOCON->P2_15 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CSN[3] @ P2.15 */
177 #endif
178 
179 #if 1
180   LPC_IOCON->P2_16 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CASN @ P2.16 */
181   LPC_IOCON->P2_17 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* RASN @ P2.17 */
182   LPC_IOCON->P2_18 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CLK[0] @ P2.18 */
183   LPC_IOCON->P2_19 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CLK[1] @ P2.19 */
184 
185   LPC_IOCON->P2_20 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DYCSN[0] @ P2.20 */
186   LPC_IOCON->P2_21 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DYCSN[1] @ P2.21 */
187   LPC_IOCON->P2_22 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DYCSN[2] @ P2.22 */
188   LPC_IOCON->P2_23 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DYCSN[3] @ P2.23 */
189 
190   LPC_IOCON->P2_24 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CKE[0] @ P2.24 */
191 
192 //  LPC_IOCON->P2_25 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CKE[1] @ P2.25 */
193   LPC_IOCON->P2_26 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CKE[2] @ P2.26 */
194   LPC_IOCON->P2_27 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* CKE[3] @ P2.27 */
195 
196   LPC_IOCON->P2_28 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DQM[0] @ P2.28 */
197   LPC_IOCON->P2_29 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DQM[1] @ P2.29 */
198   LPC_IOCON->P2_30 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DQM[2] @ P2.30 */
199   LPC_IOCON->P2_31 = (1<<0 | 0<<3 | 0<<5 | 1<<9); /* DQM[3] @ P2.31 */
200 #endif
201 }
202 
SDRAM_Init(void)203 void SDRAM_Init (void)
204 {
205     uint32_t i, dwtemp = dwtemp;
206     uint16_t wtemp = wtemp;
207     uint32_t mhz, nsPerClk;
208     /* Enable External Memory Controller power/clock */
209     LPC_SC->PCONP      |= 0x00000800;
210     LPC_SC->EMCDLYCTL   = 0x00001010;
211     LPC_EMC->Control = 0x00000001;
212     LPC_EMC->Config  = 0x00000000;
213 
214     EMC_GPIO_Init();
215 
216     mhz = SystemCoreClock / 1000000;
217     if (LPC_SC->EMCCLKSEL)
218         mhz >>= 1;
219     nsPerClk = 1000 / mhz;
220     LPC_EMC->DynamicRP         = EMC_NS2CLK(20, nsPerClk); /* 20ns,  */
221     LPC_EMC->DynamicRAS        = /*EMC_NS2CLK(42, nsPerClk);*/ 15; /* 42ns to 100K ns,  */
222     LPC_EMC->DynamicSREX       = 1 - 1; /* tSRE, 1clk, */
223     LPC_EMC->DynamicAPR        = 2 - 1; /* Not found!!! Estimated as 2clk, */
224     LPC_EMC->DynamicDAL        = EMC_NS2CLK(20, nsPerClk) + 2; /* tDAL = tRP + tDPL = 20ns + 2clk  */
225     LPC_EMC->DynamicWR         = 2 - 1; /* 2CLK,  */
226     LPC_EMC->DynamicRC         = EMC_NS2CLK(63, nsPerClk); /* H57V2562GTR-75C tRC=63ns(min)*/
227     LPC_EMC->DynamicRFC        = EMC_NS2CLK(63, nsPerClk); /* H57V2562GTR-75C tRFC=tRC */
228     LPC_EMC->DynamicXSR        = 0x0000000F; /* exit self-refresh to active, 不知道,设为最久  */
229     LPC_EMC->DynamicRRD        = EMC_NS2CLK(63, nsPerClk); /* 3clk, tRRD=15ns(min) */
230     LPC_EMC->DynamicMRD        = 2 - 1; /* 2clk, tMRD=2clk(min) */
231 
232 //    LPC_EMC->DynamicRP         = 0x00000002; /* 3clk=24ns,  */
233 //    LPC_EMC->DynamicRAS        = 0x00000005; /* 6clk=48ns,  */
234 //    LPC_EMC->DynamicSREX       = 0x00000001; /* 2clk, */
235 //    LPC_EMC->DynamicAPR        = 0x00000001; /* 2clk, */
236 //    LPC_EMC->DynamicDAL        = 0x00000005; /* 6clk,  */
237 //    LPC_EMC->DynamicWR         = 0x00000001; /* 2CLK,  */
238 //    LPC_EMC->DynamicRC         = 0x00000008; /* 9clk, H57V2562GTR-75C tRC=63ns(min)*/
239 //    LPC_EMC->DynamicRFC        = 0x00000008; /* 9clk, H57V2562GTR-75C tRFC=63ns(min) */
240 //    LPC_EMC->DynamicXSR        = 0x00000007; /* 8clk,  */
241 //    LPC_EMC->DynamicRRD        = 0x00000002; /* 3clk, tRRD=15ns(min) */
242 //    LPC_EMC->DynamicMRD        = 0x00000001; /* 2clk, tMRD=2clk(min) */
243 
244     LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
245     /* H57V2562GTR-75C: tCL=3CLK, tRCD=20ns(min), 3 CLK=24ns */
246     LPC_EMC->DynamicRasCas0    = 0x00000303; /* 3 RAS, 3 CAS latency */
247 
248     /* For Manley lpc1778 SDRAM: H57V2562GTR-75C, 256Mb, 16Mx16, 4 banks, row=13, column=9 */
249 #ifdef SDRAM_CONFIG_16BIT
250     LPC_EMC->DynamicConfig0    = 0x680; /* 256Mb, 16Mx16, 4 banks, row=13, column=9, RBC */
251 #elif defined SDRAM_CONFIG_32BIT
252     LPC_EMC->DynamicConfig0 = 0x4680; /* 256Mb, 16Mx16, 4 banks, row=13, column=9, RBC */
253 #endif
254     delayMs(0, 100);
255 
256     LPC_EMC->DynamicControl    = 0x00000183; /* Issue NOP command */
257     delayMs(0, 200);                              /* wait 200ms */
258 
259     LPC_EMC->DynamicControl    = 0x00000103; /* Issue PALL command */
260 
261     LPC_EMC->DynamicRefresh    = 0x00000002; /* ( n * 16 ) -> 32 clock cycles */
262     for(i = 0; i < 0x80; i++);                /* wait 128 AHB clock cycles */
263     /* 64ms/8192=7.8125us, nx16x8.33ns<7.8125us, n<58.6*/
264     wtemp = 64000000 / (1 << 13);
265     wtemp -= 16;
266     wtemp >>= 4;
267     wtemp = wtemp * mhz / 1000;
268     LPC_EMC->DynamicRefresh    = wtemp;
269 
270     LPC_EMC->DynamicControl    = 0x00000083; /* Issue MODE command */
271 
272 #ifdef SDRAM_CONFIG_16BIT
273 
274     wtemp = *((volatile uint16_t *)(SDRAM_BASE | (0x33<<12))); /* 8 burst, 3 CAS latency */
275 #elif defined SDRAM_CONFIG_32BIT
276     dwtemp = *((volatile uint32_t *)(SDRAM_BASE | (0x32<<13))); /* 4 burst, 3 CAS latency */
277 #endif
278 
279     LPC_EMC->DynamicControl    = 0x00000000; /* Issue NORMAL command */
280 
281     LPC_EMC->DynamicConfig0 |= 0x80000; /* enable buffer */
282     delayMs(0, 1);
283 
284 }
285 
286 
287