* 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.
This commit is contained in:
Sebastian Huber
2010-06-23 08:27:57 +00:00
parent b18fd861ba
commit 3103d4cbad
29 changed files with 2723 additions and 161 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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])

View File

@@ -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 */

View File

@@ -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 [];
/** @} */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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);

View File

@@ -1,5 +1,5 @@
#
# Config file for boot loader.
# Config file for MZX application.
#
# $Id$
#

View File

@@ -0,0 +1,7 @@
#
# Config file for MZX stage-1 program.
#
# $Id$
#
include $(RTEMS_ROOT)/make/custom/lpc32xx.inc

View File

@@ -0,0 +1,7 @@
#
# Config file for MZX stage-2 program.
#
# $Id$
#
include $(RTEMS_ROOT)/make/custom/lpc32xx.inc

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)
);
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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 */
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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