From 687e34b6194bd4722d5955a8cdb89389d52f89f9 Mon Sep 17 00:00:00 2001 From: Thomas Doerfler Date: Mon, 21 Sep 2009 07:44:28 +0000 Subject: Add missing files. --- .../lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c | 410 +++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c (limited to 'c/src/lib/libbsp/arm/lpc24xx/startup') diff --git a/c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c b/c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c new file mode 100644 index 0000000000..c86cd02171 --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c @@ -0,0 +1,410 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief Startup code. + */ + +/* + * Copyright (c) 2008, 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +#include +#include +#include +#include + +#ifdef LPC24XX_EMC_MICRON + static void __attribute__((section(".bsp_start"))) lpc24xx_ram_test_32(void) + { + #ifdef LPC24XX_EMC_TEST + int *begin = (int *) 0xa0000000; + const int *end = (const int *) 0xa0800000; + int *out = begin; + + while (out != end) { + *out = (int) out; + ++out; + } + + out = begin; + while (out != end) { + if (*out != (int) out) { + while (true) { + /* Do nothing */ + } + } + ++out; + } + #endif + } + + static void __attribute__((section(".bsp_start"))) lpc24xx_cpu_delay( + unsigned ticks + ) + { + unsigned i = 0; + + /* One loop execution needs four instructions */ + ticks /= 4; + + for (i = 0; i <= ticks; ++i) { + asm volatile ("nop"); + } + } +#endif + +/** + * @brief EMC initialization hook 0. + */ +static void __attribute__((section(".bsp_start"))) lpc24xx_init_emc_0(void) +{ + #ifdef LPC24XX_EMC_NUMONYX + /* + * Static Memory 1: Numonyx M29W160EB + * + * 1 clock cycle = 1/72MHz = 13.9ns + * + * We cannot use an initializer since this will result in the usage of the + * read-only data section which is not available here. + */ + lpc24xx_emc_static numonyx; + + /* + * 16 bit, page mode disabled, active LOW chip select, extended wait + * disabled, writes not protected, byte lane state LOW/LOW (!). + */ + numonyx.cfg = 0x81; + + /* 1 clock cycles delay from the chip select 1 to the write enable */ + numonyx.waitwen = 0; + + /* + * 0 clock cycles delay from the chip select 1 or address change + * (whichever is later) to the output enable + */ + numonyx.waitoen = 0; + + /* 7 clock cycles delay from the chip select 1 to the read access */ + numonyx.waitrd = 0x6; + + /* + * 32 clock cycles delay for asynchronous page mode sequential accesses + */ + numonyx.waitpage = 0x1f; + + /* 5 clock cycles delay from the chip select 1 to the write access */ + numonyx.waitwr = 0x3; + + /* 16 bus turnaround cycles */ + numonyx.waitrun = 0xf; + #endif + + /* Set pin functions for EMC */ + PINSEL5 = (PINSEL5 & 0xf000f000) | 0x05550555; + PINSEL6 = 0x55555555; + PINSEL8 = 0x55555555; + PINSEL9 = (PINSEL9 & 0x0f000000) | 0x50555555; + + #ifdef LPC24XX_EMC_NUMONYX + /* Static Memory 1 settings */ + bsp_start_memcpy_arm( + (int *) EMC_STA_BASE_1, + (const int *) &numonyx, + sizeof(numonyx) + ); + #endif +} + +/** + * @brief EMC initialization hook 1. + */ +static void __attribute__((section(".bsp_start"))) lpc24xx_init_emc_1(void) +{ + /* Use normal memory map */ + EMC_CTRL = CLEAR_FLAG(EMC_CTRL, 0x2); + + #ifdef LPC24XX_EMC_MICRON + /* Check if we need to initialize it */ + if (IS_FLAG_CLEARED(EMC_DYN_CFG0, 0x00080000)) { + /* + * The buffer enable bit is not set. Now we assume that the controller + * is not properly initialized. + */ + + /* Global dynamic settings */ + + /* FIXME */ + EMC_DYN_APR = 2; + + /* Data-in to active command period tWR + tRP */ + EMC_DYN_DAL = 4; + + /* Load mode register to active or refresh command period 2 tCK */ + EMC_DYN_MRD = 1; + + /* Active to precharge command period 44 ns */ + EMC_DYN_RAS = 3; + + /* Active to active command period 66 ns */ + EMC_DYN_RC = 4; + + /* Use command delayed strategy */ + EMC_DYN_RD_CFG = 1; + + /* Auto refresh period 66 ns */ + EMC_DYN_RFC = 4; + + /* Precharge command period 20 ns */ + EMC_DYN_RP = 1; + + /* Active bank a to active bank b command period 15 ns */ + EMC_DYN_RRD = 1; + + /* FIXME */ + EMC_DYN_SREX = 5; + + /* Write recovery time 15 ns */ + EMC_DYN_WR = 1; + + /* Exit self refresh to active command period 75 ns */ + EMC_DYN_XSR = 5; + + /* Dynamic Memory 0: Micron M T48LC 4M16 A2 P 75 IT */ + + /* + * Use SDRAM, 0 0 001 01 address mapping, disabled buffer, unprotected writes + */ + EMC_DYN_CFG0 = 0x0280; + + /* CAS and RAS latency */ + EMC_DYN_RASCAS0 = 0x0202; + + /* Wait 50 micro seconds */ + lpc24xx_cpu_delay(3600); + + /* Send command: NOP */ + EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_NOP; + + /* Wait 50 micro seconds */ + lpc24xx_cpu_delay(3600); + + /* Send command: PRECHARGE ALL */ + EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_PALL; + + /* Shortest possible refresh period */ + EMC_DYN_RFSH = 0x01; + + /* Wait at least 128 AHB clock cycles */ + lpc24xx_cpu_delay(128); + + /* Wait 1 micro second */ + lpc24xx_cpu_delay(72); + + /* Set refresh period */ + EMC_DYN_RFSH = 0x46; + + /* Send command: MODE */ + EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_MODE; + + /* Set mode register in SDRAM */ + *((volatile uint32_t *) (0xa0000000 | (0x23 << (1 + 2 + 8)))); + + /* Send command: NORMAL */ + EMC_DYN_CTRL = 0; + + /* Enable buffer */ + EMC_DYN_CFG0 |= 0x00080000; + + /* Test RAM */ + lpc24xx_ram_test_32(); + } + #endif +} + +static void __attribute__((section(".bsp_start"))) lpc24xx_pll_config( + uint32_t val +) +{ + PLLCON = val; + PLLFEED = 0xaa; + PLLFEED = 0x55; +} + +/** + * @brief Sets the Phase Locked Loop (PLL). + * + * All parameter values are the actual register field values. + * + * @param clksrc Selects the clock source for the PLL. + * + * @param nsel Selects PLL pre-divider value (sometimes named psel). + * + * @param msel Selects PLL multiplier value. + * + * @param cclksel Selects the divide value for creating the CPU clock (CCLK) + * from the PLL output. + */ +static void __attribute__((section(".bsp_start"))) lpc24xx_set_pll( + unsigned clksrc, + unsigned nsel, + unsigned msel, + unsigned cclksel +) +{ + uint32_t pllstat = PLLSTAT; + uint32_t pllcfg = SET_PLLCFG_NSEL(0, nsel) | SET_PLLCFG_MSEL(0, msel); + uint32_t clksrcsel = SET_CLKSRCSEL_CLKSRC(0, clksrc); + uint32_t cclkcfg = SET_CCLKCFG_CCLKSEL(0, cclksel | 1); + bool pll_enabled = IS_FLAG_SET(pllstat, PLLSTAT_PLLE); + + /* Disconnect PLL if necessary */ + if (IS_FLAG_SET(pllstat, PLLSTAT_PLLC)) { + if (pll_enabled) { + /* Check if we run already with the desired settings */ + if (PLLCFG == pllcfg && CLKSRCSEL == clksrcsel && CCLKCFG == cclkcfg) { + /* Nothing to do */ + return; + } + lpc24xx_pll_config(PLLCON_PLLE); + } else { + lpc24xx_pll_config(0); + } + } + + /* Set CPU clock divider to a reasonable save value */ + CCLKCFG = 0; + + /* Disable PLL if necessary */ + if (pll_enabled) { + lpc24xx_pll_config(0); + } + + /* Select clock source */ + CLKSRCSEL = clksrcsel; + + /* Set PLL Configuration Register */ + PLLCFG = pllcfg; + + /* Enable PLL */ + lpc24xx_pll_config(PLLCON_PLLE); + + /* Wait for lock */ + while (IS_FLAG_CLEARED(PLLSTAT, PLLSTAT_PLOCK)) { + /* Wait */ + } + + /* Set CPU clock divider and ensure that we have an odd value */ + CCLKCFG = cclkcfg; + + /* Connect PLL */ + lpc24xx_pll_config(PLLCON_PLLE | PLLCON_PLLC); +} + +static void __attribute__((section(".bsp_start"))) lpc24xx_init_pll(void) +{ + /* Enable main oscillator */ + if (IS_FLAG_CLEARED(SCS, 0x40)) { + SCS = SET_FLAG(SCS, 0x20); + while (IS_FLAG_CLEARED(SCS, 0x40)) { + /* Wait */ + } + } + + /* Set PLL */ + lpc24xx_set_pll(1, 0, 11, 3); +} + +static void __attribute__((section(".bsp_start"))) lpc24xx_clear_bss(void) +{ + const int *end = (const int *) bsp_section_bss_end; + int *out = (int *) bsp_section_bss_begin; + + /* Clear BSS */ + while (out != end) { + *out = 0; + ++out; + } +} + +void __attribute__((section(".bsp_start"))) bsp_start_hook_0(void) +{ + /* Initialize PLL */ + lpc24xx_init_pll(); + + /* Initialize EMC hook 0 */ + lpc24xx_init_emc_0(); +} + +void __attribute__((section(".bsp_start"))) bsp_start_hook_1(void) +{ + /* Re-map interrupt vectors to internal RAM */ + MEMMAP = SET_MEMMAP_MAP(MEMMAP, 2); + + /* Set memory accelerator module (MAM) */ + MAMCR = 0; + MAMTIM = 4; + + /* Enable fast IO for ports 0 and 1 */ + SCS = SET_FLAG(SCS, 0x1); + + /* Set fast IO */ + FIO0DIR = 0; + FIO1DIR = 0; + FIO2DIR = 0; + FIO3DIR = 0; + FIO4DIR = 0; + FIO0CLR = 0xffffffff; + FIO1CLR = 0xffffffff; + FIO2CLR = 0xffffffff; + FIO3CLR = 0xffffffff; + FIO4CLR = 0xffffffff; + + /* Initialize EMC hook 1 */ + lpc24xx_init_emc_1(); + + /* Copy .text section */ + bsp_start_memcpy_arm( + (int *) bsp_section_text_begin, + (const int *) bsp_section_text_load_begin, + (size_t) bsp_section_text_size + ); + + /* Copy .rodata section */ + bsp_start_memcpy_arm( + (int *) bsp_section_rodata_begin, + (const int *) bsp_section_rodata_load_begin, + (size_t) bsp_section_rodata_size + ); + + /* Copy .data section */ + bsp_start_memcpy_arm( + (int *) bsp_section_data_begin, + (const int *) bsp_section_data_load_begin, + (size_t) bsp_section_data_size + ); + + /* Copy .fast section */ + bsp_start_memcpy_arm( + (int *) bsp_section_fast_begin, + (const int *) bsp_section_fast_load_begin, + (size_t) bsp_section_fast_size + ); + + /* Clear .bss section */ + lpc24xx_clear_bss(); + + /* At this point we can use objects outside the .start section */ +} -- cgit v1.2.3