diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2008-06-20 14:58:34 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2008-06-20 14:58:34 +0000 |
commit | 6b56ec3327a541aa711116d8bb37e22ede976dd6 (patch) | |
tree | 4a2655f3db869a052e17923f76ee3207c7b7f7d6 | |
parent | 2008-06-19 Matthew Riek <matthew.riek@ibiscomputer.com.au> (diff) | |
download | rtems-6b56ec3327a541aa711116d8bb37e22ede976dd6.tar.bz2 |
2008-06-20 Matthew Riek <matthew.riek@ibiscomputer.com.au>
* ChangeLog, Makefile.am, README, bsp_specs, configure.ac, gdb-init,
preinstall.am, clock/clock.c, console/console.c, include/bsp.h,
include/bspopts.h.in, include/coverhd.h, include/tm27.h,
network/network.c, start/start.S, startup/bspclean.c,
startup/bspstart.c, startup/cfinit.c, startup/init5329.c,
startup/linkcmds, startup/linkcmdsflash, timer/timer.c: New files.
22 files changed, 3661 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/mcf5329/ChangeLog b/c/src/lib/libbsp/m68k/mcf5329/ChangeLog new file mode 100644 index 0000000000..ca6961891e --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/ChangeLog @@ -0,0 +1,9 @@ +2008-06-20 Matthew Riek <matthew.riek@ibiscomputer.com.au> + + * ChangeLog, Makefile.am, README, bsp_specs, configure.ac, gdb-init, + preinstall.am, clock/clock.c, console/console.c, include/bsp.h, + include/bspopts.h.in, include/coverhd.h, include/tm27.h, + network/network.c, start/start.S, startup/bspclean.c, + startup/bspstart.c, startup/cfinit.c, startup/init5329.c, + startup/linkcmds, startup/linkcmdsflash, timer/timer.c: New files. + diff --git a/c/src/lib/libbsp/m68k/mcf5329/Makefile.am b/c/src/lib/libbsp/m68k/mcf5329/Makefile.am new file mode 100644 index 0000000000..9ad3168a89 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/Makefile.am @@ -0,0 +1,61 @@ +## +## $Id$ +## + +ACLOCAL_AMFLAGS = -I ../../../../aclocal + +include $(top_srcdir)/../../../../automake/compile.am +include $(top_srcdir)/../../bsp.am + +dist_project_lib_DATA = bsp_specs + +include_HEADERS = include/bsp.h +include_HEADERS += include/tm27.h + +nodist_include_HEADERS = include/bspopts.h +DISTCLEANFILES = include/bspopts.h +noinst_PROGRAMS = + +include_HEADERS += include/coverhd.h + +EXTRA_DIST = start/start.S +start.$(OBJEXT): start/start.S + $(CPPASCOMPILE) -o $@ -c $< +project_lib_DATA = start.$(OBJEXT) + +dist_project_lib_DATA += startup/linkcmds startup/linkcmdsflash + +startup_SOURCES = startup/bspclean.c ../../shared/bsppredriverhook.c \ + ../../shared/bsplibc.c ../../shared/bsppost.c \ + ../../m68k/shared/m68kpretaskinghook.c \ + ../../m68k/shared/m68kbspgetworkarea.c \ + startup/init5329.c startup/bspstart.c startup/cfinit.c\ + ../../shared/bootcard.c \ + ../../shared/sbrk.c ../../m68k/shared/setvec.c \ + ../../shared/gnatinstallhandler.c +clock_SOURCES = clock/clock.c +console_SOURCES = console/console.c +timer_SOURCES = timer/timer.c + +if HAS_NETWORKING +network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ +noinst_PROGRAMS += network.rel +network_rel_SOURCES = network/network.c +network_rel_CPPFLAGS = $(AM_CPPFLAGS) \ + $(network_CPPFLAGS) +network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) +endif + +noinst_LIBRARIES = libbsp.a +libbsp_a_SOURCES = $(startup_SOURCES) $(clock_SOURCES) $(console_SOURCES) \ + $(timer_SOURCES) + +libbsp_a_LIBADD = \ + ../../../libcpu/@RTEMS_CPU@/shared/cache.rel \ + ../../../libcpu/@RTEMS_CPU@/shared/misc.rel +if HAS_NETWORKING +libbsp_a_LIBADD += network.rel +endif + +include $(srcdir)/preinstall.am +include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/m68k/mcf5329/README b/c/src/lib/libbsp/m68k/mcf5329/README new file mode 100644 index 0000000000..f3dea7bfe2 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/README @@ -0,0 +1,51 @@ +# +# $Id: +# + +Description: Motorola MCF5329EVB Zoom + (LogicPD) +============ +CPU: MCF5329, 240MHz +CORESRAM: 32K +FLASH: 2M +DRAM: 32M + +This is a Motorola Zoom evaluation board that uses the MCF5329 Coldfire CPU on +a logicPD card. This board is running at 240MHz with DRAM clocking at 80MHz. + +The bsp is configured for the MT46V16M16TG-75:F DRAM. + +NOTES: +====== + +This BSP is based heavily off the 5235 BSP. + +TODO: +====== + +Add other drivers for can, i2c, lcd (fb), qspi etc. + +============================================================================ + Interrupt map + ++-----+-----------------------------------------------------------------------+ +| | PRIORITY | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +|LEVEL| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +| 7 | | | | | | | | | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +| 6 | | | | | | | | | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +| 5 | | | | | | | | | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +| 4 | FEC RX | FEC TX | | | | | | PIT | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +| 3 | UART 0 | UART 1 | UART 2 | | | | | | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +| 2 | | | | | | | | | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ +| 1 | | | | | | | | | ++-----+--------+--------+--------+--------+--------+--------+--------+--------+ + +============================================================================ + Timings diff --git a/c/src/lib/libbsp/m68k/mcf5329/bsp_specs b/c/src/lib/libbsp/m68k/mcf5329/bsp_specs new file mode 100644 index 0000000000..4a5560b651 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/bsp_specs @@ -0,0 +1,13 @@ +%rename endfile old_endfile +%rename startfile old_startfile +%rename link old_link + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: start.o%s crti.o%s crtbegin.o%s}} + +*link: +%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N -e start} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c new file mode 100644 index 0000000000..ecb1c7e875 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c @@ -0,0 +1,98 @@ + +/* + * Use the last periodic interval timer (PIT2) as the system clock. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> + +/* + * Use INTC1 base + */ +#define CLOCK_VECTOR (128+46) + +static uint32_t s_pcntrAtTick = 0; +static uint32_t s_nanoScale = 0; + +/* + * Provide nanosecond extension + */ +static uint32_t bsp_clock_nanoseconds_since_last_tick(void) +{ + uint32_t i; + + if (MCF_PIT3_PCSR & MCF_PIT_PCSR_PIF) { + i = s_pcntrAtTick + (MCF_PIT3_PMR - MCF_PIT3_PCNTR); + } else { + i = s_pcntrAtTick - MCF_PIT3_PCNTR; + } + return i * s_nanoScale; +} + +#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick + +/* + * Periodic interval timer interrupt handler + */ +#define Clock_driver_support_at_tick() \ + do { \ + s_pcntrAtTick = MCF_PIT3_PCNTR; \ + MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF; \ + } while (0) \ + + +/* + * Attach clock interrupt handler + */ +#define Clock_driver_support_install_isr( _new, _old ) \ + do { \ + _old = (rtems_isr_entry)set_vector(_new, CLOCK_VECTOR, 1); \ + } while(0) + +/* + * Turn off the clock + */ +static void Clock_driver_support_shutdown_hardware() +{ + MCF_PIT3_PCSR &= ~MCF_PIT_PCSR_EN; +} + +/* + * Set up the clock hardware + * + * We need to have 1 interrupt every BSP_Configuration.microseconds_per_tick + */ +static void Clock_driver_support_initialize_hardware() +{ + int level; + uint32_t pmr; + uint32_t preScaleCode = 0; + uint32_t clk = bsp_get_BUS_clock_speed(); + uint32_t tps = 1000000 / Configuration.microseconds_per_tick; + + while (preScaleCode < 15) { + pmr = (clk >> preScaleCode) / tps; + if (pmr < (1 << 15)) + break; + preScaleCode++; + } + s_nanoScale = 1000000000 / (clk >> preScaleCode); + + MCF_INTC1_ICR46 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL); + + rtems_interrupt_disable(level); + MCF_INTC1_IMRH &= ~MCF_INTC_IMRH_INT_MASK46; + MCF_PIT3_PCSR &= ~MCF_PIT_PCSR_EN; + rtems_interrupt_enable(level); + + MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) | + MCF_PIT_PCSR_OVW | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD; + MCF_PIT3_PMR = pmr; + MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) | + MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN; + s_pcntrAtTick = MCF_PIT3_PCNTR; +} + +#include "../../../shared/clockdrv_shell.c" diff --git a/c/src/lib/libbsp/m68k/mcf5329/configure.ac b/c/src/lib/libbsp/m68k/mcf5329/configure.ac new file mode 100644 index 0000000000..7d232d4fdb --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/configure.ac @@ -0,0 +1,25 @@ +## Process this file with autoconf to produce a configure script. +## +## $Id$ + +AC_PREREQ(2.60) +AC_INIT([rtems-c-src-lib-libbsp-m68k-mcf52235],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([bsp_specs]) +RTEMS_TOP(../../../../../..) + +RTEMS_CANONICAL_TARGET_CPU +AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.10]) +RTEMS_BSP_CONFIGURE + +RTEMS_PROG_CC_FOR_TARGET +RTEMS_CANONICALIZE_TOOLS +RTEMS_PROG_CCAS + +RTEMS_BSP_BOOTCARD_HANDLES_RAM_ALLOCATION + +RTEMS_CHECK_NETWORKING +AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/c/src/lib/libbsp/m68k/mcf5329/console/console.c b/c/src/lib/libbsp/m68k/mcf5329/console/console.c new file mode 100644 index 0000000000..e2768b5e80 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/console/console.c @@ -0,0 +1,690 @@ + /* + * Multi UART console serial I/O. + * + * TO DO: Add DMA input/output + */ + +#include <stdio.h> +#include <fcntl.h> +#include <rtems/libio.h> +#include <rtems/termiostypes.h> +#include <termios.h> +#include <bsp.h> +#include <malloc.h> +#include <rtems/mw_uid.h> + +#include <rtems/bspIo.h> + +#define UART_INTC0_IRQ_VECTOR(x) (64+26+(x)) + +#define MCF_UART_USR_ERROR ( MCF_UART_USR_RB | \ + MCF_UART_USR_FE | \ + MCF_UART_USR_PE | \ + MCF_UART_USR_OE ) + +static int IntUartPollWrite(int minor, const char *buf, int len); +static int IntUartInterruptWrite(int minor, const char *buf, int len); + +static void _BSP_null_char(char c) +{ + int level; + + if (c == '\n') + _BSP_null_char('\r'); + rtems_interrupt_disable(level); + while ((MCF_UART_USR(CONSOLE_PORT) & MCF_UART_USR_TXRDY) == 0) + continue; + MCF_UART_UTB(CONSOLE_PORT) = c; + while ((MCF_UART_USR(CONSOLE_PORT) & MCF_UART_USR_TXRDY) == 0) + continue; + rtems_interrupt_enable(level); +} + +BSP_output_char_function_type BSP_output_char = _BSP_null_char; + +#define MAX_UART_INFO 3 +#define RX_BUFFER_SIZE 512 + +struct IntUartInfoStruct +{ + int iomode; + volatile int uimr; + int baud; + int databits; + int parity; + int stopbits; + int hwflow; + int rx_in; + int rx_out; + char rx_buffer[RX_BUFFER_SIZE]; + void *ttyp; +}; + +struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO]; + +/*************************************************************************** + Function : IntUartSet + + Description : This updates the hardware UART settings. + ***************************************************************************/ +static void +IntUartSet(int minor, int baud, int databits, int parity, int stopbits, + int hwflow) +{ + int divisor; + uint32_t clock_speed; + uint8_t umr1 = 0; + uint8_t umr2 = 0; + struct IntUartInfoStruct *info = &IntUartInfo[minor]; + int level; + + rtems_interrupt_disable(level); + + /* disable interrupts, clear RTS line, and disable the UARTS */ + MCF_UART_UIMR(minor) = 0; + MCF_UART_UOP0(minor) = 1; + MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_DISABLED | MCF_UART_UCR_RX_DISABLED); + + /* save the current values */ + info->uimr = 0; + info->baud = baud; + info->databits = databits; + info->parity = parity; + info->stopbits = stopbits; + info->hwflow = hwflow; + + clock_speed = bsp_get_BUS_clock_speed(); + /* determine the baud divisor value */ + divisor = ((clock_speed) / (32 * baud)); + if (divisor < 2) + divisor = 2; + + /* check to see if doing hardware flow control */ + if (hwflow) { + /* set hardware flow options */ + umr1 |= MCF_UART_UMR_RXRTS; + umr2 |= MCF_UART_UMR_TXCTS; + } + + /* determine the new umr values */ + umr1 |= (parity | databits); + umr2 |= (stopbits); + + /* reset the uart */ + MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_ERROR; + MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_RX; + MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_TX; + + /* reset the uart mode register and update values */ + MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_MR; + MCF_UART_UMR(minor) = umr1; + MCF_UART_UMR(minor) = umr2; + + /* set the baud rate values */ + MCF_UART_UCSR(minor) = + (MCF_UART_UCSR_RCS_SYS_CLK | MCF_UART_UCSR_TCS_SYS_CLK); + MCF_UART_UBG1(minor) = (divisor & 0xff00) >> 8; + MCF_UART_UBG2(minor) = (divisor & 0x00ff); + + /* enable the uart */ + MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED); + + /* check to see if interrupts need to be enabled */ + if (info->iomode != TERMIOS_POLLED) { + /* enable rx interrupts */ + info->uimr |= MCF_UART_UIMR_RXRDY_FU; + MCF_UART_UIMR(minor) = info->uimr; + } + + /* check to see if doing hardware flow control */ + if (hwflow) { + /* assert the RTS line */ + MCF_UART_UOP1(minor) = 1; + } + + rtems_interrupt_enable(level); + +} + +/*************************************************************************** + Function : IntUartSetAttributes + + Description : This provides the hardware-dependent portion of tcsetattr(). + value and sets it. At the moment this just sets the baud rate. + + Note: The highest baudrate is 115200 as this stays within + an error of +/- 5% at 25MHz processor clock + ***************************************************************************/ +static int IntUartSetAttributes(int minor, const struct termios *t) +{ + /* set default index values */ + int baud = (int) 19200; + int databits = (int) MCF_UART_UMR_BC_8; + int parity = (int) MCF_UART_UMR_PM_NONE; + int stopbits = (int) MCF_UART_UMR_SB_STOP_BITS_1; + int hwflow = (int) 0; + struct IntUartInfoStruct *info = &IntUartInfo[minor]; + + /* check to see if input is valid */ + if (t != (const struct termios *) 0) { + /* determine baud rate index */ + baud = termios_baud_to_number(t->c_cflag & CBAUD); + + /* determine data bits */ + switch (t->c_cflag & CSIZE) { + case CS5: + databits = (int) MCF_UART_UMR_BC_5; + break; + case CS6: + databits = (int) MCF_UART_UMR_BC_6; + break; + case CS7: + databits = (int) MCF_UART_UMR_BC_7; + break; + case CS8: + databits = (int) MCF_UART_UMR_BC_8; + break; + } + + /* determine if parity is enabled */ + if (t->c_cflag & PARENB) { + if (t->c_cflag & PARODD) { + /* odd parity */ + parity = (int) MCF_UART_UMR_PM_ODD; + } else { + /* even parity */ + parity = (int) MCF_UART_UMR_PM_EVEN; + } + } + + /* determine stop bits */ + if (t->c_cflag & CSTOPB) { + /* two stop bits */ + stopbits = (int) MCF_UART_UMR_SB_STOP_BITS_2; + } + + /* check to see if hardware flow control */ + if (t->c_cflag & CRTSCTS) { + hwflow = 1; + } + } + + /* check to see if values have changed */ + if ((baud != info->baud) || + (databits != info->databits) || + (parity != info->parity) || + (stopbits != info->stopbits) || (hwflow != info->hwflow)) { + + /* call function to set values */ + IntUartSet(minor, baud, databits, parity, stopbits, hwflow); + } + + return (RTEMS_SUCCESSFUL); + +} + +/*************************************************************************** + Function : IntUartInterruptHandler + + Description : This is the interrupt handler for the internal uart. It + determines which channel caused the interrupt before queueing any received + chars and dequeueing chars waiting for transmission. + ***************************************************************************/ +static rtems_isr IntUartInterruptHandler(rtems_vector_number v) +{ + unsigned int chan = v - UART_INTC0_IRQ_VECTOR(0); + struct IntUartInfoStruct *info = &IntUartInfo[chan]; + + /* check to see if received data */ + if (MCF_UART_UISR(chan) & MCF_UART_UISR_RXRDY_FU) { + /* read data and put into the receive buffer */ + while (MCF_UART_USR(chan) & MCF_UART_USR_RXRDY) { + + if (MCF_UART_USR(chan) & MCF_UART_USR_ERROR) { + /* clear the error */ + MCF_UART_UCR(chan) = MCF_UART_UCR_RESET_ERROR; + } + /* put data in rx buffer and check for errors */ + info->rx_buffer[info->rx_in] = MCF_UART_URB(chan); + + /* update buffer values */ + info->rx_in++; + + if (info->rx_in >= RX_BUFFER_SIZE) { + info->rx_in = 0; + } + } + /* Make sure the port has been opened */ + if (info->ttyp) { + + /* check to see if task driven */ + if (info->iomode == TERMIOS_TASK_DRIVEN) { + /* notify rx task that rx buffer has data */ + rtems_termios_rxirq_occured(info->ttyp); + } else { + /* Push up the received data */ + rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, + info->rx_in); + info->rx_in = 0; + } + } + } + + /* check to see if data needs to be transmitted */ + if ((info->uimr & MCF_UART_UIMR_TXRDY) && + (MCF_UART_UISR(chan) & MCF_UART_UISR_TXRDY)) { + + /* disable tx interrupts */ + info->uimr &= ~MCF_UART_UIMR_TXRDY; + MCF_UART_UIMR(chan) = info->uimr; + + /* tell upper level that character has been sent */ + if (info->ttyp) + rtems_termios_dequeue_characters(info->ttyp, 1); + } +} + +/*************************************************************************** + Function : IntUartInitialize + + Description : This initialises the internal uart hardware for all + internal uarts. If the internal uart is to be interrupt driven then the + interrupt vectors are hooked. + ***************************************************************************/ +static void IntUartInitialize(void) +{ + unsigned int chan; + struct IntUartInfoStruct *info; + rtems_isr_entry old_handler; + int level; + + for (chan = 0; chan < MAX_UART_INFO; chan++) { + info = &IntUartInfo[chan]; + + info->ttyp = NULL; + info->rx_in = 0; + info->rx_out = 0; + info->baud = -1; + info->databits = -1; + info->parity = -1; + info->stopbits = -1; + info->hwflow = -1; + info->iomode = TERMIOS_POLLED; /*polled console io */ + + MCF_UART_UACR(chan) = 0; + MCF_UART_UIMR(chan) = 0; + if (info->iomode != TERMIOS_POLLED) { + rtems_interrupt_catch(IntUartInterruptHandler, + UART_INTC0_IRQ_VECTOR(chan), &old_handler); + } + + /* set uart default values */ + IntUartSetAttributes(chan, NULL); + + /* unmask interrupt */ + rtems_interrupt_disable(level); + switch (chan) { + case 0: + MCF_INTC0_ICR26 = MCF_INTC_ICR_IL(UART0_IRQ_LEVEL); + MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK26); + break; + + case 1: + MCF_INTC0_ICR27 = MCF_INTC_ICR_IL(UART1_IRQ_LEVEL); + MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK27); + break; + + case 2: + MCF_INTC0_ICR28 = MCF_INTC_ICR_IL(UART2_IRQ_LEVEL); + MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK28); + break; + } + rtems_interrupt_enable(level); + + } /* of chan loop */ + +} /* IntUartInitialise */ + +/*************************************************************************** + Function : IntUartInterruptWrite + + Description : This writes a single character to the appropriate uart + channel. This is either called during an interrupt or in the user's task + to initiate a transmit sequence. Calling this routine enables Tx + interrupts. + ***************************************************************************/ +static int IntUartInterruptWrite(int minor, const char *buf, int len) +{ + int level; + + rtems_interrupt_disable(level); + + /* write out character */ + MCF_UART_UTB(minor) = *buf; + + /* enable tx interrupt */ + IntUartInfo[minor].uimr |= MCF_UART_UIMR_TXRDY; + MCF_UART_UIMR(minor) = IntUartInfo[minor].uimr; + + rtems_interrupt_enable(level); + return (0); +} + +/*************************************************************************** + Function : IntUartInterruptOpen + + Description : This enables interrupts when the tty is opened. + ***************************************************************************/ +static int IntUartInterruptOpen(int major, int minor, void *arg) +{ + struct IntUartInfoStruct *info = &IntUartInfo[minor]; + + /* enable the uart */ + MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED); + + /* check to see if interrupts need to be enabled */ + if (info->iomode != TERMIOS_POLLED) { + /* enable rx interrupts */ + info->uimr |= MCF_UART_UIMR_RXRDY_FU; + MCF_UART_UIMR(minor) = info->uimr; + } + + /* check to see if doing hardware flow control */ + if (info->hwflow) { + /* assert the RTS line */ + MCF_UART_UOP1(minor) = 1; + } + + return (0); +} + +/*************************************************************************** + Function : IntUartInterruptClose + + Description : This disables interrupts when the tty is closed. + ***************************************************************************/ +static int IntUartInterruptClose(int major, int minor, void *arg) +{ + struct IntUartInfoStruct *info = &IntUartInfo[minor]; + + /* disable the interrupts and the uart */ + MCF_UART_UIMR(minor) = 0; + MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_DISABLED | MCF_UART_UCR_RX_DISABLED); + + /* reset values */ + info->ttyp = NULL; + info->uimr = 0; + info->rx_in = 0; + info->rx_out = 0; + + return (0); +} + +/*************************************************************************** + Function : IntUartTaskRead + + Description : This reads all available characters from the internal uart + and places them into the termios buffer. The rx interrupts will be + re-enabled after all data has been read. + ***************************************************************************/ +static int IntUartTaskRead(int minor) +{ + char buffer[RX_BUFFER_SIZE]; + int count; + int rx_in; + int index = 0; + struct IntUartInfoStruct *info = &IntUartInfo[minor]; + + /* determine number of values to copy out */ + rx_in = info->rx_in; + if (info->rx_out <= rx_in) { + count = rx_in - info->rx_out; + } else { + count = (RX_BUFFER_SIZE - info->rx_out) + rx_in; + } + + /* copy data into local buffer from rx buffer */ + while ((index < count) && (index < RX_BUFFER_SIZE)) { + /* copy data byte */ + buffer[index] = info->rx_buffer[info->rx_out]; + index++; + + /* increment rx buffer values */ + info->rx_out++; + if (info->rx_out >= RX_BUFFER_SIZE) { + info->rx_out = 0; + } + } + + /* check to see if buffer is not empty */ + if (count > 0) { + /* set characters into termios buffer */ + rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count); + } + + return (EOF); +} + +/*************************************************************************** + Function : IntUartPollRead + + Description : This reads a character from the internal uart. It returns + to the caller without blocking if not character is waiting. + ***************************************************************************/ +static int IntUartPollRead(int minor) +{ + if ((MCF_UART_USR(minor) & MCF_UART_USR_RXRDY) == 0) + return (-1); + + return (MCF_UART_URB(minor)); +} + +/*************************************************************************** + Function : IntUartPollWrite + + Description : This writes out each character in the buffer to the + appropriate internal uart channel waiting till each one is sucessfully + transmitted. + ***************************************************************************/ +static int IntUartPollWrite(int minor, const char *buf, int len) +{ + /* loop over buffer */ + while (len--) { + /* block until we can transmit */ + while ((MCF_UART_USR(minor) & MCF_UART_USR_TXRDY) == 0) + continue; + /* transmit data byte */ + MCF_UART_UTB(minor) = *buf++; + } + return (0); +} + +/*************************************************************************** + Function : console_initialize + + Description : This initialises termios, both sets of uart hardware before + registering /dev/tty devices for each channel and the system /dev/console. + ***************************************************************************/ +rtems_device_driver console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code status; + + /* Set up TERMIOS */ + rtems_termios_initialize(); + + /* set io modes for the different channels and initialize device */ + IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN; + IntUartInitialize(); + + /* Register the console port */ + status = rtems_io_register_name("/dev/console", major, CONSOLE_PORT); + if (status != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(status); + } + + /* Register the other port */ + if (CONSOLE_PORT != 0) { + status = rtems_io_register_name("/dev/tty00", major, 0); + if (status != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(status); + } + } + if (CONSOLE_PORT != 1) { + status = rtems_io_register_name("/dev/tty01", major, 1); + if (status != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(status); + } + } + + return (RTEMS_SUCCESSFUL); +} + +/*************************************************************************** + Function : console_open + + Description : This actually opens the device depending on the minor + number set during initialisation. The device specific access routines are + passed to termios when the devices is opened depending on whether it is + polled or not. + ***************************************************************************/ +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, void *arg) +{ + rtems_status_code status = RTEMS_INVALID_NUMBER; + rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *) arg; + struct IntUartInfoStruct *info; + + static const rtems_termios_callbacks IntUartPollCallbacks = { + NULL, /* firstOpen */ + NULL, /* lastClose */ + IntUartPollRead, /* pollRead */ + IntUartPollWrite, /* write */ + IntUartSetAttributes, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + TERMIOS_POLLED /* mode */ + }; + static const rtems_termios_callbacks IntUartIntrCallbacks = { + IntUartInterruptOpen, /* firstOpen */ + IntUartInterruptClose, /* lastClose */ + NULL, /* pollRead */ + IntUartInterruptWrite, /* write */ + IntUartSetAttributes, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + TERMIOS_IRQ_DRIVEN /* mode */ + }; + + static const rtems_termios_callbacks IntUartTaskCallbacks = { + IntUartInterruptOpen, /* firstOpen */ + IntUartInterruptClose, /* lastClose */ + IntUartTaskRead, /* pollRead */ + IntUartInterruptWrite, /* write */ + IntUartSetAttributes, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + TERMIOS_TASK_DRIVEN /* mode */ + }; + + /* open the port depending on the minor device number */ + if ((minor >= 0) && (minor < MAX_UART_INFO)) { + info = &IntUartInfo[minor]; + switch (info->iomode) { + case TERMIOS_POLLED: + status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks); + break; + case TERMIOS_IRQ_DRIVEN: + status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks); + info->ttyp = args->iop->data1; + break; + case TERMIOS_TASK_DRIVEN: + status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks); + info->ttyp = args->iop->data1; + break; + } + } + + if (status == RTEMS_SUCCESSFUL) { + /* + * Reset the default baudrate. + */ + struct termios term; + + if (tcgetattr(STDIN_FILENO, &term) >= 0) { + term.c_cflag &= ~(CBAUD | CSIZE); + term.c_cflag |= CS8 | B19200; + tcsetattr(STDIN_FILENO, TCSANOW, &term); + } + } + + return (status); +} + +/*************************************************************************** + Function : console_close + + Description : This closes the device via termios + ***************************************************************************/ +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, void *arg) +{ + return (rtems_termios_close(arg)); +} + +/****************** +********************************************************* + Function : console_read + + Description : Read from the device via termios + ***************************************************************************/ +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, void *arg) +{ + return (rtems_termios_read(arg)); +} + +/*************************************************************************** + Function : console_write + + Description : Write to the device via termios + ***************************************************************************/ +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, void *arg) +{ + return (rtems_termios_write(arg)); +} + +/*************************************************************************** + Function : console_ioctl + + Description : Pass the IOCtl call to termios + ***************************************************************************/ +rtems_device_driver console_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + return (rtems_termios_ioctl(arg)); +} +int DEBUG_OUTCHAR(int c) +{ + if (c == '\n') + DEBUG_OUTCHAR('\r'); + _BSP_null_char(c); + return c; +} +void DEBUG_OUTSTR(const char *msg) +{ + while (*msg) + DEBUG_OUTCHAR(*msg++); +} +void DEBUG_OUTNUM(int i) +{ + int n; + static const char map[] = "0123456789ABCDEF"; + + DEBUG_OUTCHAR(' '); + for (n = 28; n >= 0; n -= 4) + DEBUG_OUTCHAR(map[(i >> n) & 0xF]); +} diff --git a/c/src/lib/libbsp/m68k/mcf5329/gdb-init b/c/src/lib/libbsp/m68k/mcf5329/gdb-init new file mode 100644 index 0000000000..fbcf796ce1 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/gdb-init @@ -0,0 +1,104 @@ +#target remote | m68k-bdm-gdbserver pipe /dev/bdmcf0 -v -d +target remote | m68k-bdm-gdbserver pipe /dev/bdmcf0 + +#monitor set remote-debug 1 +#monitor set debug 1 +monitor bdm-reset + +# +# Show the exception stack frame. +# +define show-exception-sframe + set $frsr = *(unsigned short *)((unsigned long)$sp + 2) + set $frpc = *(unsigned long *)((unsigned long)$sp + 4) + set $frfvo = *(unsigned short *)((unsigned long)$sp + 0) + set $frcode = $frfvo >> 12 + set $frvect = ($frfvo & 0xFFF) >> 2 + set $frstatus = ((($frfvo >> 10) & 3) << 2) | ($frfvo & 3) + printf "EXCEPTION -- SR:0x%X PC:0x%X FRAME:0x%x VECTOR:%d STATUS:%d\n", $frsr, $frpc, $frcode, $frvect, $frstatus + if $frstatus == 4 + printf " Fault Type: Error on instruction fetch" + end + if $frstatus == 8 + printf " Fault Type: Error on operand write" + end + if $frstatus == 12 + printf " Fault Type: Error on operand read" + end + if $frstatus == 9 + printf " Fault Type: Attempted write to write-protected space" + end +end + +# I have to do this as there seems to be a problem with me setting up the +# chip selects. As far as I can tell, gdb is probing whats at the program +# counter. It issues a 2 byte read (smallest instruction) followed by a +# 4 byte read (depending on the result of the 2 byte read). gdb issues these +# reads after each and every write that the .gdbinit script issues. This means +# that as I'm initializing the chip selects the gdb reads can happen in an +# invalid memory address and this causes a target bus error. For now I'm just +# setting pc to 0, which seems to stop gdb from probing around to read +# assembler. This lets me setup chip selects without error. + +set $pc = 0x00000000 + +# Turn on RAMBAR1 at address 80000000 +monitor bdm-ctl-set 0x0C05 0x80000221 + +# Set VBR to the beginning of what will be SDRAM +# VBR is an absolute CPU register +monitor bdm-ctl-set 0x0801 0x40000000 + +# Disable watchdog timer +set *((short*) 0xFC098000) = 0x0000 + +#Init CS0 +set *((long*) 0xFC008000) = 0x00000000 +set *((long*) 0xFC008008) = 0x00001FA0 +set *((long*) 0xFC008004) = 0x001F0001 + +# SDRAM Initialization + +monitor delay-ms 100 + +# SDCS0 +set *((long*) 0xFC0B8110) = 0x40000018 +# SDCFG1 +set *((long*) 0xFC0B8008) = 0x53722730 +# SDCFG2 +set *((long*) 0xFC0B800C) = 0x56670000 + +# Issue PALL +# SDCR +set *((long*) 0xFC0B8004) = 0xE1092002 + +# Issue LEMR +# SDMR +set *((long*) 0xFC0B8000) = 0x40010000 + +# Write mode register +# SDMR +set *((long*) 0xFC0B8000) = 0x058D0000 + +# Wait a bit +monitor delay-ms 600 + +# Issue PALL +# SDCR +set *((long*) 0xFC0B8004) = 0xE1092002 + +# Perform two refresh cycles +# SDCR +set *((long*) 0xFC0B8004) = 0xE1092004 +# SDCR +set *((long*) 0xFC0B8004) = 0xE1092004 + +# SDMR +set *((long*) 0xFC0B8000) = 0x018D0000 +# SDCR +set *((long*) 0xFC0B8004) = 0x71092C00 + +# Wait a bit +monitor delay-ms 100 + +load diff --git a/c/src/lib/libbsp/m68k/mcf5329/include/bsp.h b/c/src/lib/libbsp/m68k/mcf5329/include/bsp.h new file mode 100644 index 0000000000..9f55434eea --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/include/bsp.h @@ -0,0 +1,88 @@ +/* + * mcf52235 BSP header file + */ + +#ifndef _BSP_H +#define _BSP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <bspopts.h> +#include <rtems.h> +#include <rtems/iosupp.h> +#include <rtems/console.h> +#include <rtems/clockdrv.h> +#include <rtems/iosupp.h> +#include <rtems/bspIo.h> + +/***************************************************************************/ +/** Hardware data structure headers **/ +#include <mcf532x/mcf532x.h> + +typedef volatile unsigned char vuint8; +typedef volatile unsigned short vuint16; +typedef volatile unsigned long vuint32; + +/***************************************************************************/ +/** Network driver configuration **/ +struct rtems_bsdnet_ifconfig; +extern int rtems_fec_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching ); +#define RTEMS_BSP_NETWORK_DRIVER_NAME "fec0" +#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_fec_driver_attach + +/***************************************************************************/ +/** User Definable configuration **/ + +/* define which port the console should use - all other ports are then defined as general purpose */ +#define CONSOLE_PORT 0 + +/* externals */ + +/* constants */ + +/* miscellaneous stuff assumed to exist */ + +/* + * Device Driver Table Entries + */ + +/* + * NOTE: Use the standard Console driver entry + */ + +/* + * NOTE: Use the standard Clock driver entry + */ + + +/* functions */ + +uint32_t bsp_get_CPU_clock_speed(void); +uint32_t bsp_get_BUS_clock_speed(void); + +void bsp_cleanup(void); +m68k_isr_entry set_vector( + rtems_isr_entry handler, + rtems_vector_number vector, + int type +); + +/* + * Interrupt assignments + * Highest-priority listed first + */ +#define FEC_IRQ_LEVEL 4 + +#define PIT3_IRQ_LEVEL 4 + +#define UART0_IRQ_LEVEL 3 +#define UART1_IRQ_LEVEL 3 +#define UART2_IRQ_LEVEL 3 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/m68k/mcf5329/include/bspopts.h.in b/c/src/lib/libbsp/m68k/mcf5329/include/bspopts.h.in new file mode 100644 index 0000000000..a8a4bcbb38 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/include/bspopts.h.in @@ -0,0 +1,24 @@ +/* include/bspopts.h.in. Generated from configure.ac by autoheader. */ + +/* BSP uses shared logic in bootcard.c */ +#undef BSP_BOOTCARD_HANDLES_RAM_ALLOCATION + +/* If defined, then PSIM will put a non-zero pattern into the RTEMS Workspace + and C program heap. This should assist in finding code that assumes memory + starts set to zero. */ +#undef BSP_DIRTY_MEMORY + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION diff --git a/c/src/lib/libbsp/m68k/mcf5329/include/coverhd.h b/c/src/lib/libbsp/m68k/mcf5329/include/coverhd.h new file mode 100644 index 0000000000..a0aaa20535 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/include/coverhd.h @@ -0,0 +1,105 @@ +/* coverhd.h + * + * This include file has defines to represent the overhead associated + * with calling a particular directive from C. These are used in the + * Timing Test Suite to ignore the overhead required to pass arguments + * to directives. On some CPUs and/or target boards, this overhead + * is significant and makes it difficult to distinguish internal + * RTEMS execution time from that used to call the directive. + * This file should be updated after running the C overhead timing + * test. Once this update has been performed, the RTEMS Time Test + * Suite should be rebuilt to account for these overhead times in the + * timing results. + * + * NOTE: If these are all zero, then the times reported include + * all calling overhead including passing of arguments. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * + * 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. + * + * $Id$ + */ + +#ifndef __COVERHD_h +#define __COVERHD_h + +#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 0 +#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 0 +#define CALLING_OVERHEAD_TASK_CREATE 0 +#define CALLING_OVERHEAD_TASK_IDENT 0 +#define CALLING_OVERHEAD_TASK_START 0 +#define CALLING_OVERHEAD_TASK_RESTART 0 +#define CALLING_OVERHEAD_TASK_DELETE 0 +#define CALLING_OVERHEAD_TASK_SUSPEND 0 +#define CALLING_OVERHEAD_TASK_RESUME 0 +#define CALLING_OVERHEAD_TASK_SET_PRIORITY 0 +#define CALLING_OVERHEAD_TASK_MODE 0 +#define CALLING_OVERHEAD_TASK_GET_NOTE 0 +#define CALLING_OVERHEAD_TASK_SET_NOTE 0 +#define CALLING_OVERHEAD_TASK_WAKE_WHEN 1 +#define CALLING_OVERHEAD_TASK_WAKE_AFTER 0 +#define CALLING_OVERHEAD_INTERRUPT_CATCH 0 +#define CALLING_OVERHEAD_CLOCK_GET 1 +#define CALLING_OVERHEAD_CLOCK_SET 1 +#define CALLING_OVERHEAD_CLOCK_TICK 0 + +#define CALLING_OVERHEAD_TIMER_CREATE 0 +#define CALLING_OVERHEAD_TIMER_IDENT 0 +#define CALLING_OVERHEAD_TIMER_DELETE 0 +#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 1 +#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 1 +#define CALLING_OVERHEAD_TIMER_RESET 0 +#define CALLING_OVERHEAD_TIMER_CANCEL 0 +#define CALLING_OVERHEAD_SEMAPHORE_CREATE 0 +#define CALLING_OVERHEAD_SEMAPHORE_IDENT 0 +#define CALLING_OVERHEAD_SEMAPHORE_DELETE 0 +#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 0 +#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 0 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 0 + +#define CALLING_OVERHEAD_EVENT_SEND 0 +#define CALLING_OVERHEAD_EVENT_RECEIVE 0 +#define CALLING_OVERHEAD_SIGNAL_CATCH 0 +#define CALLING_OVERHEAD_SIGNAL_SEND 0 +#define CALLING_OVERHEAD_PARTITION_CREATE 0 +#define CALLING_OVERHEAD_PARTITION_IDENT 0 +#define CALLING_OVERHEAD_PARTITION_DELETE 0 +#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 0 +#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 0 +#define CALLING_OVERHEAD_REGION_CREATE 0 +#define CALLING_OVERHEAD_REGION_IDENT 0 +#define CALLING_OVERHEAD_REGION_DELETE 0 +#define CALLING_OVERHEAD_REGION_GET_SEGMENT 0 +#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 0 +#define CALLING_OVERHEAD_PORT_CREATE 0 +#define CALLING_OVERHEAD_PORT_IDENT 0 +#define CALLING_OVERHEAD_PORT_DELETE 0 +#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 0 +#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 0 + +#define CALLING_OVERHEAD_IO_INITIALIZE 0 +#define CALLING_OVERHEAD_IO_OPEN 0 +#define CALLING_OVERHEAD_IO_CLOSE 0 +#define CALLING_OVERHEAD_IO_READ 0 +#define CALLING_OVERHEAD_IO_WRITE 0 +#define CALLING_OVERHEAD_IO_CONTROL 0 +#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 0 +#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 0 +#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 0 + +#endif diff --git a/c/src/lib/libbsp/m68k/mcf5329/include/tm27.h b/c/src/lib/libbsp/m68k/mcf5329/include/tm27.h new file mode 100644 index 0000000000..f8fe447335 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/include/tm27.h @@ -0,0 +1,29 @@ +/* + * 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 _RTEMS_TMTEST27 +#error "This is an RTEMS internal file you must not include directly." +#endif + +#ifndef __tm27_h +#define __tm27_h + +/* + * Stuff for Time Test 27 + * Don't bother with hardware -- just use a software-interrupt + */ + +#define MUST_WAIT_FOR_INTERRUPT 0 + +#define Install_tm27_vector( handler ) set_vector( (handler), 35, 1 ) + +#define Cause_tm27_intr() asm volatile ("trap #3"); + +#define Clear_tm27_intr() /* empty */ + +#define Lower_tm27_intr() /* empty */ + +#endif diff --git a/c/src/lib/libbsp/m68k/mcf5329/network/network.c b/c/src/lib/libbsp/m68k/mcf5329/network/network.c new file mode 100644 index 0000000000..15b383961c --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/network/network.c @@ -0,0 +1,857 @@ + +/* + * RTEMS/TCPIP driver for MCF5329 Fast Ethernet Controller + * + * TO DO: Check network stack code -- force longword alignment of all tx mbufs? + */ + +#include <bsp.h> +#include <stdio.h> +#include <errno.h> +#include <stdarg.h> +#include <string.h> +#include <rtems.h> +#include <rtems/error.h> +#include <rtems/rtems_bsdnet.h> + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/sockio.h> + +#include <net/ethernet.h> +#include <net/if.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +/* + * Number of interfaces supported by this driver + */ +#define NIFACES 1 + +#define FEC_INTC0_TX_VECTOR (64+36) +#define FEC_INTC0_RX_VECTOR (64+40) + +/* + * Default number of buffer descriptors set aside for this driver. + * The number of transmit buffer descriptors has to be quite large + * since a single frame often uses three or more buffer descriptors. + */ +#define RX_BUF_COUNT 32 +#define TX_BUF_COUNT 20 +#define TX_BD_PER_BUF 3 + +#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") + +/* + * RTEMS event used by interrupt handler to signal daemons. + * This must *not* be the same event used by the TCP/IP task synchronization. + */ +#define TX_INTERRUPT_EVENT RTEMS_EVENT_1 +#define RX_INTERRUPT_EVENT RTEMS_EVENT_1 + +/* + * RTEMS event used to start transmit daemon. + * This must not be the same as INTERRUPT_EVENT. + */ +#define START_TRANSMIT_EVENT RTEMS_EVENT_2 + +/* + * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). + * Round off to nearest multiple of RBUF_ALIGN. + */ +#define MAX_MTU_SIZE 1518 +#define RBUF_ALIGN 4 +#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) + +#if (MCLBYTES < RBUF_SIZE) +# error "Driver must have MCLBYTES > RBUF_SIZE" +#endif + +typedef struct mcf5329BufferDescriptor_ +{ + volatile uint16_t status; + uint16_t length; + volatile void *buffer; +} mcf5329BufferDescriptor_t; + +/* + * Per-device data + */ +struct mcf5329_enet_struct +{ + struct arpcom arpcom; + struct mbuf **rxMbuf; + struct mbuf **txMbuf; + int acceptBroadcast; + int rxBdCount; + int txBdCount; + int txBdHead; + int txBdTail; + int txBdActiveCount; + mcf5329BufferDescriptor_t *rxBdBase; + mcf5329BufferDescriptor_t *txBdBase; + rtems_id rxDaemonTid; + rtems_id txDaemonTid; + + /* + * Statistics + */ + unsigned long rxInterrupts; + unsigned long txInterrupts; + unsigned long txRawWait; + unsigned long txRealign; +}; +static struct mcf5329_enet_struct enet_driver[NIFACES]; + +static rtems_isr mcf5329_fec_rx_interrupt_handler(rtems_vector_number v) +{ + MCF_FEC_EIR = MCF_FEC_EIR_RXF; + MCF_FEC_EIMR &= ~MCF_FEC_EIMR_RXF; + enet_driver[0].rxInterrupts++; + rtems_event_send(enet_driver[0].rxDaemonTid, RX_INTERRUPT_EVENT); +} + +static rtems_isr mcf5329_fec_tx_interrupt_handler(rtems_vector_number v) +{ + MCF_FEC_EIR = MCF_FEC_EIR_TXF; + MCF_FEC_EIMR &= ~MCF_FEC_EIMR_TXF; + enet_driver[0].txInterrupts++; + rtems_event_send(enet_driver[0].txDaemonTid, TX_INTERRUPT_EVENT); +} + +/* + * Allocate buffer descriptors from (non-cached) on-chip static RAM + * Ensure 128-bit (16-byte) alignment + */ +static mcf5329BufferDescriptor_t *mcf5329_bd_allocate(unsigned int count) +{ + extern char _CoreSRamBase[]; + static mcf5329BufferDescriptor_t *bdp = + (mcf5329BufferDescriptor_t *) _CoreSRamBase; + mcf5329BufferDescriptor_t *p = bdp; + + bdp += count; + if ((int) bdp & 0xF) + bdp = + (mcf5329BufferDescriptor_t *) ((char *) bdp + (16 - ((int) bdp & 0xF))); + return p; +} + +#if UNUSED + +/* + * Read MII register + * Busy-waits, but transfer time should be short! + */ +static int getMII(int phyNumber, int regNumber) +{ + MCF_FEC_MMFR = (0x1 << 30) | + (0x2 << 28) | (phyNumber << 23) | (regNumber << 18) | (0x2 << 16); + while ((MCF_FEC_EIR & MCF_FEC_EIR_MII) == 0) ; + MCF_FEC_EIR = MCF_FEC_EIR_MII; + return MCF_FEC_MMFR & 0xFFFF; +} +#endif + +/* + * Write MII register + * Busy-waits, but transfer time should be short! + */ +static void setMII(int phyNumber, int regNumber, int value) +{ + MCF_FEC_MMFR = (0x1 << 30) | + (0x1 << 28) | + (phyNumber << 23) | (regNumber << 18) | (0x2 << 16) | (value & 0xFFFF); + while ((MCF_FEC_EIR & MCF_FEC_EIR_MII) == 0) ; + MCF_FEC_EIR = MCF_FEC_EIR_MII; +} + +static void mcf5329_fec_initialize_hardware(struct mcf5329_enet_struct *sc) +{ + int i; + const unsigned char *hwaddr = 0; + rtems_status_code status; + rtems_isr_entry old_handler; + uint32_t clock_speed = bsp_get_BUS_clock_speed(); + + /* + * Issue reset to FEC + */ + MCF_FEC_ECR = MCF_FEC_ECR_RESET; + rtems_task_wake_after(1); + MCF_FEC_ECR = 0; + + /* + * Configuration of I/O ports is done outside of this function + */ +#if 0 + imm->gpio.pbcnt |= MCF_GPIO_PBCNT_SET_FEC; /* Set up port b FEC pins */ +#endif + + /* + * Set our physical address + */ + hwaddr = sc->arpcom.ac_enaddr; + MCF_FEC_PALR = (hwaddr[0] << 24) | (hwaddr[1] << 16) | + (hwaddr[2] << 8) | (hwaddr[3] << 0); + MCF_FEC_PAUR = (hwaddr[4] << 24) | (hwaddr[5] << 16); + + /* + * Clear the hash table + */ + MCF_FEC_GAUR = 0; + MCF_FEC_GALR = 0; + + /* + * Set up receive buffer size + */ + MCF_FEC_EMRBR = 1520; /* Standard Ethernet */ + + /* + * Allocate mbuf pointers + */ + sc->rxMbuf = malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); + sc->txMbuf = malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); + if (!sc->rxMbuf || !sc->txMbuf) + rtems_panic("No memory for mbuf pointers"); + + /* + * Set receiver and transmitter buffer descriptor bases + */ + sc->rxBdBase = mcf5329_bd_allocate(sc->rxBdCount); + sc->txBdBase = mcf5329_bd_allocate(sc->txBdCount); + MCF_FEC_ERDSR = (int) sc->rxBdBase; + MCF_FEC_ETDSR = (int) sc->txBdBase; + + /* + * Set up Receive Control Register: + * Not promiscuous + * MII mode + * Full duplex + * No loopback + */ + MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(MAX_MTU_SIZE) | MCF_FEC_RCR_MII_MODE; + + /* + * Set up Transmit Control Register: + * Full duplex + * No heartbeat + */ + MCF_FEC_TCR = MCF_FEC_TCR_FDEN; + + /* + * Initialize statistic counters + */ + MCF_FEC_MIBC = MCF_FEC_MIBC_MIB_DISABLE; + { + vuint32 *vuip = &MCF_FEC_RMON_T_DROP; + + while (vuip <= &MCF_FEC_IEEE_R_OCTETS_OK) + *vuip++ = 0; + } + MCF_FEC_MIBC = 0; + + /* + * Set MII speed to <= 2.5 MHz + */ + i = (clock_speed + 5000000 - 1) / 5000000; + MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED(i); + + /* + * Set PHYS to 100 Mb/s, full duplex + */ + setMII(1, 0, 0x2100); + + /* + * Set up receive buffer descriptors + */ + for (i = 0; i < sc->rxBdCount; i++) + (sc->rxBdBase + i)->status = 0; + + /* + * Set up transmit buffer descriptors + */ + for (i = 0; i < sc->txBdCount; i++) { + sc->txBdBase[i].status = 0; + sc->txMbuf[i] = NULL; + } + sc->txBdHead = sc->txBdTail = 0; + sc->txBdActiveCount = 0; + + /* + * Set up interrupts + */ + status = + rtems_interrupt_catch(mcf5329_fec_tx_interrupt_handler, + FEC_INTC0_TX_VECTOR, &old_handler); + if (status != RTEMS_SUCCESSFUL) + rtems_panic("Can't attach MCF FEC TX interrupt handler: %s\n", + rtems_status_text(status)); + status = + rtems_interrupt_catch(mcf5329_fec_rx_interrupt_handler, + FEC_INTC0_RX_VECTOR, &old_handler); + if (status != RTEMS_SUCCESSFUL) + rtems_panic("Can't attach MCF FEC RX interrupt handler: %s\n", + rtems_status_text(status)); + MCF_INTC0_ICR36 = MCF_INTC_ICR_IL(FEC_IRQ_LEVEL); + MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK36); + MCF_INTC0_ICR40 = MCF_INTC_ICR_IL(FEC_IRQ_LEVEL); + MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK40); +} + +/* + * Get the MAC address from the hardware. + */ +static void +fec_get_mac_address(volatile struct mcf5329_enet_struct *sc, + unsigned char *hwaddr) +{ + unsigned long addr; + + addr = MCF_FEC_PALR; + + hwaddr[0] = (addr >> 24) & 0xff; + hwaddr[1] = (addr >> 16) & 0xff; + hwaddr[2] = (addr >> 8) & 0xff; + hwaddr[3] = (addr >> 0) & 0xff; + + addr = MCF_FEC_PAUR; + + hwaddr[4] = (addr >> 24) & 0xff; + hwaddr[5] = (addr >> 16) & 0xff; +} + +/* + * Soak up buffer descriptors that have been sent. + */ +static void fec_retire_tx_bd(volatile struct mcf5329_enet_struct *sc) +{ + struct mbuf *m, *n; + + while ((sc->txBdActiveCount != 0) + && ((sc->txBdBase[sc->txBdTail].status & MCF_FEC_TxBD_R) == 0)) { + m = sc->txMbuf[sc->txBdTail]; + MFREE(m, n); + if (++sc->txBdTail == sc->txBdCount) + sc->txBdTail = 0; + sc->txBdActiveCount--; + } +} + +static void fec_rxDaemon(void *arg) +{ + volatile struct mcf5329_enet_struct *sc = + (volatile struct mcf5329_enet_struct *) arg; + struct ifnet *ifp = (struct ifnet *) &sc->arpcom.ac_if; + struct mbuf *m; + volatile uint16_t status; + volatile mcf5329BufferDescriptor_t *rxBd; + int rxBdIndex; + + /* + * Allocate space for incoming packets and start reception + */ + for (rxBdIndex = 0;;) { + rxBd = sc->rxBdBase + rxBdIndex; + MGETHDR(m, M_WAIT, MT_DATA); + MCLGET(m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + sc->rxMbuf[rxBdIndex] = m; + rxBd->buffer = mtod(m, void *); + + rxBd->status = MCF_FEC_RxBD_E; + if (++rxBdIndex == sc->rxBdCount) { + rxBd->status |= MCF_FEC_RxBD_W; + break; + } + } + + /* + * Input packet handling loop + */ + /* Indicate we have some ready buffers available */ + MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; + + rxBdIndex = 0; + for (;;) { + rxBd = sc->rxBdBase + rxBdIndex; + + /* + * Wait for packet if there's not one ready + */ + if ((status = rxBd->status) & MCF_FEC_RxBD_E) { + /* + * Clear old events. + */ + MCF_FEC_EIR = MCF_FEC_EIR_RXF; + + /* + * Wait for packet to arrive. + * Check the buffer descriptor before waiting for the event. + * This catches the case when a packet arrives between the + * `if' above, and the clearing of the RXF bit in the EIR. + */ + while ((status = rxBd->status) & MCF_FEC_RxBD_E) { + rtems_event_set events; + int level; + + rtems_interrupt_disable(level); + MCF_FEC_EIMR |= MCF_FEC_EIMR_RXF; + rtems_interrupt_enable(level); + rtems_bsdnet_event_receive(RX_INTERRUPT_EVENT, + RTEMS_WAIT | RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, &events); + } + } + + /* + * Check that packet is valid + */ + if (status & MCF_FEC_RxBD_L) { + /* + * Pass the packet up the chain. + * FIXME: Packet filtering hook could be done here. + */ + struct ether_header *eh; + int len = rxBd->length - sizeof(uint32_t);; + + /* + * Invalidate the cache and push the packet up. + * The cache is so small that it's more efficient to just + * invalidate the whole thing unless the packet is very small. + */ + m = sc->rxMbuf[rxBdIndex]; + if (len < 128) + rtems_cache_invalidate_multiple_data_lines(m->m_data, len); + else + rtems_cache_invalidate_entire_data(); + m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); + eh = mtod(m, struct ether_header *); + m->m_data += sizeof(struct ether_header); + ether_input(ifp, eh, m); + + /* + * Allocate a new mbuf + */ + MGETHDR(m, M_WAIT, MT_DATA); + MCLGET(m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + sc->rxMbuf[rxBdIndex] = m; + rxBd->buffer = mtod(m, void *); + } + + /* + * Reenable the buffer descriptor + */ + rxBd->status = (status & MCF_FEC_RxBD_W) | MCF_FEC_RxBD_E; + MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; + + /* + * Move to next buffer descriptor + */ + if (++rxBdIndex == sc->rxBdCount) + rxBdIndex = 0; + } +} + +static void fec_sendpacket(struct ifnet *ifp, struct mbuf *m) +{ + struct mcf5329_enet_struct *sc = ifp->if_softc; + volatile mcf5329BufferDescriptor_t *firstTxBd, *txBd; + uint16_t status; + int nAdded; + + /* + * Free up buffer descriptors + */ + fec_retire_tx_bd(sc); + + /* + * Set up the transmit buffer descriptors. + * No need to pad out short packets since the + * hardware takes care of that automatically. + * No need to copy the packet to a contiguous buffer + * since the hardware is capable of scatter/gather DMA. + */ + nAdded = 0; + firstTxBd = sc->txBdBase + sc->txBdHead; + + for (;;) { + /* + * Wait for buffer descriptor to become available + */ + if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { + /* + * Clear old events. + */ + MCF_FEC_EIR = MCF_FEC_EIR_TXF; + + /* + * Wait for buffer descriptor to become available. + * Check for buffer descriptors before waiting for the event. + * This catches the case when a buffer became available between + * the `if' above, and the clearing of the TXF bit in the EIR. + */ + fec_retire_tx_bd(sc); + while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { + rtems_event_set events; + int level; + + rtems_interrupt_disable(level); + MCF_FEC_EIMR |= MCF_FEC_EIMR_TXF; + rtems_interrupt_enable(level); + sc->txRawWait++; + rtems_bsdnet_event_receive(TX_INTERRUPT_EVENT, + RTEMS_WAIT | RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, &events); + fec_retire_tx_bd(sc); + } + } + + /* + * Don't set the READY flag on the first fragment + * until the whole packet has been readied. + */ + status = nAdded ? MCF_FEC_TxBD_R : 0; + + /* + * The IP fragmentation routine in ip_output + * can produce fragments with zero length. + */ + txBd = sc->txBdBase + sc->txBdHead; + if (m->m_len) { + char *p = mtod(m, char *); + + /* + * Stupid FEC can't handle misaligned data! + * Given the way that mbuf's are layed out it should be + * safe to shuffle the data down like this..... + * Perhaps this code could be improved with a "Duff's Device". + */ + if ((int) p & 0x3) { + int l = m->m_len; + char *dest = p - ((int) p & 0x3); + uint16_t *o = (uint16_t *) dest, *i = (uint16_t *) p; + + while (l > 0) { + *o++ = *i++; + l -= sizeof(uint16_t); + } + p = dest; + sc->txRealign++; + } + txBd->buffer = p; + txBd->length = m->m_len; + sc->txMbuf[sc->txBdHead] = m; + nAdded++; + if (++sc->txBdHead == sc->txBdCount) { + status |= MCF_FEC_TxBD_W; + sc->txBdHead = 0; + } + m = m->m_next; + } else { + /* + * Just toss empty mbufs + */ + struct mbuf *n; + + MFREE(m, n); + m = n; + } + if (m == NULL) { + if (nAdded) { + txBd->status = status | MCF_FEC_TxBD_R + | MCF_FEC_TxBD_L | MCF_FEC_TxBD_TC; + if (nAdded > 1) + firstTxBd->status |= MCF_FEC_TxBD_R; + MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE; + sc->txBdActiveCount += nAdded; + } + break; + } + txBd->status = status; + } +} + +void fec_txDaemon(void *arg) +{ + struct mcf5329_enet_struct *sc = (struct mcf5329_enet_struct *) arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mbuf *m; + rtems_event_set events; + + for (;;) { + /* + * Wait for packet + */ + rtems_bsdnet_event_receive(START_TRANSMIT_EVENT, + RTEMS_EVENT_ANY | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, &events); + + /* + * Send packets till queue is empty + */ + for (;;) { + /* + * Get the next mbuf chain to transmit. + */ + IF_DEQUEUE(&ifp->if_snd, m); + if (!m) + break; + fec_sendpacket(ifp, m); + } + ifp->if_flags &= ~IFF_OACTIVE; + } +} + +/* + * Send packet (caller provides header). + */ +static void mcf5329_enet_start(struct ifnet *ifp) +{ + struct mcf5329_enet_struct *sc = ifp->if_softc; + + rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); + ifp->if_flags |= IFF_OACTIVE; +} + +static void fec_init(void *arg) +{ + struct mcf5329_enet_struct *sc = arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + + if (sc->txDaemonTid == 0) { + /* + * Set up hardware + */ + mcf5329_fec_initialize_hardware(sc); + + /* + * Start driver tasks + */ + sc->txDaemonTid = rtems_bsdnet_newproc("FECtx", 4096, fec_txDaemon, sc); + sc->rxDaemonTid = rtems_bsdnet_newproc("FECrx", 4096, fec_rxDaemon, sc); + } + + /* + * Set flags appropriately + */ + if (ifp->if_flags & IFF_PROMISC) + MCF_FEC_RCR |= MCF_FEC_RCR_PROM; + else + MCF_FEC_RCR &= ~MCF_FEC_RCR_PROM; + + /* + * Tell the world that we're running. + */ + ifp->if_flags |= IFF_RUNNING; + + /* + * Enable receiver and transmitter + */ + MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN; +} + +static void fec_stop(struct mcf5329_enet_struct *sc) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + + ifp->if_flags &= ~IFF_RUNNING; + + /* + * Shut down receiver and transmitter + */ + MCF_FEC_ECR = 0x0; +} + +/* + * Show interface statistics + */ +static void enet_stats(struct mcf5329_enet_struct *sc) +{ + printf(" Rx Interrupts:%-10lu", sc->rxInterrupts); + printf("Rx Packet Count:%-10lu", MCF_FEC_RMON_R_PACKETS); + printf(" Rx Broadcast:%-10lu\n", MCF_FEC_RMON_R_BC_PKT); + printf(" Rx Multicast:%-10lu", MCF_FEC_RMON_R_MC_PKT); + printf("CRC/Align error:%-10lu", MCF_FEC_RMON_R_CRC_ALIGN); + printf(" Rx Undersize:%-10lu\n", MCF_FEC_RMON_R_UNDERSIZE); + printf(" Rx Oversize:%-10lu", MCF_FEC_RMON_R_OVERSIZE); + printf(" Rx Fragment:%-10lu", MCF_FEC_RMON_R_FRAG); + printf(" Rx Jabber:%-10lu\n", MCF_FEC_RMON_R_JAB); + printf(" Rx 64:%-10lu", MCF_FEC_RMON_R_P64); + printf(" Rx 65-127:%-10lu", MCF_FEC_RMON_R_P65TO127); + printf(" Rx 128-255:%-10lu\n", MCF_FEC_RMON_R_P128TO255); + printf(" Rx 256-511:%-10lu", MCF_FEC_RMON_R_P256TO511); + printf(" Rx 511-1023:%-10lu", MCF_FEC_RMON_R_512TO1023); + printf(" Rx 1024-2047:%-10lu\n", MCF_FEC_RMON_R_1024TO2047); + printf(" Rx >=2048:%-10lu", MCF_FEC_RMON_R_P_GTE2048); + printf(" Rx Octets:%-10lu", MCF_FEC_RMON_R_OCTETS); + printf(" Rx Dropped:%-10lu\n", MCF_FEC_IEEE_R_DROP); + printf(" Rx frame OK:%-10lu", MCF_FEC_IEEE_R_FRAME_OK); + printf(" Rx CRC error:%-10lu", MCF_FEC_IEEE_R_CRC); + printf(" Rx Align error:%-10lu\n", MCF_FEC_IEEE_R_ALIGN); + printf(" FIFO Overflow:%-10lu", MCF_FEC_IEEE_R_MACERR); + printf("Rx Pause Frames:%-10lu", MCF_FEC_IEEE_R_FDXFC); + printf(" Rx Octets OK:%-10lu\n", MCF_FEC_IEEE_R_OCTETS_OK); + printf(" Tx Interrupts:%-10lu", sc->txInterrupts); + printf("Tx Output Waits:%-10lu", sc->txRawWait); + printf("Tx Realignments:%-10lu\n", sc->txRealign); + printf(" Tx Unaccounted:%-10lu", MCF_FEC_RMON_T_DROP); + printf("Tx Packet Count:%-10lu", MCF_FEC_RMON_T_PACKETS); + printf(" Tx Broadcast:%-10lu\n", MCF_FEC_RMON_T_BC_PKT); + printf(" Tx Multicast:%-10lu", MCF_FEC_RMON_T_MC_PKT); + printf("CRC/Align error:%-10lu", MCF_FEC_RMON_T_CRC_ALIGN); + printf(" Tx Undersize:%-10lu\n", MCF_FEC_RMON_T_UNDERSIZE); + printf(" Tx Oversize:%-10lu", MCF_FEC_RMON_T_OVERSIZE); + printf(" Tx Fragment:%-10lu", MCF_FEC_RMON_T_FRAG); + printf(" Tx Jabber:%-10lu\n", MCF_FEC_RMON_T_JAB); + printf(" Tx Collisions:%-10lu", MCF_FEC_RMON_T_COL); + printf(" Tx 64:%-10lu", MCF_FEC_RMON_T_P64); + printf(" Tx 65-127:%-10lu\n", MCF_FEC_RMON_T_P65TO127); + printf(" Tx 128-255:%-10lu", MCF_FEC_RMON_T_P128TO255); + printf(" Tx 256-511:%-10lu", MCF_FEC_RMON_T_P256TO511); + printf(" Tx 511-1023:%-10lu\n", MCF_FEC_RMON_T_P512TO1023); + printf(" Tx 1024-2047:%-10lu", MCF_FEC_RMON_T_P1024TO2047); + printf(" Tx >=2048:%-10lu", MCF_FEC_RMON_T_P_GTE2048); + printf(" Tx Octets:%-10lu\n", MCF_FEC_RMON_T_OCTETS); + printf(" Tx Dropped:%-10lu", MCF_FEC_IEEE_T_DROP); + printf(" Tx Frame OK:%-10lu", MCF_FEC_IEEE_T_FRAME_OK); + printf(" Tx 1 Collision:%-10lu\n", MCF_FEC_IEEE_T_1COL); + printf("Tx >1 Collision:%-10lu", MCF_FEC_IEEE_T_MCOL); + printf(" Tx Deferred:%-10lu", MCF_FEC_IEEE_T_DEF); + printf(" Late Collision:%-10lu\n", MCF_FEC_IEEE_T_LCOL); + printf(" Excessive Coll:%-10lu", MCF_FEC_IEEE_T_EXCOL); + printf(" FIFO Underrun:%-10lu", MCF_FEC_IEEE_T_MACERR); + printf(" Carrier Error:%-10lu\n", MCF_FEC_IEEE_T_CSERR); + printf(" Tx SQE Error:%-10lu", MCF_FEC_IEEE_T_SQE); + printf("Tx Pause Frames:%-10lu", MCF_FEC_IEEE_T_FDXFC); + printf(" Tx Octets OK:%-10lu\n", MCF_FEC_IEEE_T_OCTETS_OK); +} + +static int fec_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) +{ + struct mcf5329_enet_struct *sc = ifp->if_softc; + int error = 0; + + switch (command) { + case SIOCGIFADDR: + case SIOCSIFADDR: + ether_ioctl(ifp, command, data); + break; + + case SIOCSIFFLAGS: + switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { + case IFF_RUNNING: + fec_stop(sc); + break; + + case IFF_UP: + fec_init(sc); + break; + + case IFF_UP | IFF_RUNNING: + fec_stop(sc); + fec_init(sc); + break; + + default: + break; + } + break; + + case SIO_RTEMS_SHOW_STATS: + enet_stats(sc); + break; + + /* + * FIXME: All sorts of multicast commands need to be added here! + */ + default: + error = EINVAL; + break; + } + return error; +} + +int +rtems_fec_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching) +{ + struct mcf5329_enet_struct *sc; + struct ifnet *ifp; + int mtu; + int unitNumber; + char *unitName; + unsigned char *hwaddr; + + /* + * Parse driver name + */ + if ((unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0) + return 0; + + /* + * Is driver free? + */ + if ((unitNumber < 0) || (unitNumber >= NIFACES)) { + printf("mcf5329: bad FEC unit number.\n"); + return 0; + } + sc = &enet_driver[unitNumber]; + ifp = &sc->arpcom.ac_if; + if (ifp->if_softc != NULL) { + printf("mcf5329: driver already in use.\n"); + return 0; + } + + /* + * Process options + */ + if (config->hardware_address) + memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); + else + fec_get_mac_address(sc, sc->arpcom.ac_enaddr); + + hwaddr = config->hardware_address; + printf("%s%d: mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + unitName, unitNumber, + hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); + + if (config->mtu) + mtu = config->mtu; + else + mtu = ETHERMTU; + if (config->rbuf_count) + sc->rxBdCount = config->rbuf_count; + else + sc->rxBdCount = RX_BUF_COUNT; + if (config->xbuf_count) + sc->txBdCount = config->xbuf_count; + else + sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; + + sc->acceptBroadcast = !config->ignore_broadcast; + + /* + * Set up network interface values + */ + ifp->if_softc = sc; + ifp->if_unit = unitNumber; + ifp->if_name = unitName; + ifp->if_mtu = mtu; + ifp->if_init = fec_init; + ifp->if_ioctl = fec_ioctl; + ifp->if_start = mcf5329_enet_start; + ifp->if_output = ether_output; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; + + /* + * Attach the interface + */ + if_attach(ifp); + ether_ifattach(ifp); + return 1; +}; diff --git a/c/src/lib/libbsp/m68k/mcf5329/preinstall.am b/c/src/lib/libbsp/m68k/mcf5329/preinstall.am new file mode 100644 index 0000000000..ed793f80fe --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/preinstall.am @@ -0,0 +1,62 @@ +## Automatically generated by ampolish3 - Do not edit + +if AMPOLISH3 +$(srcdir)/preinstall.am: Makefile.am + $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am +endif + +PREINSTALL_DIRS = +DISTCLEANFILES += $(PREINSTALL_DIRS) + +all-local: $(TMPINSTALL_FILES) + +TMPINSTALL_FILES = +CLEANFILES = $(TMPINSTALL_FILES) + +all-am: $(PREINSTALL_FILES) + +PREINSTALL_FILES = +CLEANFILES += $(PREINSTALL_FILES) + +$(PROJECT_LIB)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_LIB) + @: > $(PROJECT_LIB)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp) + +$(PROJECT_INCLUDE)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE) + @: > $(PROJECT_INCLUDE)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp) + +$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs +PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs + +$(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: include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h + +$(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h + +$(PROJECT_INCLUDE)/coverhd.h: include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h + +$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT) +TMPINSTALL_FILES += $(PROJECT_LIB)/start.$(OBJEXT) + +$(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds +PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds + +$(PROJECT_LIB)/linkcmdsflash: startup/linkcmdsflash $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmdsflash +PREINSTALL_FILES += $(PROJECT_LIB)/linkcmdsflash + diff --git a/c/src/lib/libbsp/m68k/mcf5329/start/start.S b/c/src/lib/libbsp/m68k/mcf5329/start/start.S new file mode 100644 index 0000000000..217d6595a1 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/start/start.S @@ -0,0 +1,382 @@ +/* + * mcf52235 startup code + * + * This file contains the entry point for the application. + * The name of this entry point is compiler dependent. + * It jumps to the BSP which is responsible for performing + * all initialization. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * + * 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. + * + * $Id$ + */ + +#include <rtems/asm.h> + +.extern _StackInit + +BEGIN_CODE + + PUBLIC (_INTERRUPT_VECTOR) +SYM(_INTERRUPT_VECTOR): + + .long _StackInit /* 00 Initial 'SSP' */ + .long SYM(start) /* 01 Initial PC */ + .long SYM(_uhoh) /* 02 Access Error */ + .long SYM(_uhoh) /* 03 Address Error */ + .long SYM(_uhoh) /* 04 Illegal Instruction */ + .long SYM(_uhoh) /* 05 Divide by Zero */ + .long SYM(_uhoh) /* 06 Reserved */ + .long SYM(_uhoh) /* 07 Reserved */ + .long SYM(_uhoh) /* 08 Privilege Violation */ + .long SYM(_uhoh) /* 09 Trace */ + .long SYM(_uhoh) /* 10 Unimplemented A-Line */ + .long SYM(_uhoh) /* 11 Unimplemented F-Line */ + .long SYM(_uhoh) /* 12 Debug Interrupt */ + .long SYM(_uhoh) /* 13 Reserved */ + .long SYM(_uhoh) /* 14 Format Error */ + .long SYM(_uhoh) /* 15 Reserved */ + .long SYM(_uhoh) /* 16 Reserved */ + .long SYM(_uhoh) /* 17 Reserved */ + .long SYM(_uhoh) /* 18 Reserved */ + .long SYM(_uhoh) /* 19 Reserved */ + .long SYM(_uhoh) /* 20 Reserved */ + .long SYM(_uhoh) /* 21 Reserved */ + .long SYM(_uhoh) /* 22 Reserved */ + .long SYM(_uhoh) /* 23 Reserved */ + .long SYM(_spuriousInterrupt) /* 24 Spurious Interrupt */ + .long SYM(_uhoh) /* Reserved */ + .long SYM(_uhoh) /* Reserved */ + .long SYM(_uhoh) /* Reserved */ + .long SYM(_uhoh) /* Reserved */ + .long SYM(_uhoh) /* Reserved */ + .long SYM(_uhoh) /* Reserved */ + .long SYM(_uhoh) /* Reserved */ + .long SYM(_uhoh) /* 32 TRAP #0 */ + .long SYM(_uhoh) /* 33 TRAP #1 */ + .long SYM(_uhoh) /* 34 TRAP #2 */ + .long SYM(_uhoh) /* 35 TRAP #3 */ + .long SYM(_uhoh) /* 36 TRAP #4 */ + .long SYM(_uhoh) /* 37 TRAP #5 */ + .long SYM(_uhoh) /* 38 TRAP #6 */ + .long SYM(_uhoh) /* 39 TRAP #7 */ + .long SYM(_uhoh) /* 40 TRAP #8 */ + .long SYM(_uhoh) /* 41 TRAP #9 */ + .long SYM(_uhoh) /* 42 TRAP #10 */ + .long SYM(_uhoh) /* 43 TRAP #11 */ + .long SYM(_uhoh) /* 44 TRAP #12 */ + .long SYM(_uhoh) /* 45 TRAP #13 */ + .long SYM(_uhoh) /* 46 TRAP #14 */ + .long SYM(_uhoh) /* 47 TRAP #15 */ + .long SYM(_uhoh) /* 48 Reserved */ + .long SYM(_uhoh) /* 49 Reserved */ + .long SYM(_uhoh) /* 50 Reserved */ + .long SYM(_uhoh) /* 51 Reserved */ + .long SYM(_uhoh) /* 52 Reserved */ + .long SYM(_uhoh) /* 53 Reserved */ + .long SYM(_uhoh) /* 54 Reserved */ + .long SYM(_uhoh) /* 55 Reserved */ + .long SYM(_uhoh) /* 56 Reserved */ + .long SYM(_uhoh) /* 57 Reserved */ + .long SYM(_uhoh) /* 58 Reserved */ + .long SYM(_uhoh) /* 59 Reserved */ + .long SYM(_uhoh) /* 60 Reserved */ + .long SYM(_uhoh) /* 61 Reserved */ + .long SYM(_uhoh) /* 62 Reserved */ + .long SYM(_uhoh) /* 63 Reserved */ + + /* INTC0 */ + + .long SYM(_uhoh) /* 64*/ + .long SYM(_uhoh) /* 65*/ + .long SYM(_uhoh) /* 66*/ + .long SYM(_uhoh) /* 67*/ + .long SYM(_uhoh) /* 68*/ + .long SYM(_uhoh) /* 69*/ + .long SYM(_uhoh) /* 70*/ + .long SYM(_uhoh) /* 71*/ + .long SYM(_uhoh) /* 72*/ + .long SYM(_uhoh) /* 73*/ + .long SYM(_uhoh) /* 74*/ + .long SYM(_uhoh) /* 75*/ + .long SYM(_uhoh) /* 76*/ + .long SYM(_uhoh) /* 77*/ + .long SYM(_uhoh) /* 78*/ + .long SYM(_uhoh) /* 79*/ + .long SYM(_uhoh) /* 80*/ + .long SYM(_uhoh) /* 81*/ + .long SYM(_uhoh) /* 82*/ + .long SYM(_uhoh) /* 83*/ + .long SYM(_uhoh) /* 84*/ + .long SYM(_uhoh) /* 85*/ + .long SYM(_uhoh) /* 86*/ + .long SYM(_uhoh) /* 87*/ + .long SYM(_uhoh) /* 88*/ + .long SYM(_uhoh) /* 89*/ + .long SYM(_uhoh) /* 90*/ + .long SYM(_uhoh) /* 91*/ + .long SYM(_uhoh) /* 92*/ + .long SYM(_uhoh) /* 93*/ + .long SYM(_uhoh) /* 94*/ + .long SYM(_uhoh) /* 95*/ + .long SYM(_uhoh) /* 96*/ + .long SYM(_uhoh) /* 97*/ + .long SYM(_uhoh) /* 98*/ + .long SYM(_uhoh) /* 99*/ + .long SYM(_uhoh) /* 100*/ + .long SYM(_uhoh) /* 101*/ + .long SYM(_uhoh) /* 102*/ + .long SYM(_uhoh) /* 103*/ + .long SYM(_uhoh) /* 104*/ + .long SYM(_uhoh) /* 105*/ + .long SYM(_uhoh) /* 106*/ + .long SYM(_uhoh) /* 107*/ + .long SYM(_uhoh) /* 108*/ + .long SYM(_uhoh) /* 109*/ + .long SYM(_uhoh) /* 110*/ + .long SYM(_uhoh) /* 111*/ + .long SYM(_uhoh) /* 112*/ + .long SYM(_uhoh) /* 113*/ + .long SYM(_uhoh) /* 114*/ + .long SYM(_uhoh) /* 115*/ + .long SYM(_uhoh) /* 116*/ + .long SYM(_uhoh) /* 117*/ + .long SYM(_uhoh) /* 118*/ + .long SYM(_uhoh) /* 119*/ + .long SYM(_uhoh) /* 120*/ + .long SYM(_uhoh) /* 121*/ + .long SYM(_uhoh) /* 122*/ + .long SYM(_uhoh) /* 123*/ + .long SYM(_uhoh) /* 124*/ + .long SYM(_uhoh) /* 125*/ + .long SYM(_uhoh) /* 126*/ + .long SYM(_uhoh) /* 127*/ + + /* INTC1 */ + + .long SYM(_uhoh) /* 128*/ + .long SYM(_uhoh) /* 129*/ + .long SYM(_uhoh) /* 130*/ + .long SYM(_uhoh) /* 131*/ + .long SYM(_uhoh) /* 132*/ + .long SYM(_uhoh) /* 133*/ + .long SYM(_uhoh) /* 134*/ + .long SYM(_uhoh) /* 135*/ + .long SYM(_uhoh) /* 136*/ + .long SYM(_uhoh) /* 137*/ + .long SYM(_uhoh) /* 138*/ + .long SYM(_uhoh) /* 139*/ + .long SYM(_uhoh) /* 140*/ + .long SYM(_uhoh) /* 141*/ + .long SYM(_uhoh) /* 142*/ + .long SYM(_uhoh) /* 143*/ + .long SYM(_uhoh) /* 144*/ + .long SYM(_uhoh) /* 145*/ + .long SYM(_uhoh) /* 146*/ + .long SYM(_uhoh) /* 147*/ + .long SYM(_uhoh) /* 148*/ + .long SYM(_uhoh) /* 149*/ + .long SYM(_uhoh) /* 150*/ + .long SYM(_uhoh) /* 151*/ + .long SYM(_uhoh) /* 152*/ + .long SYM(_uhoh) /* 153*/ + .long SYM(_uhoh) /* 154*/ + .long SYM(_uhoh) /* 155*/ + .long SYM(_uhoh) /* 156*/ + .long SYM(_uhoh) /* 157*/ + .long SYM(_uhoh) /* 158*/ + .long SYM(_uhoh) /* 159*/ + .long SYM(_uhoh) /* 160*/ + .long SYM(_uhoh) /* 161*/ + .long SYM(_uhoh) /* 162*/ + .long SYM(_uhoh) /* 163*/ + .long SYM(_uhoh) /* 164*/ + .long SYM(_uhoh) /* 165*/ + .long SYM(_uhoh) /* 166*/ + .long SYM(_uhoh) /* 167*/ + .long SYM(_uhoh) /* 168*/ + .long SYM(_uhoh) /* 169*/ + .long SYM(_uhoh) /* 170*/ + .long SYM(_uhoh) /* 171*/ + .long SYM(_uhoh) /* 172*/ + .long SYM(_uhoh) /* 173*/ + .long SYM(_uhoh) /* 174*/ + .long SYM(_uhoh) /* 175*/ + .long SYM(_uhoh) /* 176*/ + .long SYM(_uhoh) /* 177*/ + .long SYM(_uhoh) /* 178*/ + .long SYM(_uhoh) /* 179*/ + .long SYM(_uhoh) /* 180*/ + .long SYM(_uhoh) /* 181*/ + .long SYM(_uhoh) /* 182*/ + .long SYM(_uhoh) /* 183*/ + .long SYM(_uhoh) /* 184*/ + .long SYM(_uhoh) /* 185*/ + .long SYM(_uhoh) /* 186*/ + .long SYM(_uhoh) /* 187*/ + .long SYM(_uhoh) /* 188*/ + .long SYM(_uhoh) /* 189*/ + .long SYM(_uhoh) /* 190*/ + .long SYM(_uhoh) /* 191*/ + .long SYM(_uhoh) /* 192*/ + + /* */ + + .long SYM(_uhoh) /* 193*/ + .long SYM(_uhoh) /* 194*/ + .long SYM(_uhoh) /* 195*/ + .long SYM(_uhoh) /* 196*/ + .long SYM(_uhoh) /* 197*/ + .long SYM(_uhoh) /* 198*/ + .long SYM(_uhoh) /* 199*/ + .long SYM(_uhoh) /* 200*/ + .long SYM(_uhoh) /* 201*/ + .long SYM(_uhoh) /* 202*/ + .long SYM(_uhoh) /* 203*/ + .long SYM(_uhoh) /* 204*/ + .long SYM(_uhoh) /* 205*/ + .long SYM(_uhoh) /* 206*/ + .long SYM(_uhoh) /* 207*/ + .long SYM(_uhoh) /* 208*/ + .long SYM(_uhoh) /* 209*/ + .long SYM(_uhoh) /* 210*/ + .long SYM(_uhoh) /* 211*/ + .long SYM(_uhoh) /* 212*/ + .long SYM(_uhoh) /* 213*/ + .long SYM(_uhoh) /* 214*/ + .long SYM(_uhoh) /* 215*/ + .long SYM(_uhoh) /* 216*/ + .long SYM(_uhoh) /* 217*/ + .long SYM(_uhoh) /* 218*/ + .long SYM(_uhoh) /* 219*/ + .long SYM(_uhoh) /* 220*/ + .long SYM(_uhoh) /* 221*/ + .long SYM(_uhoh) /* 222*/ + .long SYM(_uhoh) /* 223*/ + .long SYM(_uhoh) /* 224*/ + .long SYM(_uhoh) /* 225*/ + .long SYM(_uhoh) /* 226*/ + .long SYM(_uhoh) /* 227*/ + .long SYM(_uhoh) /* 228*/ + .long SYM(_uhoh) /* 229*/ + .long SYM(_uhoh) /* 230*/ + .long SYM(_uhoh) /* 231*/ + .long SYM(_uhoh) /* 232*/ + .long SYM(_uhoh) /* 233*/ + .long SYM(_uhoh) /* 234*/ + .long SYM(_uhoh) /* 235*/ + .long SYM(_uhoh) /* 236*/ + .long SYM(_uhoh) /* 237*/ + .long SYM(_uhoh) /* 238*/ + .long SYM(_uhoh) /* 239*/ + .long SYM(_uhoh) /* 240*/ + .long SYM(_uhoh) /* 241*/ + .long SYM(_uhoh) /* 242*/ + .long SYM(_uhoh) /* 243*/ + .long SYM(_uhoh) /* 244*/ + .long SYM(_uhoh) /* 245*/ + .long SYM(_uhoh) /* 246*/ + .long SYM(_uhoh) /* 247*/ + .long SYM(_uhoh) /* 248*/ + .long SYM(_uhoh) /* 249*/ + .long SYM(_uhoh) /* 250*/ + .long SYM(_uhoh) /* 251*/ + .long SYM(_uhoh) /* 252*/ + .long SYM(_uhoh) /* 253*/ + .long SYM(_uhoh) /* 254*/ + .long SYM(_uhoh) /* 255*/ + +/* + * Default trap handler + * With an oscilloscope you can see AS* stop + */ +.align 4 + PUBLIC (_uhoh) +SYM(_uhoh): + nop | Leave spot for breakpoint + stop #0x2700 | Stop with interrupts disabled + bra.w SYM(_uhoh) | Stuck forever + +/* + * Spurious Interrupt Handler + */ +.align 4 + PUBLIC (_spuriousInterrupt) +SYM(_spuriousInterrupt): + addql #1, SYM(_M68kSpuriousInterruptCount) + rte + +/* + * Write VBR Register + */ +.align 4 + PUBLIC (_wr_vbr) +SYM(_wr_vbr): + move.l 4(sp), d0 + movec d0, vbr + nop + rts + +/* + * Board startup + * Disable watchdog, interrupts + * Enable sram + */ +.align 4 + PUBLIC (start) +SYM(start): + + /* Mask off interupts */ + move.w #0x2700,sr + + /* Save off reset values of D0 and D1 */ + move.l d0,d6 + move.l d1,d7 + + /* Initialize RAMBAR1: locate SRAM and validate it */ + move.l #_CoreSRamBase,d0 + add.l #0x221,d0 + movec d0,%rambar + + /* Save off intial D0 and D1 to RAM */ + move.l d6, SYM(_d0_reset) + move.l d7, SYM(_d1_reset) + + /* Locate Stack Pointer */ + move.l #_StackInit,sp + + /* + * Remainder of the startup code is handled by C code + * This never returns + */ + jmp SYM(Init5329) + +END_CODE + + +BEGIN_DATA_DCL + + .align 4 + +PUBLIC (_M68kSpuriousInterruptCount) +SYM (_M68kSpuriousInterruptCount): + .long 0 + +PUBLIC (_d0_reset) +SYM (_d0_reset): + .long 0 + +PUBLIC (_d1_reset) +SYM (_d1_reset): + .long 0 + +END_DATA_DCL + +END + diff --git a/c/src/lib/libbsp/m68k/mcf5329/startup/bspclean.c b/c/src/lib/libbsp/m68k/mcf5329/startup/bspclean.c new file mode 100644 index 0000000000..0a51e87e49 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/startup/bspclean.c @@ -0,0 +1,33 @@ + +/* + * SBC5206 bsp_cleanup + * + * This routine returns control from RTEMS to the monitor. + * + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * + * 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. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include <rtems/bspIo.h> + +void bsp_cleanup(void) +{ + printk("\nRTEMS exited!\n"); + for (;;) { + asm volatile (" nop "); + asm volatile (" nop "); + } +} diff --git a/c/src/lib/libbsp/m68k/mcf5329/startup/bspstart.c b/c/src/lib/libbsp/m68k/mcf5329/startup/bspstart.c new file mode 100644 index 0000000000..46c839ab2b --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/startup/bspstart.c @@ -0,0 +1,97 @@ + +/* + * BSP startup + * + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + * + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * + * 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. + * + * $Id$ + */ + +#include <bsp.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> + +/* + * Cannot be frozen + */ +void _CPU_cache_freeze_data(void) +{ +} +void _CPU_cache_unfreeze_data(void) +{ +} +void _CPU_cache_freeze_instruction(void) +{ +} +void _CPU_cache_unfreeze_instruction(void) +{ +} + +/* + * Write-through data cache -- flushes are unnecessary + */ +void _CPU_cache_flush_1_data_line(const void *d_addr) +{ +} +void _CPU_cache_flush_entire_data(void) +{ +} + +void _CPU_cache_enable_instruction(void) +{ +} +void _CPU_cache_disable_instruction(void) +{ +} +void _CPU_cache_invalidate_entire_instruction(void) +{ +} +void _CPU_cache_invalidate_1_instruction_line(const void *addr) +{ +} + +void _CPU_cache_enable_data(void) +{ +} +void _CPU_cache_disable_data(void) +{ +} +void _CPU_cache_invalidate_entire_data(void) +{ +} +void _CPU_cache_invalidate_1_data_line(const void *addr) +{ +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialisation. + */ +void bsp_start(void) +{ +} + +uint32_t bsp_get_CPU_clock_speed(void) +{ + return 240000000; +} + +uint32_t bsp_get_BUS_clock_speed(void) +{ + return 80000000; +} diff --git a/c/src/lib/libbsp/m68k/mcf5329/startup/cfinit.c b/c/src/lib/libbsp/m68k/mcf5329/startup/cfinit.c new file mode 100644 index 0000000000..c133bc4bf0 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/startup/cfinit.c @@ -0,0 +1,435 @@ + +/********************************************************************* +* Initialisation Code for ColdFire MCF5329 Processor * +********************************************************************** + Generated by ColdFire Initialisation Utility 2.10.8 + Mon Jun 16 10:41:41 2008 + + MicroAPL Ltd makes no warranties in respect of the suitability + of this code for any particular purpose, and accepts + no liability for any loss arising out of its use. The person or + persons making use of this file must make the final evaluation + as to its suitability and correctness for a particular application. + + $Id$ +*/ + +/* External reference frequency is 16.0000 MHz + Internal bus clock frequency = 80.00 MHz + Processor core frequency = 240.00 MHz +*/ + +#include <bsp.h> + +/* eDMA Transfer Control Descriptor definitions */ +#define MCF_EDMA_TCD_W0(channel) (*(vuint32 *)(0xFC045000+((channel)*0x20))) /* Transfer Control Descriptor Word 0 */ +#define MCF_EDMA_TCD_W1(channel) (*(vuint32 *)(0xFC045004+((channel)*0x20))) /* Transfer Control Descriptor Word 1 */ +#define MCF_EDMA_TCD_W2(channel) (*(vuint32 *)(0xFC045008+((channel)*0x20))) /* Transfer Control Descriptor Word 2 */ +#define MCF_EDMA_TCD_W3(channel) (*(vuint32 *)(0xFC04500C+((channel)*0x20))) /* Transfer Control Descriptor Word 3 */ +#define MCF_EDMA_TCD_W4(channel) (*(vuint32 *)(0xFC045010+((channel)*0x20))) /* Transfer Control Descriptor Word 4 */ +#define MCF_EDMA_TCD_W5(channel) (*(vuint32 *)(0xFC045014+((channel)*0x20))) /* Transfer Control Descriptor Word 5 */ +#define MCF_EDMA_TCD_W6(channel) (*(vuint32 *)(0xFC045018+((channel)*0x20))) /* Transfer Control Descriptor Word 6 */ +#define MCF_EDMA_TCD_W7(channel) (*(vuint32 *)(0xFC04501C+((channel)*0x20))) /* Transfer Control Descriptor Word 7 */ + +/* Function prototypes */ +void init_main(void); +static void disable_interrupts(void); +static void disable_watchdog_timer(void); +static void disable_cache(void); +extern void init_clock_config(void) __attribute__ ((section(".ram_code"))); +extern void init_chip_selects(void) __attribute__ ((section(".ram_code"))); +static void init_real_time_clock(void); +static void init_watchdog_timers(void); +static void init_pin_assignments(void); +extern void init_sdram_controller(void) + __attribute__ ((section(".ram_code"))); + +/********************************************************************* +* init_main - Main entry point for initialisation code * +**********************************************************************/ +void init_main(void) +{ + /* Mask all interrupts */ + init_clock_config(); + + /* Disable interrupts, watchdog timer, cache */ + disable_interrupts(); + disable_watchdog_timer(); + disable_cache(); + + /* Initialise individual modules */ + init_chip_selects(); + init_real_time_clock(); + init_watchdog_timers(); + init_pin_assignments(); + + /* Initialise SDRAM controller (must be done after pin assignments) */ + init_sdram_controller(); +} + +/********************************************************************* +* disable_interrupts - Disable all interrupt sources * +**********************************************************************/ +static void disable_interrupts(void) +{ + vuint8 *p; + int i; + + /* Set ICR001-ICR063 to 0x0 */ + p = (vuint8 *) & MCF_INTC0_ICR1; + for (i = 1; i <= 63; i++) + *p++ = 0x0; + + /* Set ICR100-ICR163 to 0x0 */ + p = (vuint8 *) & MCF_INTC1_ICR0; + for (i = 100; i <= 163; i++) + *p++ = 0x0; +} + +/********************************************************************* +* disable_watchdog_timer - Disable system watchdog timer * +**********************************************************************/ +static void disable_watchdog_timer(void) +{ + /* Disable Core Watchdog Timer */ + MCF_SCM_CWCR = 0; +} + +/********************************************************************* +* disable_cache - Disable and invalidate cache * +**********************************************************************/ +static void disable_cache(void) +{ + asm("move.l #0x01000000,%d0"); + asm("movec %d0,%CACR"); +} + +/********************************************************************* +* init_clock_config - Clock Module * +**********************************************************************/ + +void init_clock_config(void) +{ + /* Clock module uses normal PLL mode with 16.0000 MHz external reference + Bus clock frequency = 80.00 MHz + Processor clock frequency = 3 x bus clock = 240.00 MHz + Dithering disabled + */ + + /* Check to see if the SDRAM has already been initialized + by a run control tool. If it has, put SDRAM into self-refresh mode before + initializing the PLL + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE; + + /* Temporarily switch to LIMP mode + NOTE: Ensure that this code is not executing from SDRAM, since the + SDRAM Controller is disabled in LIMP mode + */ + MCF_CCM_CDR = (MCF_CCM_CDR & 0xf0ff) | MCF_CCM_CDR_LPDIV(0x2); + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP; + + /* Configure the PLL settings */ + MCF_PLL_PODR = MCF_PLL_PODR_CPUDIV(0x2) | MCF_PLL_PODR_BUSDIV(0x6); + MCF_PLL_PFDR = MCF_PLL_PFDR_MFD(0x78); + MCF_PLL_PLLCR = 0; + MCF_PLL_PMDR = 0; + + /* Enable PLL and wait for lock */ + MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_LIMP; + while ((MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK) == 0) ; + + /* From the Device Errata: + + "After exiting LIMP mode, the value of 0x40000000 should be written + to address 0xFC0B8080 before attempting to initialize the SDRAMC + or exit the SDRAM from self-refresh mode." + */ + *(vuint32 *) 0xfc0b8080 = 0x40000000; + + /* If we put the SDRAM into self-refresh mode earlier, restore mode now */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE; +} + +/********************************************************************* +* init_chip_selects - Chip Select Module (FlexBus) * +**********************************************************************/ +void init_chip_selects(void) +{ + /* Chip Select 0: 2 MB of Flash at base address $00000000 + Port size = 16 bits + Assert chip select on first rising clock edge after address is asserted + Generate internal transfer acknowledge after 7 wait states + Address is held for 1 clock at end of read and write cycles + */ + MCF_FBCS0_CSCR = MCF_FBCS_CSCR_WS(0x7) | + (0x1 << 9) | MCF_FBCS_CSCR_AA | MCF_FBCS_CSCR_PS(0x2) | MCF_FBCS_CSCR_BEM; + MCF_FBCS0_CSMR = MCF_FBCS_CSMR_BAM(0x1f) | MCF_FBCS_CSMR_V; +} + +/********************************************************************* +* init_sdram_controller - SDRAM Controller * +**********************************************************************/ +void init_sdram_controller(void) +{ + /* Check to see if the SDRAM has already been initialized + by a run control tool and skip if so + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + return; + + /* Ensure that there is a delay from processor reset of the time recommended in + the SDRAM data sheet (typically 100-200 microseconds) until the following + code so that the SDRAM is ready for commands... + */ + + /* SDRAM controller configured for Double-data rate (DDR) SDRAM + Bus width = 16 bits + SDRAM specification: + SDRAM clock frequency = 80.00 MHz + CASL = 2.5 + ACTV-to-read/write delay, tRCD = 20.0 nanoseconds + Write recovery time, tWR = 15.0 nanoseconds + Precharge comand to ACTV command, tRP = 20.0 nanoseconds + Auto refresh command period, tRFC = 75.0 nanoseconds + Average periodic refresh interval, tREFI = 7.8 microseconds + */ + + /* Memory block 0 enabled - 32 MBytes at address $40000000 + Block consists of 1 device x 256 MBits (13 rows x 9 columns x 4 banks) + */ + MCF_SDRAMC_SDCS0 = MCF_SDRAMC_SDCS_BASE(0x400) | MCF_SDRAMC_SDCS_CSSZ(0x18); + + /* Memory block 1 disabled */ + MCF_SDRAMC_SDCS1 = 0; + + /* Initialise SDCFG1 register with delay and timing values + SRD2RWP = 4, SWT2RWP = 3, RD_LAT = 7, ACT2RW = 2 + PRE2ACT = 2, REF2ACT = 6, WT_LAT = 3 + */ + MCF_SDRAMC_SDCFG1 = MCF_SDRAMC_SDCFG1_SRD2RW(0x4) | + MCF_SDRAMC_SDCFG1_SWT2RD(0x3) | + MCF_SDRAMC_SDCFG1_RDLAT(0x7) | + MCF_SDRAMC_SDCFG1_ACT2RW(0x2) | + MCF_SDRAMC_SDCFG1_PRE2ACT(0x2) | + MCF_SDRAMC_SDCFG1_REF2ACT(0x6) | MCF_SDRAMC_SDCFG1_WTLAT(0x3); + + /* Initialise SDCFG2 register with delay and timing values + BRD2RP = 5, BWT2RWP = 6, BRD2W = 6, BL = 7 + */ + MCF_SDRAMC_SDCFG2 = MCF_SDRAMC_SDCFG2_BRD2PRE(0x5) | + MCF_SDRAMC_SDCFG2_BWT2RW(0x6) | + MCF_SDRAMC_SDCFG2_BRD2WT(0x6) | MCF_SDRAMC_SDCFG2_BL(0x7); + + /* Issue a Precharge All command */ + MCF_SDRAMC_SDCR = MCF_SDRAMC_SDCR_MODE_EN | + MCF_SDRAMC_SDCR_CKE | + MCF_SDRAMC_SDCR_DDR | + MCF_SDRAMC_SDCR_MUX(0x1) | + MCF_SDRAMC_SDCR_RCNT(0x8) | MCF_SDRAMC_SDCR_PS_16 | MCF_SDRAMC_SDCR_IPALL; + + /* Write Extended Mode Register */ + MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_BNKAD_LEMR | MCF_SDRAMC_SDMR_CMD; + + /* Write Mode Register and Reset DLL */ + MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_BNKAD_LMR | + MCF_SDRAMC_SDMR_AD(0x163) | MCF_SDRAMC_SDMR_CMD; + + /* Insert code here to pause for DLL lock time specified by memory... */ + + /* Issue a second Precharge All command */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL; + + /* Refresh sequence... + (check the number of refreshes required by the SDRAM manufacturer) + */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + + /* Write Mode Register and clear the Reset DLL bit */ + MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_BNKAD_LMR | + MCF_SDRAMC_SDMR_AD(0x63) | MCF_SDRAMC_SDMR_CMD; + + /* Enable automatic refresh and lock SDMR */ + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN; + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_REF | + MCF_SDRAMC_SDCR_DQS_OE(0x8) | MCF_SDRAMC_SDCR_DQS_OE(0x4); + +} + +/********************************************************************* +* init_real_time_clock - Real-Time Clock (RTC) * +**********************************************************************/ +static void init_real_time_clock(void) +{ + /* Disable the RTC */ + MCF_RTC_CR = 0; +} + +/********************************************************************* +* init_watchdog_timers - Watchdog Timers * +**********************************************************************/ +static void init_watchdog_timers(void) +{ + /* Watchdog Timer disabled (WCR[EN]=0) + NOTE: WCR and WMR cannot be written again until after the + processor is reset. + */ + MCF_WTM_WCR = MCF_WTM_WCR_WAIT | MCF_WTM_WCR_DOZE | MCF_WTM_WCR_HALTED; + + /* Core watchdog timer disabled */ + MCF_SCM_CWCR = MCF_SCM_CWCR_CWT(0x8); +} + +/********************************************************************* +* init_pin_assignments - Pin Assignment and General Purpose I/O * +**********************************************************************/ +static void init_pin_assignments(void) +{ + /* Pin assignments for port BUSCTL + Pin BUSCTL3 : External bus output enable, /OE + Pin BUSCTL2 : External bus transfer acknowledge, /TA + Pin BUSCTL1 : External bus read/write, R/W + Pin BUSCTL0 : External bus transfer start, /TS + */ + MCF_GPIO_PDDR_BUSCTL = 0; + MCF_GPIO_PAR_BUSCTL = MCF_GPIO_PAR_BUSCTL_PAR_OE | + MCF_GPIO_PAR_BUSCTL_PAR_TA | + MCF_GPIO_PAR_BUSCTL_PAR_RWB | MCF_GPIO_PAR_BUSCTL_PAR_TS(0x3); + + /* Pin assignments for port BE + Pin BE3 : External bus byte enable BW/BWE3 + Pin BE2 : External bus byte enable BW/BWE2 + Pin BE1 : External bus byte enable BW/BWE1 + Pin BE0 : External bus byte enable BW/BWE0 + */ + MCF_GPIO_PDDR_BE = 0; + MCF_GPIO_PAR_BE = MCF_GPIO_PAR_BE_PAR_BE3 | + MCF_GPIO_PAR_BE_PAR_BE2 | + MCF_GPIO_PAR_BE_PAR_BE1 | MCF_GPIO_PAR_BE_PAR_BE0; + + /* Pin assignments for port CS + Pin CS5 : Flex bus chip select /FB_CS5 + Pin CS4 : Flex bus chip select /FB_CS4 + Pin CS3 : Flex bus chip select /FB_CS3 + Pin CS2 : Flex bus chip select /FB_CS2 + Pin CS1 : Flex bus chip select /FB_CS1 + */ + MCF_GPIO_PDDR_CS = 0; + MCF_GPIO_PAR_CS = MCF_GPIO_PAR_CS_PAR_CS5 | + MCF_GPIO_PAR_CS_PAR_CS4 | + MCF_GPIO_PAR_CS_PAR_CS3 | + MCF_GPIO_PAR_CS_PAR_CS2 | MCF_GPIO_PAR_CS_PAR_CS1; + + /* Pin assignments for port FECI2C + Pin FECI2C3 : FEC management data clock, FEC_MDC + Pin FECI2C2 : FEC management data, FEC_MDIO + Pin FECI2C1 : GPIO input + Pin FECI2C0 : GPIO input + */ + MCF_GPIO_PDDR_FECI2C = 0; + MCF_GPIO_PAR_FECI2C = MCF_GPIO_PAR_FECI2C_PAR_MDC(0x3) | + MCF_GPIO_PAR_FECI2C_PAR_MDIO(0x3); + + /* Pin assignments for ports FECH and FECL + Pin FECH7 : FEC transmit clock, FEC_TXCLK + Pin FECH6 : FEC transmit enable, FEC_TXEN + Pin FECH5 : FEC transmit data 0, FEC_TXD0 + Pin FECH4 : FEC collision, FEC_COL + Pin FECH3 : FEC receive clock, FEC_RXCLK + Pin FECH2 : FEC receive data valid, FEC_RXDV + Pin FECH1 : FEC receive data 0, FEC_RXD0 + Pin FECH0 : FEC carrier receive sense, FEC_CRS + Pin FECL7 : FEC transmit data 3, FEC_TXD3 + Pin FECL6 : FEC transmit data 2, FEC_TXD2 + Pin FECL5 : FEC transmit data 1, FEC_TXD1 + Pin FECL4 : FEC transmit error, FEC_TXER + Pin FECL3 : FEC receive data 3, FEX_RXD3 + Pin FECL2 : FEC receive data 2, FEX_RXD2 + Pin FECL1 : FEC receive data 1, FEX_RXD1 + Pin FECL0 : FEC receive error, FEC_RXER + */ + MCF_GPIO_PDDR_FECH = 0; + MCF_GPIO_PDDR_FECL = 0; + MCF_GPIO_PAR_FEC = MCF_GPIO_PAR_FEC_PAR_FEC_7W(0x3) | + MCF_GPIO_PAR_FEC_PAR_FEC_MII(0x3); + + /* Pin assignments for port IRQ + Pins are all used for EdgePort GPIO/IRQ + */ + MCF_GPIO_PAR_IRQ = 0; + + /* Pin assignments for port LCDDATAH + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDDATAH = 0; + MCF_GPIO_PAR_LCDDATA = 0; + + /* Pin assignments for port LCDDATAM + Port LCDDATAM pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDDATAM = 0; + + /* Pin assignments for port LCDDATAL + Port LCDDATAL pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDDATAL = 0; + + /* Pin assignments for port LCDCTLH + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDCTLH = 0; + MCF_GPIO_PAR_LCDCTL = 0; + + /* Pin assignments for port LCDCTLL + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDCTLL = 0; + + /* Pin assignments for port PWM + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_PWM = 0; + MCF_GPIO_PAR_PWM = 0; + + /* Pin assignments for port QSPI + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_QSPI = 0; + MCF_GPIO_PAR_QSPI = 0; + + /* Pin assignments for port SSI + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_SSI = 0; + MCF_GPIO_PAR_SSI = 0; + + /* Pin assignments for port TIMER + Pins are all GPIO outputs + */ + MCF_GPIO_PDDR_TIMER = MCF_GPIO_PDDR_TIMER_PDDR_TIMER3 | + MCF_GPIO_PDDR_TIMER_PDDR_TIMER2 | + MCF_GPIO_PDDR_TIMER_PDDR_TIMER1 | MCF_GPIO_PDDR_TIMER_PDDR_TIMER0; + MCF_GPIO_PAR_TIMER = 0; + + /* Pin assignments for port UART + Pin UART7 : UART 1 clear-to-send, /U1CTS + Pin UART6 : UART 1 request-to-send, /U1RTS + Pin UART5 : UART 1 transmit data, U1TXD + Pin UART4 : UART 1 receive data, U1RXD + Pin UART3 : UART 0 clear-to-send, /U0CTS + Pin UART2 : UART 0 request-to-send, /U0RTS + Pin UART1 : UART 0 transmit data, U0TXD + Pin UART0 : UART 0 receive data, U0RXD + */ + MCF_GPIO_PDDR_UART = 0; + MCF_GPIO_PAR_UART = MCF_GPIO_PAR_UART_PAR_UCTS1(0x3) | + MCF_GPIO_PAR_UART_PAR_URTS1(0x3) | + MCF_GPIO_PAR_UART_PAR_URXD1(0x3) | + MCF_GPIO_PAR_UART_PAR_UTXD1(0x3) | + MCF_GPIO_PAR_UART_PAR_UCTS0 | + MCF_GPIO_PAR_UART_PAR_URTS0 | + MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0; +} diff --git a/c/src/lib/libbsp/m68k/mcf5329/startup/init5329.c b/c/src/lib/libbsp/m68k/mcf5329/startup/init5329.c new file mode 100644 index 0000000000..892dcc4a60 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/startup/init5329.c @@ -0,0 +1,82 @@ + +/* + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + */ + +#include <stdint.h> + +extern void _wr_vbr(uint32_t); +extern void init_main(); +extern int boot_card(int, char **, char **); + +/* + * From linkcmds + */ + +extern uint8_t _VBR[]; +extern uint8_t _INTERRUPT_VECTOR[]; + +extern uint8_t _clear_start[]; +extern uint8_t _clear_end[]; + +extern uint8_t _data_src_start[]; +extern uint8_t _data_dest_start[]; +extern uint8_t _data_dest_end[]; + +void Init5329(void) +{ + register uint32_t i; + register uint8_t *dbp, *sbp; + register uint32_t *dp, *sp; + + /* + * Initialize the hardware + */ + init_main(); + + /* + * Copy the vector table to RAM + */ + + if (_VBR != _INTERRUPT_VECTOR) { + sp = (uint32_t *) _INTERRUPT_VECTOR; + dp = (uint32_t *) _VBR; + for (i = 0; i < 256; i++) { + *dp++ = *sp++; + } + } + + _wr_vbr((uint32_t) _VBR); + + /* + * Move initialized data from ROM to RAM. + */ + if (_data_src_start != _data_dest_start) { + dbp = (uint8_t *) _data_dest_start; + sbp = (uint8_t *) _data_src_start; + i = _data_dest_end - _data_dest_start; + while (i--) + *dbp++ = *sbp++; + } + + /* + * Zero uninitialized data + */ + + if (_clear_start != _clear_end) { + sbp = _clear_start; + dbp = _clear_end; + i = dbp - sbp; + while (i--) + *sbp++ = 0; + } + + /* + * We have to call some kind of RTEMS function here! + */ + + boot_card(0, 0, 0); + for (;;) ; +} diff --git a/c/src/lib/libbsp/m68k/mcf5329/startup/linkcmds b/c/src/lib/libbsp/m68k/mcf5329/startup/linkcmds new file mode 100644 index 0000000000..f115d44cc0 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/startup/linkcmds @@ -0,0 +1,186 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf52235 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * 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.e + * + * $Id$ + */ + +/* + * Declare some sizes. + */ +_CoreSRamBase = DEFINED(_RamBase) ? _RamBase : 0x80000000; +_CoreSRamSize = DEFINED(_RamSize) ? _RamSize : 32K; + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x40000000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 32M; + +_BootFlashBase = DEFINED(_FlashBase) ? _FlashBase : 0x00000000; +_BootFlashSize = DEFINED(_FlashBase) ? _FlashBase : 2M; + +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x400; + +_VBR = 0x40000000; + +ENTRY(start) + +MEMORY +{ + core_sram : ORIGIN = 0x80000000, LENGTH = 32K + boot_flash : ORIGIN = 0x00000000, LENGTH = 2M + dram : ORIGIN = 0x40000000, LENGTH = 32M +} + +SECTIONS +{ + .ram_code : + { + *(.ram_code) + } > core_sram + + /* + * Text, data and bss segments + */ + .text 0x40000500 : { + + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors so we make sure it is first. Because this + * is a wildcard, it doesn't matter if the user does not + * actually link against crtbegin.o; the linker won't look for + * a file to match a wildcard. The wildcard also means that + * it doesn't matter which directory crtbegin.o is in. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } > dram + + .data : + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } > dram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : + { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (_end = .); + + _clear_end = .; + _WorkspaceBase = .; + } > dram + + .start_stack : + { + /* + * Starting Stack + */ + . += _StackSize; + . = ALIGN (16); + PROVIDE(_StackInit = .); + } > core_sram + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + PROVIDE (end_of_all = .); +} diff --git a/c/src/lib/libbsp/m68k/mcf5329/startup/linkcmdsflash b/c/src/lib/libbsp/m68k/mcf5329/startup/linkcmdsflash new file mode 100644 index 0000000000..fdc222cfab --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/startup/linkcmdsflash @@ -0,0 +1,182 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf52235 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * 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.e + * + * $Id$ + */ + +/* + * Declare some sizes. + */ +_CoreSRamBase = DEFINED(_RamBase) ? _RamBase : 0x80000000; +_CoreSRamSize = DEFINED(_RamSize) ? _RamSize : 32K; + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x40000000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 32M; + +_BootFlashBase = DEFINED(_FlashBase) ? _FlashBase : 0x00000000; +_BootFlashSize = DEFINED(_FlashBase) ? _FlashBase : 2M; + +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x400; + +_VBR = 0x40000000; + +ENTRY(start) + +MEMORY +{ + core_sram : ORIGIN = 0x80000000, LENGTH = 32K + boot_flash : ORIGIN = 0x00000000, LENGTH = 2M + dram : ORIGIN = 0x40000000, LENGTH = 32M +} + +SECTIONS +{ + /* + * Text, data and bss segments + */ + .text : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors so we make sure it is first. Because this + * is a wildcard, it doesn't matter if the user does not + * actually link against crtbegin.o; the linker won't look for + * a file to match a wildcard. The wildcard also means that + * it doesn't matter which directory crtbegin.o is in. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } > boot_flash + + .data 0x40000500 : AT (_estuff) + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } > dram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : + { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (_end = .); + + _clear_end = .; + _WorkspaceBase = .; + } > dram + + .start_stack : + { + /* + * Starting Stack + */ + . += _StackSize; + . = ALIGN (16); + PROVIDE(_StackInit = .); + } > core_sram + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + PROVIDE (end_of_all = .); +} diff --git a/c/src/lib/libbsp/m68k/mcf5329/timer/timer.c b/c/src/lib/libbsp/m68k/mcf5329/timer/timer.c new file mode 100644 index 0000000000..1f5404d3e5 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5329/timer/timer.c @@ -0,0 +1,48 @@ + +/* + * Timer Init + * + * Use the last DMA timer (DTIM3) as the diagnostic timer. + * + * Author: W. Eric Norum <norume@aps.anl.gov> + * + * COPYRIGHT (c) 2005. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include <rtems.h> +#include <bsp.h> + +void Timer_initialize(void) +{ + uint32_t preScaleDivisor = bsp_get_BUS_clock_speed() / 1000000; + + MCF_DTIM3_DTMR = 0; + MCF_DTIM3_DTMR = MCF_DTIM_DTMR_PS(preScaleDivisor - 1) | + MCF_DTIM_DTMR_CLK_DIV1 | MCF_DTIM_DTMR_RST; +} + +/* + * Return timer value in microsecond units + */ +int Read_timer(void) +{ + return MCF_DTIM3_DTCN; +} + +/* + * Empty function call used in loops to measure basic cost of looping + * in Timing Test Suite. + */ +rtems_status_code Empty_function(void) +{ + return RTEMS_SUCCESSFUL; +} + +void Set_find_average_overhead(rtems_boolean find_flag) +{ +} |