forked from Imagelibrary/rtems
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:
@@ -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>.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" \
|
||||
|
||||
@@ -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
|
||||
|
||||
27
c/src/lib/libcpu/powerpc/mpc5xx/README
Normal file
27
c/src/lib/libcpu/powerpc/mpc5xx/README
Normal 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.
|
||||
196
c/src/lib/libcpu/powerpc/mpc5xx/clock/clock.c
Normal file
196
c/src/lib/libcpu/powerpc/mpc5xx/clock/clock.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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,19 +31,18 @@
|
||||
#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)
|
||||
int mpc5xx_vector_is_valid(rtems_vector vector)
|
||||
{
|
||||
switch (current_ppc_cpu) {
|
||||
case PPC_5XX:
|
||||
switch(vector) {
|
||||
case ASM_RESET_VECTOR: /* fall through */
|
||||
case ASM_RESET_VECTOR:
|
||||
case ASM_MACH_VECTOR:
|
||||
case ASM_PROT_VECTOR:
|
||||
case ASM_ISI_VECTOR:
|
||||
|
||||
case ASM_EXT_VECTOR:
|
||||
case ASM_ALIGN_VECTOR:
|
||||
case ASM_PROG_VECTOR:
|
||||
@@ -54,32 +55,22 @@ int mpc565_vector_is_valid(rtems_vector vector)
|
||||
|
||||
case ASM_SOFTEMUL_VECTOR:
|
||||
|
||||
case ASM_ITLBERROR_VECTOR:
|
||||
case ASM_DTLBERROR_VECTOR:
|
||||
case ASM_IPROT_VECTOR:
|
||||
case ASM_DPROT_VECTOR:
|
||||
|
||||
case ASM_DBREAK_VECTOR:
|
||||
case ASM_IBREAK_VECTOR:
|
||||
case ASM_PERIFBREAK_VECTOR:
|
||||
case ASM_DEVPORT_VECTOR:
|
||||
case ASM_MEBREAK_VECTOR:
|
||||
case ASM_NMEBREAK_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)) {
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
int mpc5xx_set_exception (const rtems_raw_except_connect_data* except)
|
||||
@@ -96,17 +87,16 @@ int mpc5xx_set_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*)default_raw_except_entry.hdl.raw_hdl,default_raw_except_entry.hdl.raw_hdl_size)) {
|
||||
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);
|
||||
raw_except_table[except->exceptIndex] = *except;
|
||||
|
||||
exception_handler_table[except->exceptIndex] = except->hdl.raw_hdl;
|
||||
except->on(except);
|
||||
|
||||
_CPU_ISR_Enable(level);
|
||||
@@ -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,19 +128,15 @@ 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)) {
|
||||
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,6 +148,9 @@ 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)
|
||||
{
|
||||
@@ -177,14 +166,9 @@ int mpc5xx_init_exceptions (rtems_raw_except_global_settings* config)
|
||||
|
||||
_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);
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -2,39 +2,41 @@
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -47,43 +49,15 @@
|
||||
|
||||
#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_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
|
||||
|
||||
|
||||
37
c/src/lib/libcpu/powerpc/mpc5xx/include/console.h
Normal file
37
c/src/lib/libcpu/powerpc/mpc5xx/include/console.h
Normal 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_ */
|
||||
621
c/src/lib/libcpu/powerpc/mpc5xx/include/mpc5xx.h
Normal file
621
c/src/lib/libcpu/powerpc/mpc5xx/include/mpc5xx.h
Normal 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 */
|
||||
|
||||
495
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c
Normal file
495
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c
Normal 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...
|
||||
*/
|
||||
}
|
||||
358
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.h
Normal file
358
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.h
Normal 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
|
||||
325
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq_asm.S
Normal file
325
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq_asm.S
Normal 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
|
||||
|
||||
152
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq_init.c
Normal file
152
c/src/lib/libcpu/powerpc/mpc5xx/irq/irq_init.c
Normal 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");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
rtems_status_code Empty_function( void )
|
||||
Timer_starting = get_itimer();
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
203
c/src/lib/libcpu/powerpc/mpc5xx/vectors/vectors.S
Normal file
203
c/src/lib/libcpu/powerpc/mpc5xx/vectors/vectors.S
Normal 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
|
||||
156
c/src/lib/libcpu/powerpc/mpc5xx/vectors/vectors.h
Normal file
156
c/src/lib/libcpu/powerpc/mpc5xx/vectors/vectors.h
Normal 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 */
|
||||
137
c/src/lib/libcpu/powerpc/mpc5xx/vectors/vectors_init.c
Normal file
137
c/src/lib/libcpu/powerpc/mpc5xx/vectors/vectors_init.c
Normal 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");
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user