source: rtems/c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c @ 687e34b

4.104.115
Last change on this file since 687e34b was 687e34b, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 09/21/09 at 07:44:28

Add missing files.

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup lpc24xx
5 *
6 * @brief Startup code.
7 */
8
9/*
10 * Copyright (c) 2008, 2009
11 * embedded brains GmbH
12 * Obere Lagerstr. 30
13 * D-82178 Puchheim
14 * Germany
15 * <rtems@embedded-brains.de>
16 *
17 * The license and distribution terms for this file may be
18 * found in the file LICENSE in this distribution or at
19 * http://www.rtems.com/license/LICENSE.
20 */
21
22#include <stdbool.h>
23
24#include <bspopts.h>
25#include <bsp/start.h>
26#include <bsp/lpc24xx.h>
27#include <bsp/linker-symbols.h>
28
29#ifdef LPC24XX_EMC_MICRON
30  static void __attribute__((section(".bsp_start"))) lpc24xx_ram_test_32(void)
31  {
32    #ifdef LPC24XX_EMC_TEST
33      int *begin = (int *) 0xa0000000;
34      const int *end = (const int *) 0xa0800000;
35      int *out = begin;
36
37      while (out != end) {
38        *out = (int) out;
39        ++out;
40      }
41
42      out = begin;
43      while (out != end) {
44        if (*out != (int) out) {
45          while (true) {
46            /* Do nothing */
47          }
48        }
49        ++out;
50      }
51    #endif
52  }
53
54  static void __attribute__((section(".bsp_start"))) lpc24xx_cpu_delay(
55    unsigned ticks
56  )
57  {
58    unsigned i = 0;
59
60    /* One loop execution needs four instructions */
61    ticks /= 4;
62
63    for (i = 0; i <= ticks; ++i) {
64      asm volatile ("nop");
65    }
66  }
67#endif
68
69/**
70 * @brief EMC initialization hook 0.
71 */
72static void __attribute__((section(".bsp_start"))) lpc24xx_init_emc_0(void)
73{
74  #ifdef LPC24XX_EMC_NUMONYX
75    /*
76     * Static Memory 1: Numonyx M29W160EB
77     *
78     * 1 clock cycle = 1/72MHz = 13.9ns
79     *
80     * We cannot use an initializer since this will result in the usage of the
81     * read-only data section which is not available here.
82     */
83    lpc24xx_emc_static numonyx;
84
85    /*
86     * 16 bit, page mode disabled, active LOW chip select, extended wait
87     * disabled, writes not protected, byte lane state LOW/LOW (!).
88     */
89    numonyx.cfg = 0x81;
90
91    /* 1 clock cycles delay from the chip select 1 to the write enable */
92    numonyx.waitwen = 0;
93
94    /*
95     * 0 clock cycles delay from the chip select 1 or address change
96     * (whichever is later) to the output enable
97     */
98    numonyx.waitoen = 0;
99
100    /* 7 clock cycles delay from the chip select 1 to the read access */
101    numonyx.waitrd = 0x6;
102
103    /*
104     * 32 clock cycles delay for asynchronous page mode sequential accesses
105     */
106    numonyx.waitpage = 0x1f;
107
108    /* 5 clock cycles delay from the chip select 1 to the write access */
109    numonyx.waitwr = 0x3;
110
111    /* 16 bus turnaround cycles */
112    numonyx.waitrun = 0xf;
113  #endif
114
115  /* Set pin functions for EMC */
116  PINSEL5 = (PINSEL5 & 0xf000f000) | 0x05550555;
117  PINSEL6 = 0x55555555;
118  PINSEL8 = 0x55555555;
119  PINSEL9 = (PINSEL9 & 0x0f000000) | 0x50555555;
120
121  #ifdef LPC24XX_EMC_NUMONYX
122    /* Static Memory 1 settings */
123    bsp_start_memcpy_arm(
124      (int *) EMC_STA_BASE_1,
125      (const int *) &numonyx,
126      sizeof(numonyx)
127    );
128  #endif
129}
130
131/**
132 * @brief EMC initialization hook 1.
133 */
134static void __attribute__((section(".bsp_start"))) lpc24xx_init_emc_1(void)
135{
136  /* Use normal memory map */
137  EMC_CTRL = CLEAR_FLAG(EMC_CTRL, 0x2);
138
139  #ifdef LPC24XX_EMC_MICRON
140    /* Check if we need to initialize it */
141    if (IS_FLAG_CLEARED(EMC_DYN_CFG0, 0x00080000)) {
142      /*
143       * The buffer enable bit is not set.  Now we assume that the controller
144       * is not properly initialized.
145       */
146
147      /* Global dynamic settings */
148 
149      /* FIXME */
150      EMC_DYN_APR = 2;
151 
152      /* Data-in to active command period tWR + tRP */
153      EMC_DYN_DAL = 4;
154 
155      /* Load mode register to active or refresh command period 2 tCK */
156      EMC_DYN_MRD = 1;
157 
158      /* Active to precharge command period 44 ns */
159      EMC_DYN_RAS = 3;
160 
161      /* Active to active command period 66 ns */
162      EMC_DYN_RC = 4;
163 
164      /* Use command delayed strategy */
165      EMC_DYN_RD_CFG = 1;
166 
167      /* Auto refresh period 66 ns */
168      EMC_DYN_RFC = 4;
169 
170      /* Precharge command period 20 ns */
171      EMC_DYN_RP = 1;
172 
173      /* Active bank a to active bank b command period 15 ns */
174      EMC_DYN_RRD = 1;
175 
176      /* FIXME */
177      EMC_DYN_SREX = 5;
178 
179      /* Write recovery time 15 ns */
180      EMC_DYN_WR = 1;
181 
182      /* Exit self refresh to active command period 75 ns */
183      EMC_DYN_XSR = 5;
184 
185      /* Dynamic Memory 0: Micron M T48LC 4M16 A2 P 75 IT */
186 
187      /*
188       * Use SDRAM, 0 0 001 01 address mapping, disabled buffer, unprotected writes
189       */
190      EMC_DYN_CFG0 = 0x0280;
191 
192      /* CAS and RAS latency */
193      EMC_DYN_RASCAS0 = 0x0202;
194 
195      /* Wait 50 micro seconds */
196      lpc24xx_cpu_delay(3600);
197 
198      /* Send command: NOP */
199      EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_NOP;
200 
201      /* Wait 50 micro seconds */
202      lpc24xx_cpu_delay(3600);
203 
204      /* Send command: PRECHARGE ALL */
205      EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_PALL;
206 
207      /* Shortest possible refresh period */
208      EMC_DYN_RFSH = 0x01;
209 
210      /* Wait at least 128 AHB clock cycles */
211      lpc24xx_cpu_delay(128);
212 
213      /* Wait 1 micro second */
214      lpc24xx_cpu_delay(72);
215 
216      /* Set refresh period */
217      EMC_DYN_RFSH = 0x46;
218 
219      /* Send command: MODE */
220      EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_MODE;
221 
222      /* Set mode register in SDRAM */
223      *((volatile uint32_t *) (0xa0000000 | (0x23 << (1 + 2 + 8))));
224 
225      /* Send command: NORMAL */
226      EMC_DYN_CTRL = 0;
227 
228      /* Enable buffer */
229      EMC_DYN_CFG0 |= 0x00080000;
230 
231      /* Test RAM */
232      lpc24xx_ram_test_32();
233    }
234  #endif
235}
236
237static void __attribute__((section(".bsp_start"))) lpc24xx_pll_config(
238  uint32_t val
239)
240{
241  PLLCON = val;
242  PLLFEED = 0xaa;
243  PLLFEED = 0x55;
244}
245
246/**
247 * @brief Sets the Phase Locked Loop (PLL).
248 *
249 * All parameter values are the actual register field values.
250 *
251 * @param clksrc Selects the clock source for the PLL.
252 *
253 * @param nsel Selects PLL pre-divider value (sometimes named psel).
254 *
255 * @param msel Selects PLL multiplier value.
256 *
257 * @param cclksel Selects the divide value for creating the CPU clock (CCLK)
258 * from the PLL output.
259 */
260static void __attribute__((section(".bsp_start"))) lpc24xx_set_pll(
261  unsigned clksrc,
262  unsigned nsel,
263  unsigned msel,
264  unsigned cclksel
265)
266{
267  uint32_t pllstat = PLLSTAT;
268  uint32_t pllcfg = SET_PLLCFG_NSEL(0, nsel) | SET_PLLCFG_MSEL(0, msel);
269  uint32_t clksrcsel = SET_CLKSRCSEL_CLKSRC(0, clksrc);
270  uint32_t cclkcfg = SET_CCLKCFG_CCLKSEL(0, cclksel | 1);
271  bool pll_enabled = IS_FLAG_SET(pllstat, PLLSTAT_PLLE);
272
273  /* Disconnect PLL if necessary */
274  if (IS_FLAG_SET(pllstat, PLLSTAT_PLLC)) {
275    if (pll_enabled) {
276      /* Check if we run already with the desired settings */
277      if (PLLCFG == pllcfg && CLKSRCSEL == clksrcsel && CCLKCFG == cclkcfg) {
278        /* Nothing to do */
279        return;
280      }
281      lpc24xx_pll_config(PLLCON_PLLE);
282    } else {
283      lpc24xx_pll_config(0);
284    }
285  }
286
287  /* Set CPU clock divider to a reasonable save value */
288  CCLKCFG = 0;
289
290  /* Disable PLL if necessary */
291  if (pll_enabled) {
292    lpc24xx_pll_config(0);
293  }
294
295  /* Select clock source */
296  CLKSRCSEL = clksrcsel;
297
298  /* Set PLL Configuration Register */
299  PLLCFG = pllcfg;
300
301  /* Enable PLL */
302  lpc24xx_pll_config(PLLCON_PLLE);
303
304  /* Wait for lock */
305  while (IS_FLAG_CLEARED(PLLSTAT, PLLSTAT_PLOCK)) {
306    /* Wait */
307  }
308
309  /* Set CPU clock divider and ensure that we have an odd value */
310  CCLKCFG = cclkcfg;
311
312  /* Connect PLL */
313  lpc24xx_pll_config(PLLCON_PLLE | PLLCON_PLLC);
314}
315
316static void __attribute__((section(".bsp_start"))) lpc24xx_init_pll(void)
317{
318  /* Enable main oscillator */
319  if (IS_FLAG_CLEARED(SCS, 0x40)) {
320    SCS = SET_FLAG(SCS, 0x20);
321    while (IS_FLAG_CLEARED(SCS, 0x40)) {
322      /* Wait */
323    }
324  }
325
326  /* Set PLL */
327  lpc24xx_set_pll(1, 0, 11, 3);
328}
329
330static void __attribute__((section(".bsp_start"))) lpc24xx_clear_bss(void)
331{
332  const int *end = (const int *) bsp_section_bss_end;
333  int *out = (int *) bsp_section_bss_begin;
334
335  /* Clear BSS */
336  while (out != end) {
337    *out = 0;
338    ++out;
339  }
340}
341
342void __attribute__((section(".bsp_start"))) bsp_start_hook_0(void)
343{
344  /* Initialize PLL */
345  lpc24xx_init_pll();
346
347  /* Initialize EMC hook 0 */
348  lpc24xx_init_emc_0();
349}
350
351void __attribute__((section(".bsp_start"))) bsp_start_hook_1(void)
352{
353  /* Re-map interrupt vectors to internal RAM */
354  MEMMAP = SET_MEMMAP_MAP(MEMMAP, 2);
355
356  /* Set memory accelerator module (MAM) */
357  MAMCR = 0;
358  MAMTIM = 4;
359
360  /* Enable fast IO for ports 0 and 1 */
361  SCS = SET_FLAG(SCS, 0x1);
362
363  /* Set fast IO */
364  FIO0DIR = 0;
365  FIO1DIR = 0;
366  FIO2DIR = 0;
367  FIO3DIR = 0;
368  FIO4DIR = 0;
369  FIO0CLR = 0xffffffff;
370  FIO1CLR = 0xffffffff;
371  FIO2CLR = 0xffffffff;
372  FIO3CLR = 0xffffffff;
373  FIO4CLR = 0xffffffff;
374
375  /* Initialize EMC hook 1 */
376  lpc24xx_init_emc_1();
377
378  /* Copy .text section */
379  bsp_start_memcpy_arm(
380    (int *) bsp_section_text_begin,
381    (const int *) bsp_section_text_load_begin,
382    (size_t) bsp_section_text_size
383  );
384
385  /* Copy .rodata section */
386  bsp_start_memcpy_arm(
387    (int *) bsp_section_rodata_begin,
388    (const int *) bsp_section_rodata_load_begin,
389    (size_t) bsp_section_rodata_size
390  );
391
392  /* Copy .data section */
393  bsp_start_memcpy_arm(
394    (int *) bsp_section_data_begin,
395    (const int *) bsp_section_data_load_begin,
396    (size_t) bsp_section_data_size
397  );
398
399  /* Copy .fast section */
400  bsp_start_memcpy_arm(
401    (int *) bsp_section_fast_begin,
402    (const int *) bsp_section_fast_load_begin,
403    (size_t) bsp_section_fast_size
404  );
405
406  /* Clear .bss section */
407  lpc24xx_clear_bss();
408
409  /* At this point we can use objects outside the .start section */
410}
Note: See TracBrowser for help on using the repository browser.