summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-12 15:03:22 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-12 15:03:22 +0000
commit39c8fdb416327c5ec0c23807ae701798a5739cdf (patch)
tree0f2bb4acb60e60d74b7ef08e345a21d7896aba20
parent2010-01-11 Marc Pignat <marc.pignat@hevs.ch> (diff)
downloadrtems-39c8fdb416327c5ec0c23807ae701798a5739cdf.tar.bz2
add support for lpc32xx
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/ChangeLog7
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/Makefile.am22
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/configure.ac2
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/include/bsp.h4
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h82
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/include/lpc24xx.h230
-rw-r--r--c/src/lib/libbsp/arm/lpc24xx/preinstall.am13
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/ChangeLog8
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/Makefile.am31
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/configure.ac3
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/bsp.h4
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/bspopts.h.in3
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/irq.h2
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h81
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h1
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/irq/irq.c53
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/preinstall.am27
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c114
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c124
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore5
-rw-r--r--c/src/lib/libbsp/arm/shared/abort/abort.c14
-rw-r--r--c/src/lib/libbsp/arm/shared/abort/simple_abort.c12
-rw-r--r--c/src/lib/libbsp/arm/shared/include/linker-symbols.h6
-rw-r--r--c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c1400
-rw-r--r--c/src/lib/libbsp/arm/shared/start/start.S54
-rw-r--r--c/src/lib/libbsp/arm/shared/startup/linkcmds.base52
-rw-r--r--c/src/lib/libcpu/arm/ChangeLog7
-rw-r--r--c/src/lib/libcpu/arm/Makefile.am1
-rw-r--r--c/src/lib/libcpu/arm/preinstall.am4
-rw-r--r--c/src/lib/libcpu/arm/shared/arm920/mmu.c146
-rw-r--r--c/src/lib/libcpu/arm/shared/include/arm-cp15.h644
-rw-r--r--c/src/lib/libcpu/arm/shared/include/cache.h132
-rw-r--r--c/src/lib/libcpu/arm/shared/include/cache_.h27
-rw-r--r--cpukit/score/cpu/arm/ChangeLog9
-rw-r--r--cpukit/score/cpu/arm/Makefile.am1
-rw-r--r--cpukit/score/cpu/arm/arm_exc_abort.S123
-rw-r--r--cpukit/score/cpu/arm/arm_exc_interrupt.S20
-rw-r--r--cpukit/score/cpu/arm/cpu.c28
-rw-r--r--cpukit/score/cpu/arm/rtems/asm.h16
-rw-r--r--cpukit/score/cpu/arm/rtems/score/cpu.h169
40 files changed, 3098 insertions, 583 deletions
diff --git a/c/src/lib/libbsp/arm/lpc24xx/ChangeLog b/c/src/lib/libbsp/arm/lpc24xx/ChangeLog
index 399ebbb5e2..20d74c7726 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/ChangeLog
+++ b/c/src/lib/libbsp/arm/lpc24xx/ChangeLog
@@ -1,3 +1,10 @@
+2010-01-12 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * include/lpc-ethernet-config.h: New file.
+ * network/network.c: Removed file.
+ * Makefile.am, configure.ac, preinstall.am, include/bsp.h,
+ include/lpc24xx.h: Changes throughout.
+
2009-12-15 Sebastian Huber <sebastian.huber@embedded-brains.de>
* clock/clock-config.c: Removed file.
diff --git a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
index 765c2c1223..1ea711b82d 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
@@ -12,6 +12,7 @@ ACLOCAL_AMFLAGS = -I ../../../../aclocal
include $(top_srcdir)/../../../../automake/compile.am
include_bspdir = $(includedir)/bsp
+include_libcpudir = $(includedir)/libcpu
dist_project_lib_DATA = bsp_specs
@@ -44,9 +45,12 @@ include_bsp_HEADERS += include/dma.h
include_bsp_HEADERS += include/i2c.h
include_bsp_HEADERS += include/io.h
include_bsp_HEADERS += include/lpc-clock-config.h
+include_bsp_HEADERS += include/lpc-ethernet-config.h
include_HEADERS += ../../shared/include/tm27.h
+include_libcpu_HEADERS = ../../../libcpu/arm/shared/include/cache.h
+
###############################################################################
# Data #
###############################################################################
@@ -72,6 +76,8 @@ EXTRA_DIST += startup/linkcmds.lpc2362
noinst_LIBRARIES += libbsp.a
libbsp_a_SOURCES =
+libbsp_a_CPPFLAGS =
+libbsp_a_LIBADD =
# Shared
libbsp_a_SOURCES += ../../shared/bootcard.c \
@@ -124,12 +130,18 @@ libbsp_a_SOURCES += ssp/ssp.c
# I2C
libbsp_a_SOURCES += i2c/i2c.c
+# Cache
+libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c \
+ ../../../libcpu/arm/shared/cache/cache_.h
+libbsp_a_CPPFLAGS += -I$(srcdir)/../../../libcpu/arm/shared/include
+
# Start hooks (FIXME: This is brittle.)
libbsp_a_SOURCES += startup/bspstarthooks.c
-bspstarthooks.o: startup/bspstarthooks.c
- $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS:-mthumb=) \
- -MT bspstarthooks.o -MD -MP -MF $(DEPDIR)/bspstarthooks.Tpo -c -o bspstarthooks.o \
+libbsp_a-bspstarthooks.o: startup/bspstarthooks.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbsp_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS:-mthumb=) \
+ -MT libbsp_a-bspstarthooks.o -MD -MP -MF $(DEPDIR)/libbsp_a-bspstarthooks.Tpo -c -o libbsp_a-bspstarthooks.o \
`test -f 'startup/bspstarthooks.c' || echo '$(srcdir)/'`startup/bspstarthooks.c
+ $(am__mv) $(DEPDIR)/libbsp_a-bspstarthooks.Tpo $(DEPDIR)/libbsp_a-bspstarthooks.Po
###############################################################################
# Network #
@@ -139,11 +151,11 @@ if HAS_NETWORKING
noinst_PROGRAMS = network.rel
-network_rel_SOURCES = network/network.c
+network_rel_SOURCES = ../shared/lpc/network/lpc-ethernet.c
network_rel_CPPFLAGS = $(AM_CPPFLAGS) -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
-libbsp_a_LIBADD = network.rel
+libbsp_a_LIBADD += network.rel
endif
diff --git a/c/src/lib/libbsp/arm/lpc24xx/configure.ac b/c/src/lib/libbsp/arm/lpc24xx/configure.ac
index e5724d7238..8a1f5daf4a 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/configure.ac
+++ b/c/src/lib/libbsp/arm/lpc24xx/configure.ac
@@ -33,7 +33,7 @@ RTEMS_BSPOPTS_HELP([LPC24XX_CCLK],[CPU clock in Hz])
RTEMS_BSPOPTS_SET([LPC24XX_UART_BAUD],[*],[115200U])
RTEMS_BSPOPTS_HELP([LPC24XX_UART_BAUD],[baud for UARTs])
-RTEMS_BSPOPTS_SET([LPC24XX_ETHERNET_RMII],[lpc24xx_ncs_*],[1])
+RTEMS_BSPOPTS_SET([LPC24XX_ETHERNET_RMII],[*],[])
RTEMS_BSPOPTS_HELP([LPC24XX_ETHERNET_RMII],[enable RMII for Ethernet])
RTEMS_BSPOPTS_SET([LPC24XX_EMC_MICRON],[lpc24xx_ncs_rom_*],[1])
diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
index a982305c95..9ab0ad629e 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
+++ b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
@@ -50,7 +50,7 @@ struct rtems_bsdnet_ifconfig;
/**
* @brief Network driver attach and detach function.
*/
-int lpc24xx_eth_attach_detach(
+int lpc_eth_attach_detach(
struct rtems_bsdnet_ifconfig *config,
int attaching
);
@@ -58,7 +58,7 @@ int lpc24xx_eth_attach_detach(
/**
* @brief Standard network driver attach and detach function.
*/
-#define RTEMS_BSP_NETWORK_DRIVER_ATTACH lpc24xx_eth_attach_detach
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH lpc_eth_attach_detach
/**
* @brief Standard network driver name.
diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h b/c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h
new file mode 100644
index 0000000000..0bba1266e1
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h
@@ -0,0 +1,82 @@
+/**
+ * @file
+ *
+ * @ingroup lpc24xx
+ *
+ * @brief Ethernet driver configuration.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC24XX_LPC_ETHERNET_CONFIG_H
+#define LIBBSP_ARM_LPC24XX_LPC_ETHERNET_CONFIG_H
+
+#include <bsp.h>
+#include <bsp/io.h>
+#include <bsp/lpc24xx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define LPC_ETH_CONFIG_INTERRUPT LPC24XX_IRQ_ETHERNET
+
+#define LPC_ETH_CONFIG_REG_BASE MAC_BASE_ADDR
+
+#define LPC_ETH_CONFIG_RX_UNIT_COUNT_DEFAULT 16
+#define LPC_ETH_CONFIG_RX_UNIT_COUNT_MAX 54
+
+#define LPC_ETH_CONFIG_TX_UNIT_COUNT_DEFAULT 10
+#define LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX 10
+
+#define LPC_ETH_CONFIG_UNIT_MULTIPLE 1U
+
+#ifdef LPC24XX_ETHERNET_RMII
+ #define LPC_ETH_CONFIG_RMII
+
+ static void lpc_eth_config_module_enable(void)
+ {
+ lpc24xx_module_enable(LPC24XX_MODULE_ETHERNET, LPC24XX_MODULE_PCLK_DEFAULT);
+ lpc24xx_io_config(LPC24XX_MODULE_ETHERNET, 0);
+ }
+#else
+ static void lpc_eth_config_module_enable(void)
+ {
+ lpc24xx_module_enable(LPC24XX_MODULE_ETHERNET, LPC24XX_MODULE_PCLK_DEFAULT);
+ lpc24xx_io_config(LPC24XX_MODULE_ETHERNET, 1);
+ }
+#endif
+
+#define LPC24XX_ETH_RAM_BEGIN 0x7fe00000U
+#define LPC24XX_ETH_RAM_SIZE (16U * 1024U)
+
+static char *lpc_eth_config_alloc_table_area(size_t size)
+{
+ if (size < LPC24XX_ETH_RAM_SIZE) {
+ return (char *) LPC24XX_ETH_RAM_BEGIN;
+ } else {
+ return NULL;
+ }
+}
+
+static void lpc_eth_config_free_table_area(char *table_area)
+{
+ /* Do nothing */
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC24XX_LPC_ETHERNET_CONFIG_H */
diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/lpc24xx.h b/c/src/lib/libbsp/arm/lpc24xx/include/lpc24xx.h
index daf198f372..2f296036d5 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/include/lpc24xx.h
+++ b/c/src/lib/libbsp/arm/lpc24xx/include/lpc24xx.h
@@ -207,29 +207,29 @@
#define FIO4CLR (*(volatile uint32_t *) (FIO_BASE_ADDR + 0x9C))
/* FIOs can be accessed through WORD, HALF-WORD or BYTE. */
-#define FIO0DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x01))
-#define FIO1DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x21))
-#define FIO2DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x41))
-#define FIO3DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x61))
-#define FIO4DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x81))
-
-#define FIO0DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x02))
-#define FIO1DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x22))
-#define FIO2DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x42))
-#define FIO3DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x62))
-#define FIO4DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x82))
-
-#define FIO0DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x03))
-#define FIO1DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x23))
-#define FIO2DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x43))
-#define FIO3DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x63))
-#define FIO4DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x83))
-
-#define FIO0DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x04))
-#define FIO1DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x24))
-#define FIO2DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x44))
-#define FIO3DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x64))
-#define FIO4DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x84))
+#define FIO0DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x00))
+#define FIO1DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x20))
+#define FIO2DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x40))
+#define FIO3DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x60))
+#define FIO4DIR0 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x80))
+
+#define FIO0DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x01))
+#define FIO1DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x21))
+#define FIO2DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x41))
+#define FIO3DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x61))
+#define FIO4DIR1 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x81))
+
+#define FIO0DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x02))
+#define FIO1DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x22))
+#define FIO2DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x42))
+#define FIO3DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x62))
+#define FIO4DIR2 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x82))
+
+#define FIO0DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x03))
+#define FIO1DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x23))
+#define FIO2DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x43))
+#define FIO3DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x63))
+#define FIO4DIR3 (*(volatile uint8_t *) (FIO_BASE_ADDR + 0x83))
#define FIO0DIRL (*(volatile uint16_t *) (FIO_BASE_ADDR + 0x00))
#define FIO1DIRL (*(volatile uint16_t *) (FIO_BASE_ADDR + 0x20))
@@ -1837,190 +1837,6 @@ typedef struct {
#define GPDMA_CH_CFG_HALT 0x00040000U
-/* Ethernet (MAC) */
-
-typedef struct {
- uint32_t start;
- uint32_t control;
-} lpc24xx_eth_transfer_descriptor;
-
-typedef struct {
- uint32_t status;
- uint32_t hash_crc;
-} lpc24xx_eth_receive_info;
-
-#define ETH_TRANSFER_DESCRIPTOR_SIZE 8
-
-#define ETH_RECEIVE_INFO_SIZE 8
-
-#define ETH_TRANSMIT_STATUS_SIZE 4
-
-/* ETH_RX_CTRL */
-
-#define ETH_RX_CTRL_SIZE_MASK 0x000007ffU
-
-#define GET_ETH_RX_CTRL_SIZE(reg) \
- GET_FIELD(reg, ETH_RX_CTRL_SIZE_MASK, 0)
-
-#define SET_ETH_RX_CTRL_SIZE(reg, val) \
- SET_FIELD(reg, val, ETH_RX_CTRL_SIZE_MASK, 0)
-
-#define ETH_RX_CTRL_INTERRUPT 0x80000000U
-
-/* ETH_RX_STAT */
-
-#define ETH_RX_STAT_RXSIZE_MASK 0x000007ffU
-
-#define GET_ETH_RX_STAT_RXSIZE(reg) \
- GET_FIELD(reg, ETH_RX_STAT_RXSIZE_MASK, 0)
-
-#define SET_ETH_RX_STAT_RXSIZE(reg, val) \
- SET_FIELD(reg, val, ETH_RX_STAT_RXSIZE_MASK, 0)
-
-#define ETH_RX_STAT_BYTES 0x00000100U
-
-#define ETH_RX_STAT_CONTROL_FRAME 0x00040000U
-
-#define ETH_RX_STAT_VLAN 0x00080000U
-
-#define ETH_RX_STAT_FAIL_FILTER 0x00100000U
-
-#define ETH_RX_STAT_MULTICAST 0x00200000U
-
-#define ETH_RX_STAT_BROADCAST 0x00400000U
-
-#define ETH_RX_STAT_CRC_ERROR 0x00800000U
-
-#define ETH_RX_STAT_SYMBOL_ERROR 0x01000000U
-
-#define ETH_RX_STAT_LENGTH_ERROR 0x02000000U
-
-#define ETH_RX_STAT_RANGE_ERROR 0x04000000U
-
-#define ETH_RX_STAT_ALIGNMENT_ERROR 0x08000000U
-
-#define ETH_RX_STAT_OVERRUN 0x10000000U
-
-#define ETH_RX_STAT_NO_DESCRIPTOR 0x20000000U
-
-#define ETH_RX_STAT_LAST_FLAG 0x40000000U
-
-#define ETH_RX_STAT_ERROR 0x80000000U
-
-/* ETH_TX_CTRL */
-
-#define ETH_TX_CTRL_SIZE_MASK 0x000007ffU
-
-#define GET_ETH_TX_CTRL_SIZE(reg) \
- GET_FIELD(reg, ETH_TX_CTRL_SIZE_MASK, 0)
-
-#define SET_ETH_TX_CTRL_SIZE(reg, val) \
- SET_FIELD(reg, val, ETH_TX_CTRL_SIZE_MASK, 0)
-
-#define ETH_TX_CTRL_OVERRIDE 0x04000000U
-
-#define ETH_TX_CTRL_HUGE 0x08000000U
-
-#define ETH_TX_CTRL_PAD 0x10000000U
-
-#define ETH_TX_CTRL_CRC 0x20000000U
-
-#define ETH_TX_CTRL_LAST 0x40000000U
-
-#define ETH_TX_CTRL_INTERRUPT 0x80000000U
-
-/* ETH_TX_STAT */
-
-#define ETH_TX_STAT_COLLISION_COUNT_MASK 0x01e00000U
-
-#define GET_ETH_TX_STAT_COLLISION_COUNT(reg) \
- GET_FIELD(reg, ETH_TX_STAT_COLLISION_COUNT_MASK, 21)
-
-#define SET_ETH_TX_STAT_COLLISION_COUNT(reg, val) \
- SET_FIELD(reg, val, ETH_TX_STAT_COLLISION_COUNT_MASK, 21)
-
-#define ETH_TX_STAT_DEFER 0x02000000U
-
-#define ETH_TX_STAT_EXCESSIVE_DEFER 0x04000000U
-
-#define ETH_TX_STAT_EXCESSIVE_COLLISION 0x08000000U
-
-#define ETH_TX_STAT_LATE_COLLISION 0x10000000U
-
-#define ETH_TX_STAT_UNDERRUN 0x20000000U
-
-#define ETH_TX_STAT_NO_DESCRIPTOR 0x40000000U
-
-#define ETH_TX_STAT_ERROR 0x80000000U
-
-/* ETH_INT */
-
-#define ETH_INT_RX_OVERRUN 0x00000001U
-
-#define ETH_INT_RX_ERROR 0x00000002U
-
-#define ETH_INT_RX_FINISHED 0x00000004U
-
-#define ETH_INT_RX_DONE 0x00000008U
-
-#define ETH_INT_TX_UNDERRUN 0x00000010U
-
-#define ETH_INT_TX_ERROR 0x00000020U
-
-#define ETH_INT_TX_FINISHED 0x00000040U
-
-#define ETH_INT_TX_DONE 0x00000080U
-
-#define ETH_INT_SOFT 0x00001000U
-
-#define ETH_INT_WAKEUP 0x00002000U
-
-/* ETH_RX_FIL_CTRL */
-
-#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST 0x00000001U
-
-#define ETH_RX_FIL_CTRL_ACCEPT_BROADCAST 0x00000002U
-
-#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST 0x00000004U
-
-#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST_HASH 0x00000008U
-
-#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST_HASH 0x00000010U
-
-#define ETH_RX_FIL_CTRL_ACCEPT_PERFECT 0x00000020U
-
-#define ETH_RX_FIL_CTRL_MAGIC_PACKET_WOL 0x00001000U
-
-#define ETH_RX_FIL_CTRL_RX_FILTER_WOL 0x00002000U
-
-/* ETH_CMD */
-
-#define ETH_CMD_RX_ENABLE 0x00000001U
-
-#define ETH_CMD_TX_ENABLE 0x00000002U
-
-#define ETH_CMD_REG_RESET 0x00000008U
-
-#define ETH_CMD_TX_RESET 0x00000010U
-
-#define ETH_CMD_RX_RESET 0x00000020U
-
-#define ETH_CMD_PASS_RUNT_FRAME 0x00000040U
-
-#define ETH_CMD_PASS_RX_FILTER 0X00000080U
-
-#define ETH_CMD_TX_FLOW_CONTROL 0x00000100U
-
-#define ETH_CMD_RMII 0x00000200U
-
-#define ETH_CMD_FULL_DUPLEX 0x00000400U
-
-/* ETH_STAT */
-
-#define ETH_STAT_RX_ACTIVE 0x00000001U
-
-#define ETH_STAT_TX_ACTIVE 0x00000002U
-
/* AHBCFG */
#define AHBCFG_SCHEDULER_UNIFORM 0x00000001U
diff --git a/c/src/lib/libbsp/arm/lpc24xx/preinstall.am b/c/src/lib/libbsp/arm/lpc24xx/preinstall.am
index 3b145cd6a0..3618176b8e 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/preinstall.am
+++ b/c/src/lib/libbsp/arm/lpc24xx/preinstall.am
@@ -33,6 +33,11 @@ $(PROJECT_INCLUDE)/bsp/$(dirstamp):
@: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+$(PROJECT_INCLUDE)/libcpu/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/libcpu
+ @: > $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+
$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs
PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs
@@ -121,10 +126,18 @@ $(PROJECT_INCLUDE)/bsp/lpc-clock-config.h: include/lpc-clock-config.h $(PROJECT_
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/lpc-clock-config.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/lpc-clock-config.h
+$(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h: include/lpc-ethernet-config.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h
+
$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.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
+
$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT)
TMPINSTALL_FILES += $(PROJECT_LIB)/start.$(OBJEXT)
diff --git a/c/src/lib/libbsp/arm/lpc32xx/ChangeLog b/c/src/lib/libbsp/arm/lpc32xx/ChangeLog
index a89ffbd4d7..13500d9840 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/ChangeLog
+++ b/c/src/lib/libbsp/arm/lpc32xx/ChangeLog
@@ -1,3 +1,11 @@
+2010-01-12 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * include/lpc-ethernet-config.h, include/mmu.h: New files.
+ * Makefile.am, configure.ac, preinstall.am, include/bsp.h,
+ include/bspopts.h.in, include/irq.h, include/lpc32xx.h, irq/irq.c,
+ rtc/rtc-config.c, startup/bspstarthooks.c,
+ startup/linkcmds.lpc32xx_phycore: Changes throughout.
+
2009-12-17 Joel Sherrill <joel.sherrill@oarcorp.com>
* include/bspopts.h.in: Regenerated.
diff --git a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
index fd866bcdcd..fd33ab5a9c 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
@@ -12,6 +12,7 @@ ACLOCAL_AMFLAGS = -I ../../../../aclocal
include $(top_srcdir)/../../../../automake/compile.am
include_bspdir = $(includedir)/bsp
+include_libcpudir = $(includedir)/libcpu
dist_project_lib_DATA = bsp_specs
@@ -20,6 +21,7 @@ dist_project_lib_DATA = bsp_specs
###############################################################################
include_HEADERS = include/bsp.h
+include_HEADERS += ../../shared/include/tm27.h
nodist_include_HEADERS = ../../shared/include/coverhd.h \
include/bspopts.h
@@ -37,10 +39,13 @@ include_bsp_HEADERS += ../shared/include/start.h
include_bsp_HEADERS += ../shared/lpc/include/lpc-timer.h
include_bsp_HEADERS += include/irq-config.h
include_bsp_HEADERS += include/irq.h
+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_HEADERS += ../../shared/include/tm27.h
+include_libcpu_HEADERS = ../../../libcpu/arm/shared/include/cache.h \
+ ../../../libcpu/arm/shared/include/arm-cp15.h
###############################################################################
# Data #
@@ -64,6 +69,8 @@ EXTRA_DIST = startup/linkcmds.lpc32xx_phycore
noinst_LIBRARIES += libbsp.a
libbsp_a_SOURCES =
+libbsp_a_CPPFLAGS =
+libbsp_a_LIBADD =
# Shared
libbsp_a_SOURCES += ../../shared/bootcard.c \
@@ -109,12 +116,18 @@ libbsp_a_SOURCES += misc/timer.c
# I2C
+# Cache
+libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c \
+ ../../../libcpu/arm/shared/cache/cache_.h
+libbsp_a_CPPFLAGS += -I$(srcdir)/../../../libcpu/arm/shared/include
+
# Start hooks (FIXME: This is brittle.)
libbsp_a_SOURCES += startup/bspstarthooks.c
-bspstarthooks.o: startup/bspstarthooks.c
- $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS:-mthumb=) \
- -MT bspstarthooks.o -MD -MP -MF $(DEPDIR)/bspstarthooks.Tpo -c -o bspstarthooks.o \
+libbsp_a-bspstarthooks.o: startup/bspstarthooks.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbsp_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS:-mthumb=) \
+ -MT libbsp_a-bspstarthooks.o -MD -MP -MF $(DEPDIR)/libbsp_a-bspstarthooks.Tpo -c -o libbsp_a-bspstarthooks.o \
`test -f 'startup/bspstarthooks.c' || echo '$(srcdir)/'`startup/bspstarthooks.c
+ $(am__mv) $(DEPDIR)/libbsp_a-bspstarthooks.Tpo $(DEPDIR)/libbsp_a-bspstarthooks.Po
###############################################################################
# Network #
@@ -122,13 +135,13 @@ bspstarthooks.o: startup/bspstarthooks.c
if HAS_NETWORKING
-# noinst_PROGRAMS = network.rel
+noinst_PROGRAMS = network.rel
-# network_rel_SOURCES = network/network.c
-# network_rel_CPPFLAGS = $(AM_CPPFLAGS) -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
-# network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
+network_rel_SOURCES = ../shared/lpc/network/lpc-ethernet.c
+network_rel_CPPFLAGS = $(AM_CPPFLAGS) -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
+network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
-# libbsp_a_LIBADD = network.rel
+libbsp_a_LIBADD += network.rel
endif
diff --git a/c/src/lib/libbsp/arm/lpc32xx/configure.ac b/c/src/lib/libbsp/arm/lpc32xx/configure.ac
index 6febd9d350..a3e90456c3 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/configure.ac
+++ b/c/src/lib/libbsp/arm/lpc32xx/configure.ac
@@ -33,6 +33,9 @@ RTEMS_BSPOPTS_HELP([LPC32XX_ARM_CLK],[ARM clock in Hz])
RTEMS_BSPOPTS_SET([LPC32XX_HCLK],[*],[104000000U])
RTEMS_BSPOPTS_HELP([LPC32XX_HCLK],[AHB bus clock in Hz])
+RTEMS_BSPOPTS_SET([LPC32XX_ETHERNET_RMII],[*],[1])
+RTEMS_BSPOPTS_HELP([LPC32XX_ETHERNET_RMII],[enable RMII for Ethernet])
+
RTEMS_BSPOPTS_SET([LPC32XX_PERIPH_CLK],[*],[13000000U])
RTEMS_BSPOPTS_HELP([LPC32XX_PERIPH_CLK],[peripheral clock in Hz])
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h b/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
index a42dd7b0be..c512ab28c2 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
@@ -51,7 +51,7 @@ struct rtems_bsdnet_ifconfig;
/**
* @brief Network driver attach and detach function.
*/
-int lpc32xx_eth_attach_detach(
+int lpc_eth_attach_detach(
struct rtems_bsdnet_ifconfig *config,
int attaching
);
@@ -59,7 +59,7 @@ int lpc32xx_eth_attach_detach(
/**
* @brief Standard network driver attach and detach function.
*/
-#define RTEMS_BSP_NETWORK_DRIVER_ATTACH lpc32xx_eth_attach_detach
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH lpc_eth_attach_detach
/**
* @brief Standard network driver name.
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/bspopts.h.in b/c/src/lib/libbsp/arm/lpc32xx/include/bspopts.h.in
index f89ed3a90a..0de9964d9b 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/bspopts.h.in
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/bspopts.h.in
@@ -33,6 +33,9 @@
/* clock mode configuration for UARTs */
#undef LPC32XX_CONFIG_UART_CLKMODE
+/* enable RMII for Ethernet */
+#undef LPC32XX_ETHERNET_RMII
+
/* AHB bus clock in Hz */
#undef LPC32XX_HCLK
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/irq.h b/c/src/lib/libbsp/arm/lpc32xx/include/irq.h
index 62d28fe7e0..2e047d27c1 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/irq.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/irq.h
@@ -158,6 +158,8 @@ void lpc32xx_irq_set_activation_type(rtems_vector_number vector, lpc32xx_irq_act
lpc32xx_irq_activation_type lpc32xx_irq_get_activation_type(rtems_vector_number vector);
+void lpc32xx_set_exception_handler(Arm_symbolic_exception_name exception, void (*handler)(void));
+
/** @} */
#endif /* ASM */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h b/c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h
new file mode 100644
index 0000000000..dd20823303
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h
@@ -0,0 +1,81 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief Ethernet driver configuration.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_LPC_ETHERNET_CONFIG_H
+#define LIBBSP_ARM_LPC32XX_LPC_ETHERNET_CONFIG_H
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+
+#include <bsp.h>
+#include <bsp/lpc32xx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define LPC_ETH_CONFIG_INTERRUPT LPC32XX_IRQ_ETHERNET
+
+#define LPC_ETH_CONFIG_REG_BASE LPC32XX_BASE_ETHERNET
+
+#define LPC_ETH_CONFIG_RX_UNIT_COUNT_DEFAULT 16
+#define LPC_ETH_CONFIG_RX_UNIT_COUNT_MAX INT_MAX
+
+#define LPC_ETH_CONFIG_TX_UNIT_COUNT_DEFAULT 32
+#define LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX INT_MAX
+
+#define LPC_ETH_CONFIG_UNIT_MULTIPLE 8U
+
+#ifdef LPC32XX_ETHERNET_RMII
+ #define LPC_ETH_CONFIG_RMII
+
+ static void lpc_eth_config_module_enable(void)
+ {
+ LPC32XX_MAC_CLK_CTRL = 0x1f;
+ }
+#else
+ static void lpc_eth_config_module_enable(void)
+ {
+ LPC32XX_MAC_CLK_CTRL = 0x0f;
+ }
+#endif
+
+#define LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+
+static char *lpc_eth_config_alloc_table_area(size_t size)
+{
+ return rtems_heap_allocate_aligned_with_boundary(size, 32, 0);
+}
+
+static void lpc_eth_config_free_table_area(char *table_area)
+{
+ /* FIXME: Type */
+ free(table_area, (int) 0xdeadbeef);
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_LPC_ETHERNET_CONFIG_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h b/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
index 2e82d34b80..d69e7db7f3 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
@@ -90,5 +90,6 @@
#define LPC32XX_UART_CLKMODE (*(volatile uint32_t *) 0x40054004)
#define LPC32XX_UART_LOOP (*(volatile uint32_t *) 0x40054008)
#define LPC32XX_SW_INT (*(volatile uint32_t *) 0x400040a8)
+#define LPC32XX_MAC_CLK_CTRL (*(volatile uint32_t *) 0x40004090)
#endif /* LIBBSP_ARM_LPC32XX_LPC32XX_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c b/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c
index 187b4b310b..04eec9c921 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c
@@ -23,6 +23,8 @@
#include <bsp/irq.h>
#include <bsp/irq-generic.h>
#include <bsp/lpc32xx.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/mmu.h>
/*
* Mask out SIC 1 and 2 IRQ request. There is no need to mask out the FIQ,
@@ -125,15 +127,15 @@ static inline void lpc32xx_irq_clear_bit_in_field(unsigned index, lpc32xx_irq_fi
static inline unsigned lpc32xx_irq_get_index(uint32_t val)
{
- uint32_t reg;
+ ARM_SWITCH_REGISTERS;
asm volatile (
- THUMB_TO_ARM
- "clz %1, %1\n"
- "rsb %1, %1, #31\n"
- ARM_TO_THUMB
- : "=&r" (reg), "=r" (val)
- : "1" (val)
+ ARM_SWITCH_TO_ARM
+ "clz %[val], %[val]\n"
+ "rsb %[val], %[val], #31\n"
+ ARM_SWITCH_BACK
+ : [val] "=r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ : "[val]" (val)
);
return val;
@@ -304,6 +306,21 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
return RTEMS_SUCCESSFUL;
}
+void lpc32xx_set_exception_handler(
+ Arm_symbolic_exception_name exception,
+ void (*handler)(void)
+)
+{
+ if ((unsigned) exception < MAX_EXCEPTIONS) {
+ uint32_t *table = (uint32_t *) bsp_section_vector_begin + MAX_EXCEPTIONS;
+
+ table [exception] = (uint32_t) handler;
+
+ rtems_cache_flush_multiple_data_lines(NULL, 64);
+ rtems_cache_invalidate_multiple_data_lines(NULL, 64);
+ }
+}
+
rtems_status_code bsp_interrupt_facility_initialize(void)
{
size_t i = 0;
@@ -341,7 +358,7 @@ rtems_status_code bsp_interrupt_facility_initialize(void)
lpc32xx_sic_1->atr = 0x26000;
lpc32xx_sic_2->atr = 0x0;
- _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, arm_exc_interrupt, NULL);
+ lpc32xx_set_exception_handler(ARM_EXCEPTION_IRQ, arm_exc_interrupt);
return RTEMS_SUCCESSFUL;
}
@@ -350,23 +367,3 @@ void bsp_interrupt_handler_default(rtems_vector_number vector)
{
printk("spurious interrupt: %u\n", vector);
}
-
-static void lpc32xx_irq_dump_controller(volatile lpc32xx_irq_controller *controller)
-{
- printk(
- "er %08x\nrsr %08x\nsr %08x\napr %08x\natr %08x\nitr %08x\n",
- controller->er,
- controller->rsr,
- controller->sr,
- controller->apr,
- controller->atr,
- controller->itr
- );
-}
-
-void lpc32xx_irq_dump(void)
-{
- lpc32xx_irq_dump_controller(lpc32xx_mic);
- lpc32xx_irq_dump_controller(lpc32xx_sic_1);
- lpc32xx_irq_dump_controller(lpc32xx_sic_2);
-}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
index 3f2aa0c774..41a5255bd7 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
@@ -33,6 +33,11 @@ $(PROJECT_INCLUDE)/bsp/$(dirstamp):
@: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+$(PROJECT_INCLUDE)/libcpu/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/libcpu
+ @: > $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+
$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs
PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs
@@ -41,6 +46,10 @@ $(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h
+$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h
+
$(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
@@ -93,6 +102,10 @@ $(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
+$(PROJECT_INCLUDE)/bsp/mmu.h: include/mmu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mmu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mmu.h
+
$(PROJECT_INCLUDE)/bsp/lpc32xx.h: include/lpc32xx.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/lpc32xx.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/lpc32xx.h
@@ -101,9 +114,17 @@ $(PROJECT_INCLUDE)/bsp/lpc-clock-config.h: include/lpc-clock-config.h $(PROJECT_
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/lpc-clock-config.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/lpc-clock-config.h
-$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
- $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
-PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h
+$(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h: include/lpc-ethernet-config.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/lpc-ethernet-config.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
+
+$(PROJECT_INCLUDE)/libcpu/arm-cp15.h: ../../../libcpu/arm/shared/include/arm-cp15.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT)
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 35a2c75be9..b518db3c1f 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/rtc/rtc-config.c
@@ -21,44 +21,108 @@
#include <libchip/rtc.h>
+#include <bsp.h>
#include <bsp/lpc32xx.h>
-#define LPC32XX_RTC_COUNT 1
+#define LPC32XX_RTC_COUNT 1U
+
+#define LPC32XX_RTC_COUNTER_DELTA 0xfffffffeU
+
+#define LPC32XX_RTC_KEY 0xb5c13f27U
+
+#define LPC32XX_RTC_CTRL_FORCE_ONSW (1U << 7)
+#define LPC32XX_RTC_CTRL_STOP (1U << 6)
+#define LPC32XX_RTC_CTRL_RESET (1U << 4)
+#define LPC32XX_RTC_CTRL_MATCH_1_ONSW (1U << 3)
+#define LPC32XX_RTC_CTRL_MATCH_0_ONSW (1U << 2)
+#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;
+
+ /* It needs some time before we can read the values back */
+ while (i != 0) {
+ asm volatile ("nop");
+ --i;
+ }
+}
+
+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_set(0);
+}
static void lpc32xx_rtc_initialize(int minor)
{
- /* TODO */
+ uint32_t up_first = 0;
+ uint32_t up_second = 0;
+ uint32_t down_first = 0;
+ uint32_t down_second = 0;
+
+ 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;
+ } while (up_first != up_second || down_first != down_second);
+
+ if (up_first + down_first != LPC32XX_RTC_COUNTER_DELTA) {
+ lpc32xx_rtc_reset();
+ }
}
static int lpc32xx_rtc_get_time(int minor, rtems_time_of_day *tod)
{
- /* TODO */
-
-#if 0
- tod->ticks = 0;
- tod->second = RTC_SEC;
- tod->minute = RTC_MIN;
- tod->hour = RTC_HOUR;
- tod->day = RTC_DOM;
- tod->month = RTC_MONTH;
- tod->year = RTC_YEAR;
-#endif
-
- return 0;
+ struct timeval now = {
+ .tv_sec = lpc32xx_rtc->ucount,
+ .tv_usec = 0
+ };
+ struct tm time;
+
+ gmtime_r(&now.tv_sec, &time);
+
+ tod->year = time.tm_year + 1900;
+ tod->month = time.tm_mon + 1;
+ tod->day = time.tm_mday;
+ tod->hour = time.tm_hour;
+ tod->minute = time.tm_min;
+ tod->second = time.tm_sec;
+ tod->ticks = 0;
+
+ return RTEMS_SUCCESSFUL;
}
static int lpc32xx_rtc_set_time(int minor, const rtems_time_of_day *tod)
{
- /* TODO */
-
-#if 0
- RTC_SEC = tod->second;
- RTC_MIN = tod->minute;
- RTC_HOUR = tod->hour;
- RTC_DOM = tod->day;
- RTC_MONTH = tod->month;
- RTC_YEAR = tod->year;
-#endif
+ lpc32xx_rtc_set(_TOD_To_seconds(tod));
return 0;
}
diff --git a/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c b/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c
index 7f668f83c5..86164f518a 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c
@@ -24,9 +24,11 @@
#include <bspopts.h>
#include <bsp/start.h>
#include <bsp/lpc32xx.h>
+#include <bsp/mmu.h>
#include <bsp/linker-symbols.h>
#define BSP_START_SECTION __attribute__((section(".bsp_start")))
+#define BSP_START_DATA_SECTION __attribute__((section(".bsp_start_data")))
static void BSP_START_SECTION lpc32xx_clear_bss(void)
{
@@ -40,9 +42,125 @@ static void BSP_START_SECTION lpc32xx_clear_bss(void)
}
}
+typedef struct {
+ uint32_t begin;
+ uint32_t end;
+ uint32_t flags;
+} lpc32xx_mmu_config;
+
+static const BSP_START_DATA_SECTION lpc32xx_mmu_config
+ lpc32xx_mmu_config_table [] = {
+ {
+ .begin = (uint32_t) bsp_section_start_begin,
+ .end = (uint32_t) bsp_section_start_end,
+ .flags = LPC32XX_MMU_READ_WRITE_CACHED
+ }, {
+ .begin = (uint32_t) bsp_section_vector_begin,
+ .end = (uint32_t) bsp_section_vector_end,
+ .flags = LPC32XX_MMU_READ_WRITE_CACHED
+ }, {
+ .begin = (uint32_t) bsp_section_text_begin,
+ .end = (uint32_t) bsp_section_text_end,
+ .flags = LPC32XX_MMU_READ_WRITE_CACHED
+ }, {
+ .begin = (uint32_t) bsp_section_rodata_begin,
+ .end = (uint32_t) bsp_section_rodata_end,
+ .flags = LPC32XX_MMU_READ_ONLY_CACHED
+ }, {
+ .begin = (uint32_t) bsp_section_data_begin,
+ .end = (uint32_t) bsp_section_data_end,
+ .flags = LPC32XX_MMU_READ_WRITE
+ }, {
+ .begin = (uint32_t) bsp_section_fast_begin,
+ .end = (uint32_t) bsp_section_fast_end,
+ .flags = LPC32XX_MMU_READ_ONLY_CACHED
+ }, {
+ .begin = (uint32_t) bsp_section_bss_begin,
+ .end = (uint32_t) bsp_section_bss_end,
+ .flags = LPC32XX_MMU_READ_WRITE
+ }, {
+ .begin = (uint32_t) bsp_section_work_begin,
+ .end = (uint32_t) bsp_section_work_end,
+ .flags = LPC32XX_MMU_READ_WRITE_CACHED
+ }, {
+ .begin = (uint32_t) bsp_section_stack_begin,
+ .end = (uint32_t) bsp_section_stack_end,
+ .flags = LPC32XX_MMU_READ_WRITE_CACHED
+ }, {
+ .begin = 0x0U,
+ .end = 0x100000U,
+ .flags = LPC32XX_MMU_READ_ONLY_CACHED
+ }, {
+ .begin = 0x20000000U,
+ .end = 0x200c0000U,
+ .flags = LPC32XX_MMU_READ_WRITE
+ }, {
+ .begin = 0x30000000U,
+ .end = 0x32000000U,
+ .flags = LPC32XX_MMU_READ_WRITE
+ }, {
+ .begin = 0x40000000U,
+ .end = 0x40100000U,
+ .flags = LPC32XX_MMU_READ_WRITE
+ }
+};
+
+static void BSP_START_SECTION lpc32xx_mmu_set_entries(
+ uint32_t *ttb,
+ const lpc32xx_mmu_config *config
+)
+{
+ uint32_t i = ARM_MMU_SECT_GET_INDEX(config->begin);
+ uint32_t iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
+
+ if (config->begin != config->end) {
+ while (i < iend) {
+ ttb [i] = (i << ARM_MMU_SECT_BASE_SHIFT) | config->flags;
+ ++i;
+ }
+ }
+}
+
+static void BSP_START_SECTION lpc32xx_mmu_and_cache_setup(void)
+{
+ uint32_t const dac =
+ ARM_CP15_DAC_DOMAIN(LPC32XX_MMU_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT);
+ uint32_t ctrl = 0;
+ uint32_t *const ttb = (uint32_t *) bsp_section_work_end;
+ size_t const config_entry_count =
+ sizeof(lpc32xx_mmu_config_table) / sizeof(lpc32xx_mmu_config_table [0]);
+ size_t i = 0;
+
+ /* Disable MMU and cache, basic settings */
+ ctrl = arm_cp15_get_control();
+ ctrl &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_R | ARM_CP15_CTRL_C
+ | ARM_CP15_CTRL_V | ARM_CP15_CTRL_M);
+ ctrl |= ARM_CP15_CTRL_S | ARM_CP15_CTRL_A;
+ arm_cp15_set_control(ctrl);
+
+ arm_cp15_cache_invalidate();
+ arm_cp15_tlb_invalidate();
+
+ arm_cp15_set_domain_access_control(dac);
+ arm_cp15_set_translation_table_base(ttb);
+
+ /* Initialize translation table with invalid entries */
+ for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) {
+ ttb [i] = 0;
+ }
+
+ for (i = 0; i < config_entry_count; ++i) {
+ lpc32xx_mmu_set_entries(ttb, &lpc32xx_mmu_config_table [i]);
+ }
+
+ /* Enable MMU and cache */
+ ctrl |= ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M;
+ arm_cp15_set_control(ctrl);
+}
+
void BSP_START_SECTION bsp_start_hook_0(void)
{
- /* TODO */
+ lpc32xx_mmu_and_cache_setup();
}
void BSP_START_SECTION bsp_start_hook_1(void)
@@ -50,6 +168,7 @@ void BSP_START_SECTION bsp_start_hook_1(void)
/* TODO */
/* Copy .text section */
+ arm_cp15_instruction_cache_invalidate();
bsp_start_memcpy_arm(
(int *) bsp_section_text_begin,
(const int *) bsp_section_text_load_begin,
@@ -57,6 +176,7 @@ void BSP_START_SECTION bsp_start_hook_1(void)
);
/* Copy .rodata section */
+ arm_cp15_instruction_cache_invalidate();
bsp_start_memcpy_arm(
(int *) bsp_section_rodata_begin,
(const int *) bsp_section_rodata_load_begin,
@@ -64,6 +184,7 @@ void BSP_START_SECTION bsp_start_hook_1(void)
);
/* Copy .data section */
+ arm_cp15_instruction_cache_invalidate();
bsp_start_memcpy_arm(
(int *) bsp_section_data_begin,
(const int *) bsp_section_data_load_begin,
@@ -71,6 +192,7 @@ void BSP_START_SECTION bsp_start_hook_1(void)
);
/* Copy .fast section */
+ arm_cp15_instruction_cache_invalidate();
bsp_start_memcpy_arm(
(int *) bsp_section_fast_begin,
(const int *) bsp_section_fast_load_begin,
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 8003ecc996..2c2743caf0 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore
+++ b/c/src/lib/libbsp/arm/lpc32xx/startup/linkcmds.lpc32xx_phycore
@@ -36,7 +36,7 @@
MEMORY {
RAM_INT (AIW) : ORIGIN = 0x08000000, LENGTH = 256k
- RAM_EXT (AIW) : ORIGIN = 0x80000000, LENGTH = 64M /* SDRAM on DYCS0 */
+ RAM_EXT (AIW) : ORIGIN = 0x80000000, LENGTH = 64M - 16k /* SDRAM on DYCS0 */
ROM_EXT (RX) : ORIGIN = 0xe0000000, LENGTH = 2M /* NOR flash on CS0 */
NIRVANA : ORIGIN = 0, LENGTH = 0
}
@@ -56,5 +56,8 @@ 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.base
diff --git a/c/src/lib/libbsp/arm/shared/abort/abort.c b/c/src/lib/libbsp/arm/shared/abort/abort.c
index 3bd704c32e..123fda0f7e 100644
--- a/c/src/lib/libbsp/arm/shared/abort/abort.c
+++ b/c/src/lib/libbsp/arm/shared/abort/abort.c
@@ -63,7 +63,7 @@ char *_print_full_context_mode2txt[0x20]={
void _print_full_context(uint32_t spsr)
{
char *mode;
- uint32_t prev_sp,prev_lr,cpsr,tmp;
+ uint32_t prev_sp,prev_lr,cpsr,arm_switch_reg;
int i;
printk("active thread thread 0x%08x\n", _Thread_Executing->Object.id);
@@ -71,14 +71,16 @@ void _print_full_context(uint32_t spsr)
mode=_print_full_context_mode2txt[spsr&0x1f];
if(!mode) mode="unknown";
- asm volatile (" MRS %[cpsr], cpsr \n"
- " ORR %[tmp], %[spsr], #0xc0 \n"
- " MSR cpsr_c, %[tmp] \n"
+ asm volatile (ARM_SWITCH_TO_ARM
+ " MRS %[cpsr], cpsr \n"
+ " ORR %[arm_switch_reg], %[spsr], #0xc0 \n"
+ " MSR cpsr_c, %[arm_switch_reg] \n"
" MOV %[prev_sp], sp \n"
" MOV %[prev_lr], lr \n"
" MSR cpsr_c, %[cpsr] \n"
- : [prev_sp] "=&r" (prev_sp), [prev_lr] "=&r" (prev_lr),
- [cpsr] "=&r" (cpsr), [tmp] "=&r" (tmp)
+ ARM_SWITCH_BACK
+ : [arm_switch_reg] "=&r" (arm_switch_reg), [prev_sp] "=&r" (prev_sp), [prev_lr] "=&r" (prev_lr),
+ [cpsr] "=&r" (cpsr)
: [spsr] "r" (spsr)
: "cc");
diff --git a/c/src/lib/libbsp/arm/shared/abort/simple_abort.c b/c/src/lib/libbsp/arm/shared/abort/simple_abort.c
index 25f6aee4e5..b77c425a5e 100644
--- a/c/src/lib/libbsp/arm/shared/abort/simple_abort.c
+++ b/c/src/lib/libbsp/arm/shared/abort/simple_abort.c
@@ -56,7 +56,7 @@ char *_print_full_context_mode2txt[0x10]={
void _print_full_context(uint32_t spsr)
{
char *mode;
- uint32_t prev_sp,prev_lr,cpsr,tmp;
+ uint32_t prev_sp,prev_lr,cpsr,arm_switch_reg;
int i, j;
printk("active thread thread 0x%08x\n", _Thread_Executing->Object.id);
@@ -65,16 +65,16 @@ void _print_full_context(uint32_t spsr)
if(!mode) mode="unknown";
asm volatile (
- THUMB_TO_ARM
+ ARM_SWITCH_TO_ARM
"mrs %[cpsr], cpsr\n"
- "orr %[tmp], %[spsr], #0xc0\n"
- "msr cpsr_c, %[tmp]\n"
+ "orr %[arm_switch_reg], %[spsr], #0xc0\n"
+ "msr cpsr_c, %[arm_switch_reg]\n"
"mov %[prev_sp], sp\n"
"mov %[prev_lr], lr\n"
"msr cpsr_c, %[cpsr]\n"
- ARM_TO_THUMB
+ ARM_SWITCH_BACK
: [prev_sp] "=&r" (prev_sp), [prev_lr] "=&r" (prev_lr),
- [cpsr] "=&r" (cpsr), [tmp] "=&r" (tmp)
+ [cpsr] "=&r" (cpsr), [arm_switch_reg] "=&r" (arm_switch_reg)
: [spsr] "r" (spsr)
: "cc"
);
diff --git a/c/src/lib/libbsp/arm/shared/include/linker-symbols.h b/c/src/lib/libbsp/arm/shared/include/linker-symbols.h
index 75f7d942e0..b8afed5c77 100644
--- a/c/src/lib/libbsp/arm/shared/include/linker-symbols.h
+++ b/c/src/lib/libbsp/arm/shared/include/linker-symbols.h
@@ -54,9 +54,9 @@ LINKER_SYMBOL(bsp_stack_abt_begin)
LINKER_SYMBOL(bsp_stack_abt_end)
LINKER_SYMBOL(bsp_stack_abt_size)
-LINKER_SYMBOL(bsp_stack_undef_begin)
-LINKER_SYMBOL(bsp_stack_undef_end)
-LINKER_SYMBOL(bsp_stack_undef_size)
+LINKER_SYMBOL(bsp_stack_und_begin)
+LINKER_SYMBOL(bsp_stack_und_end)
+LINKER_SYMBOL(bsp_stack_und_size)
LINKER_SYMBOL(bsp_stack_svc_begin)
LINKER_SYMBOL(bsp_stack_svc_end)
diff --git a/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c b/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
new file mode 100644
index 0000000000..fe133c8955
--- /dev/null
+++ b/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
@@ -0,0 +1,1400 @@
+/**
+ * @file
+ *
+ * @ingroup lpc
+ *
+ * @brief Ethernet driver.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1
+#define __BSD_VISIBLE 1
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_mii_ioctl.h>
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/lpc-ethernet-config.h>
+
+#include <rtems/status-checks.h>
+
+#if MCLBYTES > (2 * 1024)
+ #error "MCLBYTES to large"
+#endif
+
+#ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ #define LPC_ETH_CONFIG_TX_BUF_SIZE sizeof(struct mbuf *)
+#else
+ #define LPC_ETH_CONFIG_TX_BUF_SIZE 1518U
+#endif
+
+typedef struct {
+ uint32_t start;
+ uint32_t control;
+} lpc_eth_transfer_descriptor;
+
+typedef struct {
+ uint32_t info;
+ uint32_t hash_crc;
+} lpc_eth_receive_status;
+
+typedef struct {
+ uint32_t mac1;
+ uint32_t mac2;
+ uint32_t ipgt;
+ uint32_t ipgr;
+ uint32_t clrt;
+ uint32_t maxf;
+ uint32_t supp;
+ uint32_t test;
+ uint32_t mcfg;
+ uint32_t mcmd;
+ uint32_t madr;
+ uint32_t mwtd;
+ uint32_t mrdd;
+ uint32_t mind;
+ uint32_t reserved_0 [2];
+ uint32_t sa0;
+ uint32_t sa1;
+ uint32_t sa2;
+ uint32_t reserved_1 [45];
+ uint32_t command;
+ uint32_t status;
+ uint32_t rxdescriptor;
+ uint32_t rxstatus;
+ uint32_t rxdescriptornum;
+ uint32_t rxproduceindex;
+ uint32_t rxconsumeindex;
+ uint32_t txdescriptor;
+ uint32_t txstatus;
+ uint32_t txdescriptornum;
+ uint32_t txproduceindex;
+ uint32_t txconsumeindex;
+ uint32_t reserved_2 [10];
+ uint32_t tsv0;
+ uint32_t tsv1;
+ uint32_t rsv;
+ uint32_t reserved_3 [3];
+ uint32_t flowcontrolcnt;
+ uint32_t flowcontrolsts;
+ uint32_t reserved_4 [34];
+ uint32_t rxfilterctrl;
+ uint32_t rxfilterwolsts;
+ uint32_t rxfilterwolclr;
+ uint32_t reserved_5 [1];
+ uint32_t hashfilterl;
+ uint32_t hashfilterh;
+ uint32_t reserved_6 [882];
+ uint32_t intstatus;
+ uint32_t intenable;
+ uint32_t intclear;
+ uint32_t intset;
+ uint32_t reserved_7 [1];
+ uint32_t powerdown;
+} lpc_eth_controller;
+
+static volatile lpc_eth_controller *const lpc_eth =
+ (volatile lpc_eth_controller *) LPC_ETH_CONFIG_REG_BASE;
+
+/* ETH_RX_CTRL */
+
+#define ETH_RX_CTRL_SIZE_MASK 0x000007ffU
+#define ETH_RX_CTRL_INTERRUPT 0x80000000U
+
+/* ETH_RX_STAT */
+
+#define ETH_RX_STAT_RXSIZE_MASK 0x000007ffU
+#define ETH_RX_STAT_BYTES 0x00000100U
+#define ETH_RX_STAT_CONTROL_FRAME 0x00040000U
+#define ETH_RX_STAT_VLAN 0x00080000U
+#define ETH_RX_STAT_FAIL_FILTER 0x00100000U
+#define ETH_RX_STAT_MULTICAST 0x00200000U
+#define ETH_RX_STAT_BROADCAST 0x00400000U
+#define ETH_RX_STAT_CRC_ERROR 0x00800000U
+#define ETH_RX_STAT_SYMBOL_ERROR 0x01000000U
+#define ETH_RX_STAT_LENGTH_ERROR 0x02000000U
+#define ETH_RX_STAT_RANGE_ERROR 0x04000000U
+#define ETH_RX_STAT_ALIGNMENT_ERROR 0x08000000U
+#define ETH_RX_STAT_OVERRUN 0x10000000U
+#define ETH_RX_STAT_NO_DESCRIPTOR 0x20000000U
+#define ETH_RX_STAT_LAST_FLAG 0x40000000U
+#define ETH_RX_STAT_ERROR 0x80000000U
+
+/* ETH_TX_CTRL */
+
+#define ETH_TX_CTRL_SIZE_MASK 0x7ffU
+#define ETH_TX_CTRL_SIZE_SHIFT 0
+#define ETH_TX_CTRL_OVERRIDE 0x04000000U
+#define ETH_TX_CTRL_HUGE 0x08000000U
+#define ETH_TX_CTRL_PAD 0x10000000U
+#define ETH_TX_CTRL_CRC 0x20000000U
+#define ETH_TX_CTRL_LAST 0x40000000U
+#define ETH_TX_CTRL_INTERRUPT 0x80000000U
+
+/* ETH_TX_STAT */
+
+#define ETH_TX_STAT_COLLISION_COUNT_MASK 0x01e00000U
+#define ETH_TX_STAT_DEFER 0x02000000U
+#define ETH_TX_STAT_EXCESSIVE_DEFER 0x04000000U
+#define ETH_TX_STAT_EXCESSIVE_COLLISION 0x08000000U
+#define ETH_TX_STAT_LATE_COLLISION 0x10000000U
+#define ETH_TX_STAT_UNDERRUN 0x20000000U
+#define ETH_TX_STAT_NO_DESCRIPTOR 0x40000000U
+#define ETH_TX_STAT_ERROR 0x80000000U
+
+/* ETH_INT */
+
+#define ETH_INT_RX_OVERRUN 0x00000001U
+#define ETH_INT_RX_ERROR 0x00000002U
+#define ETH_INT_RX_FINISHED 0x00000004U
+#define ETH_INT_RX_DONE 0x00000008U
+#define ETH_INT_TX_UNDERRUN 0x00000010U
+#define ETH_INT_TX_ERROR 0x00000020U
+#define ETH_INT_TX_FINISHED 0x00000040U
+#define ETH_INT_TX_DONE 0x00000080U
+#define ETH_INT_SOFT 0x00001000U
+#define ETH_INT_WAKEUP 0x00002000U
+
+/* ETH_RX_FIL_CTRL */
+
+#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST 0x00000001U
+#define ETH_RX_FIL_CTRL_ACCEPT_BROADCAST 0x00000002U
+#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST 0x00000004U
+#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST_HASH 0x00000008U
+#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST_HASH 0x00000010U
+#define ETH_RX_FIL_CTRL_ACCEPT_PERFECT 0x00000020U
+#define ETH_RX_FIL_CTRL_MAGIC_PACKET_WOL 0x00001000U
+#define ETH_RX_FIL_CTRL_RX_FILTER_WOL 0x00002000U
+
+/* ETH_CMD */
+
+#define ETH_CMD_RX_ENABLE 0x00000001U
+#define ETH_CMD_TX_ENABLE 0x00000002U
+#define ETH_CMD_REG_RESET 0x00000008U
+#define ETH_CMD_TX_RESET 0x00000010U
+#define ETH_CMD_RX_RESET 0x00000020U
+#define ETH_CMD_PASS_RUNT_FRAME 0x00000040U
+#define ETH_CMD_PASS_RX_FILTER 0X00000080U
+#define ETH_CMD_TX_FLOW_CONTROL 0x00000100U
+#define ETH_CMD_RMII 0x00000200U
+#define ETH_CMD_FULL_DUPLEX 0x00000400U
+
+/* ETH_STAT */
+
+#define ETH_STAT_RX_ACTIVE 0x00000001U
+#define ETH_STAT_TX_ACTIVE 0x00000002U
+
+/* Events */
+
+#define LPC_ETH_EVENT_INITIALIZE RTEMS_EVENT_1
+
+#define LPC_ETH_EVENT_START RTEMS_EVENT_2
+
+#define LPC_ETH_EVENT_INTERRUPT RTEMS_EVENT_3
+
+/* Status */
+
+#define LPC_ETH_INTERRUPT_RECEIVE \
+ (ETH_INT_RX_ERROR | ETH_INT_RX_FINISHED | ETH_INT_RX_DONE)
+
+#define LPC_ETH_INTERRUPT_TRANSMIT \
+ (ETH_INT_TX_DONE | ETH_INT_TX_FINISHED | ETH_INT_TX_ERROR)
+
+#define LPC_ETH_RX_STAT_ERRORS \
+ (ETH_RX_STAT_CRC_ERROR \
+ | ETH_RX_STAT_SYMBOL_ERROR \
+ | ETH_RX_STAT_LENGTH_ERROR \
+ | ETH_RX_STAT_ALIGNMENT_ERROR \
+ | ETH_RX_STAT_OVERRUN \
+ | ETH_RX_STAT_NO_DESCRIPTOR)
+
+#define LPC_ETH_LAST_FRAGMENT_FLAGS \
+ (ETH_TX_CTRL_OVERRIDE \
+ | ETH_TX_CTRL_PAD \
+ | ETH_TX_CTRL_CRC \
+ | ETH_TX_CTRL_INTERRUPT \
+ | ETH_TX_CTRL_LAST)
+
+/* Debug */
+
+#ifdef DEBUG
+ #define LPC_ETH_PRINTF(...) printf(__VA_ARGS__)
+ #define LPC_ETH_PRINTK(...) printk(__VA_ARGS__)
+#else
+ #define LPC_ETH_PRINTF(...)
+ #define LPC_ETH_PRINTK(...)
+#endif
+
+typedef enum {
+ LPC_ETH_NOT_INITIALIZED,
+ LPC_ETH_INITIALIZED,
+ LPC_ETH_STARTED,
+ LPC_ETH_RUNNING
+} lpc_eth_state;
+
+typedef struct {
+ struct arpcom arpcom;
+ struct rtems_mdio_info mdio_info;
+ lpc_eth_state state;
+ rtems_id receive_task;
+ rtems_id transmit_task;
+ unsigned rx_unit_count;
+ unsigned tx_unit_count;
+ volatile lpc_eth_transfer_descriptor *rx_desc_table;
+ volatile lpc_eth_receive_status *rx_status_table;
+ struct mbuf **rx_mbuf_table;
+ volatile lpc_eth_transfer_descriptor *tx_desc_table;
+ volatile uint32_t *tx_status_table;
+ void *tx_buf_table;
+ unsigned received_frames;
+ unsigned receive_interrupts;
+ unsigned transmitted_frames;
+ unsigned transmit_interrupts;
+ unsigned receive_overrun_errors;
+ unsigned receive_fragment_errors;
+ unsigned receive_crc_errors;
+ unsigned receive_symbol_errors;
+ unsigned receive_length_errors;
+ unsigned receive_alignment_errors;
+ unsigned receive_no_descriptor_errors;
+ unsigned receive_fatal_errors;
+ unsigned transmit_underrun_errors;
+ unsigned transmit_late_collision_errors;
+ unsigned transmit_excessive_collision_errors;
+ unsigned transmit_excessive_defer_errors;
+ unsigned transmit_no_descriptor_errors;
+ unsigned transmit_overflow_errors;
+ unsigned transmit_fatal_errors;
+} lpc_eth_driver_entry;
+
+static lpc_eth_driver_entry lpc_eth_driver_data = {
+ .state = LPC_ETH_NOT_INITIALIZED,
+ .receive_task = RTEMS_ID_NONE,
+ .transmit_task = RTEMS_ID_NONE
+};
+
+static inline uint32_t lpc_eth_increment(
+ uint32_t value,
+ uint32_t cycle
+)
+{
+ if (value < cycle) {
+ return ++value;
+ } else {
+ return 0;
+ }
+}
+
+static void lpc_eth_enable_promiscous_mode(bool enable)
+{
+ if (enable) {
+ lpc_eth->rxfilterctrl = ETH_RX_FIL_CTRL_ACCEPT_PERFECT
+ | ETH_RX_FIL_CTRL_ACCEPT_UNICAST
+ | ETH_RX_FIL_CTRL_ACCEPT_MULTICAST
+ | ETH_RX_FIL_CTRL_ACCEPT_BROADCAST;
+ } else {
+ lpc_eth->rxfilterctrl = ETH_RX_FIL_CTRL_ACCEPT_PERFECT
+ | ETH_RX_FIL_CTRL_ACCEPT_BROADCAST;
+ }
+}
+
+static void lpc_eth_interrupt_handler(void *arg)
+{
+ lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
+ rtems_event_set re = 0;
+ rtems_event_set te = 0;
+ uint32_t ie = 0;
+
+ /* Get interrupt status */
+ uint32_t im = lpc_eth->intenable;
+ uint32_t is = lpc_eth->intstatus & im;
+
+ /* Check receive interrupts */
+ if ((is & ETH_INT_RX_OVERRUN) != 0) {
+ re = LPC_ETH_EVENT_INITIALIZE;
+ ++e->receive_fatal_errors;
+ } else if ((is & LPC_ETH_INTERRUPT_RECEIVE) != 0) {
+ re = LPC_ETH_EVENT_INTERRUPT;
+ ie |= LPC_ETH_INTERRUPT_RECEIVE;
+ }
+
+ /* Send events to receive task */
+ if (re != 0) {
+ ++e->receive_interrupts;
+ (void) rtems_event_send(e->receive_task, re);
+ }
+
+ /* Check transmit interrupts */
+ if ((is & ETH_INT_TX_UNDERRUN) != 0) {
+ te = LPC_ETH_EVENT_INITIALIZE;
+ ++e->transmit_fatal_errors;
+ } else if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) {
+ te = LPC_ETH_EVENT_INTERRUPT;
+ ie |= LPC_ETH_INTERRUPT_TRANSMIT;
+ }
+
+ /* Send events to transmit task */
+ if (te != 0) {
+ ++e->transmit_interrupts;
+ (void) rtems_event_send(e->transmit_task, te);
+ }
+
+ LPC_ETH_PRINTK("interrupt: rx = 0x%08x, tx = 0x%08x\n", re, te);
+
+ /* Update interrupt mask */
+ lpc_eth->intenable = im & ~ie;
+
+ /* Clear interrupts */
+ lpc_eth->intclear = is;
+}
+
+static void lpc_eth_enable_receive_interrupts(void)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ lpc_eth->intenable |= LPC_ETH_INTERRUPT_RECEIVE;
+ rtems_interrupt_enable(level);
+}
+
+static void lpc_eth_disable_receive_interrupts(void)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ lpc_eth->intenable &= ~LPC_ETH_INTERRUPT_RECEIVE;
+ rtems_interrupt_enable(level);
+}
+
+static void lpc_eth_enable_transmit_interrupts(void)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ lpc_eth->intenable |= LPC_ETH_INTERRUPT_TRANSMIT;
+ rtems_interrupt_enable(level);
+}
+
+static void lpc_eth_disable_transmit_interrupts(void)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ lpc_eth->intenable &= ~LPC_ETH_INTERRUPT_TRANSMIT;
+ rtems_interrupt_enable(level);
+}
+
+#define LPC_ETH_RX_DATA_OFFSET 2
+
+static struct mbuf *lpc_eth_new_mbuf(struct ifnet *ifp, bool wait)
+{
+ struct mbuf *m = NULL;
+ int mw = wait ? M_WAIT : M_DONTWAIT;
+
+ MGETHDR(m, mw, MT_DATA);
+ if (m != NULL) {
+ MCLGET(m, mw);
+ if ((m->m_flags & M_EXT) != 0) {
+ /* Set receive interface */
+ m->m_pkthdr.rcvif = ifp;
+
+ /* Adjust by two bytes for proper IP header alignment */
+ m->m_data = mtod(m, char *) + LPC_ETH_RX_DATA_OFFSET;
+
+ return m;
+ } else {
+ m_free(m);
+ }
+ }
+
+ return NULL;
+}
+
+static bool lpc_eth_add_new_mbuf(
+ struct ifnet *ifp,
+ volatile lpc_eth_transfer_descriptor *desc,
+ struct mbuf **mbufs,
+ uint32_t i,
+ bool wait
+)
+{
+ /* New mbuf */
+ struct mbuf *m = lpc_eth_new_mbuf(ifp, wait);
+
+ /* Check mbuf */
+ if (m != NULL) {
+ /* Cache invalidate */
+ rtems_cache_invalidate_multiple_data_lines(
+ mtod(m, void *),
+ MCLBYTES - LPC_ETH_RX_DATA_OFFSET
+ );
+
+ /* Add mbuf to queue */
+ desc [i].start = mtod(m, uint32_t);
+ desc [i].control = (MCLBYTES - LPC_ETH_RX_DATA_OFFSET - 1)
+ | ETH_RX_CTRL_INTERRUPT;
+
+ /* Cache flush of descriptor */
+ rtems_cache_flush_multiple_data_lines(&desc [i], sizeof(desc [0]));
+
+ /* Add mbuf to table */
+ mbufs [i] = m;
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void lpc_eth_receive_task(void *arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_event_set events = 0;
+ lpc_eth_driver_entry *const e = (lpc_eth_driver_entry *) arg;
+ struct ifnet *const ifp = &e->arpcom.ac_if;
+ volatile lpc_eth_transfer_descriptor *const desc = e->rx_desc_table;
+ volatile lpc_eth_receive_status *const status = e->rx_status_table;
+ struct mbuf **const mbufs = e->rx_mbuf_table;
+ uint32_t const index_max = e->rx_unit_count - 1;
+ uint32_t produce_index = 0;
+ uint32_t consume_index = 0;
+ uint32_t receive_index = 0;
+
+ LPC_ETH_PRINTF("%s\n", __func__);
+
+ /* Main event loop */
+ while (true) {
+ bool wait_for_mbuf = false;
+
+ /* Wait for events */
+ sc = rtems_bsdnet_event_receive(
+ LPC_ETH_EVENT_INITIALIZE | LPC_ETH_EVENT_INTERRUPT,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events
+ );
+ RTEMS_CLEANUP_SC(sc, cleanup, "wait for events");
+
+ LPC_ETH_PRINTF("rx: wake up: 0x%08" PRIx32 "\n", events);
+
+ /* Initialize receiver? */
+ if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
+ /* Disable receive interrupts */
+ lpc_eth_disable_receive_interrupts();
+
+ /* Disable receiver */
+ lpc_eth->command &= ~ETH_CMD_RX_ENABLE;
+
+ /* Wait for inactive status */
+ while ((lpc_eth->status & ETH_STAT_RX_ACTIVE) != 0) {
+ /* Wait */
+ }
+
+ /* Reset */
+ lpc_eth->command |= ETH_CMD_RX_RESET;
+
+ /* Clear receive interrupts */
+ lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE;
+
+ /* Move existing mbufs to the front */
+ consume_index = 0;
+ for (produce_index = 0; produce_index <= index_max; ++produce_index) {
+ if (mbufs [produce_index] != NULL) {
+ mbufs [consume_index] = mbufs [produce_index];
+ ++consume_index;
+ }
+ }
+
+ /* Fill receive queue */
+ for (
+ produce_index = consume_index;
+ produce_index <= index_max;
+ ++produce_index
+ ) {
+ lpc_eth_add_new_mbuf(ifp, desc, mbufs, produce_index, true);
+ }
+
+ /* Receive descriptor table */
+ lpc_eth->rxdescriptornum = index_max;
+ lpc_eth->rxdescriptor = (uint32_t) desc;
+ lpc_eth->rxstatus = (uint32_t) status;
+
+ /* Initialize indices */
+ produce_index = lpc_eth->rxproduceindex;
+ consume_index = lpc_eth->rxconsumeindex;
+ receive_index = consume_index;
+
+ /* Enable receiver */
+ lpc_eth->command |= ETH_CMD_RX_ENABLE;
+
+ /* Enable receive interrupts */
+ lpc_eth_enable_receive_interrupts();
+
+ /* Wait for events */
+ continue;
+ }
+
+ while (true) {
+ /* Clear receive interrupt status */
+ lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE;
+
+ /* Get current produce index */
+ produce_index = lpc_eth->rxproduceindex;
+
+ if (receive_index != produce_index) {
+ uint32_t stat = 0;
+
+ /* Fragment mbuf */
+ struct mbuf *m = mbufs [receive_index];
+
+ /* Fragment status */
+ rtems_cache_invalidate_multiple_data_lines(
+ &status [receive_index],
+ sizeof(status [0])
+ );
+ stat = status [receive_index].info;
+
+ /* Remove mbuf from table */
+ mbufs [receive_index] = NULL;
+
+ if (
+ (stat & ETH_RX_STAT_LAST_FLAG) != 0
+ && (stat & LPC_ETH_RX_STAT_ERRORS) == 0
+ ) {
+ /* Ethernet header */
+ struct ether_header *eh = mtod(m, struct ether_header *);
+
+ /* Discard Ethernet header and CRC */
+ int sz = (int) (stat & ETH_RX_STAT_RXSIZE_MASK) + 1
+ - ETHER_HDR_LEN - ETHER_CRC_LEN;
+
+ /* Update mbuf */
+ m->m_len = sz;
+ m->m_pkthdr.len = sz;
+ m->m_data = mtod(m, char *) + ETHER_HDR_LEN;
+
+ LPC_ETH_PRINTF("rx: %02" PRIu32 ": %u\n", receive_index, sz);
+
+ /* Hand over */
+ ether_input(ifp, eh, m);
+
+ /* Increment received frames counter */
+ ++e->received_frames;
+ } else {
+ /* Release mbuf */
+ m_free(m);
+
+ /* Update error counters */
+ if ((stat & ETH_RX_STAT_OVERRUN) != 0) {
+ ++e->receive_overrun_errors;
+ }
+ if ((stat & ETH_RX_STAT_LAST_FLAG) == 0) {
+ ++e->receive_fragment_errors;
+ }
+ if ((stat & ETH_RX_STAT_CRC_ERROR) != 0) {
+ ++e->receive_crc_errors;
+ }
+ if ((stat & ETH_RX_STAT_SYMBOL_ERROR) != 0) {
+ ++e->receive_symbol_errors;
+ }
+ if ((stat & ETH_RX_STAT_LENGTH_ERROR) != 0) {
+ ++e->receive_length_errors;
+ }
+ if ((stat & ETH_RX_STAT_ALIGNMENT_ERROR) != 0) {
+ ++e->receive_alignment_errors;
+ }
+ if ((stat & ETH_RX_STAT_NO_DESCRIPTOR) != 0) {
+ ++e->receive_no_descriptor_errors;
+ }
+ }
+
+ /* Increment receive index */
+ receive_index = lpc_eth_increment(receive_index, index_max);
+ } else {
+ /* Nothing to do, enable receive interrupts */
+ lpc_eth_enable_receive_interrupts();
+ break;
+ }
+ }
+
+ /* Wait for mbuf? */
+ wait_for_mbuf =
+ lpc_eth_increment(produce_index, index_max) == consume_index;
+
+ /* Fill queue with new mbufs */
+ while (consume_index != produce_index) {
+ /* Add new mbuf to queue */
+ if (
+ !lpc_eth_add_new_mbuf(ifp, desc, mbufs, consume_index, wait_for_mbuf)
+ ) {
+ break;
+ }
+
+ /* We wait for at most one mbuf */
+ wait_for_mbuf = false;
+
+ /* Increment consume index */
+ consume_index = lpc_eth_increment(consume_index, index_max);
+
+ /* Update consume indices */
+ lpc_eth->rxconsumeindex = consume_index;
+ }
+ }
+
+cleanup:
+
+ /* Clear task ID */
+ e->receive_task = RTEMS_ID_NONE;
+
+ /* Release network semaphore */
+ rtems_bsdnet_semaphore_release();
+
+ /* Terminate self */
+ (void) rtems_task_delete(RTEMS_SELF);
+}
+
+static struct mbuf *lpc_eth_next_fragment(
+ struct ifnet *ifp,
+ struct mbuf *m,
+ uint32_t *ctrl
+)
+{
+ struct mbuf *n = NULL;
+ int size = 0;
+
+ while (true) {
+ if (m == NULL) {
+ /* Dequeue first fragment of the next frame */
+ IF_DEQUEUE(&ifp->if_snd, m);
+
+ /* Empty queue? */
+ if (m == NULL) {
+ return m;
+ }
+ }
+
+ /* Get fragment size */
+ size = m->m_len;
+
+ if (size > 0) {
+ /* Now we have a not empty fragment */
+ break;
+ } else {
+ /* Discard empty fragments */
+ m = m_free(m);
+ }
+ }
+
+ /* Set fragment size */
+ *ctrl = (uint32_t) (size - 1);
+
+ /* Discard empty successive fragments */
+ n = m->m_next;
+ while (n != NULL && n->m_len <= 0) {
+ n = m_free(n);
+ }
+ m->m_next = n;
+
+ /* Is our fragment the last in the frame? */
+ if (n == NULL) {
+ *ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS;
+ }
+
+ return m;
+}
+
+static void lpc_eth_transmit_task(void *arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_event_set events = 0;
+ lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
+ struct ifnet *ifp = &e->arpcom.ac_if;
+ volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table;
+ volatile uint32_t *const status = e->tx_status_table;
+ #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ struct mbuf **const mbufs = e->tx_buf_table;
+ #else
+ char *const buf = e->tx_buf_table;
+ #endif
+ struct mbuf *m = NULL;
+ uint32_t const index_max = e->tx_unit_count - 1;
+ uint32_t produce_index = 0;
+ uint32_t consume_index = 0;
+ uint32_t ctrl = 0;
+ #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ uint32_t frame_length = 0;
+ char *frame_buffer = NULL;
+ #endif
+
+ LPC_ETH_PRINTF("%s\n", __func__);
+
+ #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ /* Initialize descriptor table */
+ for (produce_index = 0; produce_index <= index_max; ++produce_index) {
+ desc [produce_index].start =
+ (uint32_t) (buf + produce_index * LPC_ETH_CONFIG_TX_BUF_SIZE);
+ }
+ #endif
+
+ /* Main event loop */
+ while (true) {
+ /* Wait for events */
+ sc = rtems_bsdnet_event_receive(
+ LPC_ETH_EVENT_INITIALIZE
+ | LPC_ETH_EVENT_START
+ | LPC_ETH_EVENT_INTERRUPT,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events
+ );
+ RTEMS_CLEANUP_SC(sc, cleanup, "wait for events");
+
+ LPC_ETH_PRINTF("tx: wake up: 0x%08" PRIx32 "\n", events);
+
+ /* Initialize transmitter? */
+ if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
+ /* Disable transmit interrupts */
+ lpc_eth_disable_transmit_interrupts();
+
+ /* Disable transmitter */
+ lpc_eth->command &= ~ETH_CMD_TX_ENABLE;
+
+ /* Wait for inactive status */
+ while ((lpc_eth->status & ETH_STAT_TX_ACTIVE) != 0) {
+ /* Wait */
+ }
+
+ /* Reset */
+ lpc_eth->command |= ETH_CMD_TX_RESET;
+
+ /* Clear transmit interrupts */
+ lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
+
+ /* Transmit descriptors */
+ lpc_eth->txdescriptornum = index_max;
+ lpc_eth->txdescriptor = (uint32_t) desc;
+ lpc_eth->txstatus = (uint32_t) status;
+
+ #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ /* Discard outstanding fragments (= data loss) */
+ for (produce_index = 0; produce_index <= index_max; ++produce_index) {
+ struct mbuf *victim = mbufs [produce_index];
+
+ if (victim != NULL) {
+ m_free(victim);
+ mbufs [produce_index] = NULL;
+ }
+ }
+ #endif
+
+ /* Initialize indices */
+ produce_index = lpc_eth->txproduceindex;
+ consume_index = lpc_eth->txconsumeindex;
+
+ #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ /* Fresh frame length and buffer start */
+ frame_length = 0;
+ frame_buffer = (char *) desc [produce_index].start;
+ #endif
+
+ /* Enable transmitter */
+ lpc_eth->command |= ETH_CMD_TX_ENABLE;
+ }
+
+ /* Free consumed fragments */
+ while (true) {
+ /* Save last known consume index */
+ uint32_t c = consume_index;
+
+ /* Clear transmit interrupt status */
+ lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
+
+ /* Get new consume index */
+ consume_index = lpc_eth->txconsumeindex;
+
+ /* Nothing consumed in the meantime? */
+ if (c == consume_index) {
+ break;
+ }
+
+ while (c != consume_index) {
+ uint32_t s = status [c];
+
+ /* Update error counters */
+ if ((s & (ETH_TX_STAT_ERROR | ETH_TX_STAT_NO_DESCRIPTOR)) != 0) {
+ if ((s & ETH_TX_STAT_UNDERRUN) != 0) {
+ ++e->transmit_underrun_errors;
+ }
+ if ((s & ETH_TX_STAT_LATE_COLLISION) != 0) {
+ ++e->transmit_late_collision_errors;
+ }
+ if ((s & ETH_TX_STAT_EXCESSIVE_COLLISION) != 0) {
+ ++e->transmit_excessive_collision_errors;
+ }
+ if ((s & ETH_TX_STAT_EXCESSIVE_DEFER) != 0) {
+ ++e->transmit_excessive_defer_errors;
+ }
+ if ((s & ETH_TX_STAT_NO_DESCRIPTOR) != 0) {
+ ++e->transmit_no_descriptor_errors;
+ }
+ }
+
+ #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ /* Release mbuf */
+ m_free(mbufs [c]);
+ mbufs [c] = NULL;
+ #endif
+
+ /* Next consume index */
+ c = lpc_eth_increment(c, index_max);
+ }
+ }
+
+ /* Transmit new fragments */
+ while (true) {
+ /* Compute next produce index */
+ uint32_t p = lpc_eth_increment(produce_index, index_max);
+
+ /* Get next fragment and control value */
+ m = lpc_eth_next_fragment(ifp, m, &ctrl);
+
+ /* Queue full? */
+ if (p == consume_index) {
+ LPC_ETH_PRINTF("tx: full queue: 0x%08x\n", m);
+
+ /* The queue is full, wait for transmit interrupt */
+ break;
+ }
+
+ /* New fragment? */
+ if (m != NULL) {
+ #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+ /* Set the transfer data */
+ rtems_cache_flush_multiple_data_lines(
+ mtod(m, const void *),
+ (size_t) m->m_len
+ );
+ desc [produce_index].start = mtod(m, uint32_t);
+ desc [produce_index].control = ctrl;
+ rtems_cache_flush_multiple_data_lines(
+ &desc [produce_index],
+ sizeof(desc [0])
+ );
+ mbufs [produce_index] = m;
+
+ LPC_ETH_PRINTF(
+ "tx: %02" PRIu32 ": %u %s\n",
+ produce_index, m->m_len,
+ (ctrl & ETH_TX_CTRL_LAST) != 0 ? "L" : ""
+ );
+
+ /* Next produce index */
+ produce_index = p;
+
+ /* Last fragment of a frame? */
+ if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
+ /* Update the produce index */
+ lpc_eth->txproduceindex = produce_index;
+
+ /* Increment transmitted frames counter */
+ ++e->transmitted_frames;
+ }
+
+ /* Next fragment of the frame */
+ m = m->m_next;
+ #else
+ size_t fragment_length = (size_t) m->m_len;
+ void *fragment_start = mtod(m, void *);
+ uint32_t new_frame_length = frame_length + fragment_length;
+
+ /* Check buffer size */
+ if (new_frame_length > LPC_ETH_CONFIG_TX_BUF_SIZE) {
+ LPC_ETH_PRINTF("tx: overflow\n");
+
+ /* Discard overflow data */
+ new_frame_length = LPC_ETH_CONFIG_TX_BUF_SIZE;
+ fragment_length = new_frame_length - frame_length;
+
+ /* Finalize frame */
+ ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS;
+
+ /* Update error counter */
+ ++e->transmit_overflow_errors;
+ }
+
+ LPC_ETH_PRINTF(
+ "tx: copy: %" PRIu32 "%s%s\n",
+ fragment_length,
+ (m->m_flags & M_EXT) != 0 ? ", E" : "",
+ (m->m_flags & M_PKTHDR) != 0 ? ", H" : ""
+ );
+
+ /* Copy fragment to buffer in Ethernet RAM */
+ memcpy(frame_buffer, fragment_start, fragment_length);
+
+ if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
+ /* Finalize descriptor */
+ desc [produce_index].control = ctrl & ~ETH_TX_CTRL_SIZE_MASK
+ | (new_frame_length - 1);
+
+ LPC_ETH_PRINTF(
+ "tx: %02" PRIu32 ": %" PRIu32 "\n",
+ produce_index,
+ new_frame_length
+ );
+
+ /* Cache flush of data */
+ rtems_cache_flush_multiple_data_lines(
+ (const void *) desc [produce_index].start,
+ new_frame_length
+ );
+
+ /* Cache flush of descriptor */
+ rtems_cache_flush_multiple_data_lines(
+ &desc [produce_index],
+ sizeof(desc [0])
+ );
+
+ /* Next produce index */
+ produce_index = p;
+
+ /* Update the produce index */
+ lpc_eth->txproduceindex = produce_index;
+
+ /* Fresh frame length and buffer start */
+ frame_length = 0;
+ frame_buffer = (char *) desc [produce_index].start;
+
+ /* Increment transmitted frames counter */
+ ++e->transmitted_frames;
+ } else {
+ /* New frame length */
+ frame_length = new_frame_length;
+
+ /* Update current frame buffer start */
+ frame_buffer += fragment_length;
+ }
+
+ /* Free mbuf and get next */
+ m = m_free(m);
+ #endif
+ } else {
+ /* Nothing to transmit */
+ break;
+ }
+ }
+
+ /* No more fragments? */
+ if (m == NULL) {
+ /* Interface is now inactive */
+ ifp->if_flags &= ~IFF_OACTIVE;
+ } else {
+ LPC_ETH_PRINTF("tx: enable interrupts\n");
+
+ /* Enable transmit interrupts */
+ lpc_eth_enable_transmit_interrupts();
+ }
+ }
+
+cleanup:
+
+ /* Clear task ID */
+ e->transmit_task = RTEMS_ID_NONE;
+
+ /* Release network semaphore */
+ rtems_bsdnet_semaphore_release();
+
+ /* Terminate self */
+ (void) rtems_task_delete(RTEMS_SELF);
+}
+
+static void lpc_eth_interface_init(void *arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
+ struct ifnet *ifp = &e->arpcom.ac_if;
+
+ LPC_ETH_PRINTF("%s\n", __func__);
+
+ if (e->state == LPC_ETH_INITIALIZED) {
+ lpc_eth_config_module_enable();
+
+ /* Soft reset */
+
+ /* Do soft reset */
+ lpc_eth->command = 0x38;
+ lpc_eth->mac1 = 0xcf00;
+ lpc_eth->mac1 = 0x0;
+
+ /* Initialize PHY */
+ /* TODO */
+
+ /* Reinitialize registers */
+ lpc_eth->mac2 = 0x31;
+ lpc_eth->ipgt = 0x15;
+ lpc_eth->ipgr = 0x12;
+ lpc_eth->clrt = 0x370f;
+ lpc_eth->maxf = 0x0600;
+ lpc_eth->supp = 0x0100;
+ lpc_eth->test = 0;
+ #ifdef LPC_ETH_CONFIG_RMII
+ lpc_eth->command = 0x0600;
+ #else
+ lpc_eth->command = 0x0400;
+ #endif
+ lpc_eth->intenable = 0;
+ lpc_eth->intclear = 0x30ff;
+ lpc_eth->powerdown = 0;
+
+ /* MAC address */
+ lpc_eth->sa0 = ((uint32_t) e->arpcom.ac_enaddr [5] << 8)
+ | (uint32_t) e->arpcom.ac_enaddr [4];
+ lpc_eth->sa1 = ((uint32_t) e->arpcom.ac_enaddr [3] << 8)
+ | (uint32_t) e->arpcom.ac_enaddr [2];
+ lpc_eth->sa2 = ((uint32_t) e->arpcom.ac_enaddr [1] << 8)
+ | (uint32_t) e->arpcom.ac_enaddr [0];
+
+ /* Enable receiver */
+ lpc_eth->mac1 = 0x03;
+
+ /* Start receive task */
+ if (e->receive_task == RTEMS_ID_NONE) {
+ e->receive_task = rtems_bsdnet_newproc(
+ "ntrx",
+ 4096,
+ lpc_eth_receive_task,
+ e
+ );
+ sc = rtems_event_send(e->receive_task, LPC_ETH_EVENT_INITIALIZE);
+ RTEMS_SYSLOG_ERROR_SC(sc, "send receive initialize event");
+ }
+
+ /* Start transmit task */
+ if (e->transmit_task == RTEMS_ID_NONE) {
+ e->transmit_task = rtems_bsdnet_newproc(
+ "nttx",
+ 4096,
+ lpc_eth_transmit_task,
+ e
+ );
+ sc = rtems_event_send(e->transmit_task, LPC_ETH_EVENT_INITIALIZE);
+ RTEMS_SYSLOG_ERROR_SC(sc, "send transmit initialize event");
+ }
+
+ /* Change state */
+ if (
+ e->receive_task != RTEMS_ID_NONE && e->transmit_task != RTEMS_ID_NONE
+ ) {
+ e->state = LPC_ETH_STARTED;
+ }
+ }
+
+ if (e->state == LPC_ETH_STARTED) {
+ /* Enable fatal interrupts */
+ lpc_eth->intenable = ETH_INT_RX_OVERRUN | ETH_INT_TX_UNDERRUN;
+
+ /* Enable promiscous mode */
+ lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0);
+
+ /* Start watchdog timer */
+ ifp->if_timer = 1;
+
+ /* Set interface to running state */
+ ifp->if_flags |= IFF_RUNNING;
+
+ /* Change state */
+ e->state = LPC_ETH_RUNNING;
+ }
+}
+
+static void lpc_eth_interface_stats(const lpc_eth_driver_entry *e)
+{
+ rtems_bsdnet_semaphore_release();
+
+ printf("received frames: %u\n", e->received_frames);
+ printf("receive interrupts: %u\n", e->receive_interrupts);
+ printf("transmitted frames: %u\n", e->transmitted_frames);
+ printf("transmit interrupts: %u\n", e->transmit_interrupts);
+ printf("receive overrun errors: %u\n", e->receive_overrun_errors);
+ printf("receive fragment errors: %u\n", e->receive_fragment_errors);
+ printf("receive CRC errors: %u\n", e->receive_crc_errors);
+ printf("receive symbol errors: %u\n", e->receive_symbol_errors);
+ printf("receive length errors: %u\n", e->receive_length_errors);
+ printf("receive alignment errors: %u\n", e->receive_alignment_errors);
+ printf("receive no descriptor errors: %u\n", e->receive_no_descriptor_errors);
+ printf("receive fatal errors: %u\n", e->receive_fatal_errors);
+ printf("transmit underrun errors: %u\n", e->transmit_underrun_errors);
+ printf("transmit late collision errors: %u\n", e->transmit_late_collision_errors);
+ printf("transmit excessive collision errors: %u\n", e->transmit_excessive_collision_errors);
+ printf("transmit excessive defer errors: %u\n", e->transmit_excessive_defer_errors);
+ printf("transmit no descriptor errors: %u\n", e->transmit_no_descriptor_errors);
+ printf("transmit overflow errors: %u\n", e->transmit_overflow_errors);
+ printf("transmit fatal errors: %u\n", e->transmit_fatal_errors);
+
+ rtems_bsdnet_semaphore_obtain();
+}
+
+static int lpc_eth_interface_ioctl(
+ struct ifnet *ifp,
+ ioctl_command_t command,
+ caddr_t data
+)
+{
+ lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
+ int rv = 0;
+
+ LPC_ETH_PRINTF("%s\n", __func__);
+
+ switch (command) {
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ rtems_mii_ioctl(&e->mdio_info, e, (int) command, (int *) data);
+ break;
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ ether_ioctl(ifp, command, data);
+ break;
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_RUNNING) {
+ /* TODO: off */
+ }
+ if (ifp->if_flags & IFF_UP) {
+ ifp->if_flags |= IFF_RUNNING;
+ /* TODO: init */
+ }
+ break;
+ case SIO_RTEMS_SHOW_STATS:
+ lpc_eth_interface_stats(e);
+ break;
+ default:
+ rv = EINVAL;
+ break;
+ }
+
+ return rv;
+}
+
+static void lpc_eth_interface_start(struct ifnet *ifp)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
+
+ ifp->if_flags |= IFF_OACTIVE;
+
+ sc = rtems_event_send(e->transmit_task, LPC_ETH_EVENT_START);
+ RTEMS_SYSLOG_ERROR_SC(sc, "send transmit start event");
+}
+
+static void lpc_eth_interface_watchdog(struct ifnet *ifp __attribute__((unused)))
+{
+ LPC_ETH_PRINTF("%s\n", __func__);
+}
+
+static unsigned lpc_eth_fixup_unit_count(int count, int default_value, int max)
+{
+ if (count <= 0) {
+ count = default_value;
+ } else if (count > max) {
+ count = max;
+ }
+
+ return LPC_ETH_CONFIG_UNIT_MULTIPLE
+ + (((unsigned) count - 1U) & ~(LPC_ETH_CONFIG_UNIT_MULTIPLE - 1U));
+}
+
+static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ lpc_eth_driver_entry *e = &lpc_eth_driver_data;
+ struct ifnet *ifp = &e->arpcom.ac_if;
+ char *unit_name = NULL;
+ int unit_index = rtems_bsdnet_parse_driver_name(config, &unit_name);
+ size_t table_area_size = 0;
+ char *table_area = NULL;
+ char *table_location = NULL;
+
+ /* Check parameter */
+ if (unit_index < 0) {
+ RTEMS_SYSLOG_ERROR("parse error for interface name\n");
+ return 0;
+ }
+ if (unit_index != 0) {
+ RTEMS_DO_CLEANUP(cleanup, "unexpected unit number");
+ }
+ if (config->hardware_address == NULL) {
+ RTEMS_DO_CLEANUP(cleanup, "MAC address missing");
+ }
+ if (e->state != LPC_ETH_NOT_INITIALIZED) {
+ RTEMS_DO_CLEANUP(cleanup, "already attached");
+ }
+
+ /* Interrupt number */
+ config->irno = LPC_ETH_CONFIG_INTERRUPT;
+
+ /* Device control */
+ config->drv_ctrl = e;
+
+ /* Receive unit count */
+ e->rx_unit_count = lpc_eth_fixup_unit_count(
+ config->rbuf_count,
+ LPC_ETH_CONFIG_RX_UNIT_COUNT_DEFAULT,
+ LPC_ETH_CONFIG_RX_UNIT_COUNT_MAX
+ );
+ config->rbuf_count = (int) e->rx_unit_count;
+
+ /* Transmit unit count */
+ e->tx_unit_count = lpc_eth_fixup_unit_count(
+ config->xbuf_count,
+ LPC_ETH_CONFIG_TX_UNIT_COUNT_DEFAULT,
+ LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX
+ );
+ config->xbuf_count = (int) e->tx_unit_count;
+
+ /* Disable interrupts */
+ lpc_eth->intenable = 0;
+
+ /* Install interrupt handler */
+ sc = rtems_interrupt_handler_install(
+ config->irno,
+ "Ethernet",
+ RTEMS_INTERRUPT_UNIQUE,
+ lpc_eth_interrupt_handler,
+ e
+ );
+ RTEMS_CLEANUP_SC(sc, cleanup, "install interrupt handler");
+
+ /* Copy MAC address */
+ memcpy(e->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
+
+ /* Allocate and clear table area */
+ table_area_size =
+ e->rx_unit_count
+ * (sizeof(lpc_eth_transfer_descriptor)
+ + sizeof(lpc_eth_receive_status)
+ + sizeof(struct mbuf *))
+ + e->tx_unit_count
+ * (sizeof(lpc_eth_transfer_descriptor)
+ + sizeof(uint32_t)
+ + LPC_ETH_CONFIG_TX_BUF_SIZE);
+ table_area = lpc_eth_config_alloc_table_area(table_area_size);
+ if (table_area == NULL) {
+ RTEMS_DO_CLEANUP(cleanup, "no memory for table area");
+ }
+ memset(table_area, 0, table_area_size);
+
+ table_location = table_area;
+
+ /*
+ * The receive status table must be the first one since it has the strictest
+ * alignment requirements.
+ */
+ e->rx_status_table = (volatile lpc_eth_receive_status *) table_location;
+ table_location += e->rx_unit_count * sizeof(e->rx_status_table [0]);
+
+ e->rx_desc_table = (volatile lpc_eth_transfer_descriptor *) table_location;
+ table_location += e->rx_unit_count * sizeof(e->rx_desc_table [0]);
+
+ e->rx_mbuf_table = (struct mbuf **) table_location;
+ table_location += e->rx_unit_count * sizeof(e->rx_mbuf_table [0]);
+
+ e->tx_desc_table = (volatile lpc_eth_transfer_descriptor *) table_location;
+ table_location += e->tx_unit_count * sizeof(e->tx_desc_table [0]);
+
+ e->tx_status_table = (volatile uint32_t *) table_location;
+ table_location += e->tx_unit_count * sizeof(e->tx_status_table [0]);
+
+ e->tx_buf_table = table_location;
+
+ /* Set interface data */
+ ifp->if_softc = e;
+ ifp->if_unit = (short) unit_index;
+ ifp->if_name = unit_name;
+ ifp->if_mtu = (config->mtu > 0) ? (u_long) config->mtu : ETHERMTU;
+ ifp->if_init = lpc_eth_interface_init;
+ ifp->if_ioctl = lpc_eth_interface_ioctl;
+ ifp->if_start = lpc_eth_interface_start;
+ ifp->if_output = ether_output;
+ ifp->if_watchdog = lpc_eth_interface_watchdog;
+ ifp->if_flags = config->ignore_broadcast ? 0 : IFF_BROADCAST;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_timer = 0;
+
+ /* Change status */
+ e->state = LPC_ETH_INITIALIZED;
+
+ /* Attach the interface */
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+ return 1;
+
+cleanup:
+
+ lpc_eth_config_free_table_area(table_area);
+
+ /* FIXME: Type */
+ free(unit_name, (int) 0xdeadbeef);
+
+ return 0;
+}
+
+static int lpc_eth_detach(
+ struct rtems_bsdnet_ifconfig *config __attribute__((unused))
+)
+{
+ /* FIXME: Detach the interface from the upper layers? */
+
+ /* Module soft reset */
+ lpc_eth->command = 0x38;
+ lpc_eth->mac1 = 0xcf00;
+
+ /* FIXME: More cleanup */
+
+ return 0;
+}
+
+int lpc_eth_attach_detach(
+ struct rtems_bsdnet_ifconfig *config,
+ int attaching
+)
+{
+ /* FIXME: Return value */
+
+ if (attaching) {
+ return lpc_eth_attach(config);
+ } else {
+ return lpc_eth_detach(config);
+ }
+}
diff --git a/c/src/lib/libbsp/arm/shared/start/start.S b/c/src/lib/libbsp/arm/shared/start/start.S
index 3b7c9fd5c2..d1843ce17f 100644
--- a/c/src/lib/libbsp/arm/shared/start/start.S
+++ b/c/src/lib/libbsp/arm/shared/start/start.S
@@ -17,6 +17,7 @@
*/
#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
#include <bspopts.h>
#include <bsp/linker-symbols.h>
@@ -33,19 +34,6 @@
.globl start
.globl bsp_start_memcpy
-/* Program Status Register definitions */
-
-.equ PSR_MODE_USR, 0x10
-.equ PSR_MODE_FIQ, 0x11
-.equ PSR_MODE_IRQ, 0x12
-.equ PSR_MODE_SVC, 0x13
-.equ PSR_MODE_ABT, 0x17
-.equ PSR_MODE_UNDEF, 0x1b
-.equ PSR_MODE_SYS, 0x1f
-.equ PSR_I, 0x80
-.equ PSR_F, 0x40
-.equ PSR_T, 0x20
-
.section ".bsp_start", "ax"
.arm
@@ -117,33 +105,33 @@ start:
/*
* Set SVC mode, disable interrupts and enable ARM instructions.
*/
- mov r0, #(PSR_MODE_SVC | PSR_I | PSR_F)
+ mov r0, #(ARM_PSR_M_SVC | ARM_PSR_I | ARM_PSR_F)
msr cpsr, r0
/* Initialize stack pointer registers for the various modes */
/* Enter IRQ mode and set up the IRQ stack pointer */
- mov r0, #(PSR_MODE_IRQ | PSR_I | PSR_F)
+ mov r0, #(ARM_PSR_M_IRQ | ARM_PSR_I | ARM_PSR_F)
msr cpsr, r0
ldr sp, =bsp_stack_irq_end
/* Enter FIQ mode and set up the FIQ stack pointer */
- mov r0, #(PSR_MODE_FIQ | PSR_I | PSR_F)
+ mov r0, #(ARM_PSR_M_FIQ | ARM_PSR_I | ARM_PSR_F)
msr cpsr, r0
ldr sp, =bsp_stack_fiq_end
/* Enter ABT mode and set up the ABT stack pointer */
- mov r0, #(PSR_MODE_ABT | PSR_I | PSR_F)
+ mov r0, #(ARM_PSR_M_ABT | ARM_PSR_I | ARM_PSR_F)
msr cpsr, r0
ldr sp, =bsp_stack_abt_end
- /* Enter UNDEF mode and set up the UNDEF stack pointer */
- mov r0, #(PSR_MODE_UNDEF | PSR_I | PSR_F)
+ /* Enter UND mode and set up the UND stack pointer */
+ mov r0, #(ARM_PSR_M_UND | ARM_PSR_I | ARM_PSR_F)
msr cpsr, r0
- ldr sp, =bsp_stack_undef_end
+ ldr sp, =bsp_stack_und_end
/* Enter SVC mode and set up the SVC stack pointer */
- mov r0, #(PSR_MODE_SVC | PSR_I | PSR_F)
+ mov r0, #(ARM_PSR_M_SVC | ARM_PSR_I | ARM_PSR_F)
msr cpsr, r0
ldr sp, =bsp_stack_svc_end
@@ -178,32 +166,16 @@ bsp_start_hook_0_done:
/* Branch to start hook 1 */
bl bsp_start_hook_1
+ SWITCH_FROM_ARM_TO_THUMB r0
+
/* Branch to boot card */
mov r0, #0
-#ifdef __thumb__
- ldr r3, =boot_card
- mov lr, pc
- bx r3
-.thumb
- bx pc
- nop
-.arm
-#else
bl boot_card
-#endif
/* Branch to reset function */
-#ifdef __thumb__
- ldr r3, =bsp_reset
- mov lr, pc
- bx r3
-.thumb
- bx pc
- nop
-.arm
-#else
bl bsp_reset
-#endif
+
+ SWITCH_FROM_THUMB_TO_ARM
/* Spin forever */
diff --git a/c/src/lib/libbsp/arm/shared/startup/linkcmds.base b/c/src/lib/libbsp/arm/shared/startup/linkcmds.base
index 0589169861..8e7764f5a3 100644
--- a/c/src/lib/libbsp/arm/shared/startup/linkcmds.base
+++ b/c/src/lib/libbsp/arm/shared/startup/linkcmds.base
@@ -25,16 +25,23 @@ OUTPUT_ARCH (arm)
ENTRY (start)
/*
- * BSP: Global symbols
+ * BSP: Global symbols that may be defined externally
*/
-bsp_section_align = 32;
+bsp_stack_align = DEFINED (bsp_stack_align) ? bsp_stack_align : 4;
-bsp_stack_align = 4;
+bsp_section_align = DEFINED (bsp_section_align) ? bsp_section_align : 32;
-/*
- * BSP: Symbols that may be defined externally
- */
+bsp_section_start_end_align = DEFINED (bsp_section_start_end_align) ? bsp_section_start_end_align : bsp_section_align;
+bsp_section_vector_end_align = DEFINED (bsp_section_vector_end_align) ? bsp_section_vector_end_align : bsp_section_align;
+bsp_section_text_end_align = DEFINED (bsp_section_text_end_align) ? bsp_section_text_end_align : bsp_section_align;
+bsp_section_rodata_end_align = DEFINED (bsp_section_rodata_end_align) ? bsp_section_rodata_end_align : bsp_section_align;
+bsp_section_data_end_align = DEFINED (bsp_section_data_end_align) ? bsp_section_data_end_align : bsp_section_align;
+bsp_section_fast_end_align = DEFINED (bsp_section_fast_end_align) ? bsp_section_fast_end_align : bsp_section_align;
+bsp_section_bss_end_align = DEFINED (bsp_section_bss_end_align) ? bsp_section_bss_end_align : bsp_section_align;
+
+bsp_section_vbarrier_align = DEFINED (bsp_section_vbarrier_align) ? bsp_section_vbarrier_align : 1;
+bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1;
bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 128;
bsp_stack_abt_size = ALIGN (bsp_stack_abt_size, bsp_stack_align);
@@ -48,8 +55,8 @@ bsp_stack_irq_size = ALIGN (bsp_stack_irq_size, bsp_stack_align);
bsp_stack_svc_size = DEFINED (bsp_stack_svc_size) ? bsp_stack_svc_size : 512;
bsp_stack_svc_size = ALIGN (bsp_stack_svc_size, bsp_stack_align);
-bsp_stack_undef_size = DEFINED (bsp_stack_undef_size) ? bsp_stack_undef_size : 128;
-bsp_stack_undef_size = ALIGN (bsp_stack_undef_size, bsp_stack_align);
+bsp_stack_und_size = DEFINED (bsp_stack_und_size) ? bsp_stack_und_size : 128;
+bsp_stack_und_size = ALIGN (bsp_stack_und_size, bsp_stack_align);
SECTIONS {
.start : {
@@ -62,8 +69,9 @@ SECTIONS {
* BSP: System startup entry
*/
KEEP (*(.bsp_start))
+ KEEP (*(.bsp_start_data))
- . = ALIGN (bsp_section_align);
+ . = ALIGN (bsp_section_start_end_align);
/*
* BSP: End of start section
@@ -107,16 +115,16 @@ SECTIONS {
. = . + bsp_stack_svc_size;
bsp_stack_svc_end = .;
- bsp_stack_undef_begin = .;
- . = . + bsp_stack_undef_size;
- bsp_stack_undef_end = .;
+ bsp_stack_und_begin = .;
+ . = . + bsp_stack_und_size;
+ bsp_stack_und_end = .;
/*
* BSP: Special vector data
*/
*(.bsp_vector)
- . = ALIGN (bsp_section_align);
+ . = ALIGN (bsp_section_vector_end_align);
/*
* BSP: End of vector section
@@ -126,6 +134,10 @@ SECTIONS {
bsp_section_vector_size = bsp_section_vector_end - bsp_section_vector_begin;
+ .vbarrier : {
+ . = ALIGN (bsp_section_vbarrier_align);
+ } > REGION_VECTOR
+
.text : {
/*
* BSP: Begin of text section
@@ -175,7 +187,7 @@ SECTIONS {
*/
KEEP (*(.fini))
- . = ALIGN (bsp_section_align);
+ . = ALIGN (bsp_section_text_end_align);
/*
* BSP: End of text section
@@ -203,7 +215,7 @@ SECTIONS {
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
- . = ALIGN (bsp_section_align);
+ . = ALIGN (bsp_section_rodata_end_align);
/*
* BSP: End of rodata section
@@ -215,6 +227,10 @@ SECTIONS {
bsp_section_rodata_load_begin = LOADADDR (.rodata);
+ .robarrier : {
+ . = ALIGN (bsp_section_robarrier_align);
+ } > REGION_RODATA
+
.data : {
/*
* BSP: Begin of data section
@@ -264,7 +280,7 @@ SECTIONS {
KEEP (*(.gnu.linkonce.d.*personality*))
SORT(CONSTRUCTORS)
- . = ALIGN (bsp_section_align);
+ . = ALIGN (bsp_section_data_end_align);
/*
* BSP: End of data section
@@ -281,7 +297,7 @@ SECTIONS {
*(.bsp_fast)
- . = ALIGN (bsp_section_align);
+ . = ALIGN (bsp_section_fast_end_align);
bsp_section_fast_end = .;
} > REGION_FAST AT > REGION_FAST_LOAD
@@ -300,7 +316,7 @@ SECTIONS {
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
- . = ALIGN (bsp_section_align);
+ . = ALIGN (bsp_section_bss_end_align);
/*
* BSP: End of bss section
diff --git a/c/src/lib/libcpu/arm/ChangeLog b/c/src/lib/libcpu/arm/ChangeLog
index 4c3a2707ba..cf99f1646a 100644
--- a/c/src/lib/libcpu/arm/ChangeLog
+++ b/c/src/lib/libcpu/arm/ChangeLog
@@ -1,3 +1,10 @@
+2010-01-12 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * shared/include/arm-cp15.h, shared/include/cache.h,
+ shared/include/cache_.h: New files.
+ * Makefile.am, preinstall.am: Update for new files.
+ * shared/arm920/mmu.c: Include and use <libcpu/arm-cp15.h>.
+
2009-11-30 Fernando Nicodemos <fgnicodemos@terra.com.br>
* at91rm9200/include/at91rm9200.h: Update to match development version.
diff --git a/c/src/lib/libcpu/arm/Makefile.am b/c/src/lib/libcpu/arm/Makefile.am
index 59d8ad1c6c..8ad15ed4b9 100644
--- a/c/src/lib/libcpu/arm/Makefile.am
+++ b/c/src/lib/libcpu/arm/Makefile.am
@@ -15,6 +15,7 @@ if shared
include_libcpudir = $(includedir)/libcpu
include_libcpu_HEADERS = shared/include/mmu.h
+include_libcpu_HEADERS += shared/include/arm-cp15.h
## shared/arm920
noinst_PROGRAMS += shared/arm920.rel
diff --git a/c/src/lib/libcpu/arm/preinstall.am b/c/src/lib/libcpu/arm/preinstall.am
index 4ae225666a..a40ee5d945 100644
--- a/c/src/lib/libcpu/arm/preinstall.am
+++ b/c/src/lib/libcpu/arm/preinstall.am
@@ -27,6 +27,10 @@ PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
$(PROJECT_INCLUDE)/libcpu/mmu.h: shared/include/mmu.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/mmu.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/mmu.h
+
+$(PROJECT_INCLUDE)/libcpu/arm-cp15.h: shared/include/arm-cp15.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
endif
if pxa255
$(PROJECT_INCLUDE)/pxa255.h: pxa255/include/pxa255.h $(PROJECT_INCLUDE)/$(dirstamp)
diff --git a/c/src/lib/libcpu/arm/shared/arm920/mmu.c b/c/src/lib/libcpu/arm/shared/arm920/mmu.c
index 752314723d..a9f90a8fa6 100644
--- a/c/src/lib/libcpu/arm/shared/arm920/mmu.c
+++ b/c/src/lib/libcpu/arm/shared/arm920/mmu.c
@@ -7,26 +7,12 @@
* $Id$
*/
#include <libcpu/mmu.h>
+#include <libcpu/arm-cp15.h>
typedef uint32_t mmu_lvl1_t;
extern uint32_t _ttbl_base;
-static inline uint32_t mmu_get_id(void);
-static inline uint32_t mmu_get_ctrl(void);
-static inline void mmu_set_ctrl(uint32_t val);
-static inline uint32_t mmu_get_trans_tbl(void);
-static inline void mmu_set_trans_tbl(uint32_t val);
-static inline uint32_t mmu_get_domain_ctrl(void);
-static inline void mmu_set_domain_ctrl(uint32_t val);
-static inline uint32_t mmu_get_fault_stat(void);
-static inline void mmu_set_fault_stat(uint32_t val);
-static inline uint32_t mmu_get_fault_addr(void);
-static inline void mmu_set_fault_addr(uint32_t val);
-static inline void mmu_set_cache_inval(void);
-static inline void mmu_set_tlb_inval(void);
-static inline uint32_t mmu_get_proc_id(void);
-static inline void mmu_set_proc_id(uint32_t val);
static void mmu_set_map_inval(mmu_lvl1_t *base);
#define MMU_CTRL_MMU_EN (1 << 0)
@@ -54,25 +40,23 @@ static void mmu_set_map_inval(mmu_lvl1_t *base);
#define MMU_SECT_AP_ALL (0x3 << 10)
-#define NOP ( { asm volatile ("nop\n" ); } )
-
void mmu_init(mmu_sect_map_t *map)
{
mmu_lvl1_t *lvl1_base;
int i;
/* flush the cache and TLB */
- mmu_set_cache_inval();
- mmu_set_tlb_inval();
+ arm_cp15_cache_invalidate();
+ arm_cp15_tlb_invalidate();
/* set manage mode access for all domains */
- mmu_set_domain_ctrl(0xffffffff);
+ arm_cp15_set_domain_access_control(0xffffffff);
lvl1_base = (mmu_lvl1_t *)&_ttbl_base;
/* set up the trans table */
mmu_set_map_inval(lvl1_base);
- mmu_set_trans_tbl((uint32_t) lvl1_base);
+ arm_cp15_set_translation_table_base(lvl1_base);
/* create a 1:1 mapping of the entire address space */
i = 0;
@@ -120,118 +104,20 @@ void mmu_init(mmu_sect_map_t *map)
}
/* flush the cache and TLB */
- mmu_set_cache_inval();
- mmu_set_tlb_inval();
-
- NOP;
- NOP;
+ arm_cp15_cache_invalidate();
+ arm_cp15_tlb_invalidate();
/* I & D caches turned on */
- mmu_set_ctrl(MMU_CTRL_DEFAULT |
- MMU_CTRL_D_CACHE_EN |
- MMU_CTRL_I_CACHE_EN |
- MMU_CTRL_ALIGN_FAULT_EN |
- MMU_CTRL_LITTLE_ENDIAN |
- MMU_CTRL_MMU_EN);
-
- NOP;
- NOP;
+ arm_cp15_set_control(MMU_CTRL_DEFAULT |
+ MMU_CTRL_D_CACHE_EN |
+ MMU_CTRL_I_CACHE_EN |
+ MMU_CTRL_ALIGN_FAULT_EN |
+ MMU_CTRL_LITTLE_ENDIAN |
+ MMU_CTRL_MMU_EN);
return;
}
-
-static inline uint32_t mmu_get_id(void)
-{
- uint32_t val;
- asm volatile ("msr 15, 0, %0, cr0, cr0\n" : "=r" (val));
- return val;
-}
-
-static inline uint32_t mmu_get_ctrl(void)
-{
- uint32_t val;
- asm volatile ("mrc 15, 0, %0, cr1, cr0\n" : "=r" (val));
- return val;
-}
-
-static inline void mmu_set_ctrl(uint32_t val)
-{
- asm volatile ("mcr 15, 0, %0, cr1, cr0, 0\n" : :"r" (val));
-}
-
-static inline uint32_t mmu_get_trans_tbl(void)
-{
- uint32_t val;
- asm volatile ("msr 15, 0, %0, cr2, cr0\n" : "=r" (val));
- return val;
-}
-
-static inline void mmu_set_trans_tbl(uint32_t val)
-{
- asm volatile ("mcr 15, 0, %0, cr2, cr0, 0\n" : :"r" (val));
-}
-
-static inline uint32_t mmu_get_domain_ctrl(void)
-{
- uint32_t val;
- asm volatile ("msr 15, 0, %0, cr3, cr0\n" : "=r" (val));
- return val;
-}
-
-static inline void mmu_set_domain_ctrl(uint32_t val)
-{
- asm volatile ("mcr 15, 0, %0, cr3, cr0, 0\n" : :"r" (val));
-}
-
-static inline uint32_t mmu_get_fault_stat(void)
-{
- uint32_t val;
- asm volatile ("msr 15, 0, %0, cr5, cr0\n" : "=r" (val));
- return val;
-}
-
-static inline void mmu_set_fault_stat(uint32_t val)
-{
- asm volatile ("mcr 15, 0, %0, cr5, cr0, 0\n" : :"r" (val));
-}
-
-static inline uint32_t mmu_get_fault_addr(void)
-{
- uint32_t val;
- asm volatile ("msr 15, 0, %0, cr6, cr0\n" : "=r" (val));
- return val;
-}
-
-static inline void mmu_set_fault_addr(uint32_t val)
-{
- asm volatile ("mcr 15, 0, %0, cr6, cr0, 0\n" : :"r" (val));
-}
-
-static inline void mmu_set_cache_inval(void)
-{
- uint32_t val = 0;
- asm volatile ("mcr 15, 0, %0, cr7, cr7, 0\n" : :"r" (val));
-}
-
-static inline void mmu_set_tlb_inval(void)
-{
- uint32_t val = 0;
- asm volatile ("mcr 15, 0, %0, cr8, cr7, 0\n" : :"r" (val));
-}
-
-static inline uint32_t mmu_get_proc_id(void)
-{
- uint32_t val;
- asm volatile ("msr 15, 0, %0, cr13, cr0\n" : "=r" (val));
- return val;
-}
-
-static inline void mmu_set_proc_id(uint32_t val)
-{
- asm volatile ("mcr 15, 0, %0, cr13, cr0, 0\n" : :"r" (val));
-}
-
/* set all the level 1 entrys to be invalid descriptors */
static void mmu_set_map_inval(mmu_lvl1_t *base)
{
@@ -241,12 +127,10 @@ static void mmu_set_map_inval(mmu_lvl1_t *base)
}
}
-
void mmu_set_cpu_async_mode(void)
{
uint32_t reg;
- reg = mmu_get_ctrl();
+ reg = arm_cp15_get_control();
reg |= 0xc0000000;
- mmu_set_ctrl(reg);
+ arm_cp15_set_control(reg);
}
-
diff --git a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
new file mode 100644
index 0000000000..3f0036f6c6
--- /dev/null
+++ b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
@@ -0,0 +1,644 @@
+/**
+ * @file
+ *
+ * @ingroup arm
+ *
+ * @brief ARM co-processor 15 (CP15) API.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBCPU_SHARED_ARM_CP15_H
+#define LIBCPU_SHARED_ARM_CP15_H
+
+#include <rtems.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define ARM_MMU_SECT_BASE_SHIFT 20
+#define ARM_MMU_SECT_BASE_MASK 0xfffU
+#define ARM_MMU_SECT_DOMAIN_SHIFT 5
+#define ARM_MMU_SECT_DOMAIN_MASK 0xfU
+#define ARM_MMU_SECT_AP_1 (1U << 11)
+#define ARM_MMU_SECT_AP_0 (1U << 10)
+#define ARM_MMU_SECT_AP_SHIFT 10
+#define ARM_MMU_SECT_AP_MASK 0x3U
+#define ARM_MMU_SECT_C (1U << 3)
+#define ARM_MMU_SECT_B (1U << 2)
+#define ARM_MMU_SECT_DEFAULT 0x12U
+#define ARM_MMU_SECT_GET_INDEX(mva) \
+ (((uint32_t) (mva)) >> ARM_MMU_SECT_BASE_SHIFT)
+#define ARM_MMU_SECT_MVA_ALIGN_UP(mva) \
+ ((1U << ARM_MMU_SECT_BASE_SHIFT) \
+ + ((((uint32_t) (mva) - 1U)) & ~((1U << ARM_MMU_SECT_BASE_SHIFT) - 1U)))
+
+#define ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE 4U
+#define ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT 4096U
+
+static inline uint32_t arm_cp15_get_id_code(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c0, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+static inline uint32_t arm_cp15_get_cache_type(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c0, c0, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+static inline uint32_t arm_cp15_get_tcm_status(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c0, c0, 2\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+#define ARM_CP15_CTRL_L4 (1U << 15)
+#define ARM_CP15_CTRL_RR (1U << 14)
+#define ARM_CP15_CTRL_V (1U << 13)
+#define ARM_CP15_CTRL_I (1U << 12)
+#define ARM_CP15_CTRL_R (1U << 9)
+#define ARM_CP15_CTRL_S (1U << 8)
+#define ARM_CP15_CTRL_B (1U << 7)
+#define ARM_CP15_CTRL_C (1U << 2)
+#define ARM_CP15_CTRL_A (1U << 1)
+#define ARM_CP15_CTRL_M (1U << 0)
+
+static inline uint32_t arm_cp15_get_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c1, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+static inline void arm_cp15_set_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c1, c0, 0\n"
+ "nop\n"
+ "nop\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ : "memory"
+ );
+}
+
+static inline uint32_t *arm_cp15_get_translation_table_base(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t *base;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[base], c2, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return base;
+}
+
+static inline void arm_cp15_set_translation_table_base(uint32_t *base)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[base], c2, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [base] "r" (base)
+ );
+}
+
+#define ARM_CP15_DAC_NO_ACCESS 0x0U
+#define ARM_CP15_DAC_CLIENT 0x1U
+#define ARM_CP15_DAC_MANAGER 0x3U
+#define ARM_CP15_DAC_DOMAIN(index, val) ((val) << (2 * index))
+
+static inline uint32_t arm_cp15_get_domain_access_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c3, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+static inline void arm_cp15_set_domain_access_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c3, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+static inline uint32_t arm_cp15_get_data_fault_status(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c5, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+static inline void arm_cp15_set_data_fault_status(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c5, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+static inline uint32_t arm_cp15_get_instruction_fault_status(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c5, c0, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+static inline void arm_cp15_set_instruction_fault_status(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c5, c0, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+static inline void *arm_cp15_get_fault_address(void)
+{
+ ARM_SWITCH_REGISTERS;
+ void *mva;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[mva], c6, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [mva] "=&r" (mva) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return mva;
+}
+
+static inline void arm_cp15_set_fault_address(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c6, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+#define ARM_CP15_CACHE_PREPARE_MVA(mva) \
+ ((const void *) (((uint32_t) (mva)) & ~0x1fU))
+
+static inline void arm_cp15_cache_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c7, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_instruction_cache_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c5, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_instruction_cache_invalidate_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c5, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_instruction_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c5, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_instruction_cache_prefetch_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c13, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+static inline void arm_cp15_data_cache_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c6, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_invalidate_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c6, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c6, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_clean_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c10, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c10, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_test_and_clean(void)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "1:\n"
+ "mrc p15, 0, r15, c7, c10, 3\n"
+ "bne 1b\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ :
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c14, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_data_cache_test_and_clean_and_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "1:\n"
+ "mrc p15, 0, r15, c7, c14, 3\n"
+ "bne 1b\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ :
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_drain_write_buffer(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c10, 4\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+static inline void arm_cp15_wait_for_interrupt(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c0, 4\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+#define ARM_CP15_TLB_PREPARE_MVA(mva) \
+ ((const void *) (((uint32_t) (mva)) & ~0x3fU))
+
+static inline void arm_cp15_tlb_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c8, c7, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ );
+}
+
+static inline void arm_cp15_tlb_invalidate_entry(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_TLB_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c8, c7, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+static inline void arm_cp15_tlb_instruction_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c8, c5, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ );
+}
+
+static inline void arm_cp15_tlb_instruction_invalidate_entry(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_TLB_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c8, c5, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+static inline void arm_cp15_tlb_data_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c8, c6, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ );
+}
+
+static inline void arm_cp15_tlb_data_invalidate_entry(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_TLB_PREPARE_MVA(mva);
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c8, c6, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+static inline void arm_cp15_tlb_lockdown_entry(const void *mva)
+{
+ uint32_t arm_switch_reg;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "add %[arm_switch_reg], pc, #16\n"
+ "mcr p15, 0, %[arm_switch_reg], c7, c13, 1\n"
+ "mcr p15, 0, %[mva], c8, c7, 1\n"
+ "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ "orr %[arm_switch_reg], #0x1\n"
+ "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ "ldr %[mva], [%[mva]]\n"
+ "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ "bic %[arm_switch_reg], #0x1\n"
+ "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [mva] "=r" (mva), [arm_switch_reg] "=&r" (arm_switch_reg)
+ : "[mva]" (mva)
+ );
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBCPU_SHARED_ARM_CP15_H */
diff --git a/c/src/lib/libcpu/arm/shared/include/cache.h b/c/src/lib/libcpu/arm/shared/include/cache.h
new file mode 100644
index 0000000000..3e6784f765
--- /dev/null
+++ b/c/src/lib/libcpu/arm/shared/include/cache.h
@@ -0,0 +1,132 @@
+/**
+ * @file
+ *
+ * @ingroup arm
+ *
+ * @brief ARM cache defines and implementation.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBCPU_ARM_CACHE_H
+#define LIBCPU_ARM_CACHE_H
+
+#ifdef __ARM_ARCH_5TEJ__
+ #include <libcpu/arm-cp15.h>
+
+ #define CPU_DATA_CACHE_ALIGNMENT 32
+ #define CPU_INSTRUCTION_CACHE_ALIGNMENT 32
+
+ static inline void _CPU_cache_flush_1_data_line(const void *d_addr)
+ {
+ arm_cp15_data_cache_clean_line(d_addr);
+ }
+
+ static inline void _CPU_cache_invalidate_1_data_line(const void *d_addr)
+ {
+ arm_cp15_data_cache_invalidate_line(d_addr);
+ }
+
+ static inline void _CPU_cache_freeze_data(void)
+ {
+ /* TODO */
+ }
+
+ static inline void _CPU_cache_unfreeze_data(void)
+ {
+ /* TODO */
+ }
+
+ static inline void _CPU_cache_invalidate_1_instruction_line(const void *d_addr)
+ {
+ arm_cp15_instruction_cache_invalidate_line(d_addr);
+ }
+
+ static inline void _CPU_cache_freeze_instruction(void)
+ {
+ /* TODO */
+ }
+
+ static inline void _CPU_cache_unfreeze_instruction(void)
+ {
+ /* TODO */
+ }
+
+ static inline void _CPU_cache_flush_entire_data(void)
+ {
+ arm_cp15_data_cache_test_and_clean();
+ }
+
+ static inline void _CPU_cache_invalidate_entire_data(void)
+ {
+ arm_cp15_data_cache_invalidate();
+ }
+
+ static inline void _CPU_cache_enable_data(void)
+ {
+ rtems_interrupt_level level;
+ uint32_t ctrl;
+
+ rtems_interrupt_disable(level);
+ ctrl = arm_cp15_get_control();
+ ctrl |= ARM_CP15_CTRL_C;
+ arm_cp15_set_control(ctrl);
+ rtems_interrupt_enable(level);
+ }
+
+ static inline void _CPU_cache_disable_data(void)
+ {
+ rtems_interrupt_level level;
+ uint32_t ctrl;
+
+ rtems_interrupt_disable(level);
+ ctrl = arm_cp15_get_control();
+ ctrl &= ~ARM_CP15_CTRL_C;
+ arm_cp15_set_control(ctrl);
+ rtems_interrupt_enable(level);
+
+ arm_cp15_data_cache_test_and_clean_and_invalidate();
+ }
+
+ static inline void _CPU_cache_invalidate_entire_instruction(void)
+ {
+ arm_cp15_instruction_cache_invalidate();
+ }
+
+ static inline void _CPU_cache_enable_instruction(void)
+ {
+ rtems_interrupt_level level;
+ uint32_t ctrl;
+
+ rtems_interrupt_disable(level);
+ ctrl = arm_cp15_get_control();
+ ctrl |= ARM_CP15_CTRL_I;
+ arm_cp15_set_control(ctrl);
+ rtems_interrupt_enable(level);
+ }
+
+ static inline void _CPU_cache_disable_instruction(void)
+ {
+ rtems_interrupt_level level;
+ uint32_t ctrl;
+
+ rtems_interrupt_disable(level);
+ ctrl = arm_cp15_get_control();
+ ctrl &= ~ARM_CP15_CTRL_I;
+ arm_cp15_set_control(ctrl);
+ rtems_interrupt_enable(level);
+ }
+#endif
+
+#endif /* LIBCPU_ARM_CACHE_H */
diff --git a/c/src/lib/libcpu/arm/shared/include/cache_.h b/c/src/lib/libcpu/arm/shared/include/cache_.h
new file mode 100644
index 0000000000..b617b65ace
--- /dev/null
+++ b/c/src/lib/libcpu/arm/shared/include/cache_.h
@@ -0,0 +1,27 @@
+/**
+ * @file
+ *
+ * @ingroup arm
+ *
+ * @brief Empty file.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBCPU_ARM_CACHE__H
+#define LIBCPU_ARM_CACHE__H
+
+/* Empty */
+
+#endif /* LIBCPU_ARM_CACHE__H */
diff --git a/cpukit/score/cpu/arm/ChangeLog b/cpukit/score/cpu/arm/ChangeLog
index 4c81e5cb1a..a47947170f 100644
--- a/cpukit/score/cpu/arm/ChangeLog
+++ b/cpukit/score/cpu/arm/ChangeLog
@@ -1,3 +1,12 @@
+2010-01-12 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * arm_exc_abort.S: New file.
+ * Makefile.am: Update for new file.
+ * arm_exc_interrupt.S, cpu.c, rtems/asm.h, rtems/score/cpu.h: Changed
+ macros which switch from and to THUMB mode. Added a default prefetch
+ and data abort handler which reports the complete processor context.
+ Added PSR defines.
+
2009-12-15 Sebastian Huber <sebastian.huber@embedded-brains.de>
* rtems/score/arm.h: Recognize ARMv5TEJ.
diff --git a/cpukit/score/cpu/arm/Makefile.am b/cpukit/score/cpu/arm/Makefile.am
index 4cab7ddcd9..57f2b70642 100644
--- a/cpukit/score/cpu/arm/Makefile.am
+++ b/cpukit/score/cpu/arm/Makefile.am
@@ -13,6 +13,7 @@ noinst_LIBRARIES = libscorecpu.a
libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
libscorecpu_a_SOURCES = cpu.c \
cpu_asm.S \
+ arm_exc_abort.S \
arm_exc_interrupt.S \
arm_exc_handler_low.S \
arm_exc_handler_high.c
diff --git a/cpukit/score/cpu/arm/arm_exc_abort.S b/cpukit/score/cpu/arm/arm_exc_abort.S
new file mode 100644
index 0000000000..906dcbb9f1
--- /dev/null
+++ b/cpukit/score/cpu/arm/arm_exc_abort.S
@@ -0,0 +1,123 @@
+/**
+ * @file
+ *
+ * @ingroup arm
+ *
+ * @brief ARM data and prefetch abort exception prologue and epilogue.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+
+.extern rtems_fatal_error_occurred
+
+.globl arm_exc_data_abort_set_handler
+.globl arm_exc_data_abort
+
+.globl arm_exc_prefetch_abort_set_handler
+.globl arm_exc_prefetch_abort
+
+.section ".bss"
+
+data_abort_handler:
+.long 0
+
+prefetch_abort_handler:
+.long 0
+
+.section ".text"
+
+#ifdef __thumb__
+ .thumb_func
+#endif
+
+arm_exc_data_abort_set_handler:
+ ldr r1, =data_abort_handler
+ str r0, [r1]
+ bx lr
+
+#ifdef __thumb__
+ .thumb_func
+#endif
+
+arm_exc_prefetch_abort_set_handler:
+ ldr r1, =prefetch_abort_handler
+ str r0, [r1]
+ bx lr
+
+.arm
+
+arm_exc_prefetch_abort:
+
+ /* Save context and load handler */
+ sub sp, #16
+ stmdb sp!, {r0-r12}
+ ldr r6, =prefetch_abort_handler
+
+ b save_more_context
+
+arm_exc_data_abort:
+
+ /* Save context and load handler */
+ sub sp, #16
+ stmdb sp!, {r0-r12}
+ ldr r6, =data_abort_handler
+
+save_more_context:
+
+ /* Save more context */
+ mov r2, lr
+ mrs r3, spsr
+ mrs r4, cpsr
+ orr r5, r3, #ARM_PSR_I
+ bic r5, #ARM_PSR_T
+ msr cpsr, r5
+ mov r0, sp
+ mov r1, lr
+ msr cpsr, r4
+ add r5, sp, #68
+ stmdb r5!, {r0-r3}
+
+ /* Call high level handler */
+ ldr r2, [r6]
+ cmp r2, #0
+ ldreq r2, =rtems_fatal_error_occurred
+ movne r0, sp
+ moveq r0, #0xaa
+#ifndef __thumb__
+ mov lr, pc
+ bx r2
+#else /* __thumb__ */
+ SWITCH_FROM_ARM_TO_THUMB r1
+ bl call_handler
+ SWITCH_FROM_THUMB_TO_ARM
+#endif /* __thumb__ */
+
+ /* Restore context */
+ ldmia r5!, {r0-r3}
+ mov lr, r2
+ msr spsr, r3
+ ldmia sp!, {r0-r12}
+ add sp, #16
+
+ /* Return from interrupt */
+ subs pc, lr, #8
+
+#ifdef __thumb__
+.thumb
+call_handler:
+ bx r2
+#endif /* __thumb__ */
diff --git a/cpukit/score/cpu/arm/arm_exc_interrupt.S b/cpukit/score/cpu/arm/arm_exc_interrupt.S
index 738c248141..a260d9dda1 100644
--- a/cpukit/score/cpu/arm/arm_exc_interrupt.S
+++ b/cpukit/score/cpu/arm/arm_exc_interrupt.S
@@ -1,6 +1,8 @@
/**
* @file
*
+ * @ingroup arm
+ *
* @brief ARM interrupt exception prologue and epilogue.
*/
@@ -23,6 +25,8 @@
* The exchange area is only accessed if INT is disabled.
*/
+#include <rtems/asm.h>
+
#define EXCHANGE_LR r4
#define EXCHANGE_SPSR r5
#define EXCHANGE_CPSR r6
@@ -41,22 +45,6 @@
.extern bsp_interrupt_dispatch
-.macro SWITCH_FROM_THUMB_TO_ARM
-#ifdef __thumb__
-.align 2
- bx pc
-.arm
-#endif /* __thumb__ */
-.endm
-
-.macro SWITCH_FROM_ARM_TO_THUMB REG
-#ifdef __thumb__
- add \REG, pc, #1
- bx \REG
-.thumb
-#endif /* __thumb__ */
-.endm
-
.arm
.globl arm_exc_interrupt
arm_exc_interrupt:
diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c
index a44cff59bb..53b42c3748 100644
--- a/cpukit/score/cpu/arm/cpu.c
+++ b/cpukit/score/cpu/arm/cpu.c
@@ -56,31 +56,31 @@ void _CPU_Context_Initialize(
void _CPU_ISR_Set_level( uint32_t level )
{
- uint32_t reg;
+ uint32_t arm_switch_reg;
asm volatile (
- THUMB_TO_ARM
- "mrs %0, cpsr\n"
- "bic %0, %0, #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n"
- "orr %0, %0, %1\n"
+ ARM_SWITCH_TO_ARM
+ "mrs %[arm_switch_reg], cpsr\n"
+ "bic %[arm_switch_reg], #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n"
+ "orr %[arm_switch_reg], %[level]\n"
"msr cpsr, %0\n"
- ARM_TO_THUMB
- : "=r" (reg)
- : "r" (level)
+ ARM_SWITCH_BACK
+ : [arm_switch_reg] "=&r" (arm_switch_reg)
+ : [level] "r" (level)
);
}
uint32_t _CPU_ISR_Get_level( void )
{
- uint32_t reg;
+ ARM_SWITCH_REGISTERS;
uint32_t level;
asm volatile (
- THUMB_TO_ARM
- "mrs %0, cpsr\n"
- "and %1, %0, #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n"
- ARM_TO_THUMB
- : "=r" (reg), "=r" (level)
+ ARM_SWITCH_TO_ARM
+ "mrs %[level], cpsr\n"
+ "and %[level], #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n"
+ ARM_SWITCH_BACK
+ : [level] "=&r" (level) ARM_SWITCH_ADDITIONAL_OUTPUT
);
return level;
diff --git a/cpukit/score/cpu/arm/rtems/asm.h b/cpukit/score/cpu/arm/rtems/asm.h
index 04c5360790..f8b027cf1b 100644
--- a/cpukit/score/cpu/arm/rtems/asm.h
+++ b/cpukit/score/cpu/arm/rtems/asm.h
@@ -141,4 +141,20 @@
.globl name ; name: ; .globl name ## _arm ; name ## _arm:
#endif
+.macro SWITCH_FROM_THUMB_TO_ARM
+#ifdef __thumb__
+.align 2
+ bx pc
+.arm
+#endif /* __thumb__ */
+.endm
+
+.macro SWITCH_FROM_ARM_TO_THUMB REG
+#ifdef __thumb__
+ add \REG, pc, #1
+ bx \REG
+.thumb
+#endif /* __thumb__ */
+.endm
+
#endif /* _RTEMS_ASM_H */
diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h
index d7eca1527c..de452e8cb4 100644
--- a/cpukit/score/cpu/arm/rtems/score/cpu.h
+++ b/cpukit/score/cpu/arm/rtems/score/cpu.h
@@ -8,6 +8,8 @@
* This include file contains information pertaining to the ARM
* processor.
*
+ * Copyright (c) 2009 embedded brains GmbH.
+ *
* Copyright (c) 2007 Ray Xu <Rayx.cn@gmail.com>
*
* Copyright (c) 2006 OAR Corporation
@@ -44,13 +46,42 @@
#endif
#ifdef __thumb__
- #define ARM_TO_THUMB "add %0, pc, #1\nbx %0\n.thumb\n"
- #define THUMB_TO_ARM ".align 2\nbx pc\n.arm\n"
+ #define ARM_SWITCH_REGISTERS uint32_t arm_switch_reg
+ #define ARM_SWITCH_TO_ARM ".align 2\nbx pc\n.arm\n"
+ #define ARM_SWITCH_BACK "add %[arm_switch_reg], pc, #1\nbx %[arm_switch_reg]\n.thumb\n"
+ #define ARM_SWITCH_OUTPUT [arm_switch_reg] "=&r" (arm_switch_reg)
+ #define ARM_SWITCH_ADDITIONAL_OUTPUT , ARM_SWITCH_OUTPUT
#else
- #define ARM_TO_THUMB
- #define THUMB_TO_ARM
+ #define ARM_SWITCH_REGISTERS
+ #define ARM_SWITCH_TO_ARM
+ #define ARM_SWITCH_BACK
+ #define ARM_SWITCH_OUTPUT
+ #define ARM_SWITCH_ADDITIONAL_OUTPUT
#endif
+#define ARM_PSR_N (1 << 31)
+#define ARM_PSR_Z (1 << 30)
+#define ARM_PSR_C (1 << 29)
+#define ARM_PSR_V (1 << 28)
+#define ARM_PSR_Q (1 << 27)
+#define ARM_PSR_J (1 << 24)
+#define ARM_PSR_GE_SHIFT 16
+#define ARM_PSR_GE_MASK (0xf << ARM_PSR_GE_SHIFT)
+#define ARM_PSR_E (1 << 9)
+#define ARM_PSR_A (1 << 8)
+#define ARM_PSR_I (1 << 7)
+#define ARM_PSR_F (1 << 6)
+#define ARM_PSR_T (1 << 5)
+#define ARM_PSR_M_SHIFT 0
+#define ARM_PSR_M_MASK (0x1f << ARM_PSR_M_SHIFT)
+#define ARM_PSR_M_USR 0x10
+#define ARM_PSR_M_FIQ 0x11
+#define ARM_PSR_M_IRQ 0x12
+#define ARM_PSR_M_SVC 0x13
+#define ARM_PSR_M_ABT 0x17
+#define ARM_PSR_M_UND 0x1b
+#define ARM_PSR_M_SYS 0x1f
+
/* If someone uses THUMB we assume she wants minimal code size */
#ifdef __thumb__
#define CPU_INLINE_ENABLE_DISPATCH FALSE
@@ -205,16 +236,16 @@ SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
static inline uint32_t arm_interrupt_disable( void )
{
- uint32_t reg;
+ uint32_t arm_switch_reg;
uint32_t level;
asm volatile (
- THUMB_TO_ARM
- "mrs %1, cpsr\n"
- "orr %0, %1, #0x80\n"
- "msr cpsr, %0\n"
- ARM_TO_THUMB
- : "=r" (reg), "=r" (level)
+ ARM_SWITCH_TO_ARM
+ "mrs %[level], cpsr\n"
+ "orr %[arm_switch_reg], %[level], #0x80\n"
+ "msr cpsr, %[arm_switch_reg]\n"
+ ARM_SWITCH_BACK
+ : [arm_switch_reg] "=&r" (arm_switch_reg), [level] "=&r" (level)
);
return level;
@@ -222,54 +253,46 @@ static inline uint32_t arm_interrupt_disable( void )
static inline void arm_interrupt_enable( uint32_t level )
{
- #ifdef __thumb__
- uint32_t reg;
-
- asm volatile (
- THUMB_TO_ARM
- "msr cpsr, %1\n"
- ARM_TO_THUMB
- : "=r" (reg)
- : "r" (level)
- );
- #else
- asm volatile (
- "msr cpsr, %0"
- :
- : "r" (level)
- );
- #endif
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "msr cpsr, %[level]\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [level] "r" (level)
+ );
}
static inline void arm_interrupt_flash( uint32_t level )
{
- uint32_t reg;
+ uint32_t arm_switch_reg;
asm volatile (
- THUMB_TO_ARM
- "mrs %0, cpsr\n"
- "msr cpsr, %1\n"
- "msr cpsr, %0\n"
- ARM_TO_THUMB
- : "=r" (reg)
- : "r" (level)
+ ARM_SWITCH_TO_ARM
+ "mrs %[arm_switch_reg], cpsr\n"
+ "msr cpsr, %[level]\n"
+ "msr cpsr, %[arm_switch_reg]\n"
+ ARM_SWITCH_BACK
+ : [arm_switch_reg] "=&r" (arm_switch_reg)
+ : [level] "r" (level)
);
}
static inline uint32_t arm_status_irq_enable( void )
{
- uint32_t reg;
+ uint32_t arm_switch_reg;
uint32_t psr;
RTEMS_COMPILER_MEMORY_BARRIER();
asm volatile (
- THUMB_TO_ARM
- "mrs %1, cpsr\n"
- "bic %0, %1, #0x80\n"
- "msr cpsr, %0\n"
- ARM_TO_THUMB
- : "=r" (reg), "=r" (psr)
+ ARM_SWITCH_TO_ARM
+ "mrs %[psr], cpsr\n"
+ "bic %[arm_switch_reg], %[psr], #0x80\n"
+ "msr cpsr, %[arm_switch_reg]\n"
+ ARM_SWITCH_BACK
+ : [arm_switch_reg] "=&r" (arm_switch_reg), [psr] "=&r" (psr)
);
return psr;
@@ -277,23 +300,15 @@ static inline uint32_t arm_status_irq_enable( void )
static inline void arm_status_restore( uint32_t psr )
{
- #ifdef __thumb__
- uint32_t reg;
-
- asm volatile (
- THUMB_TO_ARM
- "msr cpsr, %1\n"
- ARM_TO_THUMB
- : "=r" (reg)
- : "r" (psr)
- );
- #else
- asm volatile (
- "msr cpsr, %0"
- :
- : "r" (psr)
- );
- #endif
+ ARM_SWITCH_REGISTERS;
+
+ asm volatile (
+ ARM_SWITCH_TO_ARM
+ "msr cpsr, %[psr]\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [psr] "r" (psr)
+ );
RTEMS_COMPILER_MEMORY_BARRIER();
}
@@ -402,16 +417,42 @@ static inline uint16_t CPU_swap_u16( uint16_t value )
extern uint32_t arm_cpu_mode;
-void arm_exc_abort_data( void );
+typedef struct {
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r12;
+ uint32_t sp;
+ uint32_t lr;
+ uint32_t pc;
+ uint32_t cpsr;
+} arm_cpu_context;
+
+typedef void arm_exc_abort_handler( arm_cpu_context *context );
+
+void arm_exc_data_abort_set_handler( arm_exc_abort_handler handler );
+
+void arm_exc_data_abort( void );
+
+void arm_exc_prefetch_abort_set_handler( arm_exc_abort_handler handler );
+
+void arm_exc_prefetch_abort( void );
-void arm_exc_abort_prefetch( void );
+void bsp_interrupt_dispatch( void );
void arm_exc_interrupt( void );
void arm_exc_undefined( void );
-void bsp_interrupt_dispatch( void );
-
#ifdef __cplusplus
}
#endif