lpc177x_8x_emc.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  1. /*
  2. * Copyright (C) 2012 by Ole Reinhardt (ole.reinhardt@embedded-it.de)
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. *
  34. *
  35. * Parts taken from lpc177x_8x_emc.c 2011-06-02
  36. *
  37. * file lpc177x_8x_emc.c
  38. * brief Contains all functions support for EMC firmware library
  39. * on LPC177x_8x
  40. * version 1.0
  41. * date 02. June. 2011
  42. * author NXP MCU SW Application Team
  43. *
  44. * Copyright(C) 2011, NXP Semiconductor
  45. * All rights reserved.
  46. *
  47. ***********************************************************************
  48. * Software that is described herein is for illustrative purposes only
  49. * which provides customers with programming information regarding the
  50. * products. This software is supplied "AS IS" without any warranties.
  51. * NXP Semiconductors assumes no responsibility or liability for the
  52. * use of the software, conveys no license or title under any patent,
  53. * copyright, or mask work right to the product. NXP Semiconductors
  54. * reserves the right to make changes in the software without
  55. * notification. NXP Semiconductors also make no representation or
  56. * warranty that such application will be suitable for the specified
  57. * use without further testing or modification.
  58. **********************************************************************/
  59. /*
  60. * \verbatim
  61. * $Id: $
  62. * \endverbatim
  63. */
  64. #include <sys/timer.h>
  65. #include <arch/cm3.h>
  66. #if defined(MCU_LPC177x_8x)
  67. #include <arch/cm3/nxp/lpc177x_8x.h>
  68. #include <arch/cm3/nxp/lpc177x_8x_clk.h>
  69. #elif defined(MCU_LPC407x_8x)
  70. #include <arch/cm3/nxp/lpc407x_8x.h>
  71. #include <arch/cm3/nxp/lpc407x_8x_clk.h>
  72. #else
  73. #warning "Unknown LPC familiy"
  74. #endif
  75. #include <arch/cm3/nxp/lpc177x_8x_emc.h>
  76. #include <arch/cm3/nxp/lpc177x_8x_gpio.h>
  77. /* default delays: source: practical test of rolf.meeser@nxp with the
  78. Embedded Artist Board. EMC Clock <= 80MHz, Command Delay strategi +0.
  79. */
  80. #define DEFAULT_CLKOUTDLY 0
  81. #define DEFAULT_FBCLKDLY 20
  82. #define DEFAULT_CMDDLY 16
  83. /* variables to save the original delays. Needed for later re-calibration of the
  84. delay lines.
  85. */
  86. volatile uint32_t original_cmdclkdelay = 0;
  87. volatile uint32_t original_fbclkdelay = 0;
  88. volatile uint32_t initial_calibration_value;
  89. /*!
  90. * \brief Initialize EMC
  91. *
  92. * Initialize the external memory controller. GPIO pins should be correctly
  93. * configured when calling this function.
  94. *
  95. * \param none
  96. * \return none
  97. */
  98. void Lpc177x_8x_EmcInit(void)
  99. {
  100. /* uint8_t i; */
  101. /* Enable clock for EMC */
  102. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCEMC);
  103. LPC_SC->EMCDLYCTL = 0x00001010;
  104. LPC_EMC->Control = 0x00000001;
  105. LPC_EMC->Config = 0x00000000;
  106. /* Pin configuration:
  107. * P2.14 - /EMC_CS2
  108. * P2.15 - /EMC_CS3
  109. *
  110. * P2.16 - /EMC_CAS
  111. * P2.17 - /EMC_RAS
  112. * P2.18 - EMC_CLK[0]
  113. * P2.19 - EMC_CLK[1]
  114. *
  115. * P2.20 - EMC_DYCS0
  116. * P2.21 - EMC_DYCS1
  117. * P2.22 - EMC_DYCS2
  118. * P2.23 - EMC_DYCS3
  119. *
  120. * P2.24 - EMC_CKE0
  121. * P2.25 - EMC_CKE1
  122. * P2.26 - EMC_CKE2
  123. * P2.27 - EMC_CKE3
  124. *
  125. * P2.28 - EMC_DQM0
  126. * P2.29 - EMC_DQM1
  127. * P2.30 - EMC_DQM2
  128. * P2.31 - EMC_DQM3
  129. *
  130. * P3.0-P3.31 - EMC_D[0-31]
  131. * P4.0-P4.23 - EMC_A[0-23]
  132. *
  133. * P4.24 - /EMC_OE
  134. * P4.25 - /EMC_WE
  135. *
  136. * P4.30 - /EMC_CS0
  137. * P4.31 - /EMC_CS1
  138. */
  139. /* GPIO Pin configuration should be done in the board file according to
  140. the hardware configuration
  141. */
  142. }
  143. /*!
  144. * \brief SDRAM Delay line calibration.
  145. *
  146. * The estimated value gives a hint to correct the SDRAM timings
  147. *
  148. * \param none
  149. * \return value 0..4095 corresponding to the speed of logic.
  150. * Faster logik (less delay) gives larger output values.
  151. */
  152. static unsigned int sdram_calibrate (void)
  153. {
  154. unsigned int i;
  155. unsigned int value = 0;
  156. unsigned int data;
  157. for (i = 16; i; i--) { // get a mean value
  158. LPC_SC->EMCCAL = 0x4000; // start calibration
  159. do {
  160. data = LPC_SC->EMCCAL;
  161. } while (!(data & 0x8000));// wait until DONE
  162. value += data & 0xFF;
  163. }
  164. return value;
  165. }
  166. /*!
  167. * \brief Optimize the SDRAM delays.
  168. *
  169. * The complete range of a delay (0..31) is set, then tested by a SDRAM test.
  170. * Output value is the middle of the functional range.
  171. *
  172. * \param sdram SDRAM configuration struct
  173. * \param shift Bitshift value to point to the delay position in EMCDLYCTL
  174. * \param def_value Value to set if no positive range can be found.
  175. * \return Optimum value which is set in EMCDLYCTL.
  176. */
  177. static unsigned int sdram_optimize_delay(SDRAM sdram, unsigned int shift, unsigned int def_value)
  178. {
  179. int i;
  180. int start_delay = -1;
  181. int stop_delay = -1;
  182. #define DELAY_RANGE 0x1F
  183. for (i = 0; i <= DELAY_RANGE; i++) {
  184. // set delay value
  185. LPC_SC->EMCDLYCTL = ( LPC_SC->EMCDLYCTL & ~(DELAY_RANGE << shift) ) | (i << shift) ;
  186. if (Lpc177x_8x_EmcSDRAMCheck(sdram, i+10+shift) == 0) {
  187. if (start_delay < 0) {
  188. start_delay = i;
  189. }
  190. stop_delay = i;
  191. }
  192. }
  193. i = (start_delay + stop_delay) / 2;
  194. if (i < 0) {
  195. i = def_value;
  196. }
  197. // set new delay value
  198. LPC_SC->EMCDLYCTL = ( LPC_SC->EMCDLYCTL & ~(DELAY_RANGE << shift) ) | (i << shift);
  199. return i;
  200. }
  201. /*!
  202. * \brief Ajust SDRAM SDRAM timing
  203. *
  204. * This function should be called regularly to re-calibrate the delay lines
  205. * which might change their correct delays due to thermal influences
  206. *
  207. * \param none
  208. * \return none
  209. */
  210. void Lpc177x_8x_EmcSDRAMAdjustTiming(void)
  211. {
  212. /* Get the current calibration values */
  213. unsigned int calibration_value = sdram_calibrate();
  214. /* calculate the new delay line settings */
  215. unsigned int fbclkdelay = ((original_fbclkdelay * calibration_value) / initial_calibration_value);
  216. unsigned int cmdclkdelay = ((original_cmdclkdelay * calibration_value) / initial_calibration_value);
  217. /* Sanity range check */
  218. if (fbclkdelay > 0x1F) {
  219. fbclkdelay = 0x1F;
  220. }
  221. if (cmdclkdelay > 0x1F) {
  222. cmdclkdelay = 0x1F;
  223. }
  224. /* Setup new values */
  225. LPC_SC->EMCDLYCTL = (DEFAULT_CLKOUTDLY << 24) | (DEFAULT_CLKOUTDLY << 16) |
  226. (fbclkdelay << 8) | cmdclkdelay;
  227. }
  228. /*!
  229. * \brief Simple SDRAM test
  230. *
  231. * This is used at startup time (before the first usage) to find the optimum
  232. * delay time values.
  233. *
  234. * ATT: This test overwrites the previous SDRAM contents!
  235. * Please note that IT IS NOT POSSIBLE to preserve these contents because
  236. * it might be possible that garbage address commands are output and we will
  237. * not know which locations are addressed during this test.
  238. * DO NOT USE this test if executing code from SDRAM.
  239. *
  240. * ATT: This test is far from complete. We neither check differen write sizes
  241. * nor do we use selected pattern to check single bit failures etc.
  242. *
  243. * \param sdram configuration struct of the used sdram
  244. * \param offset constant used to modify the test pattern
  245. * \return 0 if test is ok, 1 in case of a failure
  246. */
  247. int Lpc177x_8x_EmcSDRAMCheck(SDRAM sdram, uint32_t offset)
  248. {
  249. volatile uint32_t *ram_ptr;
  250. uint32_t data;
  251. uint32_t i,j;
  252. uint32_t blocks;
  253. #define SDRAMTEST_BLOCKSIZE 0x100
  254. #define SDRAMTEST_JUMPSIZE 0x10000
  255. blocks = sdram.size / (sizeof(uint32_t) * SDRAMTEST_JUMPSIZE);
  256. /* Writing */
  257. ram_ptr = (uint32_t *)sdram.base_addr;
  258. data = 0x10000 + offset;
  259. for (i = 0; i < blocks; i++) {
  260. for (j = 0; j < SDRAMTEST_BLOCKSIZE; j++) {
  261. *ram_ptr++ = data;
  262. data += j + (j << 4);
  263. }
  264. ram_ptr += SDRAMTEST_JUMPSIZE - SDRAMTEST_BLOCKSIZE;
  265. data += i + (i << 4);
  266. }
  267. /* Verifying */
  268. ram_ptr = (uint32_t *)sdram.base_addr;
  269. data = 0x10000 + offset;
  270. for (i = 0; i < blocks; i++) {
  271. for (j = 0; j < SDRAMTEST_BLOCKSIZE; j++) {
  272. if (data != *ram_ptr++) {
  273. return 1;
  274. }
  275. data += j + (j << 4);
  276. }
  277. ram_ptr += SDRAMTEST_JUMPSIZE - SDRAMTEST_BLOCKSIZE;
  278. data += i + (i << 4);
  279. }
  280. return 0;
  281. }
  282. /*!
  283. * \brief EMC SDRAM initialisation
  284. *
  285. * This function configures the emc to a sdram connected to CS0
  286. * SDRAM timing parameters must be given as parameter
  287. *
  288. * \param sdram configuration struct of the used sdram
  289. * \param dynamic_config configuration values for dynamic_config register
  290. * \return none
  291. */
  292. void Lpc177x_8x_EmcSDRAMInit(SDRAM sdram, uint32_t dynamic_config)
  293. {
  294. uint32_t emc_clock;
  295. uint32_t cpu_clock;
  296. emc_clock = NutArchClockGet(NUT_HWCLK_EMC);
  297. cpu_clock = NutArchClockGet(NUT_HWCLK_CPU);
  298. /* Initialize delay lines */
  299. LPC_SC->EMCDLYCTL = 0x00000210;
  300. LPC_SC->EMCDLYCTL |= 0x00080808;
  301. /* Init SDRAM controller */
  302. LPC_EMC->Control = 0x00000001;
  303. LPC_EMC->Config = 0x00000000;
  304. LPC_EMC->DynamicReadConfig = 0x00000001;
  305. LPC_EMC->DynamicRasCas0 = ((uint32_t)sdram.cas_latency) << 8 | (uint32_t)sdram.ras_latency;
  306. LPC_EMC->DynamicRP = NS_2_CLKS(emc_clock, sdram.tRP);
  307. LPC_EMC->DynamicRAS = NS_2_CLKS(emc_clock, sdram.tRAS);
  308. LPC_EMC->DynamicSREX = NS_2_CLKS(emc_clock, sdram.tSREX);
  309. LPC_EMC->DynamicAPR = sdram.tAPR;
  310. LPC_EMC->DynamicDAL = sdram.tDAL + NS_2_CLKS(emc_clock, sdram.tRP);
  311. LPC_EMC->DynamicWR = sdram.tWR;
  312. LPC_EMC->DynamicRC = NS_2_CLKS(emc_clock, sdram.tRC);
  313. LPC_EMC->DynamicRFC = NS_2_CLKS(emc_clock, sdram.tRFC);
  314. LPC_EMC->DynamicXSR = NS_2_CLKS(emc_clock, sdram.tXSR);
  315. LPC_EMC->DynamicRRD = NS_2_CLKS(emc_clock, sdram.tRRD);
  316. LPC_EMC->DynamicMRD = sdram.tMRD;
  317. /* Configure addressing mode */
  318. LPC_EMC->DynamicConfig0 = dynamic_config;
  319. /* JEDEC General SDRAM Initialization Sequence
  320. DELAY to allow power and clocks to stabilize ~100 us
  321. NOP
  322. */
  323. LPC_EMC->DynamicControl = 0x00000183;
  324. wait_clocks(NS_2_CLKS(cpu_clock, 200000));
  325. /* PALL */
  326. LPC_EMC->DynamicControl = 0x00000103;
  327. LPC_EMC->DynamicRefresh = 0x00000002;
  328. wait_clocks(256); /* wait > 128 clk */
  329. LPC_EMC->DynamicRefresh = NS_2_CLKS(emc_clock, sdram.refresh) >> 4;
  330. wait_clocks(256); /* wait > 128 clk */
  331. /* COMM */
  332. LPC_EMC->DynamicControl = 0x00000083; /* Issue MODE command */
  333. /* Set mode register in SDRAM
  334. A0-A10 define the op-code written to the mode register.
  335. To compute the location of the A0-A10 in the SDRAM address range (MA):
  336. - MA0 = Byte Address (not used)
  337. - MA1..MA9 = Column Addresses (not used in Mode command).
  338. - MA10..MA21 = Row Addresses (MA10..MA19 used by Mode command).
  339. - MA22..MA23 = Bank Addresses (in BANK-ROW-COLUMN mode)
  340. ------------------------------------------------------------------------------------------
  341. Mode register table:
  342. bit 9: Write Burst Mode: Programmed burst length(0), Single Location Access(1) = 0
  343. bit 8~7: Operating Mode: Standard Operation(0) is the only thing defined = 00
  344. bit 6~4: CAS latency: 001(1), 010(2), 011(3) = 010
  345. bit 3: Type of Burst: Sequential(0) or Interleaved(1) = 0
  346. bit 2~0: Burst length: 000(1), 001(2), 010(4), 011(8), 111(Full Page) = 011
  347. */
  348. if (sdram.bus_width == 32) {
  349. (void) *((volatile uint32_t *)(sdram.base_addr | ((sdram.cas_latency << 4) | 0x02 /* burst length 4 */) <<
  350. (((dynamic_config & 0x1000) ? 0 : 2 /* number of bs */) + 2 /* bus width */ + sdram.cols )));
  351. } else {
  352. (void) *((volatile uint32_t *)(sdram.base_addr | ((sdram.cas_latency << 4) | 0x03 /* burst length 8 */) <<
  353. (((dynamic_config & 0x1000) ? 0 : 2 /* number of bs */) + 1 /* bus width */ + sdram.cols )));
  354. }
  355. wait_clocks(256); /* wait > 128 clk */
  356. /* NORM */
  357. LPC_EMC->DynamicControl = 0x0000;
  358. /* Reenable buffers */
  359. LPC_EMC->DynamicConfig0 |= _BV(19);
  360. wait_clocks(NS_2_CLKS(cpu_clock, 200000));
  361. initial_calibration_value = sdram_calibrate();
  362. original_cmdclkdelay = sdram_optimize_delay(sdram, 0, DEFAULT_CMDDLY);
  363. original_fbclkdelay = sdram_optimize_delay(sdram, 8, DEFAULT_FBCLKDLY);
  364. }
  365. /*!
  366. * \brief Configure Little Endian/Big Endian mode for EMC
  367. *
  368. * \param endian_mode Endian mode, should be:
  369. * - EMC_LITTLE_ENDIAN_MODE: Little-endian mode
  370. * - EMC_BIG_ENDIAN_MODE : Big-endian mode
  371. *
  372. * \return none
  373. */
  374. void Lpc177x_8x_EmcConfigEndianMode(uint32_t endian_mode)
  375. {
  376. LPC_EMC->Config = ((LPC_EMC->Config & 0x01) | endian_mode) & EMC_Config_MASK;
  377. }
  378. /****************** Group of Dynamic control functions************************/
  379. /*!
  380. * \brief Set the value for dynamic clock enable bit
  381. *
  382. * \param clock_enable clock enable mode, should be:
  383. * - 0: Clock enable of idle devices are deasserted to
  384. * save power
  385. * - EMC_DynamicControl_CE: All clock enables are driven HIGH continuously
  386. *
  387. * \return none
  388. */
  389. void Lpc177x_8x_EmcDynCtrlClockEnable(uint32_t clock_enable)
  390. {
  391. uint32_t mask = ~EMC_DynamicControl_CE;
  392. LPC_EMC->DynamicControl = ((LPC_EMC->DynamicControl & mask) | clock_enable);
  393. }
  394. /*!
  395. * \brief Set the value for dynamic memory clock control:
  396. * stops or runs continuously
  397. *
  398. * \param clock_control clock control mode, should be:
  399. * - 0: CLKOUT stops when all SDRAMs are idle and
  400. * during self-refresh mode
  401. * - EMC_DynamicControl_CS: CLKOUT runs continuously
  402. *
  403. * \return none
  404. */
  405. void Lpc177x_8x_EmcDynCtrlClockControl(uint32_t clock_control)
  406. {
  407. uint32_t mask = ~EMC_DynamicControl_CS;
  408. LPC_EMC->DynamicControl = ((LPC_EMC->DynamicControl & mask) | clock_control);
  409. }
  410. /*!
  411. * \brief Switch the Self-refresh mode between normal and self-refresh mode
  412. *
  413. * \param self_refresh_mode self refresh mode, should be:
  414. * - 0: Normal mode
  415. * - EMC_DynamicControl_SR: Enter self-refresh mode
  416. *
  417. * \return none
  418. */
  419. void Lpc177x_8x_EmcDynCtrlSelfRefresh(uint32_t self_refresh_mode)
  420. {
  421. uint32_t mask = ~EMC_DynamicControl_SR;
  422. LPC_EMC->DynamicControl = ((LPC_EMC->DynamicControl & mask) | self_refresh_mode);
  423. }
  424. /*!
  425. * \brief Enable/disable CLKOUT
  426. *
  427. * \param MMC_val Memory clock control mode, should be:
  428. * - 0: CLKOUT enabled
  429. * - EMC_DynamicControl_MMC: CLKOUT disabled
  430. *
  431. * \return none
  432. */
  433. void Lpc177x_8x_EmcDynCtrlMMC(uint32_t mmc_val)
  434. {
  435. uint32_t mask = ~EMC_DynamicControl_MMC;
  436. LPC_EMC->DynamicControl = ((LPC_EMC->DynamicControl & mask) | mmc_val);
  437. }
  438. /*!
  439. * \brief Issue SDRAM command
  440. *
  441. * \param sdram_command Command mode, should be:
  442. * - 0x00: Issue SDRAM NORMAL operation command
  443. * - 0x01: Issue SDRAM MODE command
  444. * - 0x02: Issue SDRAM PALL (precharge all) command
  445. * - 0x03: Issue SRAM NOP (no operation) command
  446. *
  447. * \return none
  448. */
  449. void Lpc177x_8x_EmcDynCtrlSDRAMCmd(uint32_t sdram_command)
  450. {
  451. uint32_t mask = ~(uint32_t)(0x03 << 7);
  452. LPC_EMC->DynamicControl = ((LPC_EMC->DynamicControl & mask)| EMC_DynamicControl_I(sdram_command));
  453. }
  454. /*!
  455. * \brief Switch between Normal operation and deep sleep power mode
  456. *
  457. * \param power_command Low-power SDRAM deep-sleep mode, should be:
  458. * - 0: Normal operation
  459. * - EMC_DynamicControl_DP: Enter deep-sleep mode
  460. *
  461. * \return none
  462. */
  463. void Lpc177x_8x_EmcDynCtrlPowerDownMode(uint32_t power_command)
  464. {
  465. uint32_t mask = ~EMC_DynamicControl_DP;
  466. LPC_EMC->DynamicControl = ((LPC_EMC->DynamicControl & mask)| power_command);
  467. }
  468. /*!
  469. * \brief Set the value of EMC dynamic memory registers
  470. *
  471. * \param par EMC register that will set value, should be:
  472. * - EMC_DYN_MEM_REFRESH_TIMER: Dynamic Refresh register
  473. * - EMC_DYN_MEM_READ_CONFIG: Dynamic Read Config register
  474. * - EMC_DYN_MEM_TRP: Dynamic RP register
  475. * - EMC_DYN_MEM_TRAS: Dynamic RAS register
  476. * - EMC_DYN_MEM_TSREX: Dynamic SREX register
  477. * - EMC_DYN_MEM_TAPR: Dynamic APR register
  478. * - EMC_DYN_MEM_TDAL: Dynamic DAL register
  479. * - EMC_DYN_MEM_TWR: Dynamic WR register
  480. * - EMC_DYN_MEM_TRC: Dynamic RC register
  481. * - EMC_DYN_MEM_TRFC: Dynamic RFC register
  482. * - EMC_DYN_MEM_TXSR: Dynamic XSR register
  483. * - EMC_DYN_MEM_TRRD: Dynamic RRD register
  484. * - EMC_DYN_MEM_TMRD: Dynamic MRD register
  485. *
  486. * \return none
  487. */
  488. void Lpc177x_8x_EmcSetDynMemoryParameter(EMC_DYN_MEM_PAR par, uint32_t val)
  489. {
  490. switch ( par) {
  491. case EMC_DYN_MEM_REFRESH_TIMER:
  492. LPC_EMC->DynamicRefresh = val;
  493. break;
  494. case EMC_DYN_MEM_READ_CONFIG:
  495. LPC_EMC->DynamicReadConfig = val;
  496. break;
  497. case EMC_DYN_MEM_TRP:
  498. LPC_EMC->DynamicRP = val;
  499. break;
  500. case EMC_DYN_MEM_TRAS:
  501. LPC_EMC->DynamicRAS = val;
  502. break;
  503. case EMC_DYN_MEM_TSREX:
  504. LPC_EMC->DynamicSREX = val;
  505. break;
  506. case EMC_DYN_MEM_TAPR:
  507. LPC_EMC->DynamicAPR = val;
  508. break;
  509. case EMC_DYN_MEM_TDAL:
  510. LPC_EMC->DynamicDAL = val;
  511. break;
  512. case EMC_DYN_MEM_TWR:
  513. LPC_EMC->DynamicWR = val;
  514. break;
  515. case EMC_DYN_MEM_TRC:
  516. LPC_EMC->DynamicRC = val;
  517. break;
  518. case EMC_DYN_MEM_TRFC:
  519. LPC_EMC->DynamicRFC = val;
  520. break;
  521. case EMC_DYN_MEM_TXSR:
  522. LPC_EMC->DynamicXSR = val;
  523. break;
  524. case EMC_DYN_MEM_TRRD:
  525. LPC_EMC->DynamicRRD = val;
  526. break;
  527. case EMC_DYN_MEM_TMRD:
  528. LPC_EMC->DynamicMRD = val;
  529. break;
  530. }
  531. }
  532. /*!
  533. * \brief Set extended wait time out for accessing static memory
  534. *
  535. * \param timeout timeout value that will be set
  536. *
  537. * \return none
  538. */
  539. void Lpc177x_8x_EmcStaticExtendedWait(uint32_t timeout)
  540. {
  541. LPC_EMC->StaticExtendedWait = timeout;
  542. }
  543. /*!
  544. * \brief Configure the memory device
  545. *
  546. * \param cs number of chip select, should be from 0 to 3
  547. * \param mem_dev memory device type, should be:
  548. * - 0x00: Low-power SDRAM
  549. * - 0x01: Low-power SDRAM
  550. * - 0x02: Micron Syncflash
  551. *
  552. * \return none
  553. */
  554. void Lpc177x_8x_EmcDynMemConfigMD(uint32_t cs, uint32_t mem_dev)
  555. {
  556. uint32_t mask = ~(uint32_t)(0x03 << 3);
  557. switch (cs) {
  558. case 0:
  559. LPC_EMC->DynamicConfig0 = (LPC_EMC->DynamicConfig0 & mask) | mem_dev;
  560. break;
  561. case 1:
  562. LPC_EMC->DynamicConfig1 = (LPC_EMC->DynamicConfig1 & mask) | mem_dev;
  563. break;
  564. case 2:
  565. LPC_EMC->DynamicConfig2 = (LPC_EMC->DynamicConfig2 & mask) | mem_dev;
  566. break;
  567. case 3:
  568. LPC_EMC->DynamicConfig3 = (LPC_EMC->DynamicConfig3 & mask) | mem_dev;
  569. break;
  570. }
  571. }
  572. /*!
  573. * \brief Map the address for the memory device
  574. *
  575. * \param cs number of chip select, should be from 0 to 3
  576. * \param addr_mapped address where the memory will be mapped
  577. *
  578. * \return none
  579. */
  580. void Lpc177x_8x_EmcDynMemConfigAM(uint32_t cs, uint32_t addr_mapped)
  581. {
  582. uint32_t mask = ~(uint32_t)(0x3F << 7) | ~(uint32_t)(_BV(14)) ;
  583. switch (cs) {
  584. case 0:
  585. LPC_EMC->DynamicConfig0 = (LPC_EMC->DynamicConfig0 & mask) | addr_mapped;
  586. break;
  587. case 1:
  588. LPC_EMC->DynamicConfig1 = (LPC_EMC->DynamicConfig1 & mask) | addr_mapped;
  589. break;
  590. case 2:
  591. LPC_EMC->DynamicConfig2 = (LPC_EMC->DynamicConfig2 & mask) | addr_mapped;
  592. break;
  593. case 3:
  594. LPC_EMC->DynamicConfig3 = (LPC_EMC->DynamicConfig3 & mask) | addr_mapped;
  595. break;
  596. }
  597. }
  598. /*!
  599. * \brief Enable/disable the buffer
  600. *
  601. * \param cs number of chip select, should be from 0 to 3
  602. * \param buff_control buffer control mode, should be:
  603. * 0 - buffer disabled
  604. * EMC_StaticConfig_B: buffer enabled for the selected chip select
  605. *
  606. * \return none
  607. */
  608. void Lpc177x_8x_EmcDynMemConfigB(uint32_t cs, uint32_t buff_control)
  609. {
  610. uint32_t mask = ~EMC_DynamicConfig_B;
  611. switch (cs) {
  612. case 0:
  613. LPC_EMC->DynamicConfig0 = (LPC_EMC->DynamicConfig0 & mask) | buff_control;
  614. break;
  615. case 1:
  616. LPC_EMC->DynamicConfig1 = (LPC_EMC->DynamicConfig1 & mask) | buff_control;
  617. break;
  618. case 2:
  619. LPC_EMC->DynamicConfig2 = (LPC_EMC->DynamicConfig2 & mask) | buff_control;
  620. break;
  621. case 3:
  622. LPC_EMC->DynamicConfig3 = (LPC_EMC->DynamicConfig3 & mask) | buff_control;
  623. break;
  624. }
  625. }
  626. /*!
  627. * \brief Configure write permission: protect or not
  628. *
  629. * \param cs number of chip select, should be from 0 to 3
  630. * \param permission permission mode, should be:
  631. * 0 - not protected
  632. * EMC_StaticConfig_P: write protection enabled
  633. *
  634. * \return none
  635. */
  636. void Lpc177x_8x_EmcDynMemConfigP(uint32_t cs, uint32_t permission)
  637. {
  638. uint32_t mask = ~EMC_DynamicConfig_P;
  639. switch (cs) {
  640. case 0:
  641. LPC_EMC->DynamicConfig0 = (LPC_EMC->DynamicConfig0 & mask) | permission;
  642. break;
  643. case 1:
  644. LPC_EMC->DynamicConfig1 = (LPC_EMC->DynamicConfig1 & mask) | permission;
  645. break;
  646. case 2:
  647. LPC_EMC->DynamicConfig2 = (LPC_EMC->DynamicConfig2 & mask) | permission;
  648. break;
  649. case 3:
  650. LPC_EMC->DynamicConfig3 = (LPC_EMC->DynamicConfig3 & mask) | permission;
  651. break;
  652. }
  653. }
  654. /*!
  655. * \brief Set value for RAS latency
  656. *
  657. * \param cs number of chip select, should be from 0 to 3
  658. * \param ras_val RAS value should be in range: 0..3
  659. *
  660. * \return none
  661. */
  662. void Lpc177x_8x_EmcDynMemRAS(uint32_t cs, uint32_t ras_val)
  663. {
  664. uint32_t mask = ~(uint32_t)(0x03) ;
  665. switch (cs) {
  666. case 0:
  667. LPC_EMC->DynamicRasCas0 = (LPC_EMC->DynamicRasCas0 & mask) | ras_val;
  668. break;
  669. case 1:
  670. LPC_EMC->DynamicRasCas1 = (LPC_EMC->DynamicRasCas1 & mask) | ras_val;
  671. break;
  672. case 2:
  673. LPC_EMC->DynamicRasCas2 = (LPC_EMC->DynamicRasCas2 & mask) | ras_val;
  674. break;
  675. case 3:
  676. LPC_EMC->DynamicRasCas3 = (LPC_EMC->DynamicRasCas3 & mask) | ras_val;
  677. break;
  678. }
  679. }
  680. /*!
  681. * \brief Set value for CAS latency
  682. *
  683. * \param cs number of chip select, should be from 0 to 3
  684. * \param cas_val CAS value should be in range: 0..3
  685. *
  686. * \return none
  687. */
  688. void Lpc177x_8x_EmcDynMemCAS(uint32_t cs, uint32_t cas_val)
  689. {
  690. uint32_t mask = ~(uint32_t)(0x03 << 8) ;
  691. switch (cs) {
  692. case 0:
  693. LPC_EMC->DynamicRasCas0 = (LPC_EMC->DynamicRasCas0 & mask) | cas_val;
  694. break;
  695. case 1:
  696. LPC_EMC->DynamicRasCas1 = (LPC_EMC->DynamicRasCas1 & mask) | cas_val;
  697. break;
  698. case 2:
  699. LPC_EMC->DynamicRasCas2 = (LPC_EMC->DynamicRasCas2 & mask) | cas_val;
  700. break;
  701. case 3:
  702. LPC_EMC->DynamicRasCas3 = (LPC_EMC->DynamicRasCas3 & mask) | cas_val;
  703. break;
  704. }
  705. }
  706. /*!
  707. * \brief Configure the memory bus width
  708. *
  709. * \param cs number of chip select, should be from 0 to 3
  710. * \param mem_width memory width, should be:
  711. * - EMC_StaticConfig_MW_8BITS
  712. * - EMC_StaticConfig_MW_16BITS
  713. * - EMC_StaticConfig_MW_32BITS
  714. *
  715. * \return none
  716. */
  717. void Lpc177x_8x_EmcStaticMemConfigMW(uint32_t cs, uint32_t mem_width)
  718. {
  719. uint32_t mask = ~(uint32_t)(0x03) ;
  720. switch (cs) {
  721. case 0:
  722. LPC_EMC->StaticConfig0 = (LPC_EMC->StaticConfig0 & mask) | mem_width;
  723. break;
  724. case 1:
  725. LPC_EMC->StaticConfig1 = (LPC_EMC->StaticConfig1 & mask) | mem_width;
  726. break;
  727. case 2:
  728. LPC_EMC->StaticConfig2 = (LPC_EMC->StaticConfig2 & mask) | mem_width;
  729. break;
  730. case 3:
  731. LPC_EMC->StaticConfig3 = (LPC_EMC->StaticConfig3 & mask) | mem_width;
  732. break;
  733. }
  734. }
  735. /*!
  736. * \brief Configure the page mode
  737. *
  738. * \param cs number of chip select, should be from 0 to 3
  739. * \param page_mode page mode, should be
  740. * - 0: disable
  741. * - EMC_StaticConfig_PM: asynchronous page mode enable
  742. *
  743. * \return none
  744. */
  745. void Lpc177x_8x_EmcStaticMemConfigPM(uint32_t cs, uint32_t page_mode)
  746. {
  747. uint32_t mask = ~EMC_StaticConfig_PM;
  748. switch (cs) {
  749. case 0:
  750. LPC_EMC->StaticConfig0 = (LPC_EMC->StaticConfig0 & mask) | page_mode;
  751. break;
  752. case 1:
  753. LPC_EMC->StaticConfig1 = (LPC_EMC->StaticConfig1 & mask) | page_mode;
  754. break;
  755. case 2:
  756. LPC_EMC->StaticConfig2 = (LPC_EMC->StaticConfig2 & mask) | page_mode;
  757. break;
  758. case 3:
  759. LPC_EMC->StaticConfig3 = (LPC_EMC->StaticConfig3 & mask) | page_mode;
  760. break;
  761. }
  762. }
  763. /*!
  764. * \brief Configure the chip select polarity
  765. *
  766. * \param cs number of chip select, should be from 0 to 3
  767. * \param polarity chip select polarity, should be:
  768. * - 0: Active LOW ship select
  769. * - EMC_StaticConfig_PC: Active HIGH chip select
  770. *
  771. * \return none
  772. */
  773. void Lpc177x_8x_EmcStaticMemConfigPC(uint32_t cs , uint32_t polarity)
  774. {
  775. uint32_t mask = ~EMC_StaticConfig_PC;
  776. switch (cs) {
  777. case 0:
  778. LPC_EMC->StaticConfig0 = (LPC_EMC->StaticConfig0 & mask) | polarity;
  779. break;
  780. case 1:
  781. LPC_EMC->StaticConfig1 = (LPC_EMC->StaticConfig1 & mask) | polarity;
  782. break;
  783. case 2:
  784. LPC_EMC->StaticConfig2 = (LPC_EMC->StaticConfig2 & mask) | polarity;
  785. break;
  786. case 3:
  787. LPC_EMC->StaticConfig3 = (LPC_EMC->StaticConfig3 & mask) | polarity;
  788. break;
  789. }
  790. }
  791. /*!
  792. * \brief Configure the byte lane state
  793. *
  794. * \param cs number of chip select, should be from 0 to 3
  795. * \param pb_val Byte lane state, should be:
  796. * - 0: For reads all bits in BLSn[3:0] are HIGH.
  797. * - EMC_StaticConfig_PB: For reads all bits in BLSn[3:0] are LOW.
  798. *
  799. * \return none
  800. */
  801. void Lpc177x_8x_EmcStaticMemConfigPB(uint32_t cs , uint32_t pb_val)
  802. {
  803. uint32_t mask = ~EMC_StaticConfig_PB ;
  804. switch (cs) {
  805. case 0:
  806. LPC_EMC->StaticConfig0 = (LPC_EMC->StaticConfig0 & mask) | pb_val;
  807. break;
  808. case 1:
  809. LPC_EMC->StaticConfig1 = (LPC_EMC->StaticConfig1 & mask) | pb_val;
  810. break;
  811. case 2:
  812. LPC_EMC->StaticConfig2 = (LPC_EMC->StaticConfig2 & mask) | pb_val;
  813. break;
  814. case 3:
  815. LPC_EMC->StaticConfig3 = (LPC_EMC->StaticConfig3 & mask) | pb_val;
  816. break;
  817. }
  818. }
  819. /*!
  820. * \brief Configure the extended wait value
  821. *
  822. * \param cs number of chip select, should be from 0 to 3
  823. * \param ex_wait Extended wait mode, should be:
  824. * - 0: Extended wait disabled.
  825. * - EMC_StaticConfig_EW: Extended wait enabled.
  826. *
  827. * \return none
  828. */
  829. void Lpc177x_8x_EmcStaticMemConfigEW(uint32_t cs , uint32_t ex_wait)
  830. {
  831. uint32_t mask = ~EMC_StaticConfig_EW;
  832. switch (cs) {
  833. case 0:
  834. LPC_EMC->StaticConfig0 = (LPC_EMC->StaticConfig0 & mask) | ex_wait;
  835. break;
  836. case 1:
  837. LPC_EMC->StaticConfig1 = (LPC_EMC->StaticConfig1 & mask) | ex_wait;
  838. break;
  839. case 2:
  840. LPC_EMC->StaticConfig2 = (LPC_EMC->StaticConfig2 & mask) | ex_wait;
  841. break;
  842. case 3:
  843. LPC_EMC->StaticConfig3 = (LPC_EMC->StaticConfig3 & mask) | ex_wait;
  844. break;
  845. }
  846. }
  847. /*!
  848. * \brief Configure the buffer enable value
  849. *
  850. * \param cs number of chip select, should be from 0 to 3
  851. * \param buf_val Buffer mode, should be:
  852. * - 0: Buffer disabled.
  853. * - EMC_StaticConfig_B: Buffer enabled.
  854. *
  855. * \return none
  856. */
  857. void Lpc177x_8x_EmcStaticMemConfigB(uint32_t cs , uint32_t buf_val)
  858. {
  859. uint32_t mask = ~EMC_StaticConfig_B;
  860. switch (cs) {
  861. case 0:
  862. LPC_EMC->StaticConfig0 = (LPC_EMC->StaticConfig0 & mask) | buf_val;
  863. break;
  864. case 1:
  865. LPC_EMC->StaticConfig1 = (LPC_EMC->StaticConfig1 & mask) | buf_val;
  866. break;
  867. case 2:
  868. LPC_EMC->StaticConfig2 = (LPC_EMC->StaticConfig2 & mask) | buf_val;
  869. break;
  870. case 3:
  871. LPC_EMC->StaticConfig3 = (LPC_EMC->StaticConfig3 & mask) | buf_val;
  872. break;
  873. }
  874. }
  875. /*!
  876. * \brief Configure the write permission
  877. *
  878. * \param cs number of chip select, should be from 0 to 3
  879. * \param permission Permission mode, should be:
  880. * - 0: Write not protected.
  881. * - EMC_StaticConfig_P: Write protected.
  882. * \return none
  883. */
  884. void Lpc177x_8x_EmcStaticMemConfigpP(uint32_t cs , uint32_t permission)
  885. {
  886. uint32_t mask = ~(uint32_t)(_BV(20)) ;
  887. switch (cs) {
  888. case 0:
  889. LPC_EMC->StaticConfig0 = (LPC_EMC->StaticConfig0 & mask) | permission;
  890. break;
  891. case 1:
  892. LPC_EMC->StaticConfig1 = (LPC_EMC->StaticConfig1 & mask) | permission;
  893. break;
  894. case 2:
  895. LPC_EMC->StaticConfig2 = (LPC_EMC->StaticConfig2 & mask) | permission;
  896. break;
  897. case 3:
  898. LPC_EMC->StaticConfig3 = (LPC_EMC->StaticConfig3 & mask) | permission;
  899. break;
  900. }
  901. }
  902. /*!
  903. * \brief Set the value of LPC_EMC static memory registers
  904. *
  905. * \param cs number of chip select, should be from 0 to 3
  906. * \param par Static register, should be:
  907. * - EMC_STA_MEM_WAITWEN: StaticWaitWen0 register
  908. * - EMC_STA_MEM_WAITOEN: StaticWaitOen0 register
  909. * - EMC_STA_MEM_WAITRD: StaticWaitRd0 register
  910. * - EMC_STA_MEM_WAITPAGE: StaticWaitPage0 register
  911. * - EMC_STA_MEM_WAITWR: StaticWaitWr0 register
  912. * - EMC_STA_MEM_WAITTURN: StaticWaitTurn0 register
  913. * \param val register value to set
  914. *
  915. * \return none
  916. */
  917. void Lpc177x_8x_EmcSetStaticMemoryParameter(uint32_t cs, EMC_STA_MEM_PAR par, uint32_t val)
  918. {
  919. switch (cs) {
  920. case 0:
  921. switch (par) {
  922. case EMC_STA_MEM_WAITWEN:
  923. LPC_EMC->StaticWaitWen0 = val;
  924. break;
  925. case EMC_STA_MEM_WAITOEN:
  926. LPC_EMC->StaticWaitOen0 = val;
  927. break;
  928. case EMC_STA_MEM_WAITRD:
  929. LPC_EMC->StaticWaitRd0 = val;
  930. break;
  931. case EMC_STA_MEM_WAITPAGE:
  932. LPC_EMC->StaticWaitPage0 = val;
  933. break;
  934. case EMC_STA_MEM_WAITWR:
  935. LPC_EMC->StaticWaitWr0 = val;
  936. break;
  937. case EMC_STA_MEM_WAITTURN:
  938. LPC_EMC->StaticWaitTurn0 = val;
  939. break;
  940. }
  941. break;
  942. case 1:
  943. switch (par) {
  944. case EMC_STA_MEM_WAITWEN:
  945. LPC_EMC->StaticWaitWen1 = val;
  946. break;
  947. case EMC_STA_MEM_WAITOEN:
  948. LPC_EMC->StaticWaitOen1 = val;
  949. break;
  950. case EMC_STA_MEM_WAITRD:
  951. LPC_EMC->StaticWaitRd1 = val;
  952. break;
  953. case EMC_STA_MEM_WAITPAGE:
  954. LPC_EMC->StaticWaitPage1 = val;
  955. break;
  956. case EMC_STA_MEM_WAITWR:
  957. LPC_EMC->StaticWaitWr1 = val;
  958. break;
  959. case EMC_STA_MEM_WAITTURN:
  960. LPC_EMC->StaticWaitTurn1 = val;
  961. break;
  962. }
  963. break;
  964. case 2:
  965. switch (par) {
  966. case EMC_STA_MEM_WAITWEN:
  967. LPC_EMC->StaticWaitWen2 = val;
  968. break;
  969. case EMC_STA_MEM_WAITOEN:
  970. LPC_EMC->StaticWaitOen2 = val;
  971. break;
  972. case EMC_STA_MEM_WAITRD:
  973. LPC_EMC->StaticWaitRd2 = val;
  974. break;
  975. case EMC_STA_MEM_WAITPAGE:
  976. LPC_EMC->StaticWaitPage2 = val;
  977. break;
  978. case EMC_STA_MEM_WAITWR:
  979. LPC_EMC->StaticWaitWr2 = val;
  980. break;
  981. case EMC_STA_MEM_WAITTURN:
  982. LPC_EMC->StaticWaitTurn2 = val;
  983. break;
  984. }
  985. break;
  986. case 3:
  987. switch (par) {
  988. case EMC_STA_MEM_WAITWEN:
  989. LPC_EMC->StaticWaitWen3 = val;
  990. break;
  991. case EMC_STA_MEM_WAITOEN:
  992. LPC_EMC->StaticWaitOen3 = val;
  993. break;
  994. case EMC_STA_MEM_WAITRD:
  995. LPC_EMC->StaticWaitRd3 = val;
  996. break;
  997. case EMC_STA_MEM_WAITPAGE:
  998. LPC_EMC->StaticWaitPage3 = val;
  999. break;
  1000. case EMC_STA_MEM_WAITWR:
  1001. LPC_EMC->StaticWaitWr3 = val;
  1002. break;
  1003. case EMC_STA_MEM_WAITTURN:
  1004. LPC_EMC->StaticWaitTurn3 = val;
  1005. break;
  1006. }
  1007. break;
  1008. }
  1009. }