LPCOpen Platform for LPC18XX/43XX microcontrollers: C:/w/lpcopen_docs/software/lpc_core/lpc_chip/chip_18xx_43xx/emc_18xx_43xx.c Source File

| LPCOpen Platform for LPC18XX/43XX microcontrollers 18XX43XX LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

emc_18xx_43xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC18xx/43xx EMC driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "chip.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /* DIV function with result rounded up */
39 #define EMC_DIV_ROUND_UP(x, y) ((x + y - 1) / y)
40
41 /*****************************************************************************
42 * Public types/enumerations/variables
43 ****************************************************************************/
44
45 /*****************************************************************************
46 * Private functions
47 ****************************************************************************/
48
49 #ifndef EMC_SUPPORT_ONLY_PL172
50 /* Get ARM External Memory Controller Version */
51 STATIC uint32_t getARMPeripheralID(void)
52 {
53 uint32_t *RegAdd;
54 RegAdd = (uint32_t *) ((uint32_t) LPC_EMC + 0xFE0);
55 return (RegAdd[0] & 0xFF) | ((RegAdd[1] & 0xFF) << 8) |
56 ((RegAdd[2] & 0xFF) << 16) | (RegAdd[3] << 24);
57 }
58
59 #endif
60
61 /* Calculate Clock Count from Timing Unit(nanoseconds) */
62 STATIC uint32_t convertTimmingParam(uint32_t EMC_Clock, int32_t input_ns, uint32_t adjust)
63 {
64 uint32_t temp;
65 if (input_ns < 0) {
66 return (-input_ns) >> 8;
67 }
68 temp = EMC_Clock / 1000000; /* MHz calculation */
69 temp = temp * input_ns / 1000;
70
71 /* round up */
72 temp += 0xFF;
73
74 /* convert to simple integer number format */
75 temp >>= 8;
76 if (temp > adjust) {
77 return temp - adjust;
78 }
79
80 return 0;
81 }
82
83 /* Get Dynamic Memory Device Colum len */
84 STATIC uint32_t getColsLen(uint32_t DynConfig)
85 {
86 uint32_t DevBusWidth;
87 DevBusWidth = (DynConfig >> EMC_DYN_CONFIG_DEV_BUS_BIT) & 0x03;
88 if (DevBusWidth == 2) {
89 return 8;
90 }
91 else if (DevBusWidth == 1) {
92 return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 8;
93 }
94 else if (DevBusWidth == 0) {
95 return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 9;
96 }
97
98 return 0;
99 }
100
101 /* Initializes the Dynamic Controller according to the specified parameters
102 in the IP_EMC_DYN_CONFIG_T */
103 void initDynMem(LPC_EMC_T *pEMC, IP_EMC_DYN_CONFIG_T *Dynamic_Config, uint32_t EMC_Clock)
104 {
105 uint32_t ChipSelect, tmpclk;
106 volatile int i;
107
108 for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
109 LPC_EMC_T *EMC_Reg_add = (LPC_EMC_T *) ((uint32_t) pEMC + (ChipSelect << 5));
110
111 EMC_Reg_add->DYNAMICRASCAS0 = Dynamic_Config->DevConfig[ChipSelect].RAS |
112 ((Dynamic_Config->DevConfig[ChipSelect].ModeRegister <<
113 (8 - EMC_DYN_MODE_CAS_BIT)) & 0xF00);
114 EMC_Reg_add->DYNAMICCONFIG0 = Dynamic_Config->DevConfig[ChipSelect].DynConfig;
115 }
116 pEMC->DYNAMICREADCONFIG = Dynamic_Config->ReadConfig; /* Read strategy */
117
118 pEMC->DYNAMICRP = convertTimmingParam(EMC_Clock, Dynamic_Config->tRP, 1);
119 pEMC->DYNAMICRAS = convertTimmingParam(EMC_Clock, Dynamic_Config->tRAS, 1);
120 pEMC->DYNAMICSREX = convertTimmingParam(EMC_Clock, Dynamic_Config->tSREX, 1);
121 pEMC->DYNAMICAPR = convertTimmingParam(EMC_Clock, Dynamic_Config->tAPR, 1);
122 pEMC->DYNAMICDAL = convertTimmingParam(EMC_Clock, Dynamic_Config->tDAL, 0);
123 pEMC->DYNAMICWR = convertTimmingParam(EMC_Clock, Dynamic_Config->tWR, 1);
124 pEMC->DYNAMICRC = convertTimmingParam(EMC_Clock, Dynamic_Config->tRC, 1);
125 pEMC->DYNAMICRFC = convertTimmingParam(EMC_Clock, Dynamic_Config->tRFC, 1);
126 pEMC->DYNAMICXSR = convertTimmingParam(EMC_Clock, Dynamic_Config->tXSR, 1);
127 pEMC->DYNAMICRRD = convertTimmingParam(EMC_Clock, Dynamic_Config->tRRD, 1);
128 pEMC->DYNAMICMRD = convertTimmingParam(EMC_Clock, Dynamic_Config->tMRD, 1);
129
130 for (i = 0; i < 1000; i++) { /* wait 100us */
131 }
132 pEMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */
133
134 for (i = 0; i < 1000; i++) {}
135 pEMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */
136
137 pEMC->DYNAMICREFRESH = 2; /* ( 2 * 16 ) -> 32 clock cycles */
138
139 for (i = 0; i < 80; i++) {}
140
141 tmpclk = EMC_DIV_ROUND_UP(convertTimmingParam(EMC_Clock, Dynamic_Config->RefreshPeriod, 0), 16);
142 pEMC->DYNAMICREFRESH = tmpclk;
143
144 pEMC->DYNAMICCONTROL = 0x00000083; /* Issue MODE command */
145
146 for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
147 /*uint32_t burst_length;*/
148 uint32_t DynAddr;
149 uint8_t Col_len;
150
151 Col_len = getColsLen(Dynamic_Config->DevConfig[ChipSelect].DynConfig);
152 /* get bus wide: if 32bit, len is 4 else if 16bit len is 2 */
153 /* burst_length = 1 << ((((Dynamic_Config->DynConfig[ChipSelect] >> 14) & 1)^1) +1); */
154 if (Dynamic_Config->DevConfig[ChipSelect].DynConfig & (1 << EMC_DYN_CONFIG_DATA_BUS_WIDTH_BIT)) {
155 /*32bit bus */
156 /*burst_length = 2;*/
157 Col_len += 2;
158 }
159 else {
160 /*burst_length = 4;*/
161 Col_len += 1;
162 }
163
164 /* Check for RBC mode */
165 if (!(Dynamic_Config->DevConfig[ChipSelect].DynConfig & EMC_DYN_CONFIG_LPSDRAM)) {
166 if (!(Dynamic_Config->DevConfig[ChipSelect].DynConfig & (0x7 << EMC_DYN_CONFIG_DEV_SIZE_BIT))) {
167 /* 2 banks => 1 bank select bit */
168 Col_len += 1;
169 }
170 else {
171 /* 4 banks => 2 bank select bits */
172 Col_len += 2;
173 }
174 }
175
176 DynAddr = Dynamic_Config->DevConfig[ChipSelect].BaseAddr;
177
178
179 if (DynAddr != 0) {
180 uint32_t temp;
181 uint32_t ModeRegister;
182 ModeRegister = Dynamic_Config->DevConfig[ChipSelect].ModeRegister;
183 temp = *((volatile uint32_t *) (DynAddr | (ModeRegister << Col_len)));
184 temp = temp;
185 }
186 }
187 pEMC->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */
188
189 /* enable buffers */
190 pEMC->DYNAMICCONFIG0 |= 1 << 19;
191 pEMC->DYNAMICCONFIG1 |= 1 << 19;
192 pEMC->DYNAMICCONFIG2 |= 1 << 19;
193 pEMC->DYNAMICCONFIG3 |= 1 << 19;
194 }
195
196 /* Initializes the Static Controller according to the specified parameters
197 * in the IP_EMC_STATIC_CONFIG_T
198 */
199 void initStaticMem(LPC_EMC_T *pEMC, IP_EMC_STATIC_CONFIG_T *Static_Config, uint32_t EMC_Clock)
200 {
201 LPC_EMC_T *EMC_Reg_add = (LPC_EMC_T *) ((uint32_t) pEMC + ((Static_Config->ChipSelect) << 5));
202 EMC_Reg_add->STATICCONFIG0 = Static_Config->Config;
203 EMC_Reg_add->STATICWAITWEN0 = convertTimmingParam(EMC_Clock, Static_Config->WaitWen, 1);
204 EMC_Reg_add->STATICWAITOEN0 = convertTimmingParam(EMC_Clock, Static_Config->WaitOen, 0);
205 EMC_Reg_add->STATICWAITRD0 = convertTimmingParam(EMC_Clock, Static_Config->WaitRd, 1);
206 EMC_Reg_add->STATICWAITPAG0 = convertTimmingParam(EMC_Clock, Static_Config->WaitPage, 1);
207 EMC_Reg_add->STATICWAITWR0 = convertTimmingParam(EMC_Clock, Static_Config->WaitWr, 2);
208 EMC_Reg_add->STATICWAITTURN0 = convertTimmingParam(EMC_Clock, Static_Config->WaitTurn, 1);
209 }
210
211 /*****************************************************************************
212 * Public functions
213 ****************************************************************************/
214
215 /* Dyanmic memory setup */
216 void Chip_EMC_Dynamic_Init(IP_EMC_DYN_CONFIG_T *Dynamic_Config)
217 {
218 uint32_t ClkFreq;
219
220 /* Note clocks must be enabled prior to this call */
221 ClkFreq = Chip_Clock_GetEMCRate();
222
223 initDynMem(LPC_EMC, Dynamic_Config, ClkFreq);
224 }
225
226 /* Enable Dynamic Memory Controller */
227 void Chip_EMC_Dynamic_Enable(uint8_t Enable)
228 {
229 if (Enable) {
230 LPC_EMC->DYNAMICCONTROL |= EMC_DYN_CONTROL_ENABLE;
231 }
232 else {
233 LPC_EMC->DYNAMICCONTROL &= ~EMC_DYN_CONTROL_ENABLE;
234 }
235 }
236
237 /* Static memory setup */
238 void Chip_EMC_Static_Init(IP_EMC_STATIC_CONFIG_T *Static_Config)
239 {
240 uint32_t ClkFreq;
241
242 /* Note clocks must be enabled prior to this call */
243 ClkFreq = Chip_Clock_GetEMCRate();
244
245 initStaticMem(LPC_EMC, Static_Config, ClkFreq);
246 }
247
248 /* Mirror CS1 to CS0 and DYCS0 */
249 void Chip_EMC_Mirror(uint8_t Enable)
250 {
251 if (Enable) {
252 LPC_EMC->CONTROL |= 1 << 1;
253 }
254 else {
255 LPC_EMC->CONTROL &= ~(1 << 1);
256 }
257 }
258
259 /* Enable EMC */
260 void Chip_EMC_Enable(uint8_t Enable)
261 {
262 if (Enable) {
263 LPC_EMC->CONTROL |= 1;
264 }
265 else {
266 LPC_EMC->CONTROL &= ~(1);
267 }
268 }
269
270 /* Set EMC LowPower Mode */
271 void Chip_EMC_LowPowerMode(uint8_t Enable)
272 {
273 if (Enable) {
274 LPC_EMC->CONTROL |= 1 << 2;
275 }
276 else {
277 LPC_EMC->CONTROL &= ~(1 << 2);
278 }
279 }
280
281 /* Initialize EMC */
282 void Chip_EMC_Init(uint32_t Enable, uint32_t ClockRatio, uint32_t EndianMode)
283 {
284 LPC_EMC->CONFIG = (EndianMode ? 1 : 0) | ((ClockRatio ? 1 : 0) << 8);
285
286 /* Enable EMC 001 Normal Memory Map, No low power mode */
287 LPC_EMC->CONTROL = (Enable ? 1 : 0);
288 }
289