Index: c/src/lib/libbsp/arm/lpc24xx/ChangeLog
===================================================================
--- c/src/lib/libbsp/arm/lpc24xx/ChangeLog	(revision 091705c07fc934b7ad1afb99e2b3dbc8010fa684)
+++ c/src/lib/libbsp/arm/lpc24xx/ChangeLog	(revision 687e34b6194bd4722d5955a8cdb89389d52f89f9)
@@ -1,2 +1,7 @@
+2009-09-21	Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+
+	* startup/bspstarthooks.c, misc/dma-copy.c, misc/timer.c: Add
+	missing files.
+
 2009-09-17	Sebastian Huber <sebastian.huber@embedded-brains.de>
 
Index: c/src/lib/libbsp/arm/lpc24xx/misc/dma-copy.c
===================================================================
--- c/src/lib/libbsp/arm/lpc24xx/misc/dma-copy.c	(revision 687e34b6194bd4722d5955a8cdb89389d52f89f9)
+++ c/src/lib/libbsp/arm/lpc24xx/misc/dma-copy.c	(revision 687e34b6194bd4722d5955a8cdb89389d52f89f9)
@@ -0,0 +1,194 @@
+/**
+ * @file
+ *
+ * @ingroup lpc24xx_dma
+ *
+ * @brief Direct memory access (DMA) support.
+ */
+
+/*
+ * Copyright (c) 2008, 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <bsp/lpc24xx.h>
+#include <bsp/dma.h>
+#include <bsp/irq.h>
+
+static rtems_id lpc24xx_dma_sema_table [GPDMA_CH_NUMBER];
+
+static bool lpc24xx_dma_status_table [GPDMA_CH_NUMBER];
+
+static void lpc24xx_dma_copy_handler(rtems_vector_number vector, void *arg)
+{
+  /* Get interrupt status */
+  uint32_t tc = GPDMA_INT_TCSTAT;
+  uint32_t err = GPDMA_INT_ERR_STAT;
+
+  /* Clear interrupt status */
+  GPDMA_INT_TCCLR = tc;
+  GPDMA_INT_ERR_CLR = err;
+
+  /* Check channel 0 */
+  if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_0)) {
+    rtems_semaphore_release(lpc24xx_dma_sema_table [0]);
+  }
+  lpc24xx_dma_status_table [0] = IS_FLAG_CLEARED(err, GPDMA_STATUS_CH_0);
+
+  /* Check channel 1 */
+  if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_1)) {
+    rtems_semaphore_release(lpc24xx_dma_sema_table [1]);
+  }
+  lpc24xx_dma_status_table [1] = IS_FLAG_CLEARED(err, GPDMA_STATUS_CH_1);
+}
+
+rtems_status_code lpc24xx_dma_copy_initialize(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_id id0 = RTEMS_ID_NONE;
+  rtems_id id1 = RTEMS_ID_NONE;
+
+  /* Create semaphore for channel 0 */
+  sc = rtems_semaphore_create(
+    rtems_build_name('D', 'M', 'A', '0'),
+    0,
+    RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
+    0,
+    &id0
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    return sc;
+  }
+
+  /* Create semaphore for channel 1 */
+  sc = rtems_semaphore_create(
+    rtems_build_name('D', 'M', 'A', '1'),
+    0,
+    RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
+    0,
+    &id1
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    rtems_semaphore_delete(id0);
+
+    return sc;
+  }
+
+  /* Install DMA interrupt handler */
+  sc = rtems_interrupt_handler_install(
+    LPC24XX_IRQ_DMA,
+    "DMA copy",
+    RTEMS_INTERRUPT_UNIQUE,
+    lpc24xx_dma_copy_handler,
+    NULL
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    rtems_semaphore_delete(id0);
+    rtems_semaphore_delete(id1);
+
+    return sc;
+  }
+
+  /* Initialize global data */
+  lpc24xx_dma_sema_table [0] = id0;
+  lpc24xx_dma_sema_table [1] = id1;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code lpc24xx_dma_copy_release(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_status_code rsc = RTEMS_SUCCESSFUL;
+
+  sc = rtems_interrupt_handler_remove(
+    LPC24XX_IRQ_DMA,
+    lpc24xx_dma_copy_handler,
+    NULL
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    rsc = sc;
+  }
+
+  sc = rtems_semaphore_delete(lpc24xx_dma_sema_table [0]);
+  if (sc != RTEMS_SUCCESSFUL) {
+    rsc = sc;
+  }
+
+  sc = rtems_semaphore_delete(lpc24xx_dma_sema_table [1]);
+  if (sc != RTEMS_SUCCESSFUL) {
+    rsc = sc;
+  }
+
+  return rsc;
+}
+
+rtems_status_code lpc24xx_dma_copy(
+  unsigned channel,
+  void *dest,
+  const void *src,
+  size_t n,
+  size_t width
+)
+{
+  volatile lpc24xx_dma_channel *e = GPDMA_CH_BASE_ADDR(channel);
+  uint32_t w = GPDMA_CH_CTRL_W_8;
+
+  switch (width) {
+    case 4:
+      w = GPDMA_CH_CTRL_W_32;
+      break;
+    case 2:
+      w = GPDMA_CH_CTRL_W_16;
+      break;
+  }
+
+  n = n >> w;
+
+  if (n > 0U && n < 4096U) {
+    e->desc.src = (uint32_t) src;
+    e->desc.dest = (uint32_t) dest;
+    e->desc.lli = 0;
+    e->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n)
+      | SET_GPDMA_CH_CTRL_SBSZ(0, GPDMA_CH_CTRL_BSZ_1)
+      | SET_GPDMA_CH_CTRL_DBSZ(0, GPDMA_CH_CTRL_BSZ_1)
+      | SET_GPDMA_CH_CTRL_SW(0, w)
+      | SET_GPDMA_CH_CTRL_DW(0, w)
+      | GPDMA_CH_CTRL_ITC
+      | GPDMA_CH_CTRL_SI
+      | GPDMA_CH_CTRL_DI;
+    e->cfg = SET_GPDMA_CH_CFG_FLOW(0, GPDMA_CH_CFG_FLOW_MEM_TO_MEM_DMA)
+      | GPDMA_CH_CFG_IE
+      | GPDMA_CH_CFG_ITC
+      | GPDMA_CH_CFG_EN;
+  } else {
+    return RTEMS_INVALID_SIZE;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code lpc24xx_dma_copy_wait(unsigned channel)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = rtems_semaphore_obtain(
+    lpc24xx_dma_sema_table [channel],
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    return sc;
+  }
+
+  return lpc24xx_dma_status_table [channel]
+    ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
+}
Index: c/src/lib/libbsp/arm/lpc24xx/misc/timer.c
===================================================================
--- c/src/lib/libbsp/arm/lpc24xx/misc/timer.c	(revision 687e34b6194bd4722d5955a8cdb89389d52f89f9)
+++ c/src/lib/libbsp/arm/lpc24xx/misc/timer.c	(revision 687e34b6194bd4722d5955a8cdb89389d52f89f9)
@@ -0,0 +1,55 @@
+/**
+ * @file
+ *
+ * @ingroup lpc24xx
+ *
+ * @brief Benchmark timer support.
+ */
+
+/*
+ * Copyright (c) 2008, 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <rtems.h>
+#include <rtems/timerdrv.h>
+
+#include <bsp/system-clocks.h>
+
+static bool benchmark_timer_find_average_overhead = false;
+
+static uint32_t benchmark_timer_base;
+
+void benchmark_timer_initialize(void)
+{
+  benchmark_timer_base = lpc24xx_timer();
+}
+
+uint32_t benchmark_timer_read(void)
+{
+  uint32_t delta = lpc24xx_timer() - benchmark_timer_base;
+
+  if (benchmark_timer_find_average_overhead) {
+    return delta;
+  } else {
+    /* Value determined by tmck for NCS board */
+    if (delta > 74) {
+      return delta - 74;
+    } else {
+      return 0;
+    }
+  }
+}
+
+void benchmark_timer_disable_subtracting_average_overhead( bool find_average_overhead )
+{
+  benchmark_timer_find_average_overhead = find_average_overhead;
+}
Index: c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c
===================================================================
--- c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c	(revision 687e34b6194bd4722d5955a8cdb89389d52f89f9)
+++ c/src/lib/libbsp/arm/lpc24xx/startup/bspstarthooks.c	(revision 687e34b6194bd4722d5955a8cdb89389d52f89f9)
@@ -0,0 +1,410 @@
+/**
+ * @file
+ *
+ * @ingroup lpc24xx
+ *
+ * @brief Startup code.
+ */
+
+/*
+ * Copyright (c) 2008, 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <stdbool.h>
+
+#include <bspopts.h>
+#include <bsp/start.h>
+#include <bsp/lpc24xx.h>
+#include <bsp/linker-symbols.h>
+
+#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 */
+}
