summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/ChangeLog17
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/Makefile.am20
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/configure.ac6
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/boot.h111
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/bsp.h41
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/emc.h231
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/i2c.h269
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h356
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h335
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/irq/irq.c73
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx.cfg (renamed from c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_boot_int.cfg)2
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_1.cfg7
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_2.cfg7
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/misc/boot.c54
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/misc/emc.c124
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/misc/i2c.c259
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-read-blocks.c132
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c166
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc.c322
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/misc/restart.c56
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/preinstall.am20
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c40
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/bspstart.c17
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c48
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx17
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx63
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_stage_1 (renamed from c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_boot_int)23
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_stage_260
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore8
29 files changed, 2723 insertions, 161 deletions
diff --git a/c/src/lib/libbsp/arm/lpc32xx/ChangeLog b/c/src/lib/libbsp/arm/lpc32xx/ChangeLog
index f57432b383..648340b26f 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/ChangeLog
+++ b/c/src/lib/libbsp/arm/lpc32xx/ChangeLog
@@ -1,3 +1,20 @@
+2010-06-23 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * make/custom/lpc32xx_mzx_boot_int.cfg,
+ startup/linkcmds.lpc32xx_mzx_boot_int: Removed files.
+ * include/boot.h, include/emc.h, include/i2c.h, include/nand-mlc.h,
+ make/custom/lpc32xx_mzx.cfg, make/custom/lpc32xx_mzx_stage_1.cfg,
+ make/custom/lpc32xx_mzx_stage_2.cfg, misc/boot.c, misc/emc.c,
+ misc/i2c.c, misc/nand-mlc.c, misc/nand-mlc-read-blocks.c,
+ misc/nand-mlc-write-blocks.c, misc/restart.c,
+ startup/linkcmds.lpc32xx, startup/linkcmds.lpc32xx_mzx,
+ startup/linkcmds.lpc32xx_mzx_stage_1,
+ startup/linkcmds.lpc32xx_mzx_stage_2: New files.
+ * configure.ac, Makefile.am, preinstall.am: Reflect changes above.
+ * include/bsp.h, include/lpc32xx.h, irq/irq.c, rtc/rtc-config.c,
+ startup/bspstart.c, startup/bspstarthooks.c,
+ startup/linkcmds.lpc32xx_phycore: Changes throughout.
+
2010-05-25 Sebastian Huber <sebastian.huber@embedded-brains.de>
* configure.ac, include/bspopts.h.in: Added BSP_SMALL_MEMORY option.
diff --git a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
index 69ae723625..98600d15c3 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
@@ -44,6 +44,10 @@ include_bsp_HEADERS += include/mmu.h
include_bsp_HEADERS += include/lpc32xx.h
include_bsp_HEADERS += include/lpc-clock-config.h
include_bsp_HEADERS += include/lpc-ethernet-config.h
+include_bsp_HEADERS += include/nand-mlc.h
+include_bsp_HEADERS += include/boot.h
+include_bsp_HEADERS += include/i2c.h
+include_bsp_HEADERS += include/emc.h
include_libcpu_HEADERS = ../../../libcpu/arm/shared/include/cache.h \
../../../libcpu/arm/shared/include/arm-cp15.h
@@ -59,10 +63,13 @@ libbspstart_a_SOURCES = ../shared/start/start.S
project_lib_DATA = start.$(OBJEXT)
project_lib_DATA += startup/linkcmds
+project_lib_DATA += startup/linkcmds.lpc32xx
project_lib_DATA += ../shared/startup/linkcmds.base
EXTRA_DIST = startup/linkcmds.lpc32xx_phycore \
- startup/linkcmds.lpc32xx_mzx_boot_int
+ startup/linkcmds.lpc32xx_mzx_stage_1 \
+ startup/linkcmds.lpc32xx_mzx_stage_2 \
+ startup/linkcmds.lpc32xx_mzx
###############################################################################
# LibBSP #
@@ -113,8 +120,15 @@ libbsp_a_SOURCES += ../shared/lpc/clock/lpc-clock-config.c \
libbsp_a_SOURCES += ../../shared/tod.c \
rtc/rtc-config.c
-# Timer
-libbsp_a_SOURCES += misc/timer.c
+# Misc
+libbsp_a_SOURCES += misc/timer.c \
+ misc/nand-mlc.c \
+ misc/nand-mlc-read-blocks.c \
+ misc/nand-mlc-write-blocks.c \
+ misc/restart.c \
+ misc/boot.c \
+ misc/emc.c \
+ misc/i2c.c
# SSP
diff --git a/c/src/lib/libbsp/arm/lpc32xx/configure.ac b/c/src/lib/libbsp/arm/lpc32xx/configure.ac
index 2b30bb6391..de171b354a 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/configure.ac
+++ b/c/src/lib/libbsp/arm/lpc32xx/configure.ac
@@ -21,7 +21,7 @@ RTEMS_PROG_CCAS
RTEMS_CHECK_NETWORKING
AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
-RTEMS_BSPOPTS_SET([BSP_SMALL_MEMORY],[lpc32xx_mzx_boot_int],[1])
+RTEMS_BSPOPTS_SET([BSP_SMALL_MEMORY],[lpc32xx_mzx_stage_1],[1])
RTEMS_BSPOPTS_SET([BSP_SMALL_MEMORY],[*],[])
RTEMS_BSPOPTS_HELP([BSP_SMALL_MEMORY],[disable testsuite samples with high memory demands])
@@ -40,6 +40,7 @@ RTEMS_BSPOPTS_HELP([LPC32XX_HCLK],[AHB bus clock in Hz])
RTEMS_BSPOPTS_SET([LPC32XX_PERIPH_CLK],[*],[13000000U])
RTEMS_BSPOPTS_HELP([LPC32XX_PERIPH_CLK],[peripheral clock in Hz])
+RTEMS_BSPOPTS_SET([LPC32XX_ETHERNET_RMII],[lpc32xx_mzx*][])
RTEMS_BSPOPTS_SET([LPC32XX_ETHERNET_RMII],[*],[1])
RTEMS_BSPOPTS_HELP([LPC32XX_ETHERNET_RMII],[enable RMII for Ethernet])
@@ -67,13 +68,14 @@ RTEMS_BSPOPTS_HELP([LPC32XX_CONFIG_U6CLK],[clock configuration for UART 6])
RTEMS_BSPOPTS_SET([LPC32XX_CONFIG_UART_CLKMODE],[*],[0x00000200U])
RTEMS_BSPOPTS_HELP([LPC32XX_CONFIG_UART_CLKMODE],[clock mode configuration for UARTs])
-RTEMS_BSPOPTS_SET([LPC32XX_DISABLE_MMU],[lpc32xx_mzx_boot_int],[1])
RTEMS_BSPOPTS_SET([LPC32XX_DISABLE_MMU],[*],[])
RTEMS_BSPOPTS_HELP([LPC32XX_DISABLE_MMU],[disable MMU])
+RTEMS_BSPOPTS_SET([LPC32XX_DISABLE_READ_WRITE_DATA_CACHE],[lpc32xx_mzx*],[1])
RTEMS_BSPOPTS_SET([LPC32XX_DISABLE_READ_WRITE_DATA_CACHE],[*],[])
RTEMS_BSPOPTS_HELP([LPC32XX_DISABLE_READ_WRITE_DATA_CACHE],[disable cache for read-write data sections])
+RTEMS_BSPOPTS_SET([LPC32XX_DISABLE_READ_ONLY_PROTECTION],[lpc32xx_mzx*],[1])
RTEMS_BSPOPTS_SET([LPC32XX_DISABLE_READ_ONLY_PROTECTION],[*],[])
RTEMS_BSPOPTS_HELP([LPC32XX_DISABLE_READ_ONLY_PROTECTION],[disable MMU protection of read-only sections])
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/boot.h b/c/src/lib/libbsp/arm/lpc32xx/include/boot.h
new file mode 100644
index 0000000000..cb8ab5c392
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/boot.h
@@ -0,0 +1,111 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_boot
+ *
+ * @brief Boot support API.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_BOOT_H
+#define LIBBSP_ARM_LPC32XX_BOOT_H
+
+#include <stdint.h>
+
+#include <bsp/nand-mlc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_boot Boot Support
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief Boot support.
+ *
+ * The NXP internal boot program shall be the "stage-0 program".
+ *
+ * The boot program within the first page of the first or second block shall be
+ * "stage-1 program". It will be invoked by the stage-0 program from NXP.
+ *
+ * The program loaded by the stage-1 program will be the "stage-2 program" or the
+ * "boot loader".
+ *
+ * The program loaded by the stage-2 program will be the "stage-3 program" or the
+ * "application".
+ *
+ * The stage-1 program image must have a format specified by NXP.
+ *
+ * The stage-2 and stage-3 program images may have any format.
+ *
+ * @{
+ */
+
+#define LPC32XX_BOOT_STAGE_1_BLOCK_0 0
+#define LPC32XX_BOOT_STAGE_1_BLOCK_1 1
+#define LPC32XX_BOOT_STAGE_2_BLOCK_0 2
+
+#define LPC32XX_BOOT_ICR_SP_3AC_8IF 0xf0
+#define LPC32XX_BOOT_ICR_SP_4AC_8IF 0xd2
+#define LPC32XX_BOOT_ICR_LP_4AC_8IF 0xb4
+#define LPC32XX_BOOT_ICR_LP_5AC_8IF 0x96
+
+typedef union {
+ struct {
+ uint8_t d0;
+ uint8_t reserved_0 [3];
+ uint8_t d1;
+ uint8_t reserved_1 [3];
+ uint8_t d2;
+ uint8_t reserved_2 [3];
+ uint8_t d3;
+ uint8_t reserved_3 [3];
+ uint8_t d4;
+ uint8_t reserved_4 [3];
+ uint8_t d5;
+ uint8_t reserved_5 [3];
+ uint8_t d6;
+ uint8_t reserved_6 [3];
+ uint8_t d7;
+ uint8_t reserved_7 [3];
+ uint8_t d8;
+ uint8_t reserved_8 [3];
+ uint8_t d9;
+ uint8_t reserved_9 [3];
+ uint8_t d10;
+ uint8_t reserved_10 [3];
+ uint8_t d11;
+ uint8_t reserved_11 [3];
+ uint8_t d12;
+ uint8_t reserved_12 [463];
+ } field;
+ uint32_t data [MLC_SMALL_DATA_WORD_COUNT];
+} lpc32xx_boot_block;
+
+void lpc32xx_setup_boot_block(
+ lpc32xx_boot_block *boot_block,
+ uint8_t icr,
+ uint8_t page_count
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_BOOT_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h b/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
index bef90e1333..b4c0c1143a 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2009
+ * Copyright (c) 2009, 2010
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
@@ -29,7 +29,6 @@
#include <rtems/clockdrv.h>
#include <bsp/lpc32xx.h>
-#include <bsp/lpc-timer.h>
#ifdef __cplusplus
extern "C" {
@@ -91,7 +90,7 @@ int lpc_eth_attach_detach(
*/
void *lpc32xx_idle(uintptr_t ignored);
-#define LPC32XX_STANDARD_TIMER ((volatile lpc_timer *) LPC32XX_BASE_TIMER_1)
+#define LPC32XX_STANDARD_TIMER (&lpc32xx.timer_1)
static inline unsigned lpc32xx_timer(void)
{
@@ -100,7 +99,41 @@ static inline unsigned lpc32xx_timer(void)
return timer->tc;
}
-#define BSP_CONSOLE_UART_BASE 0x40090000
+static inline void lpc32xx_micro_seconds_delay(unsigned us)
+{
+ unsigned start = lpc32xx_timer();
+ unsigned end = start + us * (LPC32XX_PERIPH_CLK / 1000000);
+ unsigned now = 0;
+
+ do {
+ now = lpc32xx_timer();
+ } while (now < end);
+}
+
+void lpc32xx_restart(void *addr);
+
+#define BSP_CONSOLE_UART_BASE LPC32XX_BASE_UART_5
+
+/**
+ * @brief Begin of magic zero area.
+ *
+ * A read from this area returns zero. Writes have no effect.
+ */
+extern uint32_t lpc32xx_magic_zero_begin [];
+
+/**
+ * @brief End of magic zero area.
+ *
+ * A read from this area returns zero. Writes have no effect.
+ */
+extern uint32_t lpc32xx_magic_zero_end [];
+
+/**
+ * @brief Size of magic zero area.
+ *
+ * A read from this area returns zero. Writes have no effect.
+ */
+extern uint32_t lpc32xx_magic_zero_size [];
/** @} */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/emc.h b/c/src/lib/libbsp/arm/lpc32xx/include/emc.h
new file mode 100644
index 0000000000..2eb5a3bda3
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/emc.h
@@ -0,0 +1,231 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_emc
+ *
+ * @brief EMC support API.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_EMC_H
+#define LIBBSP_ARM_LPC32XX_EMC_H
+
+#include <rtems.h>
+
+#include <bsp/lpc32xx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_emc EMC Support
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief EMC Support
+ *
+ * @{
+ */
+
+
+/**
+ * @name SDRAM Clock Control Register (SDRAMCLK_CTRL)
+ *
+ * @{
+ */
+
+#define SDRAMCLK_CLOCKS_DIS BIT32(0)
+#define SDRAMCLK_DDR_MODE BIT32(1)
+#define SDRAMCLK_DDR_DQSIN_DELAY(val) FIELD32(val, 2, 6)
+#define SDRAMCLK_RTC_TICK_EN BIT32(7)
+#define SDRAMCLK_SW_DDR_CAL BIT32(8)
+#define SDRAMCLK_CAL_DELAY BIT32(9)
+#define SDRAMCLK_SENSITIVITY_FACTOR(val) FIELD32(val, 10, 12)
+#define SDRAMCLK_DCA_STATUS BIT32(13)
+#define SDRAMCLK_COMMAND_DELAY(val) FIELD32(val, 14, 18)
+#define SDRAMCLK_SW_DDR_RESET BIT32(19)
+#define SDRAMCLK_PIN_1_FAST BIT32(20)
+#define SDRAMCLK_PIN_2_FAST BIT32(21)
+#define SDRAMCLK_PIN_3_FAST BIT32(22)
+
+/** @} */
+
+/**
+ * @name EMC Control Register (EMCControl)
+ *
+ * @{
+ */
+
+#define EMC_CTRL_EN BIT32(0)
+#define EMC_CTRL_LOW_POWER BIT32(2)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory Control Register (EMCDynamicControl)
+ *
+ * @{
+ */
+
+#define EMC_DYN_CTRL_CE BIT32(0)
+#define EMC_DYN_CTRL_CS BIT32(1)
+#define EMC_DYN_CTRL_SR BIT32(2)
+#define EMC_DYN_CTRL_SRMCC BIT32(3)
+#define EMC_DYN_CTRL_IMCC BIT32(4)
+#define EMC_DYN_CTRL_MCC BIT32(5)
+#define EMC_DYN_CTRL_I_MASK MASK32(7, 8)
+#define EMC_DYN_CTRL_I_NORMAL FIELD32(0x0, 7, 8)
+#define EMC_DYN_CTRL_I_MODE FIELD32(0x1, 7, 8)
+#define EMC_DYN_CTRL_I_PALL FIELD32(0x2, 7, 8)
+#define EMC_DYN_CTRL_I_NOP FIELD32(0x3, 7, 8)
+#define EMC_DYN_CTRL_DP BIT32(9)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory Read Configuration Register (EMCDynamicReadConfig)
+ *
+ * @{
+ */
+
+#define EMC_DYN_READ_CONFIG_SDR_STRAT(val) FIELD32(val, 0, 1)
+#define EMC_DYN_READ_CONFIG_SDR_POL_POS BIT32(4)
+#define EMC_DYN_READ_CONFIG_DDR_STRAT(val) FIELD32(val, 8, 9)
+#define EMC_DYN_READ_CONFIG_DDR_POL_POS BIT32(12)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory Configuration N Register (EMCDynamicConfigN)
+ *
+ * @{
+ */
+
+#define EMC_DYN_CFG_MD(val) FIELD32(val, 0, 2)
+#define EMC_DYN_CFG_AM(val) FIELD32(val, 7, 14)
+#define EMC_DYN_CFG_P(val) BIT32(20)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory RAS and CAS Delay N Register (EMCDynamicRasCasN)
+ *
+ * @{
+ */
+
+#define EMC_DYN_RAS(val) FIELD32(val, 0, 3)
+#define EMC_DYN_CAS(val) FIELD32(val, 7, 10)
+
+/** @} */
+
+/**
+ * @name EMC AHB Control Register (EMCAHBControl)
+ *
+ * @{
+ */
+
+#define EMC_AHB_PORT_BUFF_EN BIT32(0)
+
+/** @} */
+
+/**
+ * @name EMC AHB Timeout Register (EMCAHBTimeOut)
+ *
+ * @{
+ */
+
+#define EMC_AHB_TIMEOUT(val) FIELD32(val, 0, 9)
+
+/** @} */
+
+/**
+ * @name SDRAM Mode and Extended Mode Registers
+ *
+ * @{
+ */
+
+#define SDRAM_ADDR_ROW_16MB(val) ((uint32_t) (val) << 10)
+#define SDRAM_ADDR_ROW_32MB(val) ((uint32_t) (val) << 11)
+#define SDRAM_ADDR_ROW_64MB(val) ((uint32_t) (val) << 11)
+
+#define SDRAM_ADDR_BANK_16MB(ba1, ba0) \
+ (((uint32_t) (ba1) << 23) | ((uint32_t) (ba0) << 22))
+#define SDRAM_ADDR_BANK_32MB(ba1, ba0) \
+ (((uint32_t) (ba1) << 23) | ((uint32_t) (ba0) << 24))
+#define SDRAM_ADDR_BANK_64MB(ba1, ba0) \
+ (((uint32_t) (ba1) << 25) | ((uint32_t) (ba0) << 24))
+
+#define SDRAM_MODE_16MB(mode) \
+ (SDRAM_ADDR_BANK_16MB(0, 0) | SDRAM_ADDR_ROW_16MB(mode))
+#define SDRAM_MODE_32MB(mode) \
+ (SDRAM_ADDR_BANK_32MB(0, 0) | SDRAM_ADDR_ROW_32MB(mode))
+#define SDRAM_MODE_64MB(mode) \
+ (SDRAM_ADDR_BANK_64MB(0, 0) | SDRAM_ADDR_ROW_64MB(mode))
+
+#define SDRAM_EXTMODE_16MB(mode) \
+ (SDRAM_ADDR_BANK_16MB(1, 0) | SDRAM_ADDR_ROW_16MB(mode))
+#define SDRAM_EXTMODE_32MB(mode) \
+ (SDRAM_ADDR_BANK_32MB(1, 0) | SDRAM_ADDR_ROW_32MB(mode))
+#define SDRAM_EXTMODE_64MB(mode) \
+ (SDRAM_ADDR_BANK_64MB(1, 0) | SDRAM_ADDR_ROW_64MB(mode))
+
+#define SDRAM_MODE_BURST_LENGTH(val) FIELD32(val, 0, 2)
+#define SDRAM_MODE_BURST_INTERLEAVE BIT32(3)
+#define SDRAM_MODE_CAS(val) FIELD32(val, 4, 6)
+#define SDRAM_MODE_TEST_MODE(val) FIELD32(val, 7, 8)
+#define SDRAM_MODE_WRITE_BURST_SINGLE_BIT BIT32(9)
+
+#define SDRAM_EXTMODE_PASR(val) FIELD32(val, 0, 2)
+#define SDRAM_EXTMODE_DRIVER_STRENGTH(val) FIELD32(val, 5, 6)
+
+/** @} */
+
+typedef struct {
+ uint32_t size;
+ uint32_t config;
+ uint32_t rascas;
+ uint32_t mode;
+ uint32_t extmode;
+} lpc32xx_emc_dynamic_chip_config;
+
+typedef struct {
+ uint32_t sdramclk_ctrl;
+ uint32_t nop_time_in_us;
+ uint32_t control;
+ uint32_t refresh;
+ uint32_t readconfig;
+ uint32_t trp;
+ uint32_t tras;
+ uint32_t tsrex;
+ uint32_t twr;
+ uint32_t trc;
+ uint32_t trfc;
+ uint32_t txsr;
+ uint32_t trrd;
+ uint32_t tmrd;
+ uint32_t tcdlr;
+ lpc32xx_emc_dynamic_chip_config chip [EMC_DYN_CHIP_COUNT];
+} lpc32xx_emc_dynamic_config;
+
+void lpc32xx_emc_init(const lpc32xx_emc_dynamic_config *dyn_cfg);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_EMC_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/i2c.h b/c/src/lib/libbsp/arm/lpc32xx/include/i2c.h
new file mode 100644
index 0000000000..b25ea28c0a
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/i2c.h
@@ -0,0 +1,269 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_i2c
+ *
+ * @brief I2C support API.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_I2C_H
+#define LIBBSP_ARM_LPC32XX_I2C_H
+
+#include <rtems.h>
+
+#include <bsp/lpc32xx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_i2c I2C Support
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief I2C Support
+ *
+ * All writes and reads will be performed in master mode. Exclusive bus access
+ * will be assumed.
+ *
+ * @{
+ */
+
+/**
+ * @name I2C Clock Control Register (I2CCLK_CTRL)
+ *
+ * @{
+ */
+
+#define I2CCLK_1_EN BIT32(0)
+#define I2CCLK_2_EN BIT32(1)
+#define I2CCLK_1_HIGH_DRIVE BIT32(2)
+#define I2CCLK_2_HIGH_DRIVE BIT32(3)
+#define I2CCLK_USB_HIGH_DRIVE BIT32(4)
+
+/** @} */
+
+/**
+ * @name I2C TX Data FIFO Register (I2Cn_TX)
+ *
+ * @{
+ */
+
+#define I2C_TX_READ BIT32(0)
+#define I2C_TX_ADDR(val) FIELD32(val, 1, 7)
+#define I2C_TX_START BIT32(8)
+#define I2C_TX_STOP BIT32(9)
+
+/** @} */
+
+/**
+ * @name I2C Status Register (I2Cn_STAT)
+ *
+ * @{
+ */
+
+#define I2C_STAT_TDI BIT32(0)
+#define I2C_STAT_AFI BIT32(1)
+#define I2C_STAT_NAI BIT32(2)
+#define I2C_STAT_DRMI BIT32(3)
+#define I2C_STAT_DRSI BIT32(4)
+#define I2C_STAT_ACTIVE BIT32(5)
+#define I2C_STAT_SCL BIT32(6)
+#define I2C_STAT_SDA BIT32(7)
+#define I2C_STAT_RFF BIT32(8)
+#define I2C_STAT_RFE BIT32(9)
+#define I2C_STAT_TFF BIT32(10)
+#define I2C_STAT_TFE BIT32(11)
+#define I2C_STAT_TFFS BIT32(12)
+#define I2C_STAT_TFES BIT32(13)
+
+/** @} */
+
+/**
+ * @name I2C Control Register (I2Cn_CTRL)
+ *
+ * @{
+ */
+
+#define I2C_CTRL_TDIE BIT32(0)
+#define I2C_CTRL_AFIE BIT32(1)
+#define I2C_CTRL_NAIE BIT32(2)
+#define I2C_CTRL_DRMIE BIT32(3)
+#define I2C_CTRL_DRSIE BIT32(4)
+#define I2C_CTRL_RFFIE BIT32(5)
+#define I2C_CTRL_RFDAIE BIT32(6)
+#define I2C_CTRL_TFFIO BIT32(7)
+#define I2C_CTRL_RESET BIT32(8)
+#define I2C_CTRL_SEVEN BIT32(9)
+#define I2C_CTRL_TFFSIE BIT32(10)
+
+/** @} */
+
+/**
+ * @brief Initializes the I2C module @a i2c.
+ *
+ * Valid @a clock_in_hz values are 100000 and 400000.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a i2c value.
+ * @retval RTEMS_INVALID_CLOCK Invalid @a clock_in_hz value.
+ */
+rtems_status_code lpc32xx_i2c_init(
+ volatile lpc32xx_i2c *i2c,
+ unsigned clock_in_hz
+);
+
+/**
+ * @brief Resets the I2C module @a i2c.
+ */
+void lpc32xx_i2c_reset(volatile lpc32xx_i2c *i2c);
+
+/**
+ * @brief Sets the I2C module @a i2c clock.
+ *
+ * Valid @a clock_in_hz values are 100000 and 400000.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_CLOCK Invalid @a clock_in_hz value.
+ */
+rtems_status_code lpc32xx_i2c_clock(
+ volatile lpc32xx_i2c *i2c,
+ unsigned clock_in_hz
+);
+
+/**
+ * @brief Starts a write transaction on the I2C module @a i2c.
+ *
+ * The address parameter @a addr must not contain the read/write bit.
+ *
+ * The error status may be delayed to the next
+ * lpc32xx_i2c_write_with_optional_stop() due to controller flaws.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_write_start(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr
+);
+
+/**
+ * @brief Writes data via the I2C module @a i2c with optional stop.
+ *
+ * The error status may be delayed to the next
+ * lpc32xx_i2c_write_with_optional_stop() due to controller flaws.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_write_with_optional_stop(
+ volatile lpc32xx_i2c *i2c,
+ const uint8_t *out,
+ size_t n,
+ bool stop
+);
+
+/**
+ * @brief Starts a read transaction on the I2C module @a i2c.
+ *
+ * The address parameter @a addr must not contain the read/write bit.
+ *
+ * The error status may be delayed to the next
+ * lpc32xx_i2c_read_with_optional_stop() due to controller flaws.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_read_start(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr
+);
+
+/**
+ * @brief Reads data via the I2C module @a i2c with optional stop.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ * @retval RTEMS_NOT_IMPLEMENTED Stop is @a false.
+ */
+rtems_status_code lpc32xx_i2c_read_with_optional_stop(
+ volatile lpc32xx_i2c *i2c,
+ uint8_t *in,
+ size_t n,
+ bool stop
+);
+
+/**
+ * @brief Writes and reads data via the I2C module @a i2c.
+ *
+ * This will be one bus transaction.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_write_and_read(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr,
+ const uint8_t *out,
+ size_t out_size,
+ uint8_t *in,
+ size_t in_size
+);
+
+/**
+ * @brief Writes data via the I2C module @a i2c.
+ *
+ * This will be one bus transaction.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+static inline rtems_status_code lpc32xx_i2c_write(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr,
+ const uint8_t *out,
+ size_t out_size
+)
+{
+ return lpc32xx_i2c_write_and_read(i2c, addr, out, out_size, NULL, 0);
+}
+
+/**
+ * @brief Reads data via the I2C module @a i2c.
+ *
+ * This will be one bus transaction.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+static inline rtems_status_code lpc32xx_i2c_read(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr,
+ uint8_t *in,
+ size_t in_size
+)
+{
+ return lpc32xx_i2c_write_and_read(i2c, addr, NULL, 0, in, in_size);
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_I2C_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h b/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
index 540438874b..0f00981ca3 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2009
+ * Copyright (c) 2009, 2010
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
@@ -25,6 +25,7 @@
#include <stdint.h>
#include <bsp/utility.h>
+#include <bsp/lpc-timer.h>
/**
* @defgroup lpc32xx_reg Register Definitions
@@ -164,41 +165,9 @@
#define LPC32XX_KEYCLK_CTRL (*(volatile uint32_t *) 0x400040b0)
#define LPC32XX_PWMCLK_CTRL (*(volatile uint32_t *) 0x400040b8)
#define LPC32XX_UARTCLK_CTRL (*(volatile uint32_t *) 0x400040e4)
-#define LPC32XX_POS0_IRAM_CTRl (*(volatile uint32_t *) 0x40004110)
-#define LPC32XX_POS1_IRAM_CTRl (*(volatile uint32_t *) 0x40004114)
-
-/** @} */
-
-/**
- * @name GPIO Registers
- *
- * @{
- */
-
-#define LPC32XX_P0_INP_STATE (*(volatile uint32_t *) 0x40028040)
-#define LPC32XX_P0_OUTP_SET (*(volatile uint32_t *) 0x40028044)
-#define LPC32XX_P0_OUTP_CLR (*(volatile uint32_t *) 0x40028048)
-#define LPC32XX_P0_DIR_SET (*(volatile uint32_t *) 0x40028050)
-#define LPC32XX_P0_DIR_CLR (*(volatile uint32_t *) 0x40028054)
-#define LPC32XX_P0_DIR_STATE (*(volatile uint32_t *) 0x40028058)
-#define LPC32XX_P0_OUTP_STATE (*(volatile uint32_t *) 0x4002804c)
-#define LPC32XX_P1_INP_STATE (*(volatile uint32_t *) 0x40028060)
-#define LPC32XX_P1_OUTP_SET (*(volatile uint32_t *) 0x40028064)
-#define LPC32XX_P1_OUTP_CLR (*(volatile uint32_t *) 0x40028068)
-#define LPC32XX_P1_DIR_SET (*(volatile uint32_t *) 0x40028070)
-#define LPC32XX_P1_DIR_CLR (*(volatile uint32_t *) 0x40028074)
-#define LPC32XX_P1_DIR_STATE (*(volatile uint32_t *) 0x40028078)
-#define LPC32XX_P1_OUTP_STATE (*(volatile uint32_t *) 0x4002806c)
-#define LPC32XX_P2_INP_STATE (*(volatile uint32_t *) 0x4002801c)
-#define LPC32XX_P2_OUTP_SET (*(volatile uint32_t *) 0x40028020)
-#define LPC32XX_P2_OUTP_CLR (*(volatile uint32_t *) 0x40028024)
-#define LPC32XX_P2_DIR_SET (*(volatile uint32_t *) 0x40028010)
-#define LPC32XX_P2_DIR_CLR (*(volatile uint32_t *) 0x40028014)
-#define LPC32XX_P2_DIR_STATE (*(volatile uint32_t *) 0x40028018)
-#define LPC32XX_P3_INP_STATE (*(volatile uint32_t *) 0x40028000)
-#define LPC32XX_P3_OUTP_SET (*(volatile uint32_t *) 0x40028004)
-#define LPC32XX_P3_OUTP_CLR (*(volatile uint32_t *) 0x40028008)
-#define LPC32XX_P3_OUTP_STATE (*(volatile uint32_t *) 0x4002800c)
+#define LPC32XX_POS0_IRAM_CTRL (*(volatile uint32_t *) 0x40004110)
+#define LPC32XX_POS1_IRAM_CTRL (*(volatile uint32_t *) 0x40004114)
+#define LPC32XX_SDRAMCLK_CTRL (*(volatile uint32_t *) 0x40004068)
/** @} */
@@ -250,6 +219,321 @@
/** @} */
+#define LPC32XX_RESERVED(a, b, s) (((b) - (a) - sizeof(s)) / 4)
+
+typedef struct {
+} lpc32xx_nand_slc;
+
+typedef struct {
+} lpc32xx_ssp;
+
+typedef struct {
+} lpc32xx_spi;
+
+typedef struct {
+} lpc32xx_i2s;
+
+typedef struct {
+} lpc32xx_sd_card;
+
+typedef struct {
+} lpc32xx_dma;
+
+typedef struct {
+} lpc32xx_usb;
+
+typedef struct {
+} lpc32xx_lcd;
+
+typedef struct {
+} lpc32xx_etb;
+
+typedef struct {
+} lpc32xx_syscon;
+
+typedef struct {
+} lpc32xx_uart_ctrl;
+
+typedef struct {
+} lpc32xx_uart;
+
+typedef struct {
+} lpc32xx_ms_timer;
+
+typedef struct {
+} lpc32xx_hs_timer;
+
+typedef struct {
+} lpc32xx_wdg_timer;
+
+typedef struct {
+} lpc32xx_debug;
+
+typedef struct {
+} lpc32xx_adc;
+
+typedef struct {
+} lpc32xx_keyscan;
+
+typedef struct {
+} lpc32xx_pwm;
+
+typedef struct {
+} lpc32xx_mcpwm;
+
+typedef struct {
+} lpc32xx_eth;
+
+typedef struct {
+ uint32_t er;
+ uint32_t rsr;
+ uint32_t sr;
+ uint32_t apr;
+ uint32_t atr;
+ uint32_t itr;
+} lpc32xx_irq;
+
+typedef struct {
+ uint32_t p3_inp_state;
+ uint32_t p3_outp_set;
+ uint32_t p3_outp_clr;
+ uint32_t p3_outp_state;
+ uint32_t p2_dir_set;
+ uint32_t p2_dir_clr;
+ uint32_t p2_dir_state;
+ uint32_t p2_inp_state;
+ uint32_t p2_outp_set;
+ uint32_t p2_outp_clr;
+ uint32_t reserved_0 [6];
+ uint32_t p0_inp_state;
+ uint32_t p0_outp_set;
+ uint32_t p0_outp_clr;
+ uint32_t p0_outp_state;
+ uint32_t p0_dir_set;
+ uint32_t p0_dir_clr;
+ uint32_t p0_dir_state;
+ uint32_t reserved_1 [1];
+ uint32_t p1_inp_state;
+ uint32_t p1_outp_set;
+ uint32_t p1_outp_clr;
+ uint32_t p1_outp_state;
+ uint32_t p1_dir_set;
+ uint32_t p1_dir_clr;
+ uint32_t p1_dir_state;
+} lpc32xx_gpio;
+
+typedef struct {
+ uint32_t rx_or_tx;
+ uint32_t stat;
+ uint32_t ctrl;
+ uint32_t clk_hi;
+ uint32_t clk_lo;
+ uint32_t adr;
+ uint32_t rxfl;
+ uint32_t txfl;
+ uint32_t rxb;
+ uint32_t txb;
+ uint32_t s_tx;
+ uint32_t s_txfl;
+} lpc32xx_i2c;
+
+typedef struct {
+ uint32_t ucount;
+ uint32_t dcount;
+ uint32_t match0;
+ uint32_t match1;
+ uint32_t ctrl;
+ uint32_t intstat;
+ uint32_t key;
+ uint32_t sram [32];
+} lpc32xx_rtc;
+
+#define EMC_DYN_CHIP_COUNT 2
+
+#define EMC_STATIC_CHIP_COUNT 4
+
+typedef struct {
+ uint32_t config;
+ uint32_t rascas;
+ uint32_t reserved_0 [6];
+} lpc32xx_emc_dynamic;
+
+typedef struct {
+ uint32_t config;
+ uint32_t waitwen;
+ uint32_t waitoen;
+ uint32_t waitrd;
+ uint32_t waitpage;
+ uint32_t waitwr;
+ uint32_t waitturn;
+ uint32_t reserved_0 [1];
+} lpc32xx_emc_static;
+
+typedef struct {
+ uint32_t control;
+ uint32_t status;
+ uint32_t timeout;
+ uint32_t reserved_0 [5];
+} lpc32xx_emc_ahb;
+
+typedef struct {
+ uint32_t control;
+ uint32_t status;
+ uint32_t config;
+ uint32_t reserved_0 [5];
+ uint32_t dynamiccontrol;
+ uint32_t dynamicrefresh;
+ uint32_t dynamicreadconfig;
+ uint32_t reserved_1;
+ uint32_t dynamictrp;
+ uint32_t dynamictras;
+ uint32_t dynamictsrex;
+ uint32_t reserved_2 [2];
+ uint32_t dynamictwr;
+ uint32_t dynamictrc;
+ uint32_t dynamictrfc;
+ uint32_t dynamictxsr;
+ uint32_t dynamictrrd;
+ uint32_t dynamictmrd;
+ uint32_t dynamictcdlr;
+ uint32_t reserved_3 [8];
+ uint32_t staticextendedwait;
+ uint32_t reserved_4 [31];
+ lpc32xx_emc_dynamic dynamic [EMC_DYN_CHIP_COUNT];
+ uint32_t reserved_5 [48];
+ lpc32xx_emc_static emcstatic [EMC_STATIC_CHIP_COUNT];
+ uint32_t reserved_6 [96];
+ lpc32xx_emc_ahb ahb [5];
+} lpc32xx_emc;
+
+typedef struct {
+ union {
+ uint32_t w32;
+ uint16_t w16;
+ uint8_t w8;
+ } buff;
+ uint32_t reserved_0 [8191];
+ union {
+ uint32_t w32;
+ uint16_t w16;
+ uint8_t w8;
+ } data;
+ uint32_t reserved_1 [8191];
+ uint32_t cmd;
+ uint32_t addr;
+ uint32_t ecc_enc;
+ uint32_t ecc_dec;
+ uint32_t ecc_auto_enc;
+ uint32_t ecc_auto_dec;
+ uint32_t rpr;
+ uint32_t wpr;
+ uint32_t rubp;
+ uint32_t robp;
+ uint32_t sw_wp_add_low;
+ uint32_t sw_wp_add_hig;
+ uint32_t icr;
+ uint32_t time;
+ uint32_t irq_mr;
+ uint32_t irq_sr;
+ uint32_t lock_pr;
+ uint32_t isr;
+ uint32_t ceh;
+} lpc32xx_nand_mlc;
+
+typedef struct {
+ lpc32xx_nand_slc nand_slc;
+ uint32_t reserved_0 [LPC32XX_RESERVED(0x20020000, 0x20084000, lpc32xx_nand_slc)];
+ lpc32xx_ssp ssp_0;
+ uint32_t reserved_1 [LPC32XX_RESERVED(0x20084000, 0x20088000, lpc32xx_ssp)];
+ lpc32xx_spi spi_1;
+ uint32_t reserved_2 [LPC32XX_RESERVED(0x20088000, 0x2008c000, lpc32xx_spi)];
+ lpc32xx_ssp ssp_1;
+ uint32_t reserved_3 [LPC32XX_RESERVED(0x2008c000, 0x20090000, lpc32xx_ssp)];
+ lpc32xx_spi spi_2;
+ uint32_t reserved_4 [LPC32XX_RESERVED(0x20090000, 0x20094000, lpc32xx_spi)];
+ lpc32xx_i2s i2s_0;
+ uint32_t reserved_5 [LPC32XX_RESERVED(0x20094000, 0x20098000, lpc32xx_i2s)];
+ lpc32xx_sd_card sd_card;
+ uint32_t reserved_6 [LPC32XX_RESERVED(0x20098000, 0x2009c000, lpc32xx_sd_card)];
+ lpc32xx_i2s i2s_1;
+ uint32_t reserved_7 [LPC32XX_RESERVED(0x2009c000, 0x200a8000, lpc32xx_i2s)];
+ lpc32xx_nand_mlc nand_mlc;
+ uint32_t reserved_8 [LPC32XX_RESERVED(0x200a8000, 0x31000000, lpc32xx_nand_mlc)];
+ lpc32xx_dma dma;
+ uint32_t reserved_9 [LPC32XX_RESERVED(0x31000000, 0x31020000, lpc32xx_dma)];
+ lpc32xx_usb usb;
+ uint32_t reserved_10 [LPC32XX_RESERVED(0x31020000, 0x31040000, lpc32xx_usb)];
+ lpc32xx_lcd lcd;
+ uint32_t reserved_11 [LPC32XX_RESERVED(0x31040000, 0x31060000, lpc32xx_lcd)];
+ lpc32xx_eth eth;
+ uint32_t reserved_12 [LPC32XX_RESERVED(0x31060000, 0x31080000, lpc32xx_eth)];
+ lpc32xx_emc emc;
+ uint32_t reserved_13 [LPC32XX_RESERVED(0x31080000, 0x310c0000, lpc32xx_emc)];
+ lpc32xx_etb etb;
+ uint32_t reserved_14 [LPC32XX_RESERVED(0x310c0000, 0x40004000, lpc32xx_etb)];
+ lpc32xx_syscon syscon;
+ uint32_t reserved_15 [LPC32XX_RESERVED(0x40004000, 0x40008000, lpc32xx_syscon)];
+ lpc32xx_irq mic;
+ uint32_t reserved_16 [LPC32XX_RESERVED(0x40008000, 0x4000c000, lpc32xx_irq)];
+ lpc32xx_irq sic_1;
+ uint32_t reserved_17 [LPC32XX_RESERVED(0x4000c000, 0x40010000, lpc32xx_irq)];
+ lpc32xx_irq sic_2;
+ uint32_t reserved_18 [LPC32XX_RESERVED(0x40010000, 0x40014000, lpc32xx_irq)];
+ lpc32xx_uart uart_1;
+ uint32_t reserved_19 [LPC32XX_RESERVED(0x40014000, 0x40018000, lpc32xx_uart)];
+ lpc32xx_uart uart_2;
+ uint32_t reserved_20 [LPC32XX_RESERVED(0x40018000, 0x4001c000, lpc32xx_uart)];
+ lpc32xx_uart uart_7;
+ uint32_t reserved_21 [LPC32XX_RESERVED(0x4001c000, 0x40024000, lpc32xx_uart)];
+ lpc32xx_rtc rtc;
+ uint32_t reserved_22 [LPC32XX_RESERVED(0x40024000, 0x40028000, lpc32xx_rtc)];
+ lpc32xx_gpio gpio;
+ uint32_t reserved_23 [LPC32XX_RESERVED(0x40028000, 0x4002c000, lpc32xx_gpio)];
+ lpc_timer timer_4;
+ uint32_t reserved_24 [LPC32XX_RESERVED(0x4002c000, 0x40030000, lpc_timer)];
+ lpc_timer timer_5;
+ uint32_t reserved_25 [LPC32XX_RESERVED(0x40030000, 0x40034000, lpc_timer)];
+ lpc32xx_ms_timer ms_timer;
+ uint32_t reserved_26 [LPC32XX_RESERVED(0x40034000, 0x40038000, lpc32xx_ms_timer)];
+ lpc32xx_hs_timer hs_timer;
+ uint32_t reserved_27 [LPC32XX_RESERVED(0x40038000, 0x4003c000, lpc32xx_hs_timer)];
+ lpc32xx_wdg_timer wdg_timer;
+ uint32_t reserved_28 [LPC32XX_RESERVED(0x4003c000, 0x40040000, lpc32xx_wdg_timer)];
+ lpc32xx_debug debug;
+ uint32_t reserved_29 [LPC32XX_RESERVED(0x40040000, 0x40044000, lpc32xx_debug)];
+ lpc_timer timer_0;
+ uint32_t reserved_30 [LPC32XX_RESERVED(0x40044000, 0x40048000, lpc_timer)];
+ lpc32xx_adc adc;
+ uint32_t reserved_31 [LPC32XX_RESERVED(0x40048000, 0x4004c000, lpc32xx_adc)];
+ lpc_timer timer_1;
+ uint32_t reserved_32 [LPC32XX_RESERVED(0x4004c000, 0x40050000, lpc_timer)];
+ lpc32xx_keyscan keyscan;
+ uint32_t reserved_33 [LPC32XX_RESERVED(0x40050000, 0x40054000, lpc32xx_keyscan)];
+ lpc32xx_uart_ctrl uart_ctrl;
+ uint32_t reserved_34 [LPC32XX_RESERVED(0x40054000, 0x40058000, lpc32xx_uart_ctrl)];
+ lpc_timer timer_2;
+ uint32_t reserved_35 [LPC32XX_RESERVED(0x40058000, 0x4005c000, lpc_timer)];
+ lpc32xx_pwm pwm_1_and_pwm_2;
+ uint32_t reserved_36 [LPC32XX_RESERVED(0x4005c000, 0x40060000, lpc32xx_pwm)];
+ lpc_timer timer3;
+ uint32_t reserved_37 [LPC32XX_RESERVED(0x40060000, 0x40080000, lpc_timer)];
+ lpc32xx_uart uart_3;
+ uint32_t reserved_38 [LPC32XX_RESERVED(0x40080000, 0x40088000, lpc32xx_uart)];
+ lpc32xx_uart uart_4;
+ uint32_t reserved_39 [LPC32XX_RESERVED(0x40088000, 0x40090000, lpc32xx_uart)];
+ lpc32xx_uart uart_5;
+ uint32_t reserved_40 [LPC32XX_RESERVED(0x40090000, 0x40098000, lpc32xx_uart)];
+ lpc32xx_uart uart_6;
+ uint32_t reserved_41 [LPC32XX_RESERVED(0x40098000, 0x400a0000, lpc32xx_uart)];
+ lpc32xx_i2c i2c_1;
+ uint32_t reserved_42 [LPC32XX_RESERVED(0x400a0000, 0x400a8000, lpc32xx_i2c)];
+ lpc32xx_i2c i2c_2;
+ uint32_t reserved_43 [LPC32XX_RESERVED(0x400a8000, 0x400e8000, lpc32xx_i2c)];
+ lpc32xx_mcpwm mcpwm;
+} lpc32xx_registers;
+
+extern volatile lpc32xx_registers lpc32xx;
+
/** @} */
#endif /* LIBBSP_ARM_LPC32XX_LPC32XX_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h b/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h
new file mode 100644
index 0000000000..c5849103d0
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h
@@ -0,0 +1,335 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_nand_mlc
+ *
+ * @brief NAND MLC controller API.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_NAND_MLC_H
+#define LIBBSP_ARM_LPC32XX_NAND_MLC_H
+
+#include <rtems.h>
+
+#include <bsp/utility.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_nand_mlc NAND MLC Controller
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief NAND MLC Controller.
+ *
+ * Timing constraints:
+ *
+ * -# (WR_LOW + 1) / HCLK >= tWP
+ * -# (WR_HIGH - WR_LOW) / HCLK >= tWH
+ * -# (WR_LOW + 1) / HCLK + (WR_HIGH - WR_LOW) / HCLK >= tWC
+ * -# (RD_LOW + 1) / HCLK >= tRP
+ * -# (RD_LOW + 1) / HCLK >= tREA + tSU
+ * -# (RD_HIGH - RD_LOW) / HCLK >= tREH
+ * -# (RD_LOW + 1) / HCLK + (RD_HIGH - RD_LOW) / HCLK >= tRC
+ * -# (RD_HIGH - RD_LOW) / HCLK + NAND_TA / HCLK >= tRHZ
+ * -# BUSY_DELAY / HCLK >= max(tWB, tRB)
+ * -# TCEA_DELAY / HCLK >= tCEA - tREA
+ *
+ * Known flash layouts (Format: SP = small pages, LP = large pages / address
+ * cycles / pages per block):
+ *
+ * -# SP/3/32
+ * -# SP/4/32
+ * -# LP/4/64
+ * -# LP/5/64
+ * -# LP/5/128
+ *
+ * @{
+ */
+
+/**
+ * @name MLC NAND Flash Dimensions
+ *
+ * @{
+ */
+
+#define MLC_SMALL_PAGE_SIZE 528
+#define MLC_SMALL_DATA_SIZE 512
+#define MLC_SMALL_SPARE_SIZE 16
+#define MLC_SMALL_DATA_WORD_COUNT (MLC_SMALL_DATA_SIZE / 4)
+#define MLC_SMALL_SPARE_WORD_COUNT (MLC_SMALL_SPARE_SIZE / 4)
+#define MLC_SMALL_PAGES_PER_LARGE_PAGE 4
+#define MLC_LARGE_PAGE_SIZE \
+ (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_PAGE_SIZE)
+#define MLC_LARGE_DATA_SIZE \
+ (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_DATA_SIZE)
+#define MLC_LARGE_SPARE_SIZE \
+ (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_SPARE_SIZE)
+#define MLC_LARGE_DATA_WORD_COUNT (MLC_LARGE_DATA_SIZE / 4)
+#define MLC_LARGE_SPARE_WORD_COUNT (MLC_LARGE_SPARE_SIZE / 4)
+
+/** @} */
+
+/**
+ * @name NAND Flash Clock Control Register (FLASHCLK_CTRL)
+ *
+ * @{
+ */
+
+#define FLASHCLK_IRQ_MLC BIT32(5)
+#define FLASHCLK_MLC_DMA_RNB BIT32(4)
+#define FLASHCLK_MLC_DMA_INT BIT32(3)
+#define FLASHCLK_SELECT_SLC BIT32(2)
+#define FLASHCLK_MLC_CLK_ENABLE BIT32(1)
+#define FLASHCLK_SLC_CLK_ENABLE BIT32(0)
+
+/** @} */
+
+/**
+ * @name MLC NAND Timing Register (MLC_TIME_REG)
+ *
+ * @{
+ */
+
+#define MLC_TIME_WR_LOW(val) FIELD32(val, 0, 3)
+#define MLC_TIME_WR_HIGH(val) FIELD32(val, 4, 7)
+#define MLC_TIME_RD_LOW(val) FIELD32(val, 8, 11)
+#define MLC_TIME_RD_HIGH(val) FIELD32(val, 12, 15)
+#define MLC_TIME_NAND_TA(val) FIELD32(val, 16, 18)
+#define MLC_TIME_BUSY_DELAY(val) FIELD32(val, 19, 23)
+#define MLC_TIME_TCEA_DELAY(val) FIELD32(val, 24, 25)
+
+/** @} */
+
+/**
+ * @name MLC NAND Lock Protection Register (MLC_LOCK_PR)
+ *
+ * @{
+ */
+
+#define MLC_UNLOCK_PROT 0xa25e
+
+/** @} */
+
+/**
+ * @name MLC NAND Status Register (MLC_ISR)
+ *
+ * @{
+ */
+
+#define MLC_ISR_DECODER_FAILURE BIT32(6)
+#define MLC_ISR_ERRORS_DETECTED BIT32(3)
+#define MLC_ISR_ECC_READY BIT32(2)
+#define MLC_ISR_CONTROLLER_READY BIT32(1)
+#define MLC_ISR_NAND_READY BIT32(0)
+
+/** @} */
+
+/**
+ * @name MLC NAND Controller Configuration Register (MLC_ICR)
+ *
+ * @{
+ */
+
+#define MLC_ICR_SOFT_WRITE_PROT BIT32(3)
+#define MLC_ICR_LARGE_PAGES BIT32(2)
+#define MLC_ICR_ADDR_WORD_COUNT_4_5 BIT32(1)
+#define MLC_ICR_IO_BUS_16 BIT32(0)
+
+/** @} */
+
+/**
+ * @name MLC NAND Auto Encode Register (MLC_ECC_AUTO_ENC)
+ *
+ * @{
+ */
+
+#define MLC_ECC_AUTO_ENC_PROGRAM BIT32(8)
+
+/** @} */
+
+#define MLC_BAD_BLOCK_MASK ((uint32_t) 0xff00)
+
+/**
+ * @name NAND Status Register
+ *
+ * @{
+ */
+
+#define NAND_STATUS_ERROR (1U << 0)
+#define NAND_STATUS_READY (1U << 6)
+#define NAND_STATUS_NOT_PROTECTED (1U << 7)
+
+/** @} */
+
+/**
+ * @brief MLC NAND controller configuration.
+ */
+typedef struct {
+ /**
+ * @brief Selects small pages (512 Bytes user data and 16 Bytes spare data)
+ * or large pages (2048 Bytes user data and 64 Bytes spare data).
+ */
+ bool small_pages;
+
+ /**
+ * @brief Selects 3/4 address cycles for small pages/large pages or 4/5
+ * address cycles.
+ */
+ bool many_address_cycles;
+
+ /**
+ * @brief Selects 64 or 128 pages per block in case of large pages.
+ */
+ bool normal_blocks;
+
+ uint32_t block_count;
+
+ /**
+ * @brief Value for the MLC NAND Timing Register (MLC_TIME_REG).
+ */
+ uint32_t time;
+} lpc32xx_mlc_config;
+
+/**
+ * @brief Initializes the MLC NAND controller according to @a cfg.
+ */
+void lpc32xx_mlc_init(const lpc32xx_mlc_config *cfg);
+
+uint32_t lpc32xx_mlc_page_size(void);
+
+uint32_t lpc32xx_mlc_pages_per_block(void);
+
+uint32_t lpc32xx_mlc_block_count(void);
+
+void lpc32xx_mlc_write_protection(
+ uint32_t page_index_low,
+ uint32_t page_index_high
+);
+
+void lpc32xx_mlc_read_id(uint8_t *id, size_t n);
+
+/**
+ * @brief Reads the page with index @a page_index.
+ *
+ * 32-bit reads will be performed.
+ *
+ * Bytes 7 to 15 of the spare area will contain the ECC.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a page_index value.
+ * @retval RTEMS_IO_ERROR Uncorrectable bit error.
+ */
+rtems_status_code lpc32xx_mlc_read_page(
+ uint32_t page_index,
+ uint32_t *data,
+ uint32_t *spare
+);
+
+/**
+ * @brief Erases the block with index @a block_index.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a block_index value.
+ * @retval RTEMS_IO_ERROR Erase error.
+ */
+rtems_status_code lpc32xx_mlc_erase_block(uint32_t block_index);
+
+/**
+ * @brief Writes the page with index @a page_index.
+ *
+ * 32-bit writes will be performed.
+ *
+ * Bytes 7 to 15 of the spare area will be used for the automatically generated
+ * ECC.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a page_index value.
+ * @retval RTEMS_IO_ERROR Write error.
+ */
+rtems_status_code lpc32xx_mlc_write_page_with_ecc(
+ uint32_t page_index,
+ const uint32_t *data,
+ const uint32_t *spare
+);
+
+/**
+ * @brief Writes @a src_size Bytes from @a src to the flash area specified by
+ * @a block_begin and @a block_end.
+ *
+ * The @a page_buffer will be used as an intermediate buffer.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a block_begin or @a block_end value.
+ * @retval RTEMS_IO_ERROR To many bad blocks or source area to big.
+ */
+rtems_status_code lpc32xx_mlc_write_blocks(
+ uint32_t block_begin,
+ uint32_t block_end,
+ const void *src,
+ size_t src_size,
+ uint32_t page_buffer [MLC_LARGE_DATA_WORD_COUNT]
+);
+
+/**
+ * @brief Read blocks process function type.
+ *
+ * @see lpc32xx_mlc_read_blocks().
+ *
+ * @retval false Continue processing.
+ * @retval true Stop processing.
+ */
+typedef bool (*lpc32xx_mlc_read_process)(
+ void *process_arg,
+ uint32_t page_index,
+ uint32_t page_size,
+ uint32_t page_data [MLC_LARGE_DATA_WORD_COUNT],
+ uint32_t page_spare [MLC_LARGE_SPARE_WORD_COUNT]
+);
+
+/**
+ * @brief Reads the pages of block @a block_begin up to and excluding
+ * @a block_end.
+ *
+ * For each page @a process will be called with the @a process_arg parameter,
+ * the page_index, the page data and the page spare.
+ *
+ * The @a page_buffer_0 and @a page_buffer_1 will be used as
+ * intermediate buffers.
+ */
+rtems_status_code lpc32xx_mlc_read_blocks(
+ uint32_t block_begin,
+ uint32_t block_end,
+ lpc32xx_mlc_read_process process,
+ void *process_arg,
+ uint32_t page_buffer_0 [MLC_LARGE_DATA_WORD_COUNT],
+ uint32_t page_buffer_1 [MLC_LARGE_DATA_WORD_COUNT]
+);
+
+static inline bool lpc32xx_mlc_is_bad_page(const uint32_t *spare)
+{
+ return (spare [1] & MLC_BAD_BLOCK_MASK) != MLC_BAD_BLOCK_MASK;
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_NAND_MLC_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c b/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c
index 4ea1c1cc1c..c0f3bb8dba 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c
@@ -42,21 +42,6 @@ typedef union {
uint32_t fields_table [LPC32XX_IRQ_MODULE_COUNT];
} lpc32xx_irq_fields;
-typedef struct {
- uint32_t er;
- uint32_t rsr;
- uint32_t sr;
- uint32_t apr;
- uint32_t atr;
- uint32_t itr;
-} lpc32xx_irq_controller;
-
-static volatile lpc32xx_irq_controller *const lpc32xx_mic = (volatile lpc32xx_irq_controller *) LPC32XX_BASE_MIC;
-
-static volatile lpc32xx_irq_controller *const lpc32xx_sic_1 = (volatile lpc32xx_irq_controller *) LPC32XX_BASE_SIC_1;
-
-static volatile lpc32xx_irq_controller *const lpc32xx_sic_2 = (volatile lpc32xx_irq_controller *) LPC32XX_BASE_SIC_2;
-
static uint8_t lpc32xx_irq_priority_table [LPC32XX_IRQ_COUNT];
static lpc32xx_irq_fields lpc32xx_irq_priority_masks [LPC32XX_IRQ_PRIORITY_COUNT];
@@ -80,8 +65,8 @@ static inline bool lpc32xx_irq_priority_is_valid(unsigned priority)
#define LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE \
LPC32XX_IRQ_BIT_OPS_DEFINE; \
unsigned module_offset = module << 14; \
- volatile uint32_t *reg = \
- (volatile uint32_t *) (LPC32XX_BASE_MIC + module_offset + register_offset)
+ volatile uint32_t *reg = (volatile uint32_t *) \
+ ((volatile char *) &lpc32xx.mic + module_offset + register_offset)
#define LPC32XX_IRQ_OFFSET_ER 0U
#define LPC32XX_IRQ_OFFSET_RSR 4U
@@ -234,10 +219,10 @@ lpc32xx_irq_activation_type lpc32xx_irq_get_activation_type(rtems_vector_number
void bsp_interrupt_dispatch(void)
{
- uint32_t status = lpc32xx_mic->sr & LPC32XX_MIC_STATUS_MASK;
- uint32_t er_mic = lpc32xx_mic->er;
- uint32_t er_sic_1 = lpc32xx_sic_1->er;
- uint32_t er_sic_2 = lpc32xx_sic_2->er;
+ uint32_t status = lpc32xx.mic.sr & LPC32XX_MIC_STATUS_MASK;
+ uint32_t er_mic = lpc32xx.mic.er;
+ uint32_t er_sic_1 = lpc32xx.sic_1.er;
+ uint32_t er_sic_2 = lpc32xx.sic_2.er;
uint32_t psr = 0;
lpc32xx_irq_fields *masks = NULL;
rtems_vector_number vector = 0;
@@ -246,11 +231,11 @@ void bsp_interrupt_dispatch(void)
if (status != 0) {
vector = lpc32xx_irq_get_index(status);
} else {
- status = lpc32xx_sic_1->sr;
+ status = lpc32xx.sic_1.sr;
if (status != 0) {
vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_1;
} else {
- status = lpc32xx_sic_2->sr;
+ status = lpc32xx.sic_2.sr;
if (status != 0) {
vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_2;
} else {
@@ -263,9 +248,9 @@ void bsp_interrupt_dispatch(void)
masks = &lpc32xx_irq_priority_masks [priority];
- lpc32xx_mic->er = er_mic & masks->field.mic;
- lpc32xx_sic_1->er = er_sic_1 & masks->field.sic_1;
- lpc32xx_sic_2->er = er_sic_2 & masks->field.sic_2;
+ lpc32xx.mic.er = er_mic & masks->field.mic;
+ lpc32xx.sic_1.er = er_sic_1 & masks->field.sic_1;
+ lpc32xx.sic_2.er = er_sic_2 & masks->field.sic_2;
psr = arm_status_irq_enable();
@@ -273,9 +258,9 @@ void bsp_interrupt_dispatch(void)
arm_status_restore(psr);
- lpc32xx_mic->er = er_mic & lpc32xx_irq_enable.field.mic;
- lpc32xx_sic_1->er = er_sic_1 & lpc32xx_irq_enable.field.sic_1;
- lpc32xx_sic_2->er = er_sic_2 & lpc32xx_irq_enable.field.sic_2;
+ lpc32xx.mic.er = er_mic & lpc32xx_irq_enable.field.mic;
+ lpc32xx.sic_1.er = er_sic_1 & lpc32xx_irq_enable.field.sic_1;
+ lpc32xx.sic_2.er = er_sic_2 & lpc32xx_irq_enable.field.sic_2;
}
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
@@ -308,11 +293,7 @@ void lpc32xx_set_exception_handler(
)
{
if ((unsigned) exception < MAX_EXCEPTIONS) {
- #ifndef LPC32XX_DISABLE_MMU
- uint32_t *table = (uint32_t *) bsp_section_vector_begin + MAX_EXCEPTIONS;
- #else
- uint32_t *table = (uint32_t *) bsp_section_start_begin + MAX_EXCEPTIONS;
- #endif
+ uint32_t *table = (uint32_t *) bsp_vector_table_begin + MAX_EXCEPTIONS;
table [exception] = (uint32_t) handler;
@@ -341,24 +322,24 @@ rtems_status_code bsp_interrupt_facility_initialize(void)
lpc32xx_irq_enable.field.sic_2 = 0x0;
lpc32xx_irq_enable.field.sic_1 = 0x0;
lpc32xx_irq_enable.field.mic = 0xc0000003;
- lpc32xx_sic_1->er = 0x0;
- lpc32xx_sic_2->er = 0x0;
- lpc32xx_mic->er = 0xc0000003;
+ lpc32xx.sic_1.er = 0x0;
+ lpc32xx.sic_2.er = 0x0;
+ lpc32xx.mic.er = 0xc0000003;
/* Set interrupt types to IRQ */
- lpc32xx_mic->itr = 0x0;
- lpc32xx_sic_1->itr = 0x0;
- lpc32xx_sic_2->itr = 0x0;
+ lpc32xx.mic.itr = 0x0;
+ lpc32xx.sic_1.itr = 0x0;
+ lpc32xx.sic_2.itr = 0x0;
/* Set interrupt activation polarities */
- lpc32xx_mic->apr = 0x3ff0efe0;
- lpc32xx_sic_1->apr = 0xfbd27184;
- lpc32xx_sic_2->apr = 0x801810c0;
+ lpc32xx.mic.apr = 0x3ff0efe0;
+ lpc32xx.sic_1.apr = 0xfbd27184;
+ lpc32xx.sic_2.apr = 0x801810c0;
/* Set interrupt activation types */
- lpc32xx_mic->atr = 0x0;
- lpc32xx_sic_1->atr = 0x26000;
- lpc32xx_sic_2->atr = 0x0;
+ lpc32xx.mic.atr = 0x0;
+ lpc32xx.sic_1.atr = 0x26000;
+ lpc32xx.sic_2.atr = 0x0;
lpc32xx_set_exception_handler(ARM_EXCEPTION_IRQ, arm_exc_interrupt);
diff --git a/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_boot_int.cfg b/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx.cfg
index 398f5e0b33..a5eb519cf1 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_boot_int.cfg
+++ b/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx.cfg
@@ -1,5 +1,5 @@
#
-# Config file for boot loader.
+# Config file for MZX application.
#
# $Id$
#
diff --git a/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_1.cfg b/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_1.cfg
new file mode 100644
index 0000000000..c2127b14b3
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_1.cfg
@@ -0,0 +1,7 @@
+#
+# Config file for MZX stage-1 program.
+#
+# $Id$
+#
+
+include $(RTEMS_ROOT)/make/custom/lpc32xx.inc
diff --git a/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_2.cfg b/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_2.cfg
new file mode 100644
index 0000000000..600fc9c7c1
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/make/custom/lpc32xx_mzx_stage_2.cfg
@@ -0,0 +1,7 @@
+#
+# Config file for MZX stage-2 program.
+#
+# $Id$
+#
+
+include $(RTEMS_ROOT)/make/custom/lpc32xx.inc
diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/boot.c b/c/src/lib/libbsp/arm/lpc32xx/misc/boot.c
new file mode 100644
index 0000000000..0f624114f3
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/misc/boot.c
@@ -0,0 +1,54 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_boot
+ *
+ * @brief Boot support implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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 <string.h>
+
+#include <bsp/boot.h>
+
+void lpc32xx_setup_boot_block(
+ lpc32xx_boot_block *boot_block,
+ uint8_t icr,
+ uint8_t page_count
+)
+{
+ memset(boot_block, 0, sizeof(*boot_block));
+
+ ++page_count;
+
+ boot_block->field.d0 = icr;
+ boot_block->field.d2 = icr;
+ boot_block->field.d4 = page_count;
+ boot_block->field.d6 = page_count;
+ boot_block->field.d8 = page_count;
+ boot_block->field.d10 = page_count;
+
+ icr = (uint8_t) ~((unsigned) icr);
+ page_count = (uint8_t) ~((unsigned) page_count);
+
+ boot_block->field.d1 = icr;
+ boot_block->field.d3 = icr;
+ boot_block->field.d5 = page_count;
+ boot_block->field.d7 = page_count;
+ boot_block->field.d9 = page_count;
+ boot_block->field.d11 = page_count;
+
+ boot_block->field.d12 = 0xaa;
+}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/emc.c b/c/src/lib/libbsp/arm/lpc32xx/misc/emc.c
new file mode 100644
index 0000000000..0a6d75c5bc
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/misc/emc.c
@@ -0,0 +1,124 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_emc
+ *
+ * @brief EMC support implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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/emc.h>
+
+#include <bsp.h>
+#include <bsp/mmu.h>
+
+static volatile lpc32xx_emc *const emc = &lpc32xx.emc;
+
+static void set_translation_table_entries(
+ uint32_t begin,
+ uint32_t size
+)
+{
+ uint32_t end = begin + size;
+ uint32_t *ttb = arm_cp15_get_translation_table_base();
+ uint32_t i = ARM_MMU_SECT_GET_INDEX(begin);
+ uint32_t iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(end));
+
+ while (i < iend) {
+ ttb [i] = (i << ARM_MMU_SECT_BASE_SHIFT) | LPC32XX_MMU_READ_WRITE;
+ ++i;
+ }
+}
+
+static void dynamic_init(const lpc32xx_emc_dynamic_config *cfg)
+{
+ uint32_t chip_begin = LPC32XX_BASE_EMC_DYCS_0;
+ uint32_t dynamiccontrol = (cfg->control | EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS)
+ & ~EMC_DYN_CTRL_I_MASK;
+ size_t i = 0;
+
+ LPC32XX_SDRAMCLK_CTRL = cfg->sdramclk_ctrl;
+
+ emc->dynamicreadconfig = cfg->readconfig;
+
+ /* Timings */
+ emc->dynamictrp = cfg->trp;
+ emc->dynamictras = cfg->tras;
+ emc->dynamictsrex = cfg->tsrex;
+ emc->dynamictwr = cfg->twr;
+ emc->dynamictrc = cfg->trc;
+ emc->dynamictrfc = cfg->trfc;
+ emc->dynamictxsr = cfg->txsr;
+ emc->dynamictrrd = cfg->trrd;
+ emc->dynamictmrd = cfg->tmrd;
+ emc->dynamictcdlr = cfg->tcdlr;
+ for (i = 0; i < EMC_DYN_CHIP_COUNT; ++i) {
+ if (cfg->chip [i].size != 0) {
+ emc->dynamic [i].config = cfg->chip [i].config;
+ emc->dynamic [i].rascas = cfg->chip [i].rascas;
+ }
+ }
+
+ /* NOP period */
+ emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_NOP;
+ lpc32xx_micro_seconds_delay(cfg->nop_time_in_us);
+
+ /* Precharge */
+ emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_PALL;
+ emc->dynamicrefresh = 1;
+ /* FIXME: Why a delay, why this value? */
+ lpc32xx_micro_seconds_delay(10);
+
+ /* Refresh timing */
+ emc->dynamicrefresh = cfg->refresh;
+ /* FIXME: Why a delay, why this value? */
+ lpc32xx_micro_seconds_delay(16);
+
+ /* Set modes */
+ for (i = 0; i < EMC_DYN_CHIP_COUNT; ++i) {
+ if (cfg->chip [i].size != 0) {
+ set_translation_table_entries(chip_begin, cfg->chip [i].size);
+ emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_MODE;
+ *(volatile uint32_t *)(LPC32XX_BASE_EMC_DYCS_0 + cfg->chip [i].mode);
+ emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_MODE;
+ *(volatile uint32_t *)(LPC32XX_BASE_EMC_DYCS_0 + cfg->chip [i].extmode);
+ }
+ chip_begin += 0x20000000;
+ }
+
+ emc->dynamiccontrol = cfg->control;
+}
+
+void lpc32xx_emc_init(const lpc32xx_emc_dynamic_config *dyn_cfg)
+{
+ /* Enable clock */
+ LPC32XX_HCLKDIV_CTRL |= HCLK_DIV_DDRAM_CLK(1);
+
+ /* Enable buffers in AHB ports */
+ emc->ahb [0].control = EMC_AHB_PORT_BUFF_EN;
+ emc->ahb [3].control = EMC_AHB_PORT_BUFF_EN;
+ emc->ahb [4].control = EMC_AHB_PORT_BUFF_EN;
+
+ /* Set AHB port timeouts */
+ emc->ahb [0].timeout = EMC_AHB_TIMEOUT(32);
+ emc->ahb [3].timeout = EMC_AHB_TIMEOUT(32);
+ emc->ahb [4].timeout = EMC_AHB_TIMEOUT(32);
+
+ /* Enable EMC */
+ emc->control = EMC_CTRL_EN,
+ emc->config = 0;
+
+ dynamic_init(dyn_cfg);
+}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/i2c.c b/c/src/lib/libbsp/arm/lpc32xx/misc/i2c.c
new file mode 100644
index 0000000000..e1ade9d4ac
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/misc/i2c.c
@@ -0,0 +1,259 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_i2c
+ *
+ * @brief I2C support implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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 <bsp.h>
+#include <bsp/i2c.h>
+
+void lpc32xx_i2c_reset(volatile lpc32xx_i2c *i2c)
+{
+ i2c->ctrl = I2C_CTRL_RESET;
+}
+
+rtems_status_code lpc32xx_i2c_init(
+ volatile lpc32xx_i2c *i2c,
+ unsigned clock_in_hz
+)
+{
+ uint32_t i2cclk = 0;
+
+ if (i2c == &lpc32xx.i2c_1) {
+ i2cclk |= I2CCLK_1_EN | I2CCLK_1_HIGH_DRIVE;
+ } else if (i2c == &lpc32xx.i2c_2) {
+ i2cclk |= I2CCLK_2_EN | I2CCLK_2_HIGH_DRIVE;
+ } else {
+ return RTEMS_INVALID_ID;
+ }
+
+ LPC32XX_I2CCLK_CTRL |= i2cclk;
+
+ lpc32xx_i2c_reset(i2c);
+
+ return lpc32xx_i2c_clock(i2c, clock_in_hz);
+}
+
+#if LPC32XX_HCLK != 104000000U
+ #error "unexpected HCLK"
+#endif
+
+rtems_status_code lpc32xx_i2c_clock(
+ volatile lpc32xx_i2c *i2c,
+ unsigned clock_in_hz
+)
+{
+ uint32_t clk_lo = 0;
+ uint32_t clk_hi = 0;
+
+ switch (clock_in_hz) {
+ case 100000:
+ clk_lo = 520;
+ clk_hi = 520;
+ break;
+ case 400000:
+ clk_lo = 166;
+ clk_hi = 94;
+ break;
+ default:
+ return RTEMS_INVALID_CLOCK;
+ }
+
+ i2c->clk_lo = clk_lo;
+ i2c->clk_hi = clk_hi;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code wait_for_transaction_done(volatile lpc32xx_i2c *i2c)
+{
+ uint32_t stat = 0;
+
+ do {
+ stat = i2c->stat;
+ } while ((stat & I2C_STAT_TDI) == 0);
+
+ if ((stat & I2C_STAT_TFE) != 0) {
+ i2c->stat = I2C_STAT_TDI;
+
+ return RTEMS_SUCCESSFUL;
+ } else {
+ lpc32xx_i2c_reset(i2c);
+
+ return RTEMS_IO_ERROR;
+ }
+}
+
+static rtems_status_code tx(volatile lpc32xx_i2c *i2c, uint32_t data)
+{
+ uint32_t stat = 0;
+
+ do {
+ stat = i2c->stat;
+ } while ((stat & (I2C_STAT_TFE | I2C_STAT_TDI)) == 0);
+
+ if ((stat & I2C_STAT_TDI) == 0) {
+ i2c->rx_or_tx = data;
+
+ return RTEMS_SUCCESSFUL;
+ } else {
+ lpc32xx_i2c_reset(i2c);
+
+ return RTEMS_IO_ERROR;
+ }
+}
+
+rtems_status_code lpc32xx_i2c_write_start(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr
+)
+{
+ return tx(i2c, I2C_TX_ADDR(addr) | I2C_TX_START);
+}
+
+rtems_status_code lpc32xx_i2c_read_start(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr
+)
+{
+ return tx(i2c, I2C_TX_ADDR(addr) | I2C_TX_START | I2C_TX_READ);
+}
+
+rtems_status_code lpc32xx_i2c_write_with_optional_stop(
+ volatile lpc32xx_i2c *i2c,
+ const uint8_t *out,
+ size_t n,
+ bool stop
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ size_t i = 0;
+
+ for (i = 0; i < n - 1 && sc == RTEMS_SUCCESSFUL; ++i) {
+ sc = tx(i2c, out [i]);
+ }
+
+ if (sc == RTEMS_SUCCESSFUL) {
+ uint32_t stop_flag = stop ? I2C_TX_STOP : 0;
+
+ sc = tx(i2c, out [n - 1] | stop_flag);
+ }
+
+ if (stop && sc == RTEMS_SUCCESSFUL) {
+ sc = wait_for_transaction_done(i2c);
+ }
+
+ return sc;
+}
+
+static bool can_tx_for_rx(volatile lpc32xx_i2c *i2c)
+{
+ return (i2c->stat & (I2C_STAT_TFF | I2C_STAT_RFF)) == 0;
+}
+
+static bool can_rx(volatile lpc32xx_i2c *i2c)
+{
+ return (i2c->stat & I2C_STAT_RFE) == 0;
+}
+
+rtems_status_code lpc32xx_i2c_read_with_optional_stop(
+ volatile lpc32xx_i2c *i2c,
+ uint8_t *in,
+ size_t n,
+ bool stop
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ size_t last = n - 1;
+ size_t rx = 0;
+ size_t tx = 0;
+
+ if (!stop) {
+ return RTEMS_NOT_IMPLEMENTED;
+ }
+
+ while (rx <= last) {
+ if ((i2c->stat & I2C_STAT_TDI) != 0) {
+ stop = true;
+
+ break;
+ }
+
+ while (tx < last && can_tx_for_rx(i2c)) {
+ i2c->rx_or_tx = 0;
+ ++tx;
+ }
+
+ if (tx == last && can_tx_for_rx(i2c)) {
+ uint32_t stop_flag = stop ? I2C_TX_STOP : 0;
+
+ i2c->rx_or_tx = stop_flag;
+ ++tx;
+ }
+
+ while (rx <= last && can_rx(i2c)) {
+ in [rx] = (uint8_t) i2c->rx_or_tx;
+ ++rx;
+ }
+ }
+
+ if (stop) {
+ sc = wait_for_transaction_done(i2c);
+ }
+
+ return sc;
+}
+
+rtems_status_code lpc32xx_i2c_write_and_read(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr,
+ const uint8_t *out,
+ size_t out_size,
+ uint8_t *in,
+ size_t in_size
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (out_size > 0) {
+ bool stop = in_size == 0;
+
+ sc = lpc32xx_i2c_write_start(i2c, addr);
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
+
+ sc = lpc32xx_i2c_write_with_optional_stop(i2c, out, out_size, stop);
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
+ }
+
+ if (in_size > 0) {
+ sc = lpc32xx_i2c_read_start(i2c, addr);
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
+
+ lpc32xx_i2c_read_with_optional_stop(i2c, in, in_size, true);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-read-blocks.c b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-read-blocks.c
new file mode 100644
index 0000000000..7d00d0e52a
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-read-blocks.c
@@ -0,0 +1,132 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_nand_mlc
+ *
+ * @brief lpc32xx_mlc_read_blocks() implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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/nand-mlc.h>
+
+static rtems_status_code read_page(
+ uint32_t first_page_of_block,
+ uint32_t page,
+ uint32_t page_data [MLC_LARGE_DATA_WORD_COUNT],
+ uint32_t page_spare [MLC_LARGE_SPARE_WORD_COUNT]
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint32_t page_index = first_page_of_block + page;
+ bool possible_bad_page = page == 0 || page == 1;
+
+ if (possible_bad_page) {
+ memset(page_spare, 0, MLC_LARGE_SPARE_SIZE);
+ }
+
+ sc = lpc32xx_mlc_read_page(page_index, page_data, page_spare);
+ if (possible_bad_page && lpc32xx_mlc_is_bad_page(page_spare)) {
+ return RTEMS_UNSATISFIED;
+ } else if (sc == RTEMS_SUCCESSFUL) {
+ return RTEMS_SUCCESSFUL;
+ } else {
+ return sc;
+ }
+}
+
+rtems_status_code lpc32xx_mlc_read_blocks(
+ uint32_t block_begin,
+ uint32_t block_end,
+ lpc32xx_mlc_read_process process,
+ void *process_arg,
+ uint32_t page_buffer_0 [MLC_LARGE_DATA_WORD_COUNT],
+ uint32_t page_buffer_1 [MLC_LARGE_DATA_WORD_COUNT]
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint32_t page_spare_0 [MLC_LARGE_SPARE_WORD_COUNT];
+ uint32_t page_spare_1 [MLC_LARGE_SPARE_WORD_COUNT];
+ uint32_t pages_per_block = lpc32xx_mlc_pages_per_block();
+ uint32_t page_size = lpc32xx_mlc_page_size();
+ uint32_t block = 0;
+ uint32_t first_page_of_block = block_begin * pages_per_block;
+
+ for (
+ block = block_begin;
+ block != block_end;
+ ++block, first_page_of_block += pages_per_block
+ ) {
+ uint32_t page = 0;
+ bool done = false;
+
+ sc = read_page(first_page_of_block, 0, page_buffer_0, page_spare_0);
+ if (sc == RTEMS_UNSATISFIED) {
+ continue;
+ } else if (sc != RTEMS_SUCCESSFUL) {
+ goto done;
+ }
+
+ sc = read_page(first_page_of_block, 1, page_buffer_1, page_spare_1);
+ if (sc == RTEMS_UNSATISFIED) {
+ continue;
+ } else if (sc != RTEMS_SUCCESSFUL) {
+ goto done;
+ }
+
+ done = (*process)(
+ process_arg,
+ first_page_of_block + 0,
+ page_size,
+ page_buffer_0,
+ page_spare_0
+ );
+ if (done) {
+ goto done;
+ }
+
+ done = (*process)(
+ process_arg,
+ first_page_of_block + 1,
+ page_size,
+ page_buffer_1,
+ page_spare_1
+ );
+ if (done) {
+ goto done;
+ }
+
+ for (page = 2; page < pages_per_block; ++page) {
+ sc = read_page(first_page_of_block, page, page_buffer_1, page_spare_1);
+ if (sc != RTEMS_SUCCESSFUL) {
+ goto done;
+ }
+
+ done = (*process)(
+ process_arg,
+ first_page_of_block + page,
+ page_size,
+ page_buffer_1,
+ page_spare_1
+ );
+ if (done) {
+ goto done;
+ }
+ }
+ }
+
+done:
+
+ return sc;
+}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c
new file mode 100644
index 0000000000..8b9c438602
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc-write-blocks.c
@@ -0,0 +1,166 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_nand_mlc
+ *
+ * @brief lpc32xx_mlc_write_blocks() implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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/nand-mlc.h>
+
+#include <string.h>
+
+#include <bsp.h>
+
+static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = {
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff
+};
+
+static void zero_block(uint32_t first_page_of_block, uint32_t pages_per_block)
+{
+ uint32_t page = 0;
+
+ for (page = 0; page < pages_per_block; ++page) {
+ lpc32xx_mlc_write_page_with_ecc(
+ first_page_of_block + page,
+ lpc32xx_magic_zero_begin,
+ lpc32xx_magic_zero_begin
+ );
+ }
+}
+
+static bool is_bad_page(
+ uint32_t first_page_of_block,
+ uint32_t page
+)
+{
+ uint32_t spare [MLC_LARGE_SPARE_WORD_COUNT];
+
+ memset(spare, 0, MLC_LARGE_SPARE_SIZE);
+ lpc32xx_mlc_read_page(
+ first_page_of_block + page,
+ lpc32xx_magic_zero_begin,
+ spare
+ );
+ return lpc32xx_mlc_is_bad_page(spare);
+}
+
+static rtems_status_code erase_block(
+ uint32_t block,
+ uint32_t first_page_of_block,
+ uint32_t pages_per_block
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (is_bad_page(first_page_of_block, 0)) {
+ return RTEMS_IO_ERROR;
+ }
+
+ if (is_bad_page(first_page_of_block, 1)) {
+ return RTEMS_IO_ERROR;
+ }
+
+ sc = lpc32xx_mlc_erase_block(block);
+ if (sc != RTEMS_SUCCESSFUL) {
+ zero_block(first_page_of_block, pages_per_block);
+
+ return RTEMS_IO_ERROR;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code lpc32xx_mlc_write_blocks(
+ uint32_t block_begin,
+ uint32_t block_end,
+ const void *src,
+ size_t src_size,
+ uint32_t *page_data_buffer
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint32_t pages_per_block = lpc32xx_mlc_pages_per_block();
+ uint32_t block_count = lpc32xx_mlc_block_count();
+ uint32_t page_size = lpc32xx_mlc_page_size();
+ uint32_t block = 0;
+ const uint8_t *current = src;
+ const uint8_t *last = current;
+ const uint8_t *end = current + src_size;
+
+ if (block_begin > block_end || block_end > block_count) {
+ return RTEMS_INVALID_ID;
+ }
+
+ for (block = block_begin; block != block_end; ++block) {
+ uint32_t first_page_of_block = block * pages_per_block;
+ uint32_t page = 0;
+
+ sc = erase_block(block, first_page_of_block, pages_per_block);
+ if (sc != RTEMS_SUCCESSFUL) {
+ continue;
+ }
+
+ for (page = 0; page < pages_per_block; ++page) {
+ uintptr_t remainder = (uintptr_t) end - (uintptr_t) current;
+ size_t delta = remainder < page_size ? remainder : page_size;
+
+ if (remainder > 0) {
+ memcpy(page_data_buffer, current, delta);
+ sc = lpc32xx_mlc_write_page_with_ecc(
+ first_page_of_block + page,
+ page_data_buffer,
+ ones_spare
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ erase_block(block, first_page_of_block, pages_per_block);
+ zero_block(first_page_of_block, pages_per_block);
+ current = last;
+ continue;
+ }
+
+ current += delta;
+ } else {
+ goto done;
+ }
+ }
+
+ last = current;
+ }
+
+done:
+
+ if (current != end) {
+ return RTEMS_IO_ERROR;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc.c b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc.c
new file mode 100644
index 0000000000..16be2c98c2
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/misc/nand-mlc.c
@@ -0,0 +1,322 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_nand_mlc
+ *
+ * @brief NAND MLC controller implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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/lpc32xx.h>
+#include <bsp/nand-mlc.h>
+
+static volatile lpc32xx_nand_mlc *const mlc = &lpc32xx.nand_mlc;
+
+static bool mlc_small_pages;
+
+static bool mlc_many_address_cycles;
+
+static bool mlc_normal_blocks;
+
+static uint32_t mlc_block_count;
+
+static uint32_t mlc_page_count;
+
+uint32_t lpc32xx_mlc_page_size(void)
+{
+ if (mlc_small_pages) {
+ return 512;
+ } else {
+ return 2048;
+ }
+}
+
+uint32_t lpc32xx_mlc_pages_per_block(void)
+{
+ if (mlc_small_pages) {
+ return 32;
+ } else {
+ if (mlc_normal_blocks) {
+ return 64;
+ } else {
+ return 128;
+ }
+ }
+}
+
+uint32_t lpc32xx_mlc_block_count(void)
+{
+ return mlc_block_count;
+}
+
+static void mlc_unlock(void)
+{
+ mlc->lock_pr = MLC_UNLOCK_PROT;
+}
+
+static void mlc_wait(uint32_t flags)
+{
+ while ((mlc->isr & flags) != flags) {
+ /* Wait */
+ }
+}
+
+static void mlc_wait_until_ready(void)
+{
+ mlc_wait(MLC_ISR_CONTROLLER_READY | MLC_ISR_NAND_READY);
+}
+
+static void mlc_reset(void)
+{
+ mlc->cmd = 0xff;
+}
+
+static uint32_t mlc_status(void)
+{
+ mlc_wait_until_ready();
+ mlc->cmd = 0x70;
+
+ return mlc->data.w8;
+}
+
+static bool mlc_was_operation_successful(void)
+{
+ return (mlc_status() & (NAND_STATUS_READY | NAND_STATUS_ERROR))
+ == NAND_STATUS_READY;
+}
+
+static void mlc_set_block_address(uint32_t block_index)
+{
+ if (mlc_small_pages) {
+ mlc->addr = (uint8_t) (block_index << 5);
+ mlc->addr = (uint8_t) (block_index >> 3);
+ if (mlc_many_address_cycles) {
+ mlc->addr = (uint8_t) (block_index >> 11);
+ }
+ } else {
+ if (mlc_normal_blocks) {
+ mlc->addr = (uint8_t) (block_index << 6);
+ mlc->addr = (uint8_t) (block_index >> 2);
+ if (mlc_many_address_cycles) {
+ mlc->addr = (uint8_t) (block_index >> 10);
+ }
+ } else {
+ mlc->addr = (uint8_t) (block_index << 7);
+ mlc->addr = (uint8_t) (block_index >> 1);
+ if (mlc_many_address_cycles) {
+ mlc->addr = (uint8_t) (block_index >> 9);
+ }
+ }
+ }
+}
+
+static void mlc_set_page_address(uint32_t page_index)
+{
+ mlc->addr = 0;
+ if (mlc_small_pages) {
+ mlc->addr = (uint8_t) page_index;
+ mlc->addr = (uint8_t) (page_index >> 8);
+ if (mlc_many_address_cycles) {
+ mlc->addr = (uint8_t) (page_index >> 16);
+ }
+ } else {
+ mlc->addr = 0;
+ mlc->addr = (uint8_t) page_index;
+ mlc->addr = (uint8_t) (page_index >> 8);
+ if (mlc_many_address_cycles) {
+ mlc->addr = (uint8_t) (page_index >> 16);
+ }
+ }
+}
+
+void lpc32xx_mlc_init(const lpc32xx_mlc_config *cfg)
+{
+ uint32_t icr = 0;
+
+ mlc_small_pages = cfg->small_pages;
+ mlc_many_address_cycles = cfg->many_address_cycles;
+ mlc_normal_blocks = cfg->normal_blocks;
+ mlc_block_count = cfg->block_count;
+ mlc_page_count = cfg->block_count * lpc32xx_mlc_pages_per_block();
+
+ /* Clock */
+ LPC32XX_FLASHCLK_CTRL = FLASHCLK_IRQ_MLC | FLASHCLK_MLC_CLK_ENABLE;
+
+ /* Timing settings */
+ mlc_unlock();
+ mlc->time = cfg->time;
+
+ /* Configuration */
+ if (!mlc_small_pages) {
+ icr |= MLC_ICR_LARGE_PAGES;
+ }
+ if (mlc_many_address_cycles) {
+ icr |= MLC_ICR_ADDR_WORD_COUNT_4_5;
+ }
+ mlc_unlock();
+ mlc->icr = icr;
+
+ mlc_reset();
+}
+
+void lpc32xx_mlc_write_protection(
+ uint32_t page_index_low,
+ uint32_t page_index_high
+)
+{
+ mlc_unlock();
+ mlc->sw_wp_add_low = page_index_low;
+ mlc_unlock();
+ mlc->sw_wp_add_hig = page_index_high;
+ mlc_unlock();
+ mlc->icr |= MLC_ICR_SOFT_WRITE_PROT;
+}
+
+rtems_status_code lpc32xx_mlc_read_page(
+ uint32_t page_index,
+ uint32_t *data,
+ uint32_t *spare
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ size_t small_pages_count = mlc_small_pages ? 1 : MLC_SMALL_PAGES_PER_LARGE_PAGE;
+ size_t sp = 0;
+ size_t i = 0;
+ uint32_t isr = 0;
+
+ if (page_index >= mlc_page_count) {
+ return RTEMS_INVALID_ID;
+ }
+
+ mlc_wait_until_ready();
+ mlc->cmd = 0x00;
+ if (!mlc_small_pages) {
+ mlc->cmd = 0x30;
+ }
+ mlc_set_page_address(page_index);
+ mlc_wait(MLC_ISR_NAND_READY);
+
+ for (sp = 0; sc == RTEMS_SUCCESSFUL && sp < small_pages_count; ++sp) {
+ mlc->ecc_dec = 0;
+
+ for (i = 0; i < MLC_SMALL_DATA_WORD_COUNT; ++i) {
+ data [i] = mlc->data.w32;
+ }
+ for (i = 0; i < MLC_SMALL_SPARE_WORD_COUNT; ++i) {
+ spare [i] = mlc->data.w32;
+ }
+
+ mlc_wait(MLC_ISR_ECC_READY);
+
+ isr = mlc->isr;
+ if ((isr & MLC_ISR_ERRORS_DETECTED) != 0) {
+ if ((isr & MLC_ISR_DECODER_FAILURE) == 0) {
+ mlc->rubp = 0;
+ for (i = 0; i < MLC_SMALL_DATA_WORD_COUNT; ++i) {
+ data [i] = mlc->buff.w32;
+ }
+ mlc->robp = 0;
+ for (i = 0; i < MLC_SMALL_SPARE_WORD_COUNT; ++i) {
+ spare [i] = mlc->buff.w32;
+ }
+ } else {
+ sc = RTEMS_IO_ERROR;
+ }
+ }
+
+ data += MLC_SMALL_DATA_WORD_COUNT;
+ spare += MLC_SMALL_SPARE_WORD_COUNT;
+ }
+
+ return sc;
+}
+
+void lpc32xx_mlc_read_id(uint8_t *id, size_t n)
+{
+ size_t i = 0;
+
+ mlc_wait_until_ready();
+ mlc->cmd = 0x90;
+ mlc->addr = 0;
+ mlc_wait(MLC_ISR_NAND_READY);
+
+ for (i = 0; i < n; ++i) {
+ id [i] = mlc->data.w8;
+ }
+}
+
+rtems_status_code lpc32xx_mlc_erase_block(uint32_t block_index)
+{
+ rtems_status_code sc = RTEMS_IO_ERROR;
+
+ if (block_index >= mlc_block_count) {
+ return RTEMS_INVALID_ID;
+ }
+
+ mlc_wait_until_ready();
+ mlc->cmd = 0x60;
+ mlc_set_block_address(block_index);
+ mlc->cmd = 0xd0;
+
+ if (mlc_was_operation_successful()) {
+ sc = RTEMS_SUCCESSFUL;
+ }
+
+ return sc;
+}
+
+rtems_status_code lpc32xx_mlc_write_page_with_ecc(
+ uint32_t page_index,
+ const uint32_t *data,
+ const uint32_t *spare
+)
+{
+ rtems_status_code sc = RTEMS_IO_ERROR;
+ size_t small_pages_count = mlc_small_pages ? 1 : MLC_SMALL_PAGES_PER_LARGE_PAGE;
+ size_t sp = 0;
+ size_t i = 0;
+
+ if (page_index >= mlc_page_count) {
+ return RTEMS_INVALID_ID;
+ }
+
+ mlc_wait_until_ready();
+ mlc->cmd = 0x80;
+ mlc_set_page_address(page_index);
+
+ for (sp = 0; sp < small_pages_count; ++sp) {
+ mlc->ecc_enc = 0;
+
+ for (i = 0; i < MLC_SMALL_DATA_WORD_COUNT; ++i) {
+ mlc->data.w32 = data [i];
+ }
+ mlc->data.w32 = spare [0];
+ mlc->data.w16 = (uint16_t) spare [1];
+ mlc->wpr = 0;
+
+ mlc_wait(MLC_ISR_CONTROLLER_READY);
+
+ data += MLC_SMALL_DATA_WORD_COUNT;
+ spare += MLC_SMALL_SPARE_WORD_COUNT;
+ }
+
+ mlc->cmd = 0x10;
+
+ if (mlc_was_operation_successful()) {
+ sc = RTEMS_SUCCESSFUL;
+ }
+
+ return sc;
+}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/misc/restart.c b/c/src/lib/libbsp/arm/lpc32xx/misc/restart.c
new file mode 100644
index 0000000000..b286390237
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/misc/restart.c
@@ -0,0 +1,56 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief Restart implementation.
+ */
+
+/*
+ * Copyright (c) 2010
+ * 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 <libcpu/arm-cp15.h>
+
+#include <bsp.h>
+
+void lpc32xx_restart(void *addr)
+{
+ ARM_SWITCH_REGISTERS;
+ rtems_interrupt_level level;
+ uint32_t ctrl = 0;
+
+ /* FIXME: DMA shutdown */
+
+ /* FIXME: USB shutdown */
+
+ /* FIXME: Ethernet interface reset */
+
+ rtems_interrupt_disable(level);
+
+ arm_cp15_data_cache_test_and_clean();
+ arm_cp15_instruction_cache_invalidate();
+
+ ctrl = arm_cp15_get_control();
+ ctrl &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M);
+ arm_cp15_set_control(ctrl);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mov pc, %[addr]\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [addr] "r" (addr)
+ );
+}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
index b9eb42f3b8..dc275461f8 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
@@ -122,6 +122,22 @@ $(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h: include/lpc-ethernet-config.h $(PR
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h
+$(PROJECT_INCLUDE)/bsp/nand-mlc.h: include/nand-mlc.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/nand-mlc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/nand-mlc.h
+
+$(PROJECT_INCLUDE)/bsp/boot.h: include/boot.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/boot.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/boot.h
+
+$(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h
+
+$(PROJECT_INCLUDE)/bsp/emc.h: include/emc.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/emc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/emc.h
+
$(PROJECT_INCLUDE)/libcpu/cache.h: ../../../libcpu/arm/shared/include/cache.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/cache.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/cache.h
@@ -138,6 +154,10 @@ $(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds
TMPINSTALL_FILES += $(PROJECT_LIB)/linkcmds
+$(PROJECT_LIB)/linkcmds.lpc32xx: startup/linkcmds.lpc32xx $(PROJECT_LIB)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.lpc32xx
+TMPINSTALL_FILES += $(PROJECT_LIB)/linkcmds.lpc32xx
+
$(PROJECT_LIB)/linkcmds.base: ../shared/startup/linkcmds.base $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base
TMPINSTALL_FILES += $(PROJECT_LIB)/linkcmds.base
diff --git a/c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c b/c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c
index b518db3c1f..014392f8d6 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c
@@ -38,28 +38,14 @@
#define LPC32XX_RTC_CTRL_MATCH_1_INTR (1U << 1)
#define LPC32XX_RTC_CTRL_MATCH_0_INTR (1U << 0)
-typedef struct {
- uint32_t ucount;
- uint32_t dcount;
- uint32_t match0;
- uint32_t match1;
- uint32_t ctrl;
- uint32_t intstat;
- uint32_t key;
- uint32_t sram [32];
-} lpc32xx_rtc_registers;
-
-static volatile lpc32xx_rtc_registers *const lpc32xx_rtc =
- (volatile lpc32xx_rtc_registers *) LPC32XX_BASE_RTC;
-
static void lpc32xx_rtc_set(uint32_t val)
{
unsigned i = LPC32XX_ARM_CLK / LPC32XX_OSCILLATOR_RTC;
- lpc32xx_rtc->ctrl |= LPC32XX_RTC_CTRL_STOP;
- lpc32xx_rtc->ucount = val;
- lpc32xx_rtc->dcount = LPC32XX_RTC_COUNTER_DELTA - val;
- lpc32xx_rtc->ctrl &= ~LPC32XX_RTC_CTRL_STOP;
+ lpc32xx.rtc.ctrl |= LPC32XX_RTC_CTRL_STOP;
+ lpc32xx.rtc.ucount = val;
+ lpc32xx.rtc.dcount = LPC32XX_RTC_COUNTER_DELTA - val;
+ lpc32xx.rtc.ctrl &= ~LPC32XX_RTC_CTRL_STOP;
/* It needs some time before we can read the values back */
while (i != 0) {
@@ -70,9 +56,9 @@ static void lpc32xx_rtc_set(uint32_t val)
static void lpc32xx_rtc_reset(void)
{
- lpc32xx_rtc->ctrl = LPC32XX_RTC_CTRL_RESET;
- lpc32xx_rtc->ctrl = 0;
- lpc32xx_rtc->key = LPC32XX_RTC_KEY;
+ lpc32xx.rtc.ctrl = LPC32XX_RTC_CTRL_RESET;
+ lpc32xx.rtc.ctrl = 0;
+ lpc32xx.rtc.key = LPC32XX_RTC_KEY;
lpc32xx_rtc_set(0);
}
@@ -83,15 +69,15 @@ static void lpc32xx_rtc_initialize(int minor)
uint32_t down_first = 0;
uint32_t down_second = 0;
- if (lpc32xx_rtc->key != LPC32XX_RTC_KEY) {
+ if (lpc32xx.rtc.key != LPC32XX_RTC_KEY) {
lpc32xx_rtc_reset();
}
do {
- up_first = lpc32xx_rtc->ucount;
- down_first = lpc32xx_rtc->dcount;
- up_second = lpc32xx_rtc->ucount;
- down_second = lpc32xx_rtc->dcount;
+ up_first = lpc32xx.rtc.ucount;
+ down_first = lpc32xx.rtc.dcount;
+ up_second = lpc32xx.rtc.ucount;
+ down_second = lpc32xx.rtc.dcount;
} while (up_first != up_second || down_first != down_second);
if (up_first + down_first != LPC32XX_RTC_COUNTER_DELTA) {
@@ -102,7 +88,7 @@ static void lpc32xx_rtc_initialize(int minor)
static int lpc32xx_rtc_get_time(int minor, rtems_time_of_day *tod)
{
struct timeval now = {
- .tv_sec = lpc32xx_rtc->ucount,
+ .tv_sec = lpc32xx.rtc.ucount,
.tv_usec = 0
};
struct tm time;
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/bspstart.c b/c/src/lib/libbsp/arm/lpc32xx/startup/bspstart.c
index c8f0a728ba..c685e27146 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/startup/bspstart.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/bspstart.c
@@ -27,21 +27,6 @@
#include <bsp/stackalloc.h>
#include <bsp/lpc32xx.h>
-static void lpc32xx_timer_initialize(void)
-{
- volatile lpc_timer *timer = LPC32XX_STANDARD_TIMER;
-
- LPC32XX_TIMCLK_CTRL1 = (1U << 2) | (1U << 3);
-
- timer->tcr = LPC_TIMER_TCR_RST;
- timer->ctcr = 0x0;
- timer->pr = 0x0;
- timer->ir = 0xff;
- timer->mcr = 0x0;
- timer->ccr = 0x0;
- timer->tcr = LPC_TIMER_TCR_EN;
-}
-
void bsp_start(void)
{
if (bsp_interrupt_initialize() != RTEMS_SUCCESSFUL) {
@@ -52,6 +37,4 @@ void bsp_start(void)
bsp_section_stack_begin,
(uintptr_t) bsp_section_stack_size
);
-
- lpc32xx_timer_initialize();
}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c b/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c
index cbe26e7866..41815ac6f8 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c
@@ -42,7 +42,9 @@
#define LPC32XX_MMU_CODE LPC32XX_MMU_READ_ONLY_CACHED
#endif
-static void BSP_START_SECTION lpc32xx_clear_bss(void)
+LINKER_SYMBOL(lpc32xx_translation_table_base);
+
+static void BSP_START_SECTION clear_bss(void)
{
const int *end = (const int *) bsp_section_bss_end;
int *out = (int *) bsp_section_bss_begin;
@@ -115,10 +117,14 @@ static void BSP_START_SECTION lpc32xx_clear_bss(void)
.begin = 0x40000000U,
.end = 0x40100000U,
.flags = LPC32XX_MMU_READ_WRITE
+ }, {
+ .begin = (uint32_t) lpc32xx_magic_zero_begin,
+ .end = (uint32_t) lpc32xx_magic_zero_end,
+ .flags = LPC32XX_MMU_READ_WRITE_DATA
}
};
- static void BSP_START_SECTION lpc32xx_mmu_set_entries(
+ static void BSP_START_SECTION set_translation_table_entries(
uint32_t *ttb,
const lpc32xx_mmu_config *config
)
@@ -136,11 +142,11 @@ static void BSP_START_SECTION lpc32xx_clear_bss(void)
}
static void BSP_START_SECTION
- lpc32xx_setup_translation_table_and_enable_mmu(uint32_t ctrl)
+ setup_translation_table_and_enable_mmu(uint32_t ctrl)
{
uint32_t const dac =
ARM_CP15_DAC_DOMAIN(LPC32XX_MMU_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT);
- uint32_t *const ttb = (uint32_t *) bsp_section_work_end;
+ uint32_t *const ttb = (uint32_t *) lpc32xx_translation_table_base;
size_t const config_entry_count =
sizeof(lpc32xx_mmu_config_table) / sizeof(lpc32xx_mmu_config_table [0]);
size_t i = 0;
@@ -154,7 +160,7 @@ static void BSP_START_SECTION lpc32xx_clear_bss(void)
}
for (i = 0; i < config_entry_count; ++i) {
- lpc32xx_mmu_set_entries(ttb, &lpc32xx_mmu_config_table [i]);
+ set_translation_table_entries(ttb, &lpc32xx_mmu_config_table [i]);
}
/* Enable MMU and cache */
@@ -163,7 +169,7 @@ static void BSP_START_SECTION lpc32xx_clear_bss(void)
}
#endif
-static void BSP_START_SECTION lpc32xx_mmu_and_cache_setup(void)
+static void BSP_START_SECTION setup_mmu_and_cache(void)
{
uint32_t ctrl = 0;
@@ -178,7 +184,7 @@ static void BSP_START_SECTION lpc32xx_mmu_and_cache_setup(void)
arm_cp15_tlb_invalidate();
#ifndef LPC32XX_DISABLE_MMU
- lpc32xx_setup_translation_table_and_enable_mmu(ctrl);
+ setup_translation_table_and_enable_mmu(ctrl);
#endif
}
@@ -186,7 +192,7 @@ static void BSP_START_SECTION lpc32xx_mmu_and_cache_setup(void)
#error "unexpected main oscillator frequency"
#endif
-static void BSP_START_SECTION lpc32xx_pll_setup(void)
+static void BSP_START_SECTION setup_pll(void)
{
uint32_t pwr_ctrl = LPC32XX_PWR_CTRL;
@@ -207,11 +213,11 @@ static void BSP_START_SECTION lpc32xx_pll_setup(void)
void BSP_START_SECTION bsp_start_hook_0(void)
{
- lpc32xx_pll_setup();
- lpc32xx_mmu_and_cache_setup();
+ setup_pll();
+ setup_mmu_and_cache();
}
-static void BSP_START_SECTION bsp_start_config_uarts(void)
+static void BSP_START_SECTION setup_uarts(void)
{
uint32_t uartclk_ctrl = 0;
@@ -246,9 +252,25 @@ static void BSP_START_SECTION bsp_start_config_uarts(void)
#endif
}
+static void BSP_START_SECTION setup_timer(void)
+{
+ volatile lpc_timer *timer = LPC32XX_STANDARD_TIMER;
+
+ LPC32XX_TIMCLK_CTRL1 = (1U << 2) | (1U << 3);
+
+ timer->tcr = LPC_TIMER_TCR_RST;
+ timer->ctcr = 0x0;
+ timer->pr = 0x0;
+ timer->ir = 0xff;
+ timer->mcr = 0x0;
+ timer->ccr = 0x0;
+ timer->tcr = LPC_TIMER_TCR_EN;
+}
+
void BSP_START_SECTION bsp_start_hook_1(void)
{
- bsp_start_config_uarts();
+ setup_uarts();
+ setup_timer();
/* Copy .text section */
arm_cp15_instruction_cache_invalidate();
@@ -283,7 +305,7 @@ void BSP_START_SECTION bsp_start_hook_1(void)
);
/* Clear .bss section */
- lpc32xx_clear_bss();
+ clear_bss();
/* At this point we can use objects outside the .start section */
}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx
new file mode 100644
index 0000000000..278a23ec5b
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx
@@ -0,0 +1,17 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_linker
+ *
+ * @brief Linker support.
+ */
+
+lpc32xx_translation_table_base = ORIGIN (RAM_MMU);
+
+lpc32xx = 0x20020000;
+
+lpc32xx_magic_zero_begin = 0x05000000;
+lpc32xx_magic_zero_end = 0x07000000;
+lpc32xx_magic_zero_size = lpc32xx_magic_zero_end - lpc32xx_magic_zero_end;
+
+INCLUDE linkcmds.base
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx
new file mode 100644
index 0000000000..cd42c4537b
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx
@@ -0,0 +1,63 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_linker_mzx
+ *
+ * @brief Memory map.
+ */
+
+/**
+ * @defgroup lpc32xx_linker_mzx MZX Application Memory Map
+ *
+ * @ingroup bsp_linker
+ *
+ * @brief MZX application memory map.
+ *
+ * <table>
+ * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr>
+ * <tr><td>RAM_INT</td><td>0x08000000</td><td>256k</td></tr>
+ * <tr><td>RAM_MMU</td><td>0x80000000</td><td>16k</td></tr>
+ * <tr><td>RAM_EXT</td><td>0x80004000</td><td>32M - 16k</td></tr>
+ * </table>
+ *
+ * <table>
+ * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr>
+ * <tr><td>.start</td><td>RAM_EXT</td><td></td></tr>
+ * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr>
+ * <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.fast</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr>
+ * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr>
+ * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr>
+ * </table>
+ */
+
+MEMORY {
+ RAM_INT (AIW) : ORIGIN = 0x08000000, LENGTH = 256k
+ RAM_MMU (AIW) : ORIGIN = 0x80000000, LENGTH = 16k /* SDRAM on DYCS0 */
+ RAM_EXT (AIW) : ORIGIN = 0x80004000, LENGTH = 32M - 16k /* SDRAM on DYCS0 */
+ NIRVANA : ORIGIN = 0, LENGTH = 0
+}
+
+REGION_ALIAS ("REGION_START", RAM_EXT);
+REGION_ALIAS ("REGION_VECTOR", RAM_INT);
+REGION_ALIAS ("REGION_TEXT", RAM_EXT);
+REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_RODATA", RAM_EXT);
+REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_DATA", RAM_EXT);
+REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_FAST", RAM_EXT);
+REGION_ALIAS ("REGION_FAST_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_BSS", RAM_EXT);
+REGION_ALIAS ("REGION_WORK", RAM_EXT);
+REGION_ALIAS ("REGION_STACK", RAM_INT);
+
+bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096;
+bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024;
+
+bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1M;
+
+INCLUDE linkcmds.lpc32xx
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_boot_int b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_stage_1
index 54aef5364c..0954f0b588 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_boot_int
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_stage_1
@@ -1,21 +1,23 @@
/**
* @file
*
- * @ingroup lpc32xx_linker_boot
+ * @ingroup lpc32xx_linker_mzx_stage_1
*
* @brief Memory map.
*/
/**
- * @defgroup lpc32xx_linker_boot Boot Memory Map
+ * @defgroup lpc32xx_linker_mzx_stage_1 MZX Stage-1 Program Memory Map
*
* @ingroup bsp_linker
*
- * @brief Boot memory map.
+ * @brief MZX stage-1 program memory map.
*
* <table>
* <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr>
- * <tr><td>RAM_INT</td><td>0x08000000</td><td>256k</td></tr>
+ * <tr><td>RAM_INT</td><td>0x08000000</td><td>232k</td></tr>
+ * <tr><td>RAM_MMU</td><td>0x0803a000</td><td>16k</td></tr>
+ * <tr><td>RAM_VEC</td><td>0x0803d000</td><td>8k</td></tr>
* </table>
*
* <table>
@@ -33,12 +35,14 @@
*/
MEMORY {
- RAM_INT (AIW) : ORIGIN = 0x08000000, LENGTH = 256k
+ RAM_INT (AIW) : ORIGIN = 0x08000000, LENGTH = 232k
+ RAM_VEC (AIW) : ORIGIN = 0x0803a000, LENGTH = 8k
+ RAM_MMU (AIW) : ORIGIN = 0x0803c000, LENGTH = 16k
NIRVANA : ORIGIN = 0, LENGTH = 0
}
REGION_ALIAS ("REGION_START", RAM_INT);
-REGION_ALIAS ("REGION_VECTOR", RAM_INT);
+REGION_ALIAS ("REGION_VECTOR", RAM_VEC);
REGION_ALIAS ("REGION_TEXT", RAM_INT);
REGION_ALIAS ("REGION_TEXT_LOAD", RAM_INT);
REGION_ALIAS ("REGION_RODATA", RAM_INT);
@@ -51,7 +55,8 @@ REGION_ALIAS ("REGION_BSS", RAM_INT);
REGION_ALIAS ("REGION_WORK", RAM_INT);
REGION_ALIAS ("REGION_STACK", RAM_INT);
-bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096;
-bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024;
+bsp_stack_svc_size = DEFINED (bsp_stack_svc_size) ? bsp_stack_svc_size : 7296;
-INCLUDE linkcmds.base
+bsp_vector_table_in_start_section = 1;
+
+INCLUDE linkcmds.lpc32xx
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_stage_2 b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_stage_2
new file mode 100644
index 0000000000..dc64394982
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_mzx_stage_2
@@ -0,0 +1,60 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_linker_mzx_stage_2
+ *
+ * @brief Memory map.
+ */
+
+/**
+ * @defgroup lpc32xx_linker_mzx_stage_2 MZX Stage-2 Program Memory Map
+ *
+ * @ingroup bsp_linker
+ *
+ * @brief MZX stage-2 program memory map.
+ *
+ * <table>
+ * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr>
+ * <tr><td>RAM_INT</td><td>0x08000000</td><td>256k</td></tr>
+ * <tr><td>RAM_MMU</td><td>0x81c00000</td><td>16k</td></tr>
+ * <tr><td>RAM_EXT</td><td>0x81c04000</td><td>4M - 16k</td></tr>
+ * </table>
+ *
+ * <table>
+ * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr>
+ * <tr><td>.start</td><td>RAM_EXT</td><td></td></tr>
+ * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr>
+ * <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.fast</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr>
+ * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr>
+ * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr>
+ * </table>
+ */
+
+MEMORY {
+ RAM_INT (AIW) : ORIGIN = 0x08000000, LENGTH = 256k
+ RAM_MMU (AIW) : ORIGIN = 0x81c00000, LENGTH = 16k /* SDRAM on DYCS0 */
+ RAM_EXT (AIW) : ORIGIN = 0x81c04000, LENGTH = 4M - 16k /* SDRAM on DYCS0 */
+ NIRVANA : ORIGIN = 0, LENGTH = 0
+}
+
+REGION_ALIAS ("REGION_START", RAM_EXT);
+REGION_ALIAS ("REGION_VECTOR", RAM_INT);
+REGION_ALIAS ("REGION_TEXT", RAM_EXT);
+REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_RODATA", RAM_EXT);
+REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_DATA", RAM_EXT);
+REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_FAST", RAM_EXT);
+REGION_ALIAS ("REGION_FAST_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_BSS", RAM_EXT);
+REGION_ALIAS ("REGION_WORK", RAM_EXT);
+REGION_ALIAS ("REGION_STACK", RAM_INT);
+
+bsp_stack_svc_size = DEFINED (bsp_stack_svc_size) ? bsp_stack_svc_size : 8192;
+
+INCLUDE linkcmds.lpc32xx
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore
index 2c2743caf0..6db6497b44 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore
@@ -16,7 +16,8 @@
* <table>
* <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr>
* <tr><td>RAM_INT</td><td>0x08000000</td><td>256k</td></tr>
- * <tr><td>RAM_EXT</td><td>0x80000000</td><td>64M</td></tr>
+ * <tr><td>RAM_MMU</td><td>0x80000000</td><td>16k</td></tr>
+ * <tr><td>RAM_EXT</td><td>0x80004000</td><td>64M - 16k</td></tr>
* <tr><td>ROM_EXT</td><td>0xe0000000</td><td>2M</td></tr>
* </table>
*
@@ -36,7 +37,8 @@
MEMORY {
RAM_INT (AIW) : ORIGIN = 0x08000000, LENGTH = 256k
- RAM_EXT (AIW) : ORIGIN = 0x80000000, LENGTH = 64M - 16k /* SDRAM on DYCS0 */
+ RAM_MMU (AIW) : ORIGIN = 0x80000000, LENGTH = 16k /* SDRAM on DYCS0 */
+ RAM_EXT (AIW) : ORIGIN = 0x80004000, LENGTH = 64M - 16k /* SDRAM on DYCS0 */
ROM_EXT (RX) : ORIGIN = 0xe0000000, LENGTH = 2M /* NOR flash on CS0 */
NIRVANA : ORIGIN = 0, LENGTH = 0
}
@@ -60,4 +62,4 @@ bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024;
bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1M;
-INCLUDE linkcmds.base
+INCLUDE linkcmds.lpc32xx