2004-04-12 David Querbach <querbach@realtime.bc.ca>

* README, configure.ac, mpc5xx/Makefile.am,
	mpc5xx/exceptions/raw_exception.c, mpc5xx/exceptions/raw_exception.h,
	mpc5xx/timer/timer.c, shared/include/cpuIdent.h: addition of a
	significant amount of MPC5xx support as part of the addition of the
	SS555 BSP.
	* mpc5xx/README, mpc5xx/clock/clock.c,
	mpc5xx/console-generic/console-generic.c, mpc5xx/include/console.h,
	mpc5xx/include/mpc5xx.h, mpc5xx/irq/irq.c, mpc5xx/irq/irq.h,
	mpc5xx/irq/irq_asm.S, mpc5xx/irq/irq_init.c,
	mpc5xx/vectors/vectors.S, mpc5xx/vectors/vectors.h,
	mpc5xx/vectors/vectors_init.c: New files.
	* mpc5xx/exceptions/asm_utils.S: Removed.
This commit is contained in:
Joel Sherrill
2004-04-12 22:04:28 +00:00
parent db87589d7a
commit 8430205c22
21 changed files with 3399 additions and 328 deletions

View File

@@ -1,3 +1,18 @@
2004-04-12 David Querbach <querbach@realtime.bc.ca>
* README, configure.ac, mpc5xx/Makefile.am,
mpc5xx/exceptions/raw_exception.c, mpc5xx/exceptions/raw_exception.h,
mpc5xx/timer/timer.c, shared/include/cpuIdent.h: addition of a
significant amount of MPC5xx support as part of the addition of the
SS555 BSP.
* mpc5xx/README, mpc5xx/clock/clock.c,
mpc5xx/console-generic/console-generic.c, mpc5xx/include/console.h,
mpc5xx/include/mpc5xx.h, mpc5xx/irq/irq.c, mpc5xx/irq/irq.h,
mpc5xx/irq/irq_asm.S, mpc5xx/irq/irq_init.c,
mpc5xx/vectors/vectors.S, mpc5xx/vectors/vectors.h,
mpc5xx/vectors/vectors_init.c: New files.
* mpc5xx/exceptions/asm_utils.S: Removed.
2004-04-02 Ralf Corsepius <ralf_corsepius@rtems.org>
* ppc403/vectors/align_h.S: Include <rtems/asm.h> instead of <asm.h>.

View File

@@ -13,7 +13,7 @@ At this time, support is included for the following PowerPC
family members using the new exception processing model:
+ mpc505
+ mpc5xx (mpc565)
+ mpc5xx (5xx devices other than 505/509)
+ mpc6xx
+ mpc750
+ mpc821

View File

@@ -22,9 +22,10 @@ RTEMS_CANONICALIZE_TOOLS
RTEMS_PROG_CCAS
AM_CONDITIONAL(shared, \
test "$RTEMS_CPU_MODEL" = "mpc5xx" \
|| test "$RTEMS_CPU_MODEL" = "mpc750" \
test "$RTEMS_CPU_MODEL" = "mpc750" \
|| test "$RTEMS_CPU_MODEL" = "mpc7400" \
|| test "$RTEMS_CPU_MODEL" = "mpc555" \
|| test "$RTEMS_CPU_MODEL" = "mpc5xx" \
|| test "$RTEMS_CPU_MODEL" = "ppc603e" \
|| test "$RTEMS_CPU_MODEL" = "mpc604" \
|| test "$RTEMS_CPU_MODEL" = "mpc6xx" \
@@ -35,7 +36,8 @@ test "$RTEMS_CPU_MODEL" = "mpc5xx" \
## test on CPU type
AM_CONDITIONAL(mpc505, test "$RTEMS_CPU_MODEL" = "mpc505")
AM_CONDITIONAL(mpc5xx, test "$RTEMS_CPU_MODEL" = "mpc5xx")
AM_CONDITIONAL(mpc5xx, test "$RTEMS_CPU_MODEL" = "mpc5xx" \
|| test "$RTEMS_CPU_MODEL" = "mpc555" )
AM_CONDITIONAL(mpc6xx, test "$RTEMS_CPU_MODEL" = "mpc6xx" \
|| test "$RTEMS_CPU_MODEL" = "mpc604" \
|| test "$RTEMS_CPU_MODEL" = "mpc7400" \

View File

@@ -10,14 +10,49 @@ noinst_DATA =
include $(top_srcdir)/../../../automake/compile.am
if mpc5xx
include_mpc5xxdir = $(includedir)/mpc5xx
include_libcpudir = $(includedir)/libcpu
# exceptions
include_HEADERS = include/mpc5xx.h
## clock
EXTRA_PROGRAMS += clock.rel
CLEANFILES += clock.rel
clock_rel_SOURCES = clock/clock.c
clock_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
EXTRA_PROGRAMS += clock_g.rel
CLEANFILES += clock_g.rel
clock_g_rel_SOURCES = $(clock_rel_SOURCES)
clock_g_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
clock_g_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_DATA += clock$(LIB_VARIANT).rel
## console-generic
include_mpc5xx_HEADERS = include/console.h
EXTRA_PROGRAMS += console-generic.rel
CLEANFILES += console-generic.rel
console_generic_rel_SOURCES = console-generic/console-generic.c
console_generic_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
console_generic_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
EXTRA_PROGRAMS += console-generic_g.rel
CLEANFILES += console-generic_g.rel
console_generic_g_rel_SOURCES = $(console_generic_rel_SOURCES)
console_generic_g_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
console_generic_g_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_DATA += console-generic$(LIB_VARIANT).rel
## exceptions
include_libcpu_HEADERS = exceptions/raw_exception.h
EXTRA_PROGRAMS += exceptions.rel
CLEANFILES += exceptions.rel
exceptions_rel_SOURCES = exceptions/raw_exception.c exceptions/asm_utils.S
exceptions_rel_SOURCES = exceptions/raw_exception.c
exceptions_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
exceptions_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
@@ -29,24 +64,24 @@ exceptions_g_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_DATA += exceptions$(LIB_VARIANT).rel
# ictrl
include_HEADERS = ictrl/ictrl.h
## irq
include_libcpu_HEADERS += irq/irq.h
EXTRA_PROGRAMS += ictrl.rel
CLEANFILES += ictrl.rel
ictrl_rel_SOURCES = ictrl/ictrl.c ictrl/ictrl.h
ictrl_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
ictrl_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
EXTRA_PROGRAMS += irq.rel
CLEANFILES += irq.rel
irq_rel_SOURCES = irq/irq.c irq/irq_init.c irq/irq_asm.S
irq_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
irq_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
EXTRA_PROGRAMS += ictrl_g.rel
CLEANFILES += ictrl_g.rel
ictrl_g_rel_SOURCES = $(ictrl_rel_SOURCES)
ictrl_g_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
ictrl_g_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
EXTRA_PROGRAMS += irq_g.rel
CLEANFILES += irq_g.rel
irq_g_rel_SOURCES = $(irq_rel_SOURCES)
irq_g_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
irq_g_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_DATA += ictrl$(LIB_VARIANT).rel
noinst_DATA += irq$(LIB_VARIANT).rel
# timer
## timer
EXTRA_PROGRAMS += timer.rel
CLEANFILES += timer.rel
timer_rel_SOURCES = timer/timer.c
@@ -60,8 +95,28 @@ timer_g_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
timer_g_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_DATA += timer$(LIB_VARIANT).rel
## vectors
include_libcpu_HEADERS += vectors/vectors.h
EXTRA_PROGRAMS += vectors.rel
CLEANFILES += vectors.rel
vectors_rel_SOURCES = vectors/vectors_init.c vectors/vectors.S
vectors_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
vectors_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
EXTRA_PROGRAMS += vectors_g.rel
CLEANFILES += vectors_g.rel
vectors_g_rel_SOURCES = $(vectors_rel_SOURCES)
vectors_g_rel_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
vectors_g_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_DATA += vectors$(LIB_VARIANT).rel
endif
## --
all-local: $(PREINSTALL_FILES)
PREINSTALL_DIRS =
PREINSTALL_FILES =
@@ -71,21 +126,38 @@ $(PROJECT_INCLUDE)/$(dirstamp):
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
if mpc5xx
$(PROJECT_INCLUDE)/mpc5xx/$(dirstamp):
@$(mkdir_p) $(PROJECT_INCLUDE)/mpc5xx
@: > $(PROJECT_INCLUDE)/mpc5xx/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/mpc5xx/$(dirstamp)
$(PROJECT_INCLUDE)/libcpu/$(dirstamp):
@$(mkdir_p) $(PROJECT_INCLUDE)/libcpu
@: > $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
$(PROJECT_INCLUDE)/mpc5xx.h: include/mpc5xx.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc5xx.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc5xx.h
$(PROJECT_INCLUDE)/mpc5xx/console.h: include/console.h $(PROJECT_INCLUDE)/mpc5xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc5xx/console.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc5xx/console.h
$(PROJECT_INCLUDE)/libcpu/raw_exception.h: exceptions/raw_exception.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/raw_exception.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/raw_exception.h
$(PROJECT_INCLUDE)/ictrl.h: ictrl/ictrl.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ictrl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/ictrl.h
$(PROJECT_INCLUDE)/libcpu/irq.h: irq/irq.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/irq.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/irq.h
$(PROJECT_INCLUDE)/libcpu/vectors.h: vectors/vectors.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/vectors.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/vectors.h
endif
CLEANFILES += $(PREINSTALL_FILES)
DISTCLEANFILES = $(PREINSTALL_DIRS)
include $(top_srcdir)/../../../../../automake/local.am
include $(top_srcdir)/../../../automake/local.am

View File

@@ -0,0 +1,27 @@
#
# $Id$
#
Various non-BSP-dependent support routines.
timer - Support for the RTEMS timer tick, using the Programmable
Interval Timer (PIT).
console-generic - Console support via the on-chip dual SCI port in the QSMCM
module.
exception - Installation and deinstallation of exception handlers, by
manipulation of exception vector table.
irq - Exception handler for all external and decrementer interrupts.
Generalized interrupt handler which calls specific handlers
via entries in the interrupt connection table. Interrupt
connection table maintenance routines. USIU and UIMB
interrupt masking and level control.
timer - Support for RTEMS timer tests, using the PowerPC timebase
(TB) registers.
vectors - Compressed MPC5XX exception vector table, exception handler
prologues, default exception handler. Code to initialize
table with default handlers.

View File

@@ -0,0 +1,196 @@
/* clock.c
*
* This routine initializes the PIT on the MPC5xx.
* The tick frequency is specified by the bsp.
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from c/src/lib/libcpu/powerpc/mpc8xx/clock/clock.c:
*
* Author: Jay Monkman (jmonkman@frasca.com)
* Copyright (C) 1998 by Frasca International, Inc.
*
* Derived from c/src/lib/libcpu/ppc/ppc403/clock/clock.c:
*
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of i-cubed limited not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/lib/libcpu/hppa1_1/clock/clock.c:
*
* 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 <clockdrv.h>
#include <rtems/libio.h>
#include <libcpu/irq.h>
#include <stdlib.h> /* for atexit() */
#include <mpc5xx.h>
volatile rtems_unsigned32 Clock_driver_ticks;
extern int BSP_connect_clock_handler(rtems_isr_entry);
extern int BSP_disconnect_clock_handler();
void Clock_exit( void );
/*
* These are set by clock driver during its init
*/
rtems_device_major_number rtems_clock_major = ~0;
rtems_device_minor_number rtems_clock_minor;
/*
* ISR Handler
*/
rtems_isr Clock_isr(rtems_vector_number vector)
{
usiu.piscrk = USIU_UNLOCK_KEY;
usiu.piscr |= USIU_PISCR_PS; /* acknowledge interrupt */
usiu.piscrk = 0;
Clock_driver_ticks++;
rtems_clock_tick();
}
void clockOn(void* unused)
{
unsigned desiredLevel;
rtems_unsigned32 pit_value;
/* calculate and set modulus */
pit_value = (rtems_configuration_get_microseconds_per_tick() *
rtems_cpu_configuration_get_clicks_per_usec()) - 1 ;
if (pit_value > 0xffff) { /* pit is only 16 bits long */
rtems_fatal_error_occurred(-1);
}
usiu.sccrk = USIU_UNLOCK_KEY;
usiu.sccr &= ~USIU_SCCR_RTDIV; /* RTC and PIT clock is divided by 4 */
usiu.sccrk = 0;
usiu.pitck = USIU_UNLOCK_KEY;
usiu.pitc = pit_value;
usiu.pitck = 0;
/* set PIT irq level, enable PIT, PIT interrupts */
/* and clear int. status */
desiredLevel = CPU_irq_level_from_symbolic_name(CPU_PERIODIC_TIMER);
usiu.piscrk = USIU_UNLOCK_KEY;
usiu.piscr = USIU_PISCR_PIRQ(desiredLevel) /* set interrupt priority */
| USIU_PISCR_PS /* acknowledge interrupt */
| USIU_PISCR_PIE /* enable interrupt */
| USIU_PISCR_PITF /* freeze during debug */
| USIU_PISCR_PTE; /* enable timer */
usiu.piscrk = 0;
}
void
clockOff(void* unused)
{
/* disable PIT and PIT interrupts */
usiu.piscrk = USIU_UNLOCK_KEY;
usiu.piscr &= ~(USIU_PISCR_PTE | USIU_PISCR_PIE);
usiu.piscrk = 0;
}
int clockIsOn(void* unused)
{
if (usiu.piscr & USIU_PISCR_PIE)
return 1;
return 0;
}
/*
* Called via atexit()
* Remove the clock interrupt handler by setting handler to NULL
*/
void
Clock_exit(void)
{
(void) BSP_disconnect_clock_handler ();
}
void Install_clock(rtems_isr_entry clock_isr)
{
Clock_driver_ticks = 0;
BSP_connect_clock_handler (clock_isr);
atexit(Clock_exit);
}
void
ReInstall_clock(rtems_isr_entry new_clock_isr)
{
BSP_connect_clock_handler (new_clock_isr);
}
rtems_device_driver Clock_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
)
{
Install_clock( Clock_isr );
/*
* make major/minor avail to others such as shared memory driver
*/
rtems_clock_major = major;
rtems_clock_minor = minor;
return RTEMS_SUCCESSFUL;
}
rtems_device_driver Clock_control(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
)
{
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
goto done;
/*
* This is hokey, but until we get a defined interface
* to do this, it will just be this simple...
*/
if (args->command == rtems_build_name('I', 'S', 'R', ' ')) {
Clock_isr(0); /* vector number ignored */
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) {
ReInstall_clock(args->buffer);
}
done:
return RTEMS_SUCCESSFUL;
}

View File

@@ -0,0 +1,347 @@
/*
* General Serial I/O functions.
*
* This file contains the functions for performing serial I/O. The actual
* system calls (console_*) should be in the BSP part of the source tree.
* That way different BSPs can use whichever SCI they wish for /dev/console.
*
* On-chip resources used:
* resource minor note
* SCI1 0
* SCI2 1
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from
* c/src/lib/libcpu/powerpc/mpc8xx/console_generic/console_generic.c:
* Author: Jay Monkman (jmonkman@frasca.com)
* Copyright (C) 1998 by Frasca International, Inc.
*
* Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by:
* W. Eric Norum
* Saskatchewan Accelerator Laboratory
* University of Saskatchewan
* Saskatoon, Saskatchewan, CANADA
* eric@skatter.usask.ca
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
*
* Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
* and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>
* Copyright (c) 1999, National Research Council of Canada
*
* 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 <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/bspIo.h> /* for printk */
#include <mpc5xx.h>
#include <mpc5xx/console.h>
#include <libcpu/irq.h>
extern rtems_cpu_table Cpu_table; /* for CPU clock speed */
/*
* SCI port descriptor table.
*/
typedef struct
{
volatile m5xxSCIRegisters_t *regs; /* hardware registers */
struct rtems_termios_tty *ttyp; /* termios data for this port */
} sci_desc;
static sci_desc sci_descs[] = {
{ &imb.qsmcm.sci1, 0 }, /* SCI 1 */
{ &imb.qsmcm.sci2, 0 }, /* SCI 2 */
};
/*
* Number of SCI port initialization calls made so far. Used to avoid
* installing the common interrupt handler more than once.
*/
int init_calls = 0;
/*
* Default configuration.
*/
static struct termios default_termios = {
0, /* input mode flags */
0, /* output mode flags */
CS8 | CREAD | CLOCAL | B9600, /* control mode flags */
0, /* local mode flags */
0, /* line discipline */
{ 0 } /* control characters */
};
/*
* Termios callback functions
*/
int
m5xx_uart_firstOpen(
int major,
int minor,
void *arg
)
{
rtems_libio_open_close_args_t *args = arg;
sci_desc* desc = &sci_descs[minor];
struct rtems_termios_tty *tty = args->iop->data1;
desc->ttyp = tty; /* connect tty */
if ( tty->device.outputUsesInterrupts == TERMIOS_IRQ_DRIVEN)
desc->regs->sccr1 |= QSMCM_SCI_RIE; /* enable rx interrupt */
return RTEMS_SUCCESSFUL;
}
int
m5xx_uart_lastClose(
int major,
int minor,
void* arg
)
{
sci_desc* desc = &sci_descs[minor];
desc->regs->sccr1 &= ~(QSMCM_SCI_RIE | QSMCM_SCI_TIE); /* disable all */
desc->ttyp = NULL; /* disconnect tty */
return RTEMS_SUCCESSFUL;
}
int
m5xx_uart_pollRead(
int minor
)
{
volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
int c = -1;
if ( regs ) {
while ( (regs->scsr & QSMCM_SCI_RDRF) == 0 )
;
c = regs->scdr;
}
return c;
}
int
m5xx_uart_write(
int minor,
const char *buf,
int len
)
{
volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
regs->scdr = *buf; /* start transmission */
regs->sccr1 |= QSMCM_SCI_TIE; /* enable interrupt */
return 0;
}
int
m5xx_uart_pollWrite(
int minor,
const char *buf,
int len
)
{
volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
while ( len-- ) {
while ( (regs->scsr & QSMCM_SCI_TDRE) == 0 )
;
regs->scdr = *buf++;
}
return 0;
}
void
m5xx_uart_reserve_resources(
rtems_configuration_table *configuration
)
{
rtems_termios_reserve_resources (configuration, NUM_PORTS);
}
int
m5xx_uart_setAttributes(
int minor,
const struct termios *t
)
{
rtems_unsigned16 sccr0 = sci_descs[minor].regs->sccr0;
rtems_unsigned16 sccr1 = sci_descs[minor].regs->sccr1;
int baud;
/*
* Check that port number is valid
*/
if ( (minor < SCI1_MINOR) || (minor > SCI2_MINOR) )
return RTEMS_INVALID_NUMBER;
/* Baud rate */
switch (t->c_cflag & CBAUD) {
default: baud = -1; break;
case B50: baud = 50; break;
case B75: baud = 75; break;
case B110: baud = 110; break;
case B134: baud = 134; break;
case B150: baud = 150; break;
case B200: baud = 200; break;
case B300: baud = 300; break;
case B600: baud = 600; break;
case B1200: baud = 1200; break;
case B1800: baud = 1800; break;
case B2400: baud = 2400; break;
case B4800: baud = 4800; break;
case B9600: baud = 9600; break;
case B19200: baud = 19200; break;
case B38400: baud = 38400; break;
case B57600: baud = 57600; break;
case B115200: baud = 115200; break;
case B230400: baud = 230400; break;
case B460800: baud = 460800; break;
}
if (baud > 0) {
sccr0 &= ~QSMCM_SCI_BAUD(-1);
sccr0 |=
QSMCM_SCI_BAUD((Cpu_table.clock_speed + (16 * baud)) / (32 * baud));
}
/* Number of data bits -- not available with MPC5xx SCI */
switch ( t->c_cflag & CSIZE ) {
case CS5: break;
case CS6: break;
case CS7: break;
case CS8: break;
}
/* Stop bits -- not easily available with MPC5xx SCI */
if ( t->c_cflag & CSTOPB ) {
/* Two stop bits */
} else {
/* One stop bit */
}
/* Parity */
if ( t->c_cflag & PARENB )
sccr1 |= QSMCM_SCI_PE;
else
sccr1 &= ~QSMCM_SCI_PE;
if ( t->c_cflag & PARODD )
sccr1 |= QSMCM_SCI_PT;
else
sccr1 &= ~QSMCM_SCI_PT;
/* Transmitter and receiver enable */
sccr1 |= QSMCM_SCI_TE;
if ( t->c_cflag & CREAD )
sccr1 |= QSMCM_SCI_RE;
else
sccr1 &= ~QSMCM_SCI_RE;
/* Write hardware registers */
sci_descs[minor].regs->sccr0 = sccr0;
sci_descs[minor].regs->sccr1 = sccr1;
return RTEMS_SUCCESSFUL;
}
/*
* Interrupt handling.
*/
static void
m5xx_sci_interrupt_handler (void)
{
int minor;
for ( minor = 0; minor < NUM_PORTS; minor++ ) {
sci_desc *desc = &sci_descs[minor];
int sccr1 = desc->regs->sccr1;
int scsr = desc->regs->scsr;
/*
* Character received?
*/
if ((sccr1 & QSMCM_SCI_RIE) && (scsr & QSMCM_SCI_RDRF)) {
char c = desc->regs->scdr;
rtems_termios_enqueue_raw_characters(desc->ttyp, &c, 1);
}
/*
* Transmitter empty?
*/
if ((sccr1 & QSMCM_SCI_TIE) && (scsr & QSMCM_SCI_TDRE)) {
desc->regs->sccr1 &= ~QSMCM_SCI_TIE;
rtems_termios_dequeue_characters (desc->ttyp, 1);
}
}
}
void m5xx_sci_nop(const rtems_irq_connect_data* ptr)
{
}
int m5xx_sci_isOn(const rtems_irq_connect_data* ptr)
{
return 1;
}
/*
* Basic initialization.
*/
void
m5xx_uart_initialize (int minor)
{
/*
* Check that minor number is valid.
*/
if ( (minor < SCI1_MINOR) || (minor > SCI2_MINOR) )
return;
/*
* Configure and enable receiver and transmitter.
*/
m5xx_uart_setAttributes(minor, &default_termios);
/*
* Connect interrupt if not yet done.
*/
if ( init_calls++ == 0 ) {
rtems_irq_connect_data irq_data;
irq_data.name = CPU_IRQ_SCI;
irq_data.hdl = m5xx_sci_interrupt_handler;
irq_data.on = m5xx_sci_nop; /* can't enable both channels here */
irq_data.off = m5xx_sci_nop; /* can't disable both channels here */
irq_data.isOn = m5xx_sci_isOn;
if (!CPU_install_rtems_irq_handler (&irq_data)) {
printk("Unable to connect SCI Irq handler\n");
rtems_fatal_error_occurred(1);
}
imb.qsmcm.qdsci_il = /* set interrupt level in port */
QSMCM_ILDSCI(CPU_irq_level_from_symbolic_name(CPU_IRQ_SCI));
}
}

View File

@@ -1,64 +0,0 @@
/*
* asm_utils.s
*
* asm_utils.S,v 1.2 2002/04/18 20:55:37 joel Exp
*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
*
* This file contains the low-level support for moving exception
* exception code to appropriate location.
*
* Adapted for MPC5XX Wilfried Busalski (w.busalski@lancier-monitoring.de)
* (C) Lancier Monitoring GmbH
*/
#include <rtems/asm.h>
#include <rtems/score/cpu.h>
#include <libcpu/io.h>
//SPR defines
#define SPR_ICCST 560
.globl codemove
codemove:
.type codemove,@function
/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
cmplw cr1,r3,r4
addi r0,r5,3
srwi. r0,r0,2
beq cr1,4f /* In place copy is not necessary */
beq 7f /* Protect against 0 count */
mtctr r0
bge cr1,2f
la r8,-4(r4)
la r7,-4(r3)
1: lwzu r0,4(r8)
stwu r0,4(r7)
bdnz 1b
b 4f
2: slwi r0,r0,2
add r8,r4,r0
add r7,r3,r0
3: lwzu r0,-4(r8)
stwu r0,-4(r7)
bdnz 3b
/* Now flush the cache: note that we must start from a cache aligned
* address. Otherwise we might miss one cache line.
*/
4: lis r0, 0x0A00 // Command Unlock All
mtspr SPR_ICCST, r0 // Cache Unlock ALL
lis r0, 0x0C00 // Command Invalidate All
mtspr SPR_ICCST, r0 // Cache Invalidate ALL
lis r0, 0x0200 // Command Enable All
mtspr SPR_ICCST, r0 // Cache Enable ALL
7: sync /* Wait for all icbi to complete on bus */
isync
blr

View File

@@ -1,24 +1,26 @@
/*
* raw_exception.c - This file contains implementation of C function to
* Instanciate 8xx ppc primary exception entries.
* More detailled information can be found on motorola
* site and more precisely in the following book :
* raw_exception.c - This file contains implementation of C functions to
* Instantiate mpc5xx primary exception entries.
* More detailled information can be found on the Motorola
* site and more precisely in the following book:
*
* MPC860
* Risc Microporcessor User's Manual
* Motorola REF : MPC860UM/AD
* MPC555/MPC556 User's Manual
* Motorola REF : MPC555UM/D Rev. 3, 2000 October 15
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libcpu/powerpc/mpc8xx/exceptions/raw_exception.c:
*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Changes for MPC5XX Wilfried Busalski (w.busalski@lancier-monitoring.de)
* Copyright (C) 2003 Lancier Monitoring GmbH
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
* http://www.rtems.com/license/LICENSE.
*
* raw_exception.c,v 1.5 2002/11/04 14:29:02 joel Exp
* $Id$
*/
#include <rtems/system.h>
@@ -29,88 +31,76 @@
#include <rtems/bspIo.h> /* for printk */
#include <string.h>
void * codemove(void *, const void *, unsigned int, unsigned long);
static rtems_raw_except_connect_data* raw_except_table;
static rtems_raw_except_connect_data default_raw_except_entry;
static rtems_raw_except_global_settings* local_settings;
int mpc565_vector_is_valid(rtems_vector vector)
{
switch(vector) {
case ASM_RESET_VECTOR: /* fall through */
case ASM_MACH_VECTOR:
case ASM_PROT_VECTOR:
case ASM_ISI_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
case ASM_SYS_VECTOR:
case ASM_TRACE_VECTOR:
case ASM_FLOATASSIST_VECTOR:
case ASM_SOFTEMUL_VECTOR:
case ASM_ITLBERROR_VECTOR:
case ASM_DTLBERROR_VECTOR:
case ASM_DBREAK_VECTOR:
case ASM_IBREAK_VECTOR:
case ASM_PERIFBREAK_VECTOR:
case ASM_DEVPORT_VECTOR:
return 1;
default: return 0;
}
}
int mpc5xx_vector_is_valid(rtems_vector vector)
{
switch (current_ppc_cpu) {
case MPC_5XX:
if (!mpc565_vector_is_valid(vector)) {
return 0;
}
break;
default:
printk("Please complete libcpu/powerpc/mpc5xx/exceptions/raw_exception.c\n");
printk("current_ppc_cpu = %x\n", current_ppc_cpu);
return 0;
}
return 1;
switch (current_ppc_cpu) {
case PPC_5XX:
switch(vector) {
case ASM_RESET_VECTOR:
case ASM_MACH_VECTOR:
case ASM_EXT_VECTOR:
case ASM_ALIGN_VECTOR:
case ASM_PROG_VECTOR:
case ASM_FLOAT_VECTOR:
case ASM_DEC_VECTOR:
case ASM_SYS_VECTOR:
case ASM_TRACE_VECTOR:
case ASM_FLOATASSIST_VECTOR:
case ASM_SOFTEMUL_VECTOR:
case ASM_IPROT_VECTOR:
case ASM_DPROT_VECTOR:
case ASM_DBREAK_VECTOR:
case ASM_IBREAK_VECTOR:
case ASM_MEBREAK_VECTOR:
case ASM_NMEBREAK_VECTOR:
return 1;
default:
return 0;
}
default:
printk("Please complete libcpu/powerpc/mpc5xx/exceptions/raw_exception.c\n");
printk("current_ppc_cpu = %x\n", current_ppc_cpu);
return 0;
}
}
int mpc5xx_set_exception (const rtems_raw_except_connect_data* except)
{
unsigned int level;
unsigned int level;
if (!mpc5xx_vector_is_valid(except->exceptIndex)) {
return 0;
}
/*
* Check if default handler is actually connected. If not issue an error.
* You must first get the current handler via mpc5xx_get_current_exception
* and then disconnect it using mpc5xx_delete_exception.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (memcmp(mpc5xx_get_vector_addr(except->exceptIndex), (void*)default_raw_except_entry.hdl.raw_hdl,default_raw_except_entry.hdl.raw_hdl_size)) {
return 0;
}
if (!mpc5xx_vector_is_valid(except->exceptIndex)) {
return 0;
}
/*
* Check if default handler is actually connected. If not issue an error.
* You must first get the current handler via mpc5xx_get_current_exception
* and then disconnect it using mpc5xx_delete_exception.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (exception_handler_table[except->exceptIndex] !=
default_raw_except_entry.hdl.raw_hdl) {
return 0;
}
_CPU_ISR_Disable(level);
raw_except_table [except->exceptIndex] = *except;
codemove((void*)mpc5xx_get_vector_addr(except->exceptIndex),
except->hdl.raw_hdl,
except->hdl.raw_hdl_size,
PPC_CACHE_ALIGNMENT);
except->on(except);
_CPU_ISR_Enable(level);
return 1;
_CPU_ISR_Disable(level);
raw_except_table[except->exceptIndex] = *except;
exception_handler_table[except->exceptIndex] = except->hdl.raw_hdl;
except->on(except);
_CPU_ISR_Enable(level);
return 1;
}
int mpc5xx_get_current_exception (rtems_raw_except_connect_data* except)
@@ -119,7 +109,7 @@ int mpc5xx_get_current_exception (rtems_raw_except_connect_data* except)
return 0;
}
*except = raw_except_table [except->exceptIndex];
*except = raw_except_table[except->exceptIndex];
return 1;
}
@@ -138,20 +128,16 @@ int mpc5xx_delete_exception (const rtems_raw_except_connect_data* except)
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (memcmp(mpc5xx_get_vector_addr(except->exceptIndex),
(void*)except->hdl.raw_hdl,
except->hdl.raw_hdl_size)) {
return 0;
if (exception_handler_table[except->exceptIndex] != except->hdl.raw_hdl) {
return 0;
}
_CPU_ISR_Disable(level);
except->off(except);
codemove((void*)mpc5xx_get_vector_addr(except->exceptIndex),
default_raw_except_entry.hdl.raw_hdl,
default_raw_except_entry.hdl.raw_hdl_size,
PPC_CACHE_ALIGNMENT);
exception_handler_table[except->exceptIndex] =
default_raw_except_entry.hdl.raw_hdl;
raw_except_table[except->exceptIndex] = default_raw_except_entry;
raw_except_table[except->exceptIndex].exceptIndex = except->exceptIndex;
@@ -162,39 +148,37 @@ int mpc5xx_delete_exception (const rtems_raw_except_connect_data* except)
/*
* Exception global init.
*
* Install exception handler pointers from the raw exception table into the
* exception handler table.
*/
int mpc5xx_init_exceptions (rtems_raw_except_global_settings* config)
{
unsigned i;
unsigned int level;
/*
* store various accelerators
*/
raw_except_table = config->rawExceptHdlTbl;
local_settings = config;
default_raw_except_entry = config->defaultRawEntry;
unsigned i;
unsigned int level;
/*
* store various accelerators
*/
raw_except_table = config->rawExceptHdlTbl;
local_settings = config;
default_raw_except_entry = config->defaultRawEntry;
_CPU_ISR_Disable(level);
_CPU_ISR_Disable(level);
for (i=0; i <= LAST_VALID_EXC; i++) {
if (!mpc5xx_vector_is_valid(i)){
continue;
}
codemove((void*)mpc5xx_get_vector_addr(i),
raw_except_table[i].hdl.raw_hdl,
raw_except_table[i].hdl.raw_hdl_size,
PPC_CACHE_ALIGNMENT);
if (raw_except_table[i].hdl.raw_hdl != default_raw_except_entry.hdl.raw_hdl) {
raw_except_table[i].on(&raw_except_table[i]);
}
else {
raw_except_table[i].off(&raw_except_table[i]);
}
for (i = 0; i < NUM_EXCEPTIONS; i++) {
exception_handler_table[i] = raw_except_table[i].hdl.raw_hdl;
if (raw_except_table[i].hdl.raw_hdl != default_raw_except_entry.hdl.raw_hdl) {
raw_except_table[i].on(&raw_except_table[i]);
}
_CPU_ISR_Enable(level);
else {
raw_except_table[i].off(&raw_except_table[i]);
}
}
_CPU_ISR_Enable(level);
return 1;
return 1;
}
int mpc5xx_get_exception_config (rtems_raw_except_global_settings** config)

View File

@@ -2,88 +2,62 @@
* raw_execption.h
*
* This file contains implementation of C function to
* Instanciate 8xx ppc primary exception entries.
* More detailled information can be found on motorola
* site and more precisely in the following book :
* Instantiate mpc5xx primary exception entries.
* More detailled information can be found on the Motorola
* site and more precisely in the following book:
*
* MPC860
* Risc Microporcessor User's Manual
* Motorola REF : MPC860UM/AD 07/98 Rev .1
* MPC555/MPC556 User's Manual
* Motorola REF : MPC555UM/D Rev. 3, 2000 October 15
*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libcpu/powerpc/mpc8xx/exceptions/raw_exception.h:
*
* Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
* Canon Centre Recherche France.
*
* Changes for MPC5XX Wilfried Busalski (w.busalski@lancier-monitoring.de)
* Copyright (C) 2003 Lancier Monitoring GmbH
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
* http://www.rtems.com/license/LICENSE.
*
* raw_exception.h,v 1.1 2001/04/06 15:54:18 joel Exp
* $Id$
*/
#ifndef _LIBCPU_MPC5XX_EXCEPTION_RAW_EXCEPTION_H
#define _LIBCPU_MPC5XX_EXCEPTION_RAW_EXCEPTION_H
#include <libcpu/vectors.h>
/*
* Exception Vectors as defined in the MCP750 manual
* Exception Vectors as defined in the MPC555 User's Manual
*/
#define ASM_RESET_VECTOR 0x01
#define ASM_MACH_VECTOR 0x02
#define ASM_PROT_VECTOR 0x03
#define ASM_ISI_VECTOR 0x04
#define ASM_EXT_VECTOR 0x05
#define ASM_ALIGN_VECTOR 0x06
#define ASM_PROG_VECTOR 0x07
#define ASM_FLOAT_VECTOR 0x08
#define ASM_DEC_VECTOR 0x09
#define ASM_RESET_VECTOR 0x01
#define ASM_MACH_VECTOR 0x02
#define ASM_SYS_VECTOR 0x0C
#define ASM_TRACE_VECTOR 0x0D
#define ASM_EXT_VECTOR 0x05
#define ASM_ALIGN_VECTOR 0x06
#define ASM_PROG_VECTOR 0x07
#define ASM_FLOAT_VECTOR 0x08
#define ASM_DEC_VECTOR 0x09
#define ASM_SYS_VECTOR 0x0C
#define ASM_TRACE_VECTOR 0x0D
#define ASM_FLOATASSIST_VECTOR 0x0E
#define ASM_SOFTEMUL_VECTOR 0x10
#define ASM_SOFTEMUL_VECTOR 0x10
#define ASM_ITLBERROR_VECTOR 0x13
#define ASM_DTLBERROR_VECTOR 0x14
#define ASM_IPROT_VECTOR 0x13
#define ASM_DPROT_VECTOR 0x14
#define ASM_DBREAK_VECTOR 0x1C
#define ASM_IBREAK_VECTOR 0x1D
#define ASM_PERIFBREAK_VECTOR 0x1E
#define ASM_DEVPORT_VECTOR 0x1F
#define ASM_DBREAK_VECTOR 0x1C
#define ASM_IBREAK_VECTOR 0x1D
#define ASM_MEBREAK_VECTOR 0x1E
#define ASM_NMEBREAK_VECTOR 0x1F
#define LAST_VALID_EXC ASM_DEVPORT_VECTOR
/*
* Vector offsets as defined in the MPC860 manual
*/
#define ASM_RESET_VECTOR_OFFSET (ASM_RESET_VECTOR << 8)
#define ASM_MACH_VECTOR_OFFSET (ASM_MACH_VECTOR << 8)
#define ASM_PROT_VECTOR_OFFSET (ASM_PROT_VECTOR << 8)
#define ASM_ISI_VECTOR_OFFSET (ASM_ISI_VECTOR << 8)
#define ASM_EXT_VECTOR_OFFSET (ASM_EXT_VECTOR << 8)
#define ASM_ALIGN_VECTOR_OFFSET (ASM_ALIGN_VECTOR << 8)
#define ASM_PROG_VECTOR_OFFSET (ASM_PROG_VECTOR << 8)
#define ASM_FLOAT_VECTOR_OFFSET (ASM_FLOAT_VECTOR << 8)
#define ASM_DEC_VECTOR_OFFSET (ASM_DEC_VECTOR << 8)
#define ASM_SYS_VECTOR_OFFSET (ASM_SYS_VECTOR << 8)
#define ASM_TRACE_VECTOR_OFFSET (ASM_TRACE_VECTOR << 8)
#define ASM_FLOATASSIST_VECTOR_OFFSET (ASM_FLOATASSIST_VECTOR << 8)
#define ASM_SOFTEMUL_VECTOR_OFFSET (ASM_SOFTEMUL_VECTOR << 8)
#define ASM_ITLBERROR_VECTOR_OFFSET (ASM_ITLBERROR_VECTOR << 8)
#define ASM_DTLBERROR_VECTOR_OFFSET (ASM_DTLBERROR_VECTOR << 8)
#define ASM_DBREAK_VECTOR_OFFSET (ASM_DBREAK_VECTOR << 8)
#define ASM_IBREAK_VECTOR_OFFSET (ASM_IBREAK_VECTOR << 8)
#define ASM_PERIFBREAK_VECTOR_OFFSET (ASM_PERIFBREAK_VECTOR << 8)
#define ASM_DEVPORT_VECTOR_OFFSET (ASM_DEVPORT_VECTOR_OFFSET << 8)
#define LAST_VALID_EXC ASM_NMEBREAK_VECTOR
#ifndef ASM
@@ -93,13 +67,11 @@
typedef unsigned char rtems_vector;
struct __rtems_raw_except_connect_data__;
typedef void (*rtems_raw_except_func) (void);
typedef unsigned char rtems_raw_except_hdl_size;
typedef struct {
rtems_vector vector;
rtems_raw_except_func raw_hdl;
rtems_raw_except_hdl_size raw_hdl_size;
rtems_exception_handler_t* raw_hdl;
}rtems_raw_except_hdl;
typedef void (*rtems_raw_except_enable) (const struct __rtems_raw_except_connect_data__*);
@@ -186,5 +158,7 @@ extern int mpc5xx_get_exception_config (rtems_raw_except_global_settings** confi
# endif /* ASM */
#define SIZEOF_
#endif

View File

@@ -0,0 +1,37 @@
/*
* Console declarations
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifndef _M5xx_CONSOLE_H_
#define _M5xx_CONSOLE_H_
#include <rtems/libio.h>
#include <rtems/termiostypes.h>
void m5xx_uart_reserve_resources(rtems_configuration_table *configuration);
void m5xx_uart_initialize(int minor);
/* Termios callbacks */
int m5xx_uart_firstOpen(int maj, int min, void *arg);
int m5xx_uart_lastClose(int maj, int min, void *arg);
int m5xx_uart_pollRead(int minor);
int m5xx_uart_pollWrite(int minor, const char* buf, int len);
int m5xx_uart_write(int minor, const char *buf, int len);
int m5xx_uart_setAttributes(int, const struct termios* t);
#define NUM_PORTS 2 /* number of serial ports */
#define SCI1_MINOR 0
#define SCI2_MINOR 1
#endif /* _M5xx_CONSOLE_H_ */

View File

@@ -0,0 +1,621 @@
/*
* mpc5xx.h
*
* MPC5xx Internal I/O Definitions
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from c/src/lib/libcpu/powerpc/mpc8xx/include/mpc8xx.h:
*
* Submitted By: *
* *
* W. Eric Norum *
* Saskatchewan Accelerator Laboratory *
* University of Saskatchewan *
* 107 North Road *
* Saskatoon, Saskatchewan, CANADA *
* S7N 5C6 *
* *
* eric@skatter.usask.ca *
* *
* Modified for use with the MPC860 (original code was for MC68360) *
* by *
* Jay Monkman *
* Frasca International, Inc. *
* 906 E. Airport Rd. *
* Urbana, IL, 61801 *
* *
* jmonkman@frasca.com *
* *
* Modified further for use with the MPC821 by: *
* Andrew Bray <andy@chaos.org.uk> *
* *
* With some corrections/additions by: *
* Darlene A. Stewart and *
* Charles-Antoine Gauthier *
* Institute for Information Technology *
* National Research Council of Canada *
* Ottawa, ON K1A 0R6 *
* *
* Darlene.Stewart@iit.nrc.ca *
* charles.gauthier@iit.nrc.ca *
* *
* Corrections/additions: *
* Copyright (c) 1999, National Research Council of Canada *
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifndef _MPC5xx_h
#define _MPC5xx_h
#include <libcpu/spr.h>
#ifndef ASM
#ifdef __cplusplus
extern "C" {
#endif
/*
* Macros for accessing Special Purpose Registers (SPRs)
*/
#define _eieio __asm__ volatile ("eieio\n"::)
#define _sync __asm__ volatile ("sync\n"::)
#define _isync __asm__ volatile ("isync\n"::)
/*
* Core Registers (SPRs)
*/
#define DER 149 /* Debug Enable Register */
#define IMMR 638 /* Internal Memory Map Register */
#define IMMR_FLEN (1<<11) /* Internal flash ROM enabled */
/*
* Interrupt Control Registers (SPRs)
*/
#define EIE 80 /* External Interrupt Enable Register */
#define EID 81 /* External Interrupt Disable Register */
#define NRI 82 /* Non-Recoverable Interrupt Register */
#define ECR 148 /* Exception Cause Register */
/*
* Bus Control Registers (SPRs)
*/
#define LCTRL1 156 /* L-Bus Support Control Register 1 */
#define LCTRL2 157 /* L-Bus Support Control Register 2 */
#define ICTRL 158 /* I-Bus Support Control Register */
/*
* Burst Buffer Control Registers (SPRs)
*/
#define BBCMCR 560 /* Burst Buffer Configuration Register */
#define BBCMCR_BE (1<<13) /* Burst enable */
#define BBCMCR_ETRE (1<<12) /* Exception table relocation enable */
#define MI_RBA0 784 /* Region 0 Address Register */
#define MI_RBA1 785 /* Region 1 Address Register */
#define MI_RBA2 786 /* Region 2 Address Register */
#define MI_RBA3 787 /* Region 3 Address Register */
#define MI_RA0 816 /* Region 0 Attribute Register */
#define MI_RA1 817 /* Region 1 Attribute Register */
#define MI_RA2 818 /* Region 2 Attribute Register */
#define MI_RA3 819 /* Region 3 Attribute Register */
#define MI_GRA 528 /* Region Global Attribute Register */
#define MI_RA_PP (3 << 10) /* Protection bits: */
#define MI_RA_PP_SUPV (1 << 10) /* Supervisor */
#define MI_RA_PP_USER (2 << 10) /* User */
#define MI_RA_G (1 << 6) /* Guarded region */
/*
* L-Bus to U-Bus Interface (L2U) Registers (SPRs)
*/
#define L2U_MCR 568 /* L2U Module Configuration Register */
#define L2U_RBA0 792 /* L2U Region 0 Address Register */
#define L2U_RBA1 793 /* L2U Region 1 Address Register */
#define L2U_RBA2 794 /* L2U Region 2 Address Register */
#define L2U_RBA3 795 /* L2U Region 3 Address Register */
#define L2U_RA0 824 /* L2U Region 0 Attribute Register */
#define L2U_RA1 825 /* L2U Region 1 Attribute Register */
#define L2U_RA2 826 /* L2U Region 2 Attribute Register */
#define L2U_RA3 827 /* L2U Region 3 Attribute Register */
#define L2U_GRA 536 /* L2U Global Region Attribute Register */
#define L2U_RA_PP (3 << 10) /* Protection bits: */
#define L2U_RA_PP_SUPV (1 << 10) /* Supervisor */
#define L2U_RA_PP_USER (2 << 10) /* User */
#define L2U_RA_G (1 << 6) /* Guarded region */
/*
*************************************************************************
* REGISTER SUBBLOCKS *
*************************************************************************
*/
/*
*************************************************************************
* System Protection Control Register (SYPCR) *
*************************************************************************
*/
#define USIU_SYPCR_SWTC(x) ((x)<<16) /* Software watchdog timer count */
#define USIU_SYPCR_BMT(x) ((x)<<8) /* Bus monitor timing */
#define USIU_SYPCR_BME (1<<7) /* Bus monitor enable */
#define USIU_SYPCR_SWF (1<<3) /* Software watchdog freeze */
#define USIU_SYPCR_SWE (1<<2) /* Software watchdog enable */
#define USIU_SYPCR_SWRI (1<<1) /* Watchdog reset/interrupt sel. */
#define USIU_SYPCR_SWP (1<<0) /* Software watchdog prescale */
#define USIU_SYPCR_BMT(x) ((x)<<8) /* Bus monitor timing */
#define USIU_SYPCR_BME (1<<7) /* Bus monitor enable */
#define USIU_SYPCR_SWF (1<<3) /* Software watchdog freeze */
#define USIU_SYPCR_SWE (1<<2) /* Software watchdog enable */
#define USIU_SYPCR_SWRI (1<<1) /* Watchdog reset/interrupt sel. */
#define USIU_SYPCR_SWP (1<<0) /* Software watchdog prescale */
/*
*************************************************************************
* Software Service Register (SWSR) *
*************************************************************************
*/
#define TICKLE_WATCHDOG() \
do { \
usiu.swsr = 0x556C; \
usiu.swsr = 0xAA39; \
} while (0) \
/*
*************************************************************************
* Memory Control Registers *
*************************************************************************
*/
#define USIU_MEMC_BR_BA(x) (((rtems_unsigned32)x)&0xffff8000)
/* Base address */
#define USIU_MEMC_BR_AT(x) ((x)<<12) /* Address type */
#define USIU_MEMC_BR_PS8 (1<<10) /* 8 bit port */
#define USIU_MEMC_BR_PS16 (2<<10) /* 16 bit port */
#define USIU_MEMC_BR_PS32 (0<<10) /* 32 bit port */
#define USIU_MEMC_BR_WP (1<<8) /* Write protect */
#define USIU_MEMC_BR_WEBS (1<<5) /* Write enable/byte select */
#define USIU_MEMC_BR_TBDIP (1<<4) /* Toggle-Burst data in progress*/
#define USIU_MEMC_BR_LBDIP (1<<3) /* Late-burst data in progress */
#define USIU_MEMC_BR_SETA (1<<2) /* External transfer acknowledge */
#define USIU_MEMC_BR_BI (1<<1) /* Burst inhibit */
#define USIU_MEMC_BR_V (1<<0) /* Base/Option register are valid */
#define USIU_MEMC_OR_32K 0xffff8000 /* Address range */
#define USIU_MEMC_OR_64K 0xffff0000
#define USIU_MEMC_OR_128K 0xfffe0000
#define USIU_MEMC_OR_256K 0xfffc0000
#define USIU_MEMC_OR_512K 0xfff80000
#define USIU_MEMC_OR_1M 0xfff00000
#define USIU_MEMC_OR_2M 0xffe00000
#define USIU_MEMC_OR_4M 0xffc00000
#define USIU_MEMC_OR_8M 0xff800000
#define USIU_MEMC_OR_16M 0xff000000
#define USIU_MEMC_OR_32M 0xfe000000
#define USIU_MEMC_OR_64M 0xfc000000
#define USIU_MEMC_OR_128 0xf8000000
#define USIU_MEMC_OR_256M 0xf0000000
#define USIU_MEMC_OR_512M 0xe0000000
#define USIU_MEMC_OR_1G 0xc0000000
#define USIU_MEMC_OR_2G 0x80000000
#define USIU_MEMC_OR_4G 0x00000000
#define USIU_MEMC_OR_ATM(x) ((x)<<12) /* Address type mask */
#define USIU_MEMC_OR_CSNT (1<<11) /* Chip select is negated early */
#define USIU_MEMC_OR_ACS_NORM (0<<9) /* *CS asserted with addr lines */
#define USIU_MEMC_OR_ACS_QRTR (2<<9) /* *CS asserted 1/4 after addr */
#define USIU_MEMC_OR_ACS_HALF (3<<9) /* *CS asserted 1/2 after addr */
#define USIU_MEMC_OR_ETHR (1<<8) /* Extended hold time on reads */
#define USIU_MEMC_OR_SCY(x) ((x)<<4) /* Cycle length in clocks */
#define USIU_MEMC_OR_BSCY(x) ((x)<<1) /* Burst beat length in clocks */
#define USIU_MEMC_OR_TRLX (1<<0) /* Relaxed timing in GPCM */
/*
*************************************************************************
* Clocks and Reset Controlmer *
*************************************************************************
*/
#define USIU_SCCR_DBCT (1<<31) /* Disable backup clock for timers */
#define USIU_SCCR_COM(x) ((x)<<29) /* Clock output mode */
#define USIU_SCCR_RTDIV (1<<24) /* RTC, PIT divide by 256, not 4 */
#define USIU_PRQEN (1<<21) /* MSR[POW] controls frequency */
#define USIU_SCCR_EBDF(x) ((x)<<17) /* External bus division factor */
#define USIU_LME (1<<16) /* Enable limp mode */
#define USIU_ENGDIV(x) ((x)<<9) /* Set engineering clock divisor */
#define USIU_PLPRCR_MF(x) (((x)-1)<<20) /* PLL mult. factor (true) */
#define USIU_PLPRCR_SPLS (1<<16) /* System PLL locked */
#define USIU_PLPRCR_TEXPS (1<<14) /* Assert TEXP always */
/*
*************************************************************************
* Programmable Interval Timer *
*************************************************************************
*/
#define USIU_PISCR_PIRQ(x) (1<<(15-x)) /* PIT interrupt level */
#define USIU_PISCR_PS (1<<7) /* PIT Interrupt state */
#define USIU_PISCR_PIE (1<<2) /* PIT interrupt enable */
#define USIU_PISCR_PITF (1<<1) /* Stop timer when freeze asserted */
#define USIU_PISCR_PTE (1<<0) /* PIT enable */
/*
*************************************************************************
* Time Base *
*************************************************************************
*/
#define USIU_TBSCR_TBIRQ(x) (1<<(15-x)) /* TB interrupt level */
#define USIU_TBSCR_REFA (1<<7) /* TB matches TBREFF0 */
#define USIU_TBSCR_REFB (1<<6) /* TB matches TBREFF1 */
#define USIU_TBSCR_REFAE (1<<3) /* Enable ints for REFA */
#define USIU_TBSCR_REFBE (1<<2) /* Enable ints for REFB */
#define USIU_TBSCR_TBF (1<<1) /* TB stops on FREEZE */
#define USIU_TBSCR_TBE (1<<0) /* enable TB and decrementer */
/*
*************************************************************************
* SIU Interrupt Mask *
*************************************************************************
*/
#define USIU_SIMASK_IRM0 (1<<31)
#define USIU_SIMASK_LVM0 (1<<30)
#define USIU_SIMASK_IRM1 (1<<29)
#define USIU_SIMASK_LVM1 (1<<28)
#define USIU_SIMASK_IRM2 (1<<27)
#define USIU_SIMASK_LVM2 (1<<26)
#define USIU_SIMASK_IRM3 (1<<25)
#define USIU_SIMASK_LVM3 (1<<24)
#define USIU_SIMASK_IRM4 (1<<23)
#define USIU_SIMASK_LVM4 (1<<22)
#define USIU_SIMASK_IRM5 (1<<21)
#define USIU_SIMASK_LVM5 (1<<20)
#define USIU_SIMASK_IRM6 (1<<19)
#define USIU_SIMASK_LVM6 (1<<18)
#define USIU_SIMASK_IRM7 (1<<17)
#define USIU_SIMASK_LVM7 (1<<16)
/*
*************************************************************************
* SIU Module Control *
*************************************************************************
*/
#define USIU_SIUMCR_EARB (1<<31)
#define USIU_SIUMCR_EARP0 (0<<28)
#define USIU_SIUMCR_EARP1 (1<<28)
#define USIU_SIUMCR_EARP2 (2<<28)
#define USIU_SIUMCR_EARP3 (3<<28)
#define USIU_SIUMCR_EARP4 (4<<28)
#define USIU_SIUMCR_EARP5 (5<<28)
#define USIU_SIUMCR_EARP6 (6<<28)
#define USIU_SIUMCR_EARP7 (7<<28)
#define USIU_SIUMCR_DSHW (1<<23)
#define USIU_SIUMCR_DBGC0 (0<<21)
#define USIU_SIUMCR_DBGC1 (1<<21)
#define USIU_SIUMCR_DBGC2 (2<<21)
#define USIU_SIUMCR_DBGC3 (3<<21)
#define USIU_SIUMCR_DBPC (1<<20)
#define USIU_SIUMCR_ATWC (1<<19)
#define USIU_SIUMCR_GPC0 (0<<17)
#define USIU_SIUMCR_GPC1 (1<<17)
#define USIU_SIUMCR_GPC2 (2<<17)
#define USIU_SIUMCR_GPC3 (3<<17)
#define USIU_SIUMCR_DLK (1<<16)
#define USIU_SIUMCR_SC0 (0<<13)
#define USIU_SIUMCR_SC1 (1<<13)
#define USIU_SIUMCR_SC2 (2<<13)
#define USIU_SIUMCR_SC3 (3<<13)
#define USIU_SIUMCR_RCTX (1<<12)
#define USIU_SIUMCR_MLRC0 (0<<10)
#define USIU_SIUMCR_MLRC1 (1<<10)
#define USIU_SIUMCR_MLRC2 (2<<10)
#define USIU_SIUMCR_MLRC3 (3<<10)
#define USIU_SIUMCR_MTSC (1<<7)
/*
* Value to write to a key register to unlock the corresponding SIU register
*/
#define USIU_UNLOCK_KEY 0x55CCAA33
/*
*************************************************************************
* UIMB Module Control *
*************************************************************************
*/
#define UIMB_UMCR_STOP (1<<31)
#define UIMB_UMCR_IRQMUX(x) ((x)<<29)
#define UIMB_UMCR_HSPEED (1<<28)
/*
*************************************************************************
* QSMCM Serial Communications Interface (SCI) *
*************************************************************************
*/
#define QSMCM_ILDSCI(x) ((x)<<8) /* SCI interrupt level */
#define QSMCM_SCI_BAUD(x) ((x)&0x1FFF) /* Baud rate field */
#define QSMCM_SCI_LOOPS (1<<14) /* Loopback test mode */
#define QSMCM_SCI_WOMS (1<<13) /* Wire-or mode select */
#define QSMCM_SCI_ILT (1<<12) /* Idle-line detect type */
#define QSMCM_SCI_PT (1<<11) /* Parity type */
#define QSMCM_SCI_PE (1<<10) /* Parity enable */
#define QSMCM_SCI_M (1<<9) /* 11-bit mode */
#define QSMCM_SCI_WAKE (1<<8) /* Wakeup mode */
#define QSMCM_SCI_TIE (1<<7) /* Transmitter interrupt enable */
#define QSMCM_SCI_TCIE (1<<6) /* Transmit complete intr. enable */
#define QSMCM_SCI_RIE (1<<5) /* Receiver interrupt enable */
#define QSMCM_SCI_ILIE (1<<4) /* Idle line interrupt enable */
#define QSMCM_SCI_TE (1<<3) /* Transmitter enable */
#define QSMCM_SCI_RE (1<<2) /* Receiver enable */
#define QSMCM_SCI_RWU (1<<1) /* Receiver wake-up enable */
#define QSMCM_SCI_SBK (1<<0) /* Send break */
#define QSMCM_SCI_TDRE (1<<8) /* Transmit data register empty */
#define QSMCM_SCI_TC (1<<7) /* Transmit complete */
#define QSMCM_SCI_RDRF (1<<6) /* Receive data register full */
#define QSMCM_SCI_RAF (1<<5) /* Receiver active flag */
#define QSMCM_SCI_IDLE (1<<4) /* Idle line detected */
#define QSMCM_SCI_OR (1<<3) /* Receiver overrun error */
#define QSMCM_SCI_NF (1<<2) /* Receiver noise error flag */
#define QSMCM_SCI_FE (1<<1) /* Receiver framing error */
#define QSMCM_SCI_PF (1<<0) /* Receiver parity error */
/*
*************************************************************************
* Unified System Interface Unit *
*************************************************************************
*/
/*
* Memory controller registers
*/
typedef struct m5xxMEMCRegisters_ {
rtems_unsigned32 _br;
rtems_unsigned32 _or; /* Used to be called 'or'; reserved ANSI C++ keyword */
} m5xxMEMCRegisters_t;
/*
* USIU itself
*/
typedef struct usiu_ {
/*
* SIU Block
*/
rtems_unsigned32 siumcr;
rtems_unsigned32 sypcr;
rtems_unsigned32 _pad70;
rtems_unsigned16 _pad0;
rtems_unsigned16 swsr;
rtems_unsigned32 sipend;
rtems_unsigned32 simask;
rtems_unsigned32 siel;
rtems_unsigned32 sivec;
rtems_unsigned32 tesr;
rtems_unsigned32 sgpiodt1;
rtems_unsigned32 sgpiodt2;
rtems_unsigned32 sgpiocr;
rtems_unsigned32 emcr;
rtems_unsigned8 _pad71[0x03C-0x034];
rtems_unsigned32 pdmcr;
rtems_unsigned8 _pad2[0x100-0x40];
/*
* MEMC Block
*/
m5xxMEMCRegisters_t memc[4];
rtems_unsigned8 _pad7[0x140-0x120];
rtems_unsigned32 dmbr;
rtems_unsigned32 dmor;
rtems_unsigned8 _pad8[0x178-0x148];
rtems_unsigned16 mstat;
rtems_unsigned8 _pad9[0x200-0x17A];
/*
* System integration timers
*/
rtems_unsigned16 tbscr;
rtems_unsigned16 _pad10;
rtems_unsigned32 tbreff0;
rtems_unsigned32 tbreff1;
rtems_unsigned8 _pad11[0x220-0x20c];
rtems_unsigned16 rtcsc;
rtems_unsigned16 _pad12;
rtems_unsigned32 rtc;
rtems_unsigned32 rtsec;
rtems_unsigned32 rtcal;
rtems_unsigned32 _pad13[4];
rtems_unsigned16 piscr;
rtems_unsigned16 _pad14;
rtems_unsigned16 pitc;
rtems_unsigned16 _pad_14_1;
rtems_unsigned16 pitr;
rtems_unsigned16 _pad_14_2;
rtems_unsigned8 _pad15[0x280-0x24c];
/*
* Clocks and Reset
*/
rtems_unsigned32 sccr;
rtems_unsigned32 plprcr;
rtems_unsigned16 rsr;
rtems_unsigned16 _pad72;
rtems_unsigned16 colir;
rtems_unsigned16 _pad73;
rtems_unsigned16 vsrmcr;
rtems_unsigned8 _pad16[0x300-0x292];
/*
* System integration timers keys
*/
rtems_unsigned32 tbscrk;
rtems_unsigned32 tbreff0k;
rtems_unsigned32 tbreff1k;
rtems_unsigned32 tbk;
rtems_unsigned32 _pad17[4];
rtems_unsigned32 rtcsk;
rtems_unsigned32 rtck;
rtems_unsigned32 rtseck;
rtems_unsigned32 rtcalk;
rtems_unsigned32 _pad18[4];
rtems_unsigned32 piscrk;
rtems_unsigned32 pitck;
rtems_unsigned8 _pad19[0x380-0x348];
/*
* Clocks and Reset Keys
*/
rtems_unsigned32 sccrk;
rtems_unsigned32 plprck;
rtems_unsigned32 rsrk;
rtems_unsigned8 _pad20[0x400-0x38c];
} usiu_t;
extern volatile usiu_t usiu; /* defined in linkcmds */
/*
*************************************************************************
* Inter-Module Bus and Devices *
*************************************************************************
*/
/*
* Dual-Port TPU RAM (DPTRAM)
*/
typedef struct m5xxDPTRAMRegisters_ {
rtems_unsigned8 pad[0x4000]; /* define later */
} m5xxDPTRAMRegisters_t;
/*
* Time Processor Unit (TPU)
*/
typedef struct m5xxTPU3Registers_ {
rtems_unsigned8 pad[0x400]; /* define later */
} m5xxTPU3Registers_t;
/*
* Queued A/D Converter (QADC)
*/
typedef struct m5xxQADC64Registers_ {
rtems_unsigned8 pad[0x400]; /* define later */
} m5xxQADC64Registers_t;
/*
* Serial Communications Interface (SCI)
*/
typedef struct m5xxSCIRegisters_ {
rtems_unsigned16 sccr0;
rtems_unsigned16 sccr1;
rtems_unsigned16 scsr;
rtems_unsigned16 scdr;
} m5xxSCIRegisters_t;
/*
* Serial Peripheral Interface (SPI)
*/
typedef struct m5xxSPIRegisters_ {
rtems_unsigned16 spcr0;
rtems_unsigned16 spcr1;
rtems_unsigned16 spcr2;
rtems_unsigned8 spcr3;
rtems_unsigned8 spsr;
} m5xxSPIRegisters_t;
/*
* Queued Serial Multi-Channel Module (QSMCM)
*/
typedef struct m5xxQSMCMRegisters_ {
rtems_unsigned16 qsmcmmcr;
rtems_unsigned16 qtest;
rtems_unsigned16 qdsci_il;
rtems_unsigned16 qspi_il;
m5xxSCIRegisters_t sci1;
rtems_unsigned8 _pad10[0x14-0x10];
rtems_unsigned16 portqs;
rtems_unsigned16 pqspar;
m5xxSPIRegisters_t spi;
m5xxSCIRegisters_t sci2;
rtems_unsigned16 qsci1cr;
rtems_unsigned16 qsci1sr;
rtems_unsigned16 sctq[0x10];
rtems_unsigned16 scrq[0x10];
rtems_unsigned8 _pad6C[0x140-0x06C];
rtems_unsigned16 recram[0x20];
rtems_unsigned16 tranram[0x20];
rtems_unsigned16 comdram[0x20];
} m5xxQSMCMRegisters_t;
/*
* Modular Input/Output System (MIOS)
*/
typedef struct m5xxMIOS1Registers_ {
rtems_unsigned8 pad[0x1000]; /* define later */
} m5xxMIOS1Registers_t;
/*
* Can 2.0B Controller (TouCAN)
*/
typedef struct m5xxTouCANRegisters_ {
rtems_unsigned8 pad[0x400]; /* define later */
} m5xxTouCANRegisters_t;
/*
* U-Bus to IMB3 Bus Interface Module (UIMB)
*/
typedef struct m5xxUIMBRegisters_ {
rtems_unsigned32 umcr;
rtems_unsigned32 utstcreg;
rtems_unsigned32 uipend;
} m5xxUIMBRegisters_t;
/*
* IMB itself
*/
typedef struct imb_ {
m5xxDPTRAMRegisters_t dptram;
m5xxTPU3Registers_t tpu[2];
m5xxQADC64Registers_t qadc[2];
m5xxQSMCMRegisters_t qsmcm;
rtems_unsigned8 _pad5200[0x6000-0x5200];
m5xxMIOS1Registers_t mios;
m5xxTouCANRegisters_t toucan[2];
rtems_unsigned8 _pad7800[0x7F80-0x7800];
m5xxUIMBRegisters_t uimb;
} imb_t;
extern volatile imb_t imb; /* defined in linkcmds */
#ifdef __cplusplus
}
#endif
#endif /* ASM */
#endif /* _MPC5xx_h */

View File

@@ -0,0 +1,495 @@
/*
* irq.c
*
* This file contains the implementation of the function described in irq.h
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libbsp/powerpc/mbx8xx/irq/irq.c:
*
* Copyright (C) 1998, 1999 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#include <rtems.h>
#include <rtems/score/apiext.h>
#include <mpc5xx.h>
#include <libcpu/vectors.h>
#include <libcpu/raw_exception.h>
#include <libcpu/irq.h>
/*
* Convert an rtems_irq_symbolic_name constant to an interrupt level
* suitable for programming into an I/O device's interrupt level field.
*/
int CPU_irq_level_from_symbolic_name(const rtems_irq_symbolic_name name)
{
if (CPU_USIU_EXT_IRQ_0 <= name && name <= CPU_USIU_INT_IRQ_7)
return (name - CPU_USIU_EXT_IRQ_0) / 2;
if (CPU_UIMB_IRQ_8 <= name && name <= CPU_UIMB_IRQ_31)
return 8 + (name - CPU_UIMB_IRQ_8);
return 31; /* reasonable default */
}
/*
* default handler connected on each irq after bsp initialization
*/
static rtems_irq_connect_data default_rtems_entry;
/*
* location used to store initial tables used for interrupt
* management.
*/
static rtems_irq_global_settings* internal_config;
static rtems_irq_connect_data* rtems_hdl_tbl;
/*
* Check if symbolic IRQ name is an USIU IRQ
*/
static inline int is_usiu_irq(const rtems_irq_symbolic_name irqLine)
{
return (((int) irqLine <= CPU_USIU_IRQ_MAX_OFFSET) &&
((int) irqLine >= CPU_USIU_IRQ_MIN_OFFSET)
);
}
/*
* Check if symbolic IRQ name is an UIMB IRQ
*/
static inline int is_uimb_irq(const rtems_irq_symbolic_name irqLine)
{
return (((int) irqLine <= CPU_UIMB_IRQ_MAX_OFFSET) &&
((int) irqLine >= CPU_UIMB_IRQ_MIN_OFFSET)
);
}
/*
* Check if symbolic IRQ name is a Processor IRQ
*/
static inline int is_proc_irq(const rtems_irq_symbolic_name irqLine)
{
return (((int) irqLine <= CPU_PROC_IRQ_MAX_OFFSET) &&
((int) irqLine >= CPU_PROC_IRQ_MIN_OFFSET)
);
}
/*
* Masks used to mask off the interrupts. For exmaple, for ILVL2, the
* mask is used to mask off interrupts ILVL2, IRQ3, ILVL3, ... IRQ7
* and ILVL7.
*
*/
const static unsigned int USIU_IvectMask[CPU_USIU_IRQ_COUNT] =
{
0, /* external IRQ 0 */
0xFFFFFFFF << 31, /* internal level 0 */
0xFFFFFFFF << 30, /* external IRQ 1 */
0xFFFFFFFF << 29, /* internal level 1 */
0xFFFFFFFF << 28, /* external IRQ 2 */
0xFFFFFFFF << 27, /* internal level 2 */
0xFFFFFFFF << 26, /* external IRQ 3 */
0xFFFFFFFF << 25, /* internal level 3 */
0xFFFFFFFF << 24, /* external IRQ 4 */
0xFFFFFFFF << 23, /* internal level 4 */
0xFFFFFFFF << 22, /* external IRQ 5 */
0xFFFFFFFF << 21, /* internal level 5 */
0xFFFFFFFF << 20, /* external IRQ 6 */
0xFFFFFFFF << 19, /* internal level 6 */
0xFFFFFFFF << 18, /* external IRQ 7 */
0xFFFFFFFF << 17 /* internal level 7 */
};
/*
* ------------------------ RTEMS Irq helper functions ----------------
*/
/*
* Caution : this function assumes the variable "internal_config"
* is already set and that the tables it contains are still valid
* and accessible.
*/
static void compute_USIU_IvectMask_from_prio ()
{
/*
* In theory this is feasible. No time to code it yet. See i386/shared/irq.c
* for an example based on 8259 controller mask. The actual masks defined
* correspond to the priorities defined for the USIU in irq_init.c.
*/
}
/*
* This function check that the value given for the irq line
* is valid.
*/
static int isValidInterrupt(int irq)
{
if ( (irq < CPU_MIN_OFFSET) || (irq > CPU_MAX_OFFSET)
|| (irq == CPU_UIMB_INTERRUPT) )
return 0;
return 1;
}
int CPU_irq_enable_at_uimb(const rtems_irq_symbolic_name irqLine)
{
if (!is_uimb_irq(irqLine))
return 1;
return 0;
}
int CPU_irq_disable_at_uimb(const rtems_irq_symbolic_name irqLine)
{
if (!is_uimb_irq(irqLine))
return 1;
return 0;
}
int CPU_irq_enabled_at_uimb(const rtems_irq_symbolic_name irqLine)
{
if (!is_uimb_irq(irqLine))
return 0;
return 1;
}
int CPU_irq_enable_at_usiu(const rtems_irq_symbolic_name irqLine)
{
int usiu_irq_index;
if (!is_usiu_irq(irqLine))
return 1;
usiu_irq_index = ((int) (irqLine) - CPU_USIU_IRQ_MIN_OFFSET);
ppc_cached_irq_mask |= (1 << (31-usiu_irq_index));
usiu.simask = ppc_cached_irq_mask;
return 0;
}
int CPU_irq_disable_at_usiu(const rtems_irq_symbolic_name irqLine)
{
int usiu_irq_index;
if (!is_usiu_irq(irqLine))
return 1;
usiu_irq_index = ((int) (irqLine) - CPU_USIU_IRQ_MIN_OFFSET);
ppc_cached_irq_mask &= ~(1 << (31-usiu_irq_index));
usiu.simask = ppc_cached_irq_mask;
return 0;
}
int CPU_irq_enabled_at_usiu(const rtems_irq_symbolic_name irqLine)
{
int usiu_irq_index;
if (!is_usiu_irq(irqLine))
return 0;
usiu_irq_index = ((int) (irqLine) - CPU_USIU_IRQ_MIN_OFFSET);
return ppc_cached_irq_mask & (1 << (31-usiu_irq_index));
}
/*
* --------------- RTEMS Single Irq Handler Mngt Routines ----------------
*/
int CPU_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
{
unsigned int level;
if (!isValidInterrupt(irq->name)) {
return 0;
}
/*
* Check if default handler is actually connected. If not issue an error.
* You must first get the current handler via CPU_get_current_idt_entry
* and then disconnect it using CPU_delete_idt_entry.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
return 0;
}
_CPU_ISR_Disable(level);
/*
* store the data provided by user
*/
rtems_hdl_tbl[irq->name] = *irq;
if (is_uimb_irq(irq->name)) {
/*
* Enable interrupt at UIMB level
*/
CPU_irq_enable_at_uimb (irq->name);
}
if (is_usiu_irq(irq->name)) {
/*
* Enable interrupt at USIU level
*/
CPU_irq_enable_at_usiu (irq->name);
}
if (is_proc_irq(irq->name)) {
/*
* Should Enable exception at processor level but not needed. Will restore
* EE flags at the end of the routine anyway.
*/
}
/*
* Enable interrupt on device
*/
irq->on(irq);
_CPU_ISR_Enable(level);
return 1;
}
int CPU_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
{
if (!isValidInterrupt(irq->name)) {
return 0;
}
*irq = rtems_hdl_tbl[irq->name];
return 1;
}
int CPU_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
{
unsigned int level;
if (!isValidInterrupt(irq->name)) {
return 0;
}
/*
* Check if default handler is actually connected. If not issue an error.
* You must first get the current handler via CPU_get_current_idt_entry
* and then disconnect it using CPU_delete_idt_entry.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
return 0;
}
_CPU_ISR_Disable(level);
/*
* Disable interrupt on device
*/
irq->off(irq);
if (is_uimb_irq(irq->name)) {
/*
* disable interrupt at UIMB level
*/
CPU_irq_disable_at_uimb (irq->name);
}
if (is_usiu_irq(irq->name)) {
/*
* disable interrupt at USIU level
*/
CPU_irq_disable_at_usiu (irq->name);
}
if (is_proc_irq(irq->name)) {
/*
* disable exception at processor level
*/
}
/*
* restore the default irq value
*/
rtems_hdl_tbl[irq->name] = default_rtems_entry;
_CPU_ISR_Enable(level);
return 1;
}
/*
* ---------------- RTEMS Global Irq Handler Mngt Routines ----------------
*/
int CPU_rtems_irq_mngt_set (rtems_irq_global_settings* config)
{
int i;
unsigned int level;
/*
* Store various code accelerators
*/
internal_config = config;
default_rtems_entry = config->defaultEntry;
rtems_hdl_tbl = config->irqHdlTbl;
_CPU_ISR_Disable(level);
/*
* Start with UIMB IRQ
*/
for (i = CPU_UIMB_IRQ_MIN_OFFSET; i <= CPU_UIMB_IRQ_MAX_OFFSET ; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
CPU_irq_enable_at_uimb (i);
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
}
else {
rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
CPU_irq_disable_at_uimb (i);
}
}
/*
* Continue with USIU IRQ
* Set up internal tables used by rtems interrupt prologue
*/
compute_USIU_IvectMask_from_prio ();
for (i = CPU_USIU_IRQ_MIN_OFFSET; i <= CPU_USIU_IRQ_MAX_OFFSET ; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
CPU_irq_enable_at_usiu (i);
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
}
else {
rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
CPU_irq_disable_at_usiu (i);
}
}
/*
* Enable all UIMB interrupt lines, then enable at USIU.
*/
imb.uimb.umcr |= UIMB_UMCR_IRQMUX(3);
CPU_irq_enable_at_usiu (CPU_UIMB_INTERRUPT);
/*
* finish with Processor exceptions handled like IRQ
*/
for (i = CPU_PROC_IRQ_MIN_OFFSET; i <= CPU_PROC_IRQ_MAX_OFFSET; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
}
else {
rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
}
}
_CPU_ISR_Enable(level);
return 1;
}
int CPU_rtems_irq_mngt_get(rtems_irq_global_settings** config)
{
*config = internal_config;
return 0;
}
/*
* High level IRQ handler called from shared_raw_irq_code_entry
*/
void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
{
register unsigned int irq;
register unsigned uimbIntr; /* boolean */
register unsigned oldMask; /* old siu pic masks */
register unsigned msr;
register unsigned new_msr;
/*
* Handle decrementer interrupt
*/
if (excNum == ASM_DEC_VECTOR) {
_CPU_MSR_GET(msr);
new_msr = msr | MSR_EE;
_CPU_MSR_SET(new_msr);
rtems_hdl_tbl[CPU_DECREMENTER].hdl();
_CPU_MSR_SET(msr);
return;
}
/*
* Handle external interrupt generated by USIU on PPC core
*/
while ((ppc_cached_irq_mask & usiu.sipend) != 0) {
irq = (usiu.sivec >> 26);
uimbIntr = (irq == CPU_UIMB_INTERRUPT);
/*
* Disable the interrupt of the same and lower priority.
*/
oldMask = ppc_cached_irq_mask;
ppc_cached_irq_mask = oldMask & USIU_IvectMask[irq];
usiu.simask = ppc_cached_irq_mask;
/*
* Acknowledge current interrupt. This has no effect on internal level
* interrupts.
*/
usiu.sipend = (1 << (31 - irq));
if (uimbIntr) {
/*
* Look at the bits set in the UIMB interrupt-pending register. The
* highest-order set bit indicates the handler we will run.
*
* Unfortunately, we can't easily mask individual UIMB interrupts
* unless they use USIU levels 0 to 6, so we must mask all low-level
* (level > 7) UIMB interrupts while we service any interrupt.
*/
int uipend = imb.uimb.uipend << 8;
if (uipend == 0) { /* spurious interrupt? use last vector */
irq = CPU_UIMB_IRQ_MAX_OFFSET;
}
else {
irq = CPU_UIMB_IRQ_MIN_OFFSET;
for ( ; (uipend & 0x8000000) == 0; uipend <<= 1) {
irq++;
}
}
}
_CPU_MSR_GET(msr);
new_msr = msr | MSR_EE;
_CPU_MSR_SET(new_msr);
rtems_hdl_tbl[irq].hdl();
_CPU_MSR_SET(msr);
ppc_cached_irq_mask = oldMask;
usiu.simask = ppc_cached_irq_mask;
}
}
void _ThreadProcessSignalsFromIrq (CPU_Exception_frame* ctx)
{
/*
* Process pending signals that have not already been
* processed by _Thread_Displatch. This happens quite
* unfrequently : the ISR must have posted an action
* to the current running thread.
*/
if ( _Thread_Do_post_task_switch_extension ||
_Thread_Executing->do_post_task_switch_extension ) {
_Thread_Executing->do_post_task_switch_extension = FALSE;
_API_extensions_Run_postswitch();
}
/*
* I plan to process other thread related events here.
* This will include DEBUG session requested from keyboard...
*/
}

View File

@@ -0,0 +1,358 @@
/*
* irq.h
*
* This include file describe the data structure and the functions implemented
* by rtems to write interrupt handlers.
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libbsp/powerpc/mbx8xx/irq/irq.h:
*
* CopyRight (C) 1999 valette@crf.canon.fr
*
* This code is heavilly inspired by the public specification of STREAM V2
* that can be found at :
*
* <http://www.chorus.com/Documentation/index.html> by following
* the STREAM API Specification Document link.
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifndef LIBCPU_POWERPC_MBX8XX_IRQ_IRQ_H
#define LIBCPU_POWERPC_MBX8XX_IRQ_IRQ_H
#define CPU_ASM_IRQ_VECTOR_BASE 0x0
#ifndef ASM
extern volatile unsigned int ppc_cached_irq_mask;
/*
* Symblolic IRQ names and related definitions.
*/
typedef enum {
/*
* Base vector for our USIU IRQ handlers.
*/
CPU_USIU_VECTOR_BASE = CPU_ASM_IRQ_VECTOR_BASE,
/*
* USIU IRQ handler related definitions
*/
CPU_USIU_IRQ_COUNT = 16, /* 16 reserved but in the future... */
CPU_USIU_IRQ_MIN_OFFSET = 0,
CPU_USIU_IRQ_MAX_OFFSET = CPU_USIU_IRQ_MIN_OFFSET + CPU_USIU_IRQ_COUNT - 1,
/*
* UIMB IRQ handlers related definitions
*/
CPU_UIMB_IRQ_COUNT = 32 - 8, /* first 8 overlap USIU */
CPU_UIMB_IRQ_MIN_OFFSET = CPU_USIU_IRQ_COUNT + CPU_USIU_VECTOR_BASE,
CPU_UIMB_IRQ_MAX_OFFSET = CPU_UIMB_IRQ_MIN_OFFSET + CPU_UIMB_IRQ_COUNT - 1,
/*
* PowerPc exceptions handled as interrupt where a rtems managed interrupt
* handler might be connected
*/
CPU_PROC_IRQ_COUNT = 1,
CPU_PROC_IRQ_MIN_OFFSET = CPU_UIMB_IRQ_MAX_OFFSET + 1,
CPU_PROC_IRQ_MAX_OFFSET = CPU_PROC_IRQ_MIN_OFFSET + CPU_PROC_IRQ_COUNT - 1,
/*
* Summary
*/
CPU_IRQ_COUNT = CPU_PROC_IRQ_MAX_OFFSET + 1,
CPU_MIN_OFFSET = CPU_USIU_IRQ_MIN_OFFSET,
CPU_MAX_OFFSET = CPU_PROC_IRQ_MAX_OFFSET,
/*
* USIU IRQ symbolic name definitions.
*/
CPU_USIU_EXT_IRQ_0 = CPU_USIU_IRQ_MIN_OFFSET,
CPU_USIU_INT_IRQ_0,
CPU_USIU_EXT_IRQ_1,
CPU_USIU_INT_IRQ_1,
CPU_USIU_EXT_IRQ_2,
CPU_USIU_INT_IRQ_2,
CPU_USIU_EXT_IRQ_3,
CPU_USIU_INT_IRQ_3,
CPU_USIU_EXT_IRQ_4,
CPU_USIU_INT_IRQ_4,
CPU_USIU_EXT_IRQ_5,
CPU_USIU_INT_IRQ_5,
CPU_USIU_EXT_IRQ_6,
CPU_USIU_INT_IRQ_6,
CPU_USIU_EXT_IRQ_7,
CPU_USIU_INT_IRQ_7,
/*
* Symbolic names for UISU interrupt sources.
*/
CPU_PERIODIC_TIMER = CPU_USIU_INT_IRQ_6,
CPU_UIMB_INTERRUPT = CPU_USIU_INT_IRQ_7,
/*
* UIMB IRQ symbolic name definitions. The first 8 sources are aliases to
* the USIU interrupts of the same number, because they are detected in
* the USIU pending register rather than the UIMB pending register.
*/
CPU_UIMB_IRQ_0 = CPU_USIU_INT_IRQ_0,
CPU_UIMB_IRQ_1 = CPU_USIU_INT_IRQ_1,
CPU_UIMB_IRQ_2 = CPU_USIU_INT_IRQ_2,
CPU_UIMB_IRQ_3 = CPU_USIU_INT_IRQ_3,
CPU_UIMB_IRQ_4 = CPU_USIU_INT_IRQ_4,
CPU_UIMB_IRQ_5 = CPU_USIU_INT_IRQ_5,
CPU_UIMB_IRQ_6 = CPU_USIU_INT_IRQ_6,
CPU_UIMB_IRQ_7 = CPU_USIU_INT_IRQ_7,
CPU_UIMB_IRQ_8 = CPU_UIMB_IRQ_MIN_OFFSET,
CPU_UIMB_IRQ_9,
CPU_UIMB_IRQ_10,
CPU_UIMB_IRQ_11,
CPU_UIMB_IRQ_12,
CPU_UIMB_IRQ_13,
CPU_UIMB_IRQ_14,
CPU_UIMB_IRQ_15,
CPU_UIMB_IRQ_16,
CPU_UIMB_IRQ_17,
CPU_UIMB_IRQ_18,
CPU_UIMB_IRQ_19,
CPU_UIMB_IRQ_20,
CPU_UIMB_IRQ_21,
CPU_UIMB_IRQ_22,
CPU_UIMB_IRQ_23,
CPU_UIMB_IRQ_24,
CPU_UIMB_IRQ_25,
CPU_UIMB_IRQ_26,
CPU_UIMB_IRQ_27,
CPU_UIMB_IRQ_28,
CPU_UIMB_IRQ_29,
CPU_UIMB_IRQ_30,
CPU_UIMB_IRQ_31,
/*
* Symbolic names for UIMB interrupt sources.
*/
CPU_IRQ_SCI = CPU_UIMB_IRQ_5,
/*
* Processor exceptions handled as rtems IRQ symbolic name definitions.
*/
CPU_DECREMENTER = CPU_PROC_IRQ_MIN_OFFSET
}rtems_irq_symbolic_name;
/*
* Convert an rtems_irq_symbolic_name constant to an interrupt level
* suitable for programming into an I/O device's interrupt level field.
*/
int CPU_irq_level_from_symbolic_name(const rtems_irq_symbolic_name name);
/*
* Type definition for RTEMS managed interrupts
*/
typedef unsigned char rtems_irq_prio;
struct __rtems_irq_connect_data__; /* forward declaratiuon */
typedef void (*rtems_irq_hdl) (void);
typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*);
typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*);
typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*);
typedef struct __rtems_irq_connect_data__ {
/*
* IRQ line
*/
rtems_irq_symbolic_name name;
/*
* Handler. See comment on handler properties below in function prototype.
*/
rtems_irq_hdl hdl;
/*
* Function for enabling interrupts at device level (ONLY!).
* The CPU code will automatically enable it at USIU level and UIMB level.
* RATIONALE : anyway such code has to exist in current driver code.
* It is usually called immediately AFTER connecting the interrupt handler.
* RTEMS may well need such a function when restoring normal interrupt
* processing after a debug session.
*
*/
rtems_irq_enable on;
/*
* Function for disabling interrupts at device level (ONLY!).
* The code will disable it at USIU and UIMB level. RATIONALE : anyway
* such code has to exist for clean shutdown. It is usually called
* BEFORE disconnecting the interrupt. RTEMS may well need such
* a function when disabling normal interrupt processing for
* a debug session. May well be a NOP function.
*/
rtems_irq_disable off;
/*
* Function enabling to know what interrupt may currently occur
* if someone manipulates the USIU and UIMB interrupt mask without care...
*/
rtems_irq_is_enabled isOn;
}rtems_irq_connect_data;
typedef struct {
/*
* size of all the table fields (*Tbl) described below.
*/
unsigned int irqNb;
/*
* Default handler used when disconnecting interrupts.
*/
rtems_irq_connect_data defaultEntry;
/*
* Table containing initials/current value.
*/
rtems_irq_connect_data* irqHdlTbl;
/*
* actual value of CPU_USIU_IRQ_VECTOR_BASE...
*/
rtems_irq_symbolic_name irqBase;
/*
* software priorities associated with interrupts.
* if irqPrio [i] > intrPrio [j] it means that
* interrupt handler hdl connected for interrupt name i
* will not be interrupted by the handler connected for interrupt j
* The interrupt source will be physically masked at USIU and UIMB level.
*/
rtems_irq_prio* irqPrioTbl;
}rtems_irq_global_settings;
/*-------------------------------------------------------------------------+
| Function Prototypes.
+--------------------------------------------------------------------------*/
#if 0
/*
* -------------------- MPC5xx USIU Management Routines -----------------
*/
/*
* Function to disable a particular irq at USIU level. After calling
* this function, even if the device asserts the interrupt line it will
* not be propagated further to the processor
*/
int CPU_irq_disable_at_usiu (const rtems_irq_symbolic_name irqLine);
/*
* Function to enable a particular irq at USIU level. After calling
* this function, if the device asserts the interrupt line it will
* be propagated further to the processor
*/
int CPU_irq_enable_at_usiu (const rtems_irq_symbolic_name irqLine);
/*
* Function to acknowledge a particular irq at USIU level. After calling
* this function, if a device asserts an enabled interrupt line it will
* be propagated further to the processor. Mainly useful for people
* writing raw handlers as this is automagically done for rtems managed
* handlers.
*/
int CPU_irq_ack_at_siu (const rtems_irq_symbolic_name irqLine);
/*
* function to check if a particular irq is enabled at USIU level.
*/
int CPU_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine);
#endif
/*
* ------------ RTEMS Single Irq Handler Management Routines ----------------
*/
/*
* Function to connect a particular irq handler. This handler will NOT be
* called directly as the result of the corresponding interrupt. Instead, a
* RTEMS irq prologue will be called that will :
*
* 1) save the C scratch registers,
* 2) switch to a interrupt stack if the interrupt is not nested,
* 4) modify them to disable the current interrupt at USIU level (and
* maybe others depending on software priorities)
* 5) aknowledge the USIU',
* 6) demask the processor,
* 7) call the application handler
*
* As a result the hdl function provided
*
* a) can perfectly be written is C,
* b) may also well directly call the part of the RTEMS API that can be
* used from interrupt level,
* c) It only responsible for handling the jobs that need to be done at
* the device level including (aknowledging/re-enabling the
* interrupt at device, level, getting the data,...)
*
* When returning from the function, the following will be performed by
* the RTEMS irq epilogue :
*
* 1) masks the interrupts again,
* 2) restore the original USIU interrupt masks
* 3) switch back on the orinal stack if needed,
* 4) perform rescheduling when necessary,
* 5) restore the C scratch registers...
* 6) restore initial execution flow
*
*/
int CPU_install_rtems_irq_handler (const rtems_irq_connect_data*);
/*
* Function to connect an RTEMS irq handler for ptr->name.
*/
int CPU_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr);
/*
* Function to get the RTEMS irq handler for ptr->name.
*/
int CPU_remove_rtems_irq_handler (const rtems_irq_connect_data*);
/*
* Function to disconnect the RTEMS irq handler for ptr->name. This
* function checks that the value given is the current one for safety
* reason. The user can use the previous function to get it.
*/
/*
* ------------ RTEMS Global Irq Handler Management Routines ----------------
*/
/*
* (Re) Initialize the RTEMS interrupt management.
*
* The result of calling this function will be the same as if each
* individual handler (config->irqHdlTbl[i].hdl) different from
* "config->defaultEntry.hdl" has been individualy connected via
*
* CPU_install_rtems_irq_handler(&config->irqHdlTbl[i])
*
* and each handler currently equal to config->defaultEntry.hdl
* has been previously disconnected via
*
* CPU_remove_rtems_irq_handler (&config->irqHdlTbl[i])
*
* This is to say that all information given will be used and not just
* only the space.
*
* CAUTION : the various table address contained in config will be used
* directly by the interrupt mangement code in order to save
* data size so they must stay valid after the call => they should
* not be modified or declared on a stack.
*/
int CPU_rtems_irq_mngt_set(rtems_irq_global_settings* config);
/*
* (Re) get info on current RTEMS interrupt management.
*/
int CPU_rtems_irq_mngt_get(rtems_irq_global_settings**);
extern void CPU_rtems_irq_mng_init(unsigned cpuId);
#endif
#endif

View File

@@ -0,0 +1,325 @@
/*
* irq_asm.S
*
* This file contains the assembly code for the PowerPC
* IRQ veneers for RTEMS.
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libbsp/powerpc/mbx8xx/irq/irq_asm.S:
*
* Modified to support the MCP750.
* Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
*
* Till Straumann <strauman@slac.stanford.edu>, 2003/7:
* - store isr nesting level in _ISR_Nest_level rather than
* SPRG0 - RTEMS relies on that variable.
*
* $Id$
*/
#include <asm.h>
#include <rtems/score/cpu.h>
#include <libcpu/vectors.h>
#include <libcpu/raw_exception.h>
#define SYNC \
sync; \
isync
/*
* Common handler for interrupt exceptions.
*
* The function CPU_rtems_irq_mng_init() initializes the decrementer and
* external interrupt entries in the exception handler table with pointers
* to this routine, which saves the remainder of the interrupted code's
* state, then calls C_dispatch_irq_handler().
*
* On entry, R1 points to a new exception stack frame in which R3, R4, and
* LR have been saved. R4 holds the exception number.
*/
PUBLIC_VAR(C_dispatch_irq_handler)
PUBLIC_VAR(dispatch_irq_handler)
SYM (dispatch_irq_handler):
/*
* Save SRR0/SRR1 As soon As possible as it is the minimal needed
* to re-enable exception processing.
*
* Note that R2 should never change (it's the EABI pointer to
* .sdata2), but we save it just in case.
*/
stw r0, GPR0_OFFSET(r1)
stw r2, GPR2_OFFSET(r1)
mfsrr0 r0
mfsrr1 r3
stw r0, SRR0_FRAME_OFFSET(r1)
stw r3, SRR1_FRAME_OFFSET(r1)
/*
* Enable exception recovery. Also enable FP so that FP context
* can be saved and restored (using FP instructions).
*/
mfmsr r3
ori r3, r3, MSR_RI | MSR_FP
mtmsr r3
SYNC
/*
* Push C scratch registers on the current stack. It may actually be
* the thread stack or the interrupt stack. Anyway we have to make
* it in order to be able to call C/C++ functions. Depending on the
* nesting interrupt level, we will switch to the right stack later.
*/
stw r5, GPR5_OFFSET(r1)
stw r6, GPR6_OFFSET(r1)
stw r7, GPR7_OFFSET(r1)
stw r8, GPR8_OFFSET(r1)
stw r9, GPR9_OFFSET(r1)
stw r10, GPR10_OFFSET(r1)
stw r11, GPR11_OFFSET(r1)
stw r12, GPR12_OFFSET(r1)
stw r13, GPR13_OFFSET(r1)
mfcr r5
mfctr r6
mfxer r7
stw r5, EXC_CR_OFFSET(r1)
stw r6, EXC_CTR_OFFSET(r1)
stw r7, EXC_XER_OFFSET(r1)
/*
* Add some non volatile registers to store information that will be
* used when returning from C handler.
*/
stw r14, GPR14_OFFSET(r1)
stw r15, GPR15_OFFSET(r1)
/*
* Save current stack pointer location in R14.
*/
addi r14, r1, 0
/*
* store part of _Thread_Dispatch_disable_level address in R15
*/
addis r15, 0, _Thread_Dispatch_disable_level@ha
/*
* Retrieve current nesting level from _ISR_Nest_level
*/
lis r7, _ISR_Nest_level@ha
lwz r3, _ISR_Nest_level@l(r7)
/*
* Check if stack switch is necessary
*/
cmpwi r3, 0
bne nested
mfspr r1, SPRG1 /* switch to interrupt stack */
nested:
/*
* Start Incrementing nesting level in R3
*/
addi r3, r3, 1
/*
* Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
*/
lwz r6, _Thread_Dispatch_disable_level@l(r15)
/* store new nesting level in _ISR_Nest_level */
stw r3, _ISR_Nest_level@l(r7)
addi r6, r6, 1
/*
* store new _Thread_Dispatch_disable_level value
*/
stw r6, _Thread_Dispatch_disable_level@l(r15)
/*
* We are now running on the interrupt stack. External and decrementer
* exceptions are still disabled. I see no purpose trying to optimize
* further assembler code.
*/
/*
* Call C exception handler for decrementer or external interrupt.
* Pass frame along just in case..
*
* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4)
*/
addi r3, r14, 0x8
bl C_dispatch_irq_handler
/*
* start decrementing nesting level. Note : do not test result against 0
* value as an easy exit condition because if interrupt nesting level > 1
* then _Thread_Dispatch_disable_level > 1
*/
lis r7, _ISR_Nest_level@ha
lwz r4, _ISR_Nest_level@l(r7)
/*
* start decrementing _Thread_Dispatch_disable_level
*/
lwz r3,_Thread_Dispatch_disable_level@l(r15)
addi r4, r4, -1 /* Continue decrementing nesting level */
addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */
stw r4, _ISR_Nest_level@l(r7) /* End decrementing nesting level */
stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
cmpwi r3, 0
/*
* switch back to original stack (done here just optimize registers
* contention. Could have been done before...)
*/
addi r1, r14, 0
bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
/*
* Here we are running again on the thread system stack.
* We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
* Interrupt are still disabled. Time to check if scheduler request to
* do something with the current thread...
*/
addis r4, 0, _Context_Switch_necessary@ha
lwz r5, _Context_Switch_necessary@l(r4)
cmpwi r5, 0
bne switch
addis r6, 0, _ISR_Signals_to_thread_executing@ha
lwz r7, _ISR_Signals_to_thread_executing@l(r6)
cmpwi r7, 0
li r8, 0
beq easy_exit
stw r8, _ISR_Signals_to_thread_executing@l(r6)
/*
* going to call _ThreadProcessSignalsFromIrq
* Push a complete exception like frame...
*/
stmw r16, GPR16_OFFSET(r1)
addi r3, r1, 0x8
/*
* compute SP at exception entry
*/
addi r4, r1, EXCEPTION_FRAME_END
/*
* store it at the right place
*/
stw r4, GPR1_OFFSET(r1)
/*
* Call High Level signal handling code
*/
bl _ThreadProcessSignalsFromIrq
/*
* start restoring exception like frame
*/
lwz r31, EXC_CTR_OFFSET(r1)
lwz r30, EXC_XER_OFFSET(r1)
lwz r29, EXC_CR_OFFSET(r1)
lwz r28, EXC_LR_OFFSET(r1)
mtctr r31
mtxer r30
mtcr r29
mtlr r28
lmw r4, GPR4_OFFSET(r1)
lwz r2, GPR2_OFFSET(r1)
lwz r0, GPR0_OFFSET(r1)
/*
* Make path non recoverable...
*/
mtspr nri, r0
SYNC
/*
* Restore rfi related settings
*/
lwz r3, SRR1_FRAME_OFFSET(r1)
mtsrr1 r3
lwz r3, SRR0_FRAME_OFFSET(r1)
mtsrr0 r3
lwz r3, GPR3_OFFSET(r1)
addi r1,r1, EXCEPTION_FRAME_END
SYNC
rfi
switch:
bl SYM (_Thread_Dispatch)
easy_exit:
/*
* start restoring interrupt frame
*/
lwz r3, EXC_CTR_OFFSET(r1)
lwz r4, EXC_XER_OFFSET(r1)
lwz r5, EXC_CR_OFFSET(r1)
lwz r6, EXC_LR_OFFSET(r1)
mtctr r3
mtxer r4
mtcr r5
mtlr r6
lwz r15, GPR15_OFFSET(r1)
lwz r14, GPR14_OFFSET(r1)
lwz r13, GPR13_OFFSET(r1)
lwz r12, GPR12_OFFSET(r1)
lwz r11, GPR11_OFFSET(r1)
lwz r10, GPR10_OFFSET(r1)
lwz r9, GPR9_OFFSET(r1)
lwz r8, GPR8_OFFSET(r1)
lwz r7, GPR7_OFFSET(r1)
lwz r6, GPR6_OFFSET(r1)
lwz r5, GPR5_OFFSET(r1)
/*
* Disable nested exception processing.
*/
mtspr nri, r0
SYNC
/*
* Restore rfi related settings
*/
lwz r4, SRR1_FRAME_OFFSET(r1)
lwz r3, SRR0_FRAME_OFFSET(r1)
lwz r2, GPR2_OFFSET(r1)
lwz r0, GPR0_OFFSET(r1)
mtsrr1 r4
mtsrr0 r3
lwz r4, GPR4_OFFSET(r1)
lwz r3, GPR3_OFFSET(r1)
addi r1,r1, EXCEPTION_FRAME_END
SYNC
rfi

View File

@@ -0,0 +1,152 @@
/*
* irq_init.c
*
* This file contains the implementation of rtems initialization
* related to interrupt handling.
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libbsp/powerpc/mbx8xx/irq/irq_init.c:
*
* CopyRight (C) 2001 valette@crf.canon.fr
*
* 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 <mpc5xx.h>
#include <libcpu/vectors.h>
#include <libcpu/raw_exception.h>
#include <libcpu/irq.h>
extern rtems_exception_handler_t dispatch_irq_handler;
volatile unsigned int ppc_cached_irq_mask;
/*
* default on/off function
*/
static void nop_func(){}
/*
* default isOn function
*/
static int not_connected() {return 0;}
/*
* default possible isOn function
*/
static int connected() {return 1;}
static rtems_irq_connect_data rtemsIrq[CPU_IRQ_COUNT];
static rtems_irq_global_settings initial_config;
static rtems_irq_connect_data defaultIrq = {
/* vector, hdl , on , off , isOn */
0, nop_func , nop_func , nop_func , not_connected
};
static rtems_irq_prio irqPrioTable[CPU_IRQ_COUNT]={
/*
* actual priorities for interrupt :
* 0 means that only current interrupt is masked
* 255 means all other interrupts are masked
*/
/*
* USIU interrupts.
*/
7,7, 6,6, 5,5, 4,4, 3,3, 2,2, 1,1, 0,0,
/*
* UIMB Interrupts
*
* Note that the first 8 UIMB interrupts overlap the 8 external USIU
* interrupts.
*/
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*
* Processor exceptions handled as interrupts
*/
0
};
void CPU_USIU_irq_init()
{
/*
* In theory we should initialize two registers at least : SIMASK and
* SIEL. SIMASK is reset at 0 value meaning no interrupts. If someone
* find a reasonnable value for SIEL, and the need to change it, please
* feel free to add it here.
*/
ppc_cached_irq_mask = 0;
usiu.simask = ppc_cached_irq_mask;
usiu.sipend = 0xffff0000;
usiu.siel = usiu.siel;
}
/*
* Initialize UIMB interrupt management
*/
void
CPU_UIMB_irq_init(void)
{
}
void CPU_rtems_irq_mng_init(unsigned cpuId)
{
rtems_raw_except_connect_data vectorDesc;
int i;
CPU_USIU_irq_init();
CPU_UIMB_irq_init();
/*
* Initialize Rtems management interrupt table
*/
/*
* re-init the rtemsIrq table
*/
for (i = 0; i < CPU_IRQ_COUNT; i++) {
rtemsIrq[i] = defaultIrq;
rtemsIrq[i].name = i;
}
/*
* Init initial Interrupt management config
*/
initial_config.irqNb = CPU_IRQ_COUNT;
initial_config.defaultEntry = defaultIrq;
initial_config.irqHdlTbl = rtemsIrq;
initial_config.irqBase = CPU_ASM_IRQ_VECTOR_BASE;
initial_config.irqPrioTbl = irqPrioTable;
if (!CPU_rtems_irq_mngt_set(&initial_config)) {
/*
* put something here that will show the failure...
*/
BSP_panic("Unable to initialize RTEMS interrupt Management\n");
}
/*
* We must connect the raw irq handler for the two
* expected interrupt sources : decrementer and external interrupts.
*/
vectorDesc.exceptIndex = ASM_DEC_VECTOR;
vectorDesc.hdl.vector = ASM_DEC_VECTOR;
vectorDesc.hdl.raw_hdl = dispatch_irq_handler;
vectorDesc.on = nop_func;
vectorDesc.off = nop_func;
vectorDesc.isOn = connected;
if (!mpc5xx_set_exception (&vectorDesc)) {
BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
}
vectorDesc.exceptIndex = ASM_EXT_VECTOR;
vectorDesc.hdl.vector = ASM_EXT_VECTOR;
if (!mpc5xx_set_exception (&vectorDesc)) {
BSP_panic("Unable to initialize RTEMS external raw exception\n");
}
}

View File

@@ -1,70 +1,118 @@
/* timer.c
*
* This file manages the benchmark timer used by the RTEMS Timing Test
* Suite. Each measured time period is demarcated by calls to
* Timer_initialize() and Read_timer(). Read_timer() usually returns
* the number of microseconds since Timer_initialize() exitted.
* This file manages the interval timer on the PowerPC MPC5xx.
* NOTE: This is not the PIT, but rather the RTEMS interval
* timer
* We shall use the bottom 32 bits of the timebase register,
*
* The following was in the 403 version of this file. I don't
* know what it means. JTM 5/19/98
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from c/src/lib/libcpu/powerpc/mpc8xx/timer/timer.c:
*
* Author: Jay Monkman (jmonkman@frasca.com)
* Copywright (C) 1998 by Frasca International, Inc.
*
* Derived from c/src/lib/libcpu/ppc/ppc403/timer/timer.c:
*
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of i-cubed limited not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
* Derived from c/src/lib/libcpu/hppa1_1/timer/timer.c:
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* All rights assigned to U.S. Government, 1994.
*
* This material may be reproduced by or for the U.S. Government pursuant
* to the copyright license under the clause at DFARS 252.227-7013. This
* notice must appear in all copies of this file and its derivatives.
* 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.
*
* timer.c,v 1.2 1995/05/31 16:56:39 joel Exp
* $Id$
*/
#include <rtems.h>
#include <mpc5xx.h>
rtems_boolean Timer_driver_Find_average_overhead;
static unsigned int volatile lastInitValue;
void Timer_initialize( void )
{
asm volatile( " mftb %0": "=r" (lastInitValue) );
}
static volatile rtems_unsigned32 Timer_starting;
static rtems_boolean Timer_driver_Find_average_overhead;
/*
* The following controls the behavior of Read_timer().
*
* AVG_OVEREHAD is the overhead for starting and stopping the timer. It
* is usually deducted from the number returned.
*
* LEAST_VALID is the lowest number this routine should trust. Numbers
* below this are "noise" and zero is returned.
* This is so small that this code will be reproduced where needed.
*/
#define AVG_OVERHEAD 0 /* It typically takes X.X microseconds */
/* (Y countdowns) to start/stop the timer. */
/* This value is in microseconds. */
#define LEAST_VALID 1 /* Don't trust a clicks value lower than this */
int Read_timer( void )
static inline rtems_unsigned32 get_itimer(void)
{
uint32_t value;
asm volatile ( " mftb %0": "=r" (value) );
return value - lastInitValue;
rtems_unsigned32 ret;
asm volatile ("mftb %0" : "=r" ((ret))); /* TBLO */
return ret;
}
/*
* Empty function call used in loops to measure basic cost of looping
* in Timing Test Suite.
*/
void Timer_initialize(void)
{
/* set interrupt level and enable timebase. This should never */
/* generate an interrupt however. */
usiu.tbscrk = USIU_UNLOCK_KEY;
usiu.tbscr |= USIU_TBSCR_TBIRQ(4) /* interrupt priority level */
| USIU_TBSCR_TBF /* freeze timebase during debug */
| USIU_TBSCR_TBE; /* enable timebase */
usiu.tbscrk = 0;
Timer_starting = get_itimer();
}
rtems_status_code Empty_function( void )
#ifndef rtems_cpu_configuration_get_timer_least_valid
#define rtems_cpu_configuration_get_timer_least_valid() 0
#endif
#ifndef rtems_cpu_configuration_get_timer_average_overhead
#define rtems_cpu_configuration_get_timer_average_overhead() 0
#endif
int Read_timer(void)
{
rtems_unsigned32 clicks;
rtems_unsigned32 total;
clicks = get_itimer();
total = clicks - Timer_starting;
if ( Timer_driver_Find_average_overhead == 1 )
return total; /* in XXX microsecond units */
else {
if ( total < rtems_cpu_configuration_get_timer_least_valid() ) {
return 0; /* below timer resolution */
}
return (total - rtems_cpu_configuration_get_timer_average_overhead());
}
}
rtems_status_code Empty_function(void)
{
return RTEMS_SUCCESSFUL;
}
void Set_find_average_overhead(
rtems_boolean find_flag
)
void Set_find_average_overhead(rtems_boolean find_flag)
{
Timer_driver_Find_average_overhead = find_flag;
}

View File

@@ -0,0 +1,203 @@
/*
* vectors.S
*
* This file contains the assembly code for the PowerPC exception veneers
* for RTEMS.
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libbsp/powerpc/mbx8xx/vectors/vectors.S,
*
* (c) 1999, Eric Valette valette@crf.canon.fr
*
* $Id$
*/
#include <asm.h>
#include <rtems/score/cpu.h>
#include <libcpu/vectors.h>
#define SYNC \
sync; \
isync
/*
* Hardware exception vector table.
*
* The MPC555 can be configured to use a compressed vector table with 8
* bytes per entry, rather than the usual 0x100 bytes of other PowerPC
* devices. The following macro uses this feature to save the better part
* of 8 kbytes of flash ROM.
*
* Each vector table entry has room for only a simple branch instruction
* which branches to a prologue specific to that exception. This
* exception-specific prologue begins the context save, loads the exception
* number into a register, and jumps to a common exception prologue, below.
*/
.macro vectors num=0, total=NUM_EXCEPTIONS /* create vector table */
/* vector table entry */
.section .vectors, "ax"
ba specific_prologue\@ /* run specific prologue */
.long 0 /* each entry is 8 bytes */
/* exception-specific prologue */
.text
specific_prologue\@:
stwu r1, -EXCEPTION_FRAME_END(r1) /* open stack frame */
stw r4, GPR4_OFFSET(r1) /* preserve register */
li r4, \num /* get exception number */
b common_prologue /* run common prologue */
/* invoke macro recursively to create remainder of table */
.if \total - (\num + 1)
vectors "(\num + 1)", \total
.endif
.endm
/* invoke macro to create entire vector table */
vectors
/*
* Common exception prologue.
*
* Because the MPC555 vector table is in flash ROM, it's not possible to
* change the exception handlers by overwriting them at run-time, so this
* common exception prologue uses a table of exception handler pointers to
* provide equivalent flexibility.
*
* When the actual exception handler is run, R1 points to the base of a new
* exception stack frame, in which R3, R4 and LR have been saved. R4 holds
* the exception number.
*/
.text
common_prologue:
stw r3, GPR3_OFFSET(r1) /* preserve registers */
mflr r3
stw r3, EXC_LR_OFFSET(r1)
slwi r3, r4, 2 /* make table offset */
addis r3, r3, exception_handler_table@ha /* point to entry */
addi r3, r3, exception_handler_table@l
lwz r3, 0(r3) /* get entry */
mtlr r3 /* run it */
blr
/*
* Default exception handler.
*
* The function initialize_exceptions() initializes all of the entries in
* the exception handler table with pointers to this routine, which saves
* the remainder of the interrupted code's state, then calls
* C_default_exception_handler() to dump registers.
*
* On entry, R1 points to a new exception stack frame in which R3, R4, and
* LR have been saved. R4 holds the exception number.
*/
.text
PUBLIC_VAR(default_exception_handler)
SYM (default_exception_handler):
/*
* Save the interrupted code's program counter and MSR. Beyond this
* point, all exceptions are recoverable. Use an RCPU-specific SPR
* to set the RI bit in the MSR to indicate the recoverable state.
*/
mfsrr0 r3
stw r3, SRR0_FRAME_OFFSET(r1)
mfsrr1 r3
stw r3, SRR1_FRAME_OFFSET(r1)
mtspr eid, r3 /* set MSR[RI], clear MSR[EE] */
SYNC
/*
* Save the remainder of the general-purpose registers.
*
* Compute the value of R1 at exception entry before storing it in
* the frame.
*
* Note that R2 should never change (it's the EABI pointer to
* .sdata2), but we save it just in case.
*
* Recall that R3 and R4 were saved by the specific- and
* common-exception handlers before entry to this routine.
*/
stw r0, GPR0_OFFSET(r1)
addi r0, r1, EXCEPTION_FRAME_END
stw r0, GPR1_OFFSET(r1)
stw r2, GPR2_OFFSET(r1)
stmw r5, GPR5_OFFSET(r1) /* save R5 to R31 */
/*
* Save the remainder of the UISA special-purpose registers. Recall
* that LR was saved before entry.
*/
mfcr r0
stw r0, EXC_CR_OFFSET(r1)
mfctr r0
stw r0, EXC_CTR_OFFSET(r1)
mfxer r0
stw r0, EXC_XER_OFFSET(r1)
/*
* Call C-language portion of the default exception handler, passing
* in the address of the frame.
*
* To simplify things a bit, we assume that the target routine is
* within +/- 32 Mbyte from here, which is a reasonable assumption
* on the MPC555.
*/
stw r4, EXCEPTION_NUMBER_OFFSET(r1) /* save exception number */
addi r3, r1, 0x8 /* get frame address */
bl C_default_exception_handler /* call handler */
/*
* Restore UISA special-purpose registers.
*/
lwz r0, EXC_XER_OFFSET(r1)
mtxer r0
lwz r0, EXC_CTR_OFFSET(r1)
mtctr r0
lwz r0, EXC_CR_OFFSET(r1)
mtcr r0
lwz r0, EXC_LR_OFFSET(r1)
mtlr r0
/*
* Restore most general-purpose registers.
*/
lmw r2, GPR2_OFFSET(r1)
/*
* Restore the interrupted code's program counter and MSR, but first
* use an RCPU-specific special-purpose register to clear the RI
* bit, indicating that exceptions are temporarily non-recoverable.
*/
mtspr nri, r0 /* clear MSR[RI] */
SYNC
lwz r0, SRR1_FRAME_OFFSET(r1)
mtsrr1 r0
lwz r0, SRR0_FRAME_OFFSET(r1)
mtsrr0 r0
/*
* Restore the final GPR, close the stack frame, and return to the
* interrupted code.
*/
lwz r0, GPR0_OFFSET(r1)
addi r1, r1, EXCEPTION_FRAME_END
SYNC
rfi

View File

@@ -0,0 +1,156 @@
/*
* vectors.h Exception frame related contant and API.
*
* This include file describe the data structure and the functions implemented
* by rtems to handle exceptions.
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libbsp/powerpc/mbx8xx/vectors/vectors.h:
*
* CopyRight (C) 1999 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifndef LIBCPU_POWERPC_MBX5XX_VECTORS_H
#define LIBCPU_POWERPC_MBX5XX_VECTORS_H
/*
* Size of hardware vector table.
*/
#define NUM_EXCEPTIONS 0x20
/*
* The callee (high level exception code written in C)
* will store the Link Registers (return address) at entry r1 + 4 !!!.
* So let room for it!!!.
*/
#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4
#define SRR0_FRAME_OFFSET 8
#define SRR1_FRAME_OFFSET 12
#define EXCEPTION_NUMBER_OFFSET 16
#define GPR0_OFFSET 20
#define GPR1_OFFSET 24
#define GPR2_OFFSET 28
#define GPR3_OFFSET 32
#define GPR4_OFFSET 36
#define GPR5_OFFSET 40
#define GPR6_OFFSET 44
#define GPR7_OFFSET 48
#define GPR8_OFFSET 52
#define GPR9_OFFSET 56
#define GPR10_OFFSET 60
#define GPR11_OFFSET 64
#define GPR12_OFFSET 68
#define GPR13_OFFSET 72
#define GPR14_OFFSET 76
#define GPR15_OFFSET 80
#define GPR16_OFFSET 84
#define GPR17_OFFSET 88
#define GPR18_OFFSET 92
#define GPR19_OFFSET 96
#define GPR20_OFFSET 100
#define GPR21_OFFSET 104
#define GPR22_OFFSET 108
#define GPR23_OFFSET 112
#define GPR24_OFFSET 116
#define GPR25_OFFSET 120
#define GPR26_OFFSET 124
#define GPR27_OFFSET 128
#define GPR28_OFFSET 132
#define GPR29_OFFSET 136
#define GPR30_OFFSET 140
#define GPR31_OFFSET 144
#define EXC_CR_OFFSET 148
#define EXC_CTR_OFFSET 152
#define EXC_XER_OFFSET 156
#define EXC_LR_OFFSET 160
#define EXC_DAR_OFFSET 164
/*
* maintain the EABI requested 8 bytes aligment
* As SVR4 ABI requires 16, make it 16 (as some
* exception may need more registers to be processed...)
*/
#define EXCEPTION_FRAME_END 176
#ifndef ASM
/*
* default raw exception handlers
*/
extern void default_exception_vector_code_prolog();
extern int default_exception_vector_code_prolog_size;
extern void initialize_exceptions();
typedef struct {
unsigned EXC_SRR0;
unsigned EXC_SRR1;
unsigned _EXC_number;
unsigned GPR0;
unsigned GPR1;
unsigned GPR2;
unsigned GPR3;
unsigned GPR4;
unsigned GPR5;
unsigned GPR6;
unsigned GPR7;
unsigned GPR8;
unsigned GPR9;
unsigned GPR10;
unsigned GPR11;
unsigned GPR12;
unsigned GPR13;
unsigned GPR14;
unsigned GPR15;
unsigned GPR16;
unsigned GPR17;
unsigned GPR18;
unsigned GPR19;
unsigned GPR20;
unsigned GPR21;
unsigned GPR22;
unsigned GPR23;
unsigned GPR24;
unsigned GPR25;
unsigned GPR26;
unsigned GPR27;
unsigned GPR28;
unsigned GPR29;
unsigned GPR30;
unsigned GPR31;
unsigned EXC_CR;
unsigned EXC_CTR;
unsigned EXC_XER;
unsigned EXC_LR;
unsigned EXC_MSR;
unsigned EXC_DAR;
}CPU_Exception_frame;
typedef void rtems_exception_handler_t (CPU_Exception_frame* excPtr);
/*DEBUG typedef rtems_exception_handler_t cpuExcHandlerType; */
/*
* Exception handler table.
*
* This table contains pointers to assembly-language exception handlers.
* The common exception prologue in vectors.S looks up an entry in this
* table and jumps to it. No return address is saved, so the handlers in
* this table must return directly to the interrupted code.
*
* On entry to an exception handler, R1 points to a new exception stack
* frame in which R3, R4, and LR have been saved. R4 holds the exception
* number.
*/
extern rtems_exception_handler_t* exception_handler_table[NUM_EXCEPTIONS];
#endif /* ASM */
#endif /* LIBCPU_POWERPC_MPC5XX_VECTORS_H */

View File

@@ -0,0 +1,137 @@
/*
* vectors_init.c Exception hanlding initialisation (and generic handler).
*
* This include file describe the data structure and the functions implemented
* by rtems to handle exceptions.
*
*
* MPC5xx port sponsored by Defence Research and Development Canada - Suffield
* Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
*
* Derived from libbsp/powerpc/mbx8xx/vectors/vectors_init.c:
*
* CopyRight (C) 1999 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#include <rtems/bspIo.h>
#include <libcpu/vectors.h>
#include <libcpu/raw_exception.h>
extern rtems_exception_handler_t default_exception_handler;
static rtems_raw_except_global_settings exception_config;
static rtems_raw_except_connect_data exception_table[NUM_EXCEPTIONS];
rtems_exception_handler_t* exception_handler_table[NUM_EXCEPTIONS];
void C_default_exception_handler(CPU_Exception_frame* excPtr)
{
int recoverable = 0;
printk("exception handler called for exception %d\n", excPtr->_EXC_number);
printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0);
printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1);
printk("\t R0 = %x\n", excPtr->GPR0);
printk("\t R1 = %x\n", excPtr->GPR1);
printk("\t R2 = %x\n", excPtr->GPR2);
printk("\t R3 = %x\n", excPtr->GPR3);
printk("\t R4 = %x\n", excPtr->GPR4);
printk("\t R5 = %x\n", excPtr->GPR5);
printk("\t R6 = %x\n", excPtr->GPR6);
printk("\t R7 = %x\n", excPtr->GPR7);
printk("\t R8 = %x\n", excPtr->GPR8);
printk("\t R9 = %x\n", excPtr->GPR9);
printk("\t R10 = %x\n", excPtr->GPR10);
printk("\t R11 = %x\n", excPtr->GPR11);
printk("\t R12 = %x\n", excPtr->GPR12);
printk("\t R13 = %x\n", excPtr->GPR13);
printk("\t R14 = %x\n", excPtr->GPR14);
printk("\t R15 = %x\n", excPtr->GPR15);
printk("\t R16 = %x\n", excPtr->GPR16);
printk("\t R17 = %x\n", excPtr->GPR17);
printk("\t R18 = %x\n", excPtr->GPR18);
printk("\t R19 = %x\n", excPtr->GPR19);
printk("\t R20 = %x\n", excPtr->GPR20);
printk("\t R21 = %x\n", excPtr->GPR21);
printk("\t R22 = %x\n", excPtr->GPR22);
printk("\t R23 = %x\n", excPtr->GPR23);
printk("\t R24 = %x\n", excPtr->GPR24);
printk("\t R25 = %x\n", excPtr->GPR25);
printk("\t R26 = %x\n", excPtr->GPR26);
printk("\t R27 = %x\n", excPtr->GPR27);
printk("\t R28 = %x\n", excPtr->GPR28);
printk("\t R29 = %x\n", excPtr->GPR29);
printk("\t R30 = %x\n", excPtr->GPR30);
printk("\t R31 = %x\n", excPtr->GPR31);
printk("\t CR = %x\n", excPtr->EXC_CR);
printk("\t CTR = %x\n", excPtr->EXC_CTR);
printk("\t XER = %x\n", excPtr->EXC_XER);
printk("\t LR = %x\n", excPtr->EXC_LR);
printk("\t MSR = %x\n", excPtr->EXC_MSR);
if (excPtr->_EXC_number == ASM_DEC_VECTOR)
recoverable = 1;
if (excPtr->_EXC_number == ASM_SYS_VECTOR)
#ifdef TEST_RAW_EXCEPTION_CODE
recoverable = 1;
#else
recoverable = 0;
#endif
if (!recoverable) {
printk("unrecoverable exception!!! Push reset button\n");
while(1);
}
}
void nop_except_enable(const rtems_raw_except_connect_data* ptr)
{
}
int except_always_enabled(const rtems_raw_except_connect_data* ptr)
{
return 1;
}
void initialize_exceptions()
{
int i;
/*
* Initialize all entries of the exception table with a description of the
* default exception handler.
*/
exception_config.exceptSize = NUM_EXCEPTIONS;
exception_config.rawExceptHdlTbl = &exception_table[0];
exception_config.defaultRawEntry.exceptIndex = 0;
exception_config.defaultRawEntry.hdl.vector = 0;
exception_config.defaultRawEntry.hdl.raw_hdl = default_exception_handler;
for (i = 0; i < exception_config.exceptSize; i++) {
printk("installing exception number %d\n", i);
exception_table[i].exceptIndex = i;
exception_table[i].hdl = exception_config.defaultRawEntry.hdl;
exception_table[i].hdl.vector = i;
exception_table[i].on = nop_except_enable;
exception_table[i].off = nop_except_enable;
exception_table[i].isOn = except_always_enabled;
}
/*
* Now pass the initialized exception table to the exceptions module which
* will install the handler pointers in the exception handler table.
*/
if (!mpc5xx_init_exceptions(&exception_config)) {
/*
* At this stage we may not call CPU_Panic because it uses exceptions!!!
*/
printk("Exception handling initialization failed\n");
printk("System locked\n"); while(1);
}
else {
printk("Exception handling initialization done\n");
}
}

View File

@@ -21,20 +21,6 @@ typedef enum
{
PPC_601 = 0x1,
PPC_5XX = 0x2,
PPC_509 = PPC_5XX,
PPC_533 = PPC_5XX,
PPC_534 = PPC_5XX,
PPC_535 = PPC_5XX,
PPC_536 = PPC_5XX,
PPC_555 = PPC_5XX,
PPC_556 = PPC_5XX,
PPC_561 = PPC_5XX,
PPC_562 = PPC_5XX,
PPC_563 = PPC_5XX,
PPC_564 = PPC_5XX,
PPC_565 = PPC_5XX,
PPC_566 = PPC_5XX,
MPC_5XX = PPC_5XX,
PPC_603 = 0x3,
PPC_604 = 0x4,
PPC_603e = 0x6,