diff options
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 |