A board support package for the LPC4088 Display Module.

Dependencies:   DM_HttpServer DM_USBHost

Dependents:   lpc4088_displaymodule_emwin lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI ... more

Fork of DMSupport by EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers <title>sdram.cpp Source File</title>

sdram.cpp

00001 /*
00002  *  Copyright 2014 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 
00018 /******************************************************************************
00019  * Includes
00020  *****************************************************************************/
00021 
00022 #include "mbed.h"
00023 #include "sdram.h"
00024 
00025 #if defined(TOOLCHAIN_ARM) /* KEIL uVision and mbed online compiler */
00026 #include "sys_helper.h"
00027 #endif
00028 
00029 /******************************************************************************
00030  * Defines and typedefs
00031  *****************************************************************************/
00032 
00033 
00034 /******************************************************************************
00035  * External global variables
00036  *****************************************************************************/
00037 
00038 /******************************************************************************
00039  * Local variables
00040  *****************************************************************************/
00041 
00042 static volatile uint32_t ringosccount[2] = {0,0};
00043 
00044 static bool okToUseSdramForHeap = true;
00045 static bool initialized = false;
00046 
00047 /******************************************************************************
00048  * Overridden Global Functions
00049  *****************************************************************************/
00050 
00051 #if defined(TOOLCHAIN_ARM) /* KEIL uVision and mbed online compiler */
00052   //http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0349c/Cihehbce.html
00053   
00054   extern "C" unsigned __rt_heap_extend(unsigned size, void **block) {
00055     static uint32_t lastReturnedBlock = 0;
00056 
00057     if (okToUseSdramForHeap && !initialized) {
00058       sdram_init();
00059     }
00060     
00061     // Make sure that SDRAM is only returned once (as all of it is returned
00062     // the first time) and only if the user has chosen to do it (via the
00063     // okToUseSdramForHeap variable.
00064     if (okToUseSdramForHeap && lastReturnedBlock==0) {
00065       *block = (void*)SDRAM_BASE;
00066       lastReturnedBlock = SDRAM_BASE;
00067       return SDRAM_SIZE;
00068     }
00069     return 0;
00070   }
00071 
00072   // Overrides the WEAK function in sys_helper.cpp to allow reserving a specific
00073   // amount of memory for the stack. Without this function it is possible to allocate
00074   // so much of the internal RAM that there is no free memory for the stack which 
00075   // in turn causes the program to crash.
00076   uint32_t __reserved_stack_size() {
00077     return 0x3000; // Reserve 0x3000 bytes of the IRAM for the stack
00078   }
00079 
00080 #elif defined(TOOLCHAIN_GCC_CR) /* CodeRed's RedSuite or LPCXpresso IDE */
00081   
00082   // NOTE: This way of overriding the implementation of malloc in NEWLIB
00083   //       will prevent the internal RAM from being used by malloc as 
00084   //       it only exposes the SDRAM. 
00085   
00086   // Dynamic memory allocation related syscall.
00087   extern "C" caddr_t _sbrk(int incr) {
00088     static unsigned char* heap = (unsigned char*)SDRAM_BASE;
00089     unsigned char*        prev_heap = heap;
00090     unsigned char*        new_heap = heap + incr;
00091 
00092     if (okToUseSdramForHeap && !initialized) {
00093       sdram_init();
00094     }    
00095     if (!okToUseSdramForHeap) {
00096       //errno = ENOMEM;
00097       return (caddr_t)-1;
00098     }
00099     if (new_heap >= (unsigned char*)(SDRAM_BASE + SDRAM_SIZE)) {
00100       //errno = ENOMEM;
00101       return (caddr_t)-1;
00102     }
00103 
00104     heap = new_heap;
00105     return (caddr_t) prev_heap;
00106   }  
00107 #endif
00108  
00109 /******************************************************************************
00110  * Local Functions
00111  *****************************************************************************/
00112 
00113 static void pinConfig(void)
00114 {
00115   LPC_IOCON->P3_0 |= 1; /* D0 @ P3.0 */
00116   LPC_IOCON->P3_1 |= 1; /* D1 @ P3.1 */
00117   LPC_IOCON->P3_2 |= 1; /* D2 @ P3.2 */
00118   LPC_IOCON->P3_3 |= 1; /* D3 @ P3.3 */
00119 
00120   LPC_IOCON->P3_4 |= 1; /* D4 @ P3.4 */
00121   LPC_IOCON->P3_5 |= 1; /* D5 @ P3.5 */
00122   LPC_IOCON->P3_6 |= 1; /* D6 @ P3.6 */
00123   LPC_IOCON->P3_7 |= 1; /* D7 @ P3.7 */
00124 
00125   LPC_IOCON->P3_8 |= 1; /* D8 @ P3.8 */
00126   LPC_IOCON->P3_9 |= 1; /* D9 @ P3.9 */
00127   LPC_IOCON->P3_10 |= 1; /* D10 @ P3.10 */
00128   LPC_IOCON->P3_11 |= 1; /* D11 @ P3.11 */
00129 
00130   LPC_IOCON->P3_12 |= 1; /* D12 @ P3.12 */
00131   LPC_IOCON->P3_13 |= 1; /* D13 @ P3.13 */
00132   LPC_IOCON->P3_14 |= 1; /* D14 @ P3.14 */
00133   LPC_IOCON->P3_15 |= 1; /* D15 @ P3.15 */
00134 
00135   LPC_IOCON->P3_16 |= 1; /* D16 @ P3.16 */
00136   LPC_IOCON->P3_17 |= 1; /* D17 @ P3.17 */
00137   LPC_IOCON->P3_18 |= 1; /* D18 @ P3.18 */
00138   LPC_IOCON->P3_19 |= 1; /* D19 @ P3.19 */
00139 
00140   LPC_IOCON->P3_20 |= 1; /* D20 @ P3.20 */
00141   LPC_IOCON->P3_21 |= 1; /* D21 @ P3.21 */
00142   LPC_IOCON->P3_22 |= 1; /* D22 @ P3.22 */
00143   LPC_IOCON->P3_23 |= 1; /* D23 @ P3.23 */
00144 
00145   LPC_IOCON->P3_24 |= 1; /* D24 @ P3.24 */
00146   LPC_IOCON->P3_25 |= 1; /* D25 @ P3.25 */
00147   LPC_IOCON->P3_26 |= 1; /* D26 @ P3.26 */
00148   LPC_IOCON->P3_27 |= 1; /* D27 @ P3.27 */
00149 
00150   LPC_IOCON->P3_28 |= 1; /* D28 @ P3.28 */
00151   LPC_IOCON->P3_29 |= 1; /* D29 @ P3.29 */
00152   LPC_IOCON->P3_30 |= 1; /* D30 @ P3.30 */
00153   LPC_IOCON->P3_31 |= 1; /* D31 @ P3.31 */
00154 
00155   LPC_IOCON->P4_0 |= 1; /* A0 @ P4.0 */
00156   LPC_IOCON->P4_1 |= 1; /* A1 @ P4.1 */
00157   LPC_IOCON->P4_2 |= 1; /* A2 @ P4.2 */
00158   LPC_IOCON->P4_3 |= 1; /* A3 @ P4.3 */
00159 
00160   LPC_IOCON->P4_4 |= 1; /* A4 @ P4.4 */
00161   LPC_IOCON->P4_5 |= 1; /* A5 @ P4.5 */
00162   LPC_IOCON->P4_6 |= 1; /* A6 @ P4.6 */
00163   LPC_IOCON->P4_7 |= 1; /* A7 @ P4.7 */
00164 
00165   LPC_IOCON->P4_8 |= 1; /* A8 @ P4.8 */
00166   LPC_IOCON->P4_9 |= 1; /* A9 @ P4.9 */
00167   LPC_IOCON->P4_10 |= 1; /* A10 @ P4.10 */
00168   LPC_IOCON->P4_11 |= 1; /* A11 @ P4.11 */
00169 
00170   LPC_IOCON->P4_12 |= 1; /* A12 @ P4.12 */
00171   LPC_IOCON->P4_13 |= 1; /* A13 @ P4.13 */
00172   LPC_IOCON->P4_14 |= 1; /* A14 @ P4.14 */
00173 #if 0 // not used for SDRAM
00174   LPC_IOCON->P4_15 |= 1; /* A15 @ P4.15 */
00175 
00176   LPC_IOCON->P4_16 |= 1; /* A16 @ P4.16 */
00177   LPC_IOCON->P4_17 |= 1; /* A17 @ P4.17 */
00178   LPC_IOCON->P4_18 |= 1; /* A18 @ P4.18 */
00179   LPC_IOCON->P4_19 |= 1; /* A19 @ P4.19 */
00180 
00181   LPC_IOCON->P4_20 |= 1; /* A20 @ P4.20 */
00182   LPC_IOCON->P4_21 |= 1; /* A21 @ P4.21 */
00183   LPC_IOCON->P4_22 |= 1; /* A22 @ P4.22 */
00184   LPC_IOCON->P4_23 |= 1; /* A23 @ P4.23 */
00185 #endif
00186 
00187   //LPC_IOCON->P4_24 |= 1; /* OEN @ P4.24 */
00188   LPC_IOCON->P4_25 |= 1; /* WEN @ P4.25 */
00189 #if 0 // not used for SDRAM
00190   LPC_IOCON->P4_26 |= 1; /* BLSN[0] @ P4.26 */
00191   LPC_IOCON->P4_27 |= 1; /* BLSN[1] @ P4.27 */
00192 
00193 
00194   LPC_IOCON->P4_28 |= 1; /* BLSN[2] @ P4.28 */
00195   LPC_IOCON->P4_29 |= 1; /* BLSN[3] @ P4.29 */
00196   LPC_IOCON->P4_30 |= 1; /* CSN[0] @ P4.30 */
00197   LPC_IOCON->P4_31 |= 1; /* CSN[1] @ P4.31 */
00198 #endif
00199 
00200   LPC_IOCON->P2_14 |= 1; /* CSN[2] @ P2.14 */
00201   LPC_IOCON->P2_15 |= 1; /* CSN[3] @ P2.15 */
00202 
00203   LPC_IOCON->P2_16 |= 1; /* CASN @ P2.16 */
00204   LPC_IOCON->P2_17 |= 1; /* RASN @ P2.17 */
00205   LPC_IOCON->P2_18 |= 1; /* CLK[0] @ P2.18 */
00206 #if 0 // not used for SDRAM
00207   LPC_IOCON->P2_19 |= 1; /* CLK[1] @ P2.19 */
00208 #endif
00209 
00210   LPC_IOCON->P2_20 |= 1; /* DYCSN[0] @ P2.20 */
00211 #if 0 // not used for SDRAM
00212   LPC_IOCON->P2_21 |= 1; /* DYCSN[1] @ P2.21 */
00213   LPC_IOCON->P2_22 |= 1; /* DYCSN[2] @ P2.22 */
00214   LPC_IOCON->P2_23 |= 1; /* DYCSN[3] @ P2.23 */
00215 #endif
00216 
00217   LPC_IOCON->P2_24 |= 1; /* CKE[0] @ P2.24 */
00218 #if 0 // not used for SDRAM
00219   LPC_IOCON->P2_25 |= 1; /* CKE[1] @ P2.25 */
00220   LPC_IOCON->P2_26 |= 1; /* CKE[2] @ P2.26 */
00221   LPC_IOCON->P2_27 |= 1; /* CKE[3] @ P2.27 */
00222 #endif
00223 
00224   LPC_IOCON->P2_28 |= 1; /* DQM[0] @ P2.28 */
00225   LPC_IOCON->P2_29 |= 1; /* DQM[1] @ P2.29 */
00226   LPC_IOCON->P2_30 |= 1; /* DQM[2] @ P2.30 */
00227   LPC_IOCON->P2_31 |= 1; /* DQM[3] @ P2.31 */
00228 }
00229 
00230 
00231 static uint32_t sdram_test( void )
00232 {
00233   volatile uint32_t *wr_ptr; 
00234   volatile uint16_t *short_wr_ptr;
00235   uint32_t data;
00236   uint32_t i, j;
00237 
00238   wr_ptr = (uint32_t *)SDRAM_BASE;
00239   short_wr_ptr = (uint16_t *)wr_ptr;
00240   /* Clear content before 16 bit access test */
00241 //  for (i = 0; i < SDRAM_SIZE/4; i++)
00242 //  {
00243 //  *wr_ptr++ = 0;
00244 //  }
00245 
00246   /* 16 bit write */
00247   for (i = 0; i < SDRAM_SIZE/0x40000; i++)
00248   {
00249     for (j = 0; j < 0x100; j++)
00250     {
00251       *short_wr_ptr++ = (i + j);
00252       *short_wr_ptr++ = (i + j) + 1;
00253     }
00254   }
00255 
00256   /* Verifying */
00257   wr_ptr = (uint32_t *)SDRAM_BASE;
00258   for (i = 0; i < SDRAM_SIZE/0x40000; i++)
00259   {
00260     for (j = 0; j < 0x100; j++)
00261     {
00262       data = *wr_ptr;          
00263       if (data != (((((i + j) + 1) & 0xFFFF) << 16) | ((i + j) & 0xFFFF)))
00264       {
00265         return 0x0;
00266       }
00267       wr_ptr++;
00268     }
00269   }
00270   return 0x1;
00271 }
00272 
00273 static uint32_t find_cmddly(void)
00274 {
00275   uint32_t cmddly, cmddlystart, cmddlyend, dwtemp;
00276   uint32_t ppass = 0x0, pass = 0x0;
00277 
00278   cmddly = 0x0;
00279   cmddlystart = cmddlyend = 0xFF;
00280 
00281   while (cmddly < 32)
00282   {
00283     dwtemp = LPC_SC->EMCDLYCTL & ~0x1F;
00284     LPC_SC->EMCDLYCTL = dwtemp | cmddly;
00285 
00286     if (sdram_test() == 0x1)
00287     {
00288       /* Test passed */
00289       if (cmddlystart == 0xFF)
00290       {
00291         cmddlystart = cmddly;
00292       }
00293       ppass = 0x1;
00294     }
00295     else
00296     {
00297       /* Test failed */
00298       if (ppass == 1)
00299       {
00300         cmddlyend = cmddly;
00301         pass = 0x1;
00302         ppass = 0x0;
00303       }
00304     }
00305 
00306     /* Try next value */
00307     cmddly++;
00308   }
00309 
00310   /* If the test passed, the we can use the average of the min and max values to get an optimal DQSIN delay */
00311   if (pass == 0x1)
00312   {
00313     cmddly = (cmddlystart + cmddlyend) / 2;
00314   }
00315   else if (ppass == 0x1)
00316   {
00317     cmddly = (cmddlystart + 0x1F) / 2;
00318   }
00319   else
00320   {
00321     /* A working value couldn't be found, just pick something safe so the system doesn't become unstable */
00322     cmddly = 0x10;
00323   }
00324 
00325   dwtemp = LPC_SC->EMCDLYCTL & ~0x1F;
00326   LPC_SC->EMCDLYCTL = dwtemp | cmddly;
00327 
00328   return (pass | ppass);
00329 }
00330 
00331 static uint32_t find_fbclkdly(void)
00332 {
00333   uint32_t fbclkdly, fbclkdlystart, fbclkdlyend, dwtemp;
00334   uint32_t ppass = 0x0, pass = 0x0;
00335 
00336   fbclkdly = 0x0;
00337   fbclkdlystart = fbclkdlyend = 0xFF;
00338 
00339   while (fbclkdly < 32)
00340   {
00341     dwtemp = LPC_SC->EMCDLYCTL & ~0x1F00;
00342     LPC_SC->EMCDLYCTL = dwtemp | (fbclkdly << 8);
00343 
00344     if (sdram_test() == 0x1)
00345     {
00346       /* Test passed */
00347       if (fbclkdlystart == 0xFF)
00348       {
00349         fbclkdlystart = fbclkdly;
00350       }
00351       ppass = 0x1;
00352     }
00353     else
00354     {
00355       /* Test failed */
00356       if (ppass == 1)
00357       {
00358         fbclkdlyend = fbclkdly;
00359         pass = 0x1;
00360         ppass = 0x0;
00361       }
00362     }
00363 
00364     /* Try next value */
00365     fbclkdly++;
00366   }
00367 
00368   /* If the test passed, the we can use the average of the min and max values to get an optimal DQSIN delay */
00369   if (pass == 0x1)
00370   {
00371     fbclkdly = (fbclkdlystart + fbclkdlyend) / 2;
00372   }
00373   else if (ppass == 0x1)
00374   {
00375     fbclkdly = (fbclkdlystart + 0x1F) / 2;
00376   }
00377   else
00378   {
00379     /* A working value couldn't be found, just pick something safe so the system doesn't become unstable */
00380     fbclkdly = 0x10;
00381   }
00382 
00383   dwtemp = LPC_SC->EMCDLYCTL & ~0x1F00;
00384   LPC_SC->EMCDLYCTL = dwtemp | (fbclkdly << 8);
00385 
00386   return (pass | ppass);
00387 }
00388 
00389 static uint32_t calibration( void )
00390 {
00391   uint32_t dwtemp, i;
00392   uint32_t cnt = 0;
00393 
00394   for (i = 0; i < 10; i++)
00395   {
00396     dwtemp = LPC_SC->EMCCAL & ~0x4000;
00397     LPC_SC->EMCCAL = dwtemp | 0x4000;
00398     
00399     dwtemp = LPC_SC->EMCCAL;
00400     while ((dwtemp & 0x8000) == 0x0000)
00401     {
00402       dwtemp = LPC_SC->EMCCAL;
00403     }
00404     cnt += (dwtemp & 0xFF); 
00405   }
00406   return (cnt / 10);
00407 }
00408 
00409 static void allowExecutionOfCodeInSDRAM(void)
00410 {
00411   //----- Adjust MPU to allow execution of code from SDRAM
00412   
00413   /* Disable MPU */
00414   MPU->CTRL = 0x00;
00415   
00416   /* Select to use the default memory map as base and only modify parts */
00417   MPU->CTRL = 0x04; // PRIVDEFENA=1
00418   
00419 #define _RBAR(_ADDR, _VALID, _REGION) \
00420     ((_ADDR) | ((_VALID) << 4) | (_REGION))
00421 
00422 #define _RASR(_XN, _AP, _TYPE, _SRD, _SIZE, _ENABLE) \
00423     (((_XN) << 28) | ((_AP) << 24) | ((_TYPE) << 16) | ((_SRD) << 8) | ((_SIZE) << 1) | (_ENABLE))
00424 
00425 #define AP_RW         0x03 // 011 = Full Access
00426 #define MEM_TYPE_ERAM 0x07 // Normal, Sharable, Cached, Buffered, write-back & write allocate
00427 #define SIZE_32M      0x18 // Region size in bytes = 2^(0x18+1) = 32MB
00428 
00429   /* Setup MPU Region 4 for the SDRAM (0xA0000000 - 0xA1FFFFFF*/
00430   MPU->RBAR = _RBAR(0xA0000000, 1, 4);
00431   MPU->RASR = _RASR(0, AP_RW, MEM_TYPE_ERAM, 0, SIZE_32M, 1);
00432 
00433   /* (Re-)Enable MPU */
00434   MPU->CTRL |= 0x01;
00435   
00436   //----- End of MPU adjustments
00437 }
00438 
00439 /******************************************************************************
00440  * Public Functions
00441  *****************************************************************************/
00442 
00443 
00444 void adjust_timing( void )
00445 {
00446   uint32_t dwtemp, cmddly, fbclkdly;
00447 
00448   /* Current value */
00449   ringosccount[1] = calibration();
00450 
00451   dwtemp   = LPC_SC->EMCDLYCTL;
00452   cmddly   = ((dwtemp & 0x1F) * ringosccount[0] / ringosccount[1]) & 0x1F;
00453   fbclkdly = ((dwtemp & 0x1F00) * ringosccount[0] / ringosccount[1]) & 0x1F00;
00454   LPC_SC->EMCDLYCTL = (dwtemp & ~0x1F1F) | fbclkdly | cmddly;
00455 }
00456 
00457 /******************************************************************************
00458  *
00459  * Description:
00460  *    Initialize the SDRAM
00461  *
00462  *****************************************************************************/
00463 uint32_t sdram_init (void)
00464 {
00465   uint32_t i;
00466   uint32_t dwtemp = 0;
00467   //uint16_t wtemp = 0;
00468   
00469   if (initialized) {
00470     return 0;
00471   }
00472 
00473   LPC_SC->PCONP     |= 0x00000800;
00474   LPC_SC->EMCDLYCTL  = 0x00001010;
00475   LPC_EMC->Control   = 0x00000001;
00476   LPC_EMC->Config    = 0x00000000;
00477 
00478   pinConfig(); //Full 32-bit Data bus, 24-bit Address 
00479 
00480   /* Configure memory layout, but MUST DISABLE BUFFERs during configuration */
00481   /* 256MB, 8Mx32, 4 banks, row=12, column=9 */
00482   LPC_EMC->DynamicConfig0    = 0x00004480; 
00483 
00484   /*Configure timing for ISSI IS4x32800D SDRAM*/
00485 
00486 #if (SDRAM_SPEED==SDRAM_SPEED_48)
00487 //Timing for 48MHz Bus
00488   LPC_EMC->DynamicRasCas0    = 0x00000201; /* 1 RAS, 2 CAS latency */
00489   LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
00490   LPC_EMC->DynamicRP         = 0x00000000; /* ( n + 1 ) -> 1 clock cycles */
00491   LPC_EMC->DynamicRAS        = 0x00000002; /* ( n + 1 ) -> 3 clock cycles */
00492   LPC_EMC->DynamicSREX       = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00493   LPC_EMC->DynamicAPR        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00494   LPC_EMC->DynamicDAL        = 0x00000002; /* ( n ) -> 2 clock cycles */
00495   LPC_EMC->DynamicWR         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00496   LPC_EMC->DynamicRC         = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00497   LPC_EMC->DynamicRFC        = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00498   LPC_EMC->DynamicXSR        = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00499   LPC_EMC->DynamicRRD        = 0x00000000; /* ( n + 1 ) -> 1 clock cycles */
00500   LPC_EMC->DynamicMRD        = 0x00000000; /* ( n + 1 ) -> 1 clock cycles */
00501 #elif (SDRAM_SPEED==SDRAM_SPEED_50)
00502 //Timing for 50MHz Bus (with 100MHz M3 Core)
00503   LPC_EMC->DynamicRasCas0    = 0x00000201; /* 1 RAS, 2 CAS latency */
00504   LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
00505   LPC_EMC->DynamicRP         = 0x00000000; /* ( n + 1 ) -> 1 clock cycles */
00506   LPC_EMC->DynamicRAS        = 0x00000002; /* ( n + 1 ) -> 3 clock cycles */
00507   LPC_EMC->DynamicSREX       = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00508   LPC_EMC->DynamicAPR        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00509   LPC_EMC->DynamicDAL        = 0x00000002; /* ( n ) -> 2 clock cycles */
00510   LPC_EMC->DynamicWR         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00511   LPC_EMC->DynamicRC         = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00512   LPC_EMC->DynamicRFC        = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00513   LPC_EMC->DynamicXSR        = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00514   LPC_EMC->DynamicRRD        = 0x00000000; /* ( n + 1 ) -> 1 clock cycles */
00515   LPC_EMC->DynamicMRD        = 0x00000000; /* ( n + 1 ) -> 1 clock cycles */
00516 #elif (SDRAM_SPEED==SDRAM_SPEED_60) 
00517   //Timing for 60 MHz Bus (same as 72MHz)
00518   LPC_EMC->DynamicRasCas0    = 0x00000202; /* 2 RAS, 2 CAS latency */
00519   LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
00520   LPC_EMC->DynamicRP         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00521   LPC_EMC->DynamicRAS        = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00522   LPC_EMC->DynamicSREX       = 0x00000005; /* ( n + 1 ) -> 6 clock cycles */
00523   LPC_EMC->DynamicAPR        = 0x00000002; /* ( n + 1 ) -> 3 clock cycles */
00524   LPC_EMC->DynamicDAL        = 0x00000003; /* ( n ) -> 3 clock cycles */
00525   LPC_EMC->DynamicWR         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00526   LPC_EMC->DynamicRC         = 0x00000004; /* ( n + 1 ) -> 5 clock cycles */
00527   LPC_EMC->DynamicRFC        = 0x00000004; /* ( n + 1 ) -> 5 clock cycles */
00528   LPC_EMC->DynamicXSR        = 0x00000005; /* ( n + 1 ) -> 6 clock cycles */
00529   LPC_EMC->DynamicRRD        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00530   LPC_EMC->DynamicMRD        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00531 #elif (SDRAM_SPEED==SDRAM_SPEED_72)
00532   //Timing for 72 MHz Bus
00533   LPC_EMC->DynamicRasCas0    = 0x00000202; /* 2 RAS, 2 CAS latency */
00534   LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
00535   LPC_EMC->DynamicRP         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00536   LPC_EMC->DynamicRAS        = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00537   LPC_EMC->DynamicSREX       = 0x00000005; /* ( n + 1 ) -> 6 clock cycles */
00538   LPC_EMC->DynamicAPR        = 0x00000002; /* ( n + 1 ) -> 3 clock cycles */
00539   LPC_EMC->DynamicDAL        = 0x00000003; /* ( n ) -> 3 clock cycles */
00540   LPC_EMC->DynamicWR         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00541   LPC_EMC->DynamicRC         = 0x00000004; /* ( n + 1 ) -> 5 clock cycles */
00542   LPC_EMC->DynamicRFC        = 0x00000004; /* ( n + 1 ) -> 5 clock cycles */
00543   LPC_EMC->DynamicXSR        = 0x00000005; /* ( n + 1 ) -> 6 clock cycles */
00544   LPC_EMC->DynamicRRD        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00545   LPC_EMC->DynamicMRD        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00546 #elif (SDRAM_SPEED==SDRAM_SPEED_80)
00547   //Timing for 80 MHz Bus (same as 72MHz) 
00548   LPC_EMC->DynamicRasCas0    = 0x00000202; /* 2 RAS, 2 CAS latency */
00549   LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
00550   LPC_EMC->DynamicRP         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00551   LPC_EMC->DynamicRAS        = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
00552   LPC_EMC->DynamicSREX       = 0x00000005; /* ( n + 1 ) -> 6 clock cycles */
00553   LPC_EMC->DynamicAPR        = 0x00000002; /* ( n + 1 ) -> 3 clock cycles */
00554   LPC_EMC->DynamicDAL        = 0x00000003; /* ( n ) -> 3 clock cycles */
00555   LPC_EMC->DynamicWR         = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00556   LPC_EMC->DynamicRC         = 0x00000004; /* ( n + 1 ) -> 5 clock cycles */
00557   LPC_EMC->DynamicRFC        = 0x00000004; /* ( n + 1 ) -> 5 clock cycles */
00558   LPC_EMC->DynamicXSR        = 0x00000005; /* ( n + 1 ) -> 6 clock cycles */
00559   LPC_EMC->DynamicRRD        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00560   LPC_EMC->DynamicMRD        = 0x00000001; /* ( n + 1 ) -> 2 clock cycles */
00561 #else
00562     #error UNSUPPORTED SDRAM FREQ
00563 #endif
00564 
00565   LPC_EMC->DynamicControl    = 0x00000183; /* Issue NOP command */
00566   //wait(0.2);                         /* wait 200ms */
00567   ThisThread::sleep_for(200);
00568   LPC_EMC->DynamicControl    = 0x00000103; /* Issue PALL command */
00569   LPC_EMC->DynamicRefresh    = 0x00000002; /* ( n * 16 ) -> 32 clock cycles */
00570   for(i = 0; i < 0x80; i++);               /* wait 128 AHB clock cycles */
00571 
00572 
00573 #if (SDRAM_SPEED==SDRAM_SPEED_48)
00574   //Timing for 48MHz Bus
00575   LPC_EMC->DynamicRefresh    = 0x0000002E; /* ( n * 16 ) -> 736 clock cycles -> 15.330uS at 48MHz <= 15.625uS ( 64ms / 4096 row ) */
00576 #elif (SDRAM_SPEED==SDRAM_SPEED_50)
00577   //Timing for 50MHz Bus
00578   LPC_EMC->DynamicRefresh    = 0x0000003A; /* ( n * 16 ) -> 768 clock cycles -> 15.360uS at 50MHz <= 15.625uS ( 64ms / 4096 row ) */
00579 #elif (SDRAM_SPEED==SDRAM_SPEED_60)
00580   //Timing for 60MHz Bus
00581   LPC_EMC->DynamicRefresh    = 0x0000003A; /* ( n * 16 ) -> 928 clock cycles -> 15.466uS at 60MHz <= 15.625uS ( 64ms / 4096 row ) */
00582 #elif (SDRAM_SPEED==SDRAM_SPEED_72)
00583   //Timing for 72MHz Bus
00584   LPC_EMC->DynamicRefresh    = 0x00000046; /* ( n * 16 ) -> 1120 clock cycles -> 15.556uS at 72MHz <= 15.625uS ( 64ms / 4096 row ) */
00585 #elif (SDRAM_SPEED==SDRAM_SPEED_80)
00586   //Timing for 80MHz Bus
00587   LPC_EMC->DynamicRefresh    = 0x0000004E; /* ( n * 16 ) -> 1248 clock cycles -> 15.600uS at 80MHz <= 15.625uS ( 64ms / 4096 row ) */
00588 #else
00589     #error UNSUPPORTED SDRAM FREQ
00590 #endif
00591 
00592   LPC_EMC->DynamicControl    = 0x00000083; /* Issue MODE command */
00593   //Timing for 48/60/72MHZ Bus
00594   dwtemp = *((volatile uint32_t *)(SDRAM_BASE | (0x22<<(2+2+9)))); /* 4 burst, 2 CAS latency */
00595   dwtemp = dwtemp;
00596   LPC_EMC->DynamicControl    = 0x00000000; /* Issue NORMAL command */
00597 //[re]enable buffers
00598   LPC_EMC->DynamicConfig0    = 0x00084480; /* 256MB, 8Mx32, 4 banks, row=12, column=9 */
00599 
00600   /* Nominal value */
00601   ringosccount[0] = calibration();
00602 
00603   if (find_cmddly() == 0x0)
00604   {
00605     //while (1);  /* fatal error */
00606     return 1;//FALSE;
00607   }
00608 
00609   if (find_fbclkdly() == 0x0)
00610   {
00611     //while (1);  /* fatal error */
00612     return 1;//FALSE;
00613   }
00614 
00615   adjust_timing();
00616   
00617   allowExecutionOfCodeInSDRAM();
00618   
00619   initialized = true;
00620 
00621   return 0;//TRUE;
00622 }
00623 
00624 void sdram_disableMallocSdram()
00625 {
00626   okToUseSdramForHeap = false;
00627 }