From 0074691a67f857c9b3f880fb581e0af1d5673337 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 31 Jul 1997 22:13:29 +0000 Subject: Merged very large and much appreciated patch from Chris Johns . This patch includes the ods68302 bsp, the RTEMS++ class library, and the rtems++ test. --- c/src/lib/libbsp/m68k/ods68302/startup/Makefile.in | 59 ++ c/src/lib/libbsp/m68k/ods68302/startup/bspclean.c | 26 + c/src/lib/libbsp/m68k/ods68302/startup/bspstart.c | 263 +++++ c/src/lib/libbsp/m68k/ods68302/startup/cpuboot.c | 133 +++ c/src/lib/libbsp/m68k/ods68302/startup/crc.c | 88 ++ c/src/lib/libbsp/m68k/ods68302/startup/debugger | 54 + c/src/lib/libbsp/m68k/ods68302/startup/debugport.c | 163 +++ c/src/lib/libbsp/m68k/ods68302/startup/gdb-hooks.c | 76 ++ c/src/lib/libbsp/m68k/ods68302/startup/linkcmds | 55 + c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c | 159 +++ c/src/lib/libbsp/m68k/ods68302/startup/m68k-stub.c | 1084 ++++++++++++++++++++ c/src/lib/libbsp/m68k/ods68302/startup/memcheck.c | 33 + c/src/lib/libbsp/m68k/ods68302/startup/rom | 56 + c/src/lib/libbsp/m68k/ods68302/startup/trace.c | 175 ++++ 14 files changed, 2424 insertions(+) create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/Makefile.in create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/bspclean.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/bspstart.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/cpuboot.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/crc.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/debugger create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/debugport.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/gdb-hooks.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/linkcmds create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/m68k-stub.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/memcheck.c create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/rom create mode 100644 c/src/lib/libbsp/m68k/ods68302/startup/trace.c (limited to 'c/src/lib/libbsp/m68k/ods68302/startup') diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/Makefile.in b/c/src/lib/libbsp/m68k/ods68302/startup/Makefile.in new file mode 100644 index 0000000000..6db40dbea9 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/Makefile.in @@ -0,0 +1,59 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH=@srcdir@:@srcdir@/../../shared:@srcdir@/../../../shared + +PGM=${ARCH}/startup.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=crc debugport gdb-hooks m68302scc m68k-stub memcheck trace \ + bspstart bspclean sbrk setvec +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +SRCS=$(C_FILES) $(H_FILES) $(srcdir)/rom $(srcdir)/debugger +OBJS=$(C_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +$(srcdir)/rom: + +$(srcdir)/debugger: + +all: ${ARCH} $(SRCS) $(PGM) + $(INSTALL) $(srcdir)/rom $(srcdir)/debugger ${PROJECT_RELEASE}/lib + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/bspclean.c b/c/src/lib/libbsp/m68k/ods68302/startup/bspclean.c new file mode 100644 index 0000000000..90f64272a3 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/bspclean.c @@ -0,0 +1,26 @@ +/* bsp_cleanup() + * + * This routine normally is part of start.s and usually returns + * control to a monitor. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include + +void bsp_cleanup( void ) +{ +} diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/bspstart.c b/c/src/lib/libbsp/m68k/ods68302/startup/bspstart.c new file mode 100644 index 0000000000..c3c7bd538b --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/bspstart.c @@ -0,0 +1,263 @@ +/* bsp_start() + * + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include + +#include + +#include +#include + +#ifdef STACK_CHECKER_ON +#include +#endif + +/* + * The original table from the application and our copy of it with + * some changes. + */ + +extern rtems_configuration_table Configuration; +rtems_configuration_table BSP_Configuration; + +rtems_cpu_table Cpu_table; +rtems_interrupt_level bsp_isr_level; + +char *rtems_progname; + +/* Initialize whatever libc we are using + * called from postdriver hook + */ + +void bsp_libc_init() +{ + extern int end; + rtems_unsigned32 heap_start; + + heap_start = (rtems_unsigned32) &end; + if (heap_start & (CPU_ALIGNMENT-1)) + heap_start = (heap_start + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1); + + /* + * The last parameter to RTEMS_Malloc_Initialize is the "chunk" + * size which a multiple of will be requested on each sbrk() + * call by malloc(). A value of 0 indicates that sbrk() should + * not be called to extend the heap. + */ + + RTEMS_Malloc_Initialize((void *) heap_start, 64 * 1024, 0); + + /* + * Init the RTEMS libio facility to provide UNIX-like system + * calls for use by newlib (ie: provide __rtems_open, __rtems_close, etc) + * Uses malloc() to get area for the iops, so must be after malloc init + */ + + rtems_libio_init(); + + /* + * Set up for the libc handling. + */ + + if (BSP_Configuration.ticks_per_timeslice > 0) + libc_init(1); /* reentrant if possible */ + else + libc_init(0); /* non-reentrant */ +} + +/* + * Function: bsp_pretasking_hook + * Created: 95/03/10 + * + * Description: + * BSP pretasking hook. Called just before drivers are initialized. + * Used to setup libc and install any BSP extensions. + * + * NOTES: + * Must not use libc (to do io) from here, since drivers are + * not yet initialized. + * + */ + +void +bsp_pretasking_hook(void) +{ + bsp_libc_init(); + +#ifdef STACK_CHECKER_ON + /* + * Initialize the stack bounds checker + * We can either turn it on here or from the app. + */ + + Stack_check_Initialize(); +#endif + +#ifdef RTEMS_DEBUG + rtems_debug_enable( RTEMS_DEBUG_ALL_MASK ); +#endif +} + + +/* + * After drivers are setup, register some "filenames" + * and open stdin, stdout, stderr files + * + * Newlib will automatically associate the files with these + * (it hardcodes the numbers) + */ + +void +bsp_postdriver_hook(void) +{ + int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; + + if ((stdin_fd = __rtems_open("/dev/console", O_RDONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); + + if ((stdout_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); + + if ((stderr_fd = __rtems_open("/dev/console", O_WRONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); + + if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); +} + +void bsp_start() +{ + /* + * Allocate the memory for the RTEMS Work Space. This can come from + * a variety of places: hard coded address, malloc'ed from outside + * RTEMS world (e.g. simulator or primitive memory manager), or (as + * typically done by stock BSPs) by subtracting the required amount + * of work space from the last physical address on the CPU board. + */ +#if 0 + Cpu_table.interrupt_vector_table = (mc68000_isr *) 0/*&M68Kvec*/; +#endif + + + /* + * Copy the Configuration Table .. so we can change it + */ + + BSP_Configuration = Configuration; + + /* + * Add 1 region for the RTEMS Malloc + */ + + BSP_Configuration.RTEMS_api_configuration->maximum_regions++; + + /* + * Add 1 extension for newlib libc + */ + +#ifdef RTEMS_NEWLIB + BSP_Configuration.maximum_extensions++; +#endif + + /* + * Add another extension if using the stack checker + */ + +#ifdef STACK_CHECKER_ON + BSP_Configuration.maximum_extensions++; +#endif + + /* + * Tell libio how many fd's we want and allow it to tweak config + */ + + rtems_libio_config(&BSP_Configuration, BSP_LIBIO_MAX_FDS); + + /* + * Need to "allocate" the memory for the RTEMS Workspace and + * tell the RTEMS configuration where it is. This memory is + * not malloc'ed. It is just "pulled from the air". + */ + + BSP_Configuration.work_space_start = (void *) + (RAM_END - BSP_Configuration.work_space_size); + + /* + * initialize the CPU table for this BSP + */ + + /* + * we do not use the pretasking_hook + */ + + Cpu_table.pretasking_hook = bsp_pretasking_hook; /* init libc, etc. */ + + Cpu_table.predriver_hook = NULL; + + Cpu_table.postdriver_hook = bsp_postdriver_hook; + + Cpu_table.idle_task = NULL; /* do not override system IDLE task */ + + Cpu_table.do_zero_of_workspace = TRUE; + + Cpu_table.interrupt_stack_size = 4096; + + Cpu_table.extra_mpci_receive_server_stack = 0; + + /* + * Don't forget the other CPU Table entries. + */ + + /* + * Start RTEMS + */ + + bsp_isr_level = rtems_initialize_executive_early( &BSP_Configuration, &Cpu_table ); +} + +int main(int argc, char **argv, char **environ) +{ + if ((argc > 0) && argv && argv[0]) + rtems_progname = argv[0]; + else + rtems_progname = "RTEMS"; + + rtems_initialize_executive_late( bsp_isr_level ); + + bsp_cleanup(); + + return 0; +} + +void boot_bsp() +{ + /* the atexit hook will be before the static destructor list's entry + point */ + bsp_start(); + + exit(main(0, 0, 0)); +} + diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/cpuboot.c b/c/src/lib/libbsp/m68k/ods68302/startup/cpuboot.c new file mode 100644 index 0000000000..1a8f9bd2cf --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/cpuboot.c @@ -0,0 +1,133 @@ +/*****************************************************************************/ +/* + Boot the CPU. + + Occurs in 3 phases for a 68302. + + Phase 1. + + Called as soon as able after reset. The BAR has been programed, and + a small stack exists in the DPRAM. All interrupts are masked, and + the processor is running in supervisor mode. No other hardware or + chip selects are active. + + This phase programs the chip select registers, the parallel ports + are set into default configurations, and basic registers cleared or + reset. The leds are programmed to show the end of phase 1. + + Phase 2. + + This is a piece of code which is copied to DPRAM and executed. It + should not do any more thann is currently present. The return to ROM + is managed by modifing the return address. Again leds show the status. + + Phase 3. + + This code executes with a valid C environment. That is the data + section has been intialised and the bss section set to 0. This phase + performs any special card initialisation and then calls boot card. + + $Id$ + +*/ +/*****************************************************************************/ + +#include +#include +#include +#include + +/* + Open the address, reset all registers + */ + +void boot_phase_1() +{ + M302_SCR = SCR_DEFAULT; + + WRITE_OR(CSEL_ROM, ROM_SIZE, ROM_WAIT_STATES, OR_MASK_RW, OR_MASK_FC); + WRITE_BR(CSEL_ROM, RAM_BASE, BR_READ_ONLY, BR_FC_NULL, BR_ENABLED); + WRITE_OR(CSEL_RAM, RAM_SIZE, RAM_WAIT_STATES, OR_MASK_RW, OR_MASK_FC); + WRITE_BR(CSEL_RAM, ROM_BASE, BR_READ_WRITE, BR_FC_NULL, BR_ENABLED); + +#if defined(CSEL_1) + WRITE_OR(CSEL_1, CSEL_1_SIZE, CSEL_1_WAIT_STATES, OR_MASK_RW, OR_MASK_FC); + WRITE_BR(CSEL_1, CSEL_1_BASE, BR_READ_WRITE, BR_FC_NULL, BR_ENABLED); +#endif + +#if defined(CSEL_2) + WRITE_OR(CSEL_2, CSEL_2_SIZE, CSEL_2_WAIT_STATES, OR_MASK_RW, OR_MASK_FC); + WRITE_BR(CSEL_2, CSEL_2_BASE, BR_READ_WRITE, BR_FC_NULL, BR_ENABLED); +#endif + + m302.reg.gimr = m302.reg.ipr = m302.reg.imr = m302.reg.isr = 0; + + m302.reg.simode = 0; + + m302.reg.pacnt = CARD_PA_CONFIGURATION; + m302.reg.paddr = CARD_PA_DEFAULT_DIRECTIONS; + m302.reg.padat = CARD_PA_DEFAULT_DATA; + + m302.reg.pbcnt = CARD_PB_CONFIGURATION; + m302.reg.pbddr = CARD_PB_DEFAULT_DIRECTIONS; + m302.reg.pbdat = CARD_PB_DEFAULT_DATA; + + m302.reg.wrr = WATCHDOG_TIMEOUT_PERIOD | WATCHDOG_ENABLE; + +#if defined(LED_CONTROL) + LED_CONTROL(LED_1_RED, LED_2_OFF, LED_3_OFF, LED_4_OFF, + LED_5_OFF, LED_6_OFF, LED_7_OFF, LED_8_OFF); +#endif +} + +/* + Swap the chip select mapping for ROM and RAM + */ + +void boot_phase_2(void) +{ + rtems_unsigned32 stack; + +#if defined(LED_CONTROL) + LED_CONTROL(LED_1_RED, LED_2_RED, LED_3_OFF, LED_4_OFF, + LED_5_OFF, LED_6_OFF, LED_7_OFF, LED_8_OFF); +#endif + + WRITE_BR(CSEL_ROM, ROM_BASE, BR_READ_ONLY, BR_FC_NULL, BR_ENABLED); + WRITE_BR(CSEL_RAM, RAM_BASE, BR_READ_WRITE, BR_FC_NULL, BR_ENABLED); + +#if defined(LED_CONTROL) + LED_CONTROL(LED_1_GREEN, LED_2_RED, LED_3_OFF, LED_4_OFF, + LED_5_OFF, LED_6_OFF, LED_7_OFF, LED_8_OFF); +#endif + + /* seems to want 2, looked at assember code output */ + *(&stack + 2) |= ROM_BASE; +} + +/* + Any pre-main initialisation, the C environment is setup, how-ever C++ + static constructors have not been called, and RTEMS is not initialised. + */ + +void boot_bsp(); +void set_debug_traps(); +void breakpoint(); + +void boot_phase_3(void) +{ + if (GDB_RUN_MONITOR()) + { + set_debug_traps(); + breakpoint(); + } + + debug_port_banner(); + + /* FIXME : add RAM and ROM checks */ + + /* boot the bsp, what ever this means */ + boot_bsp(); + + WATCHDOG_TRIGGER(); +} diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/crc.c b/c/src/lib/libbsp/m68k/ods68302/startup/crc.c new file mode 100644 index 0000000000..b589ccd2ba --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/crc.c @@ -0,0 +1,88 @@ +/*****************************************************************************/ +/* + $Id$ + + CRC 16 Calculation + + This module calculates the CRC-16. + + */ +/*****************************************************************************/ + +#include "bsp.h" +#include "m68302.h" +#include "crc.h" + + /* ---- + C O N S T A N T S + + */ + +static const rtems_unsigned16 factor[] = + { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 + }; + +/* + MACRO : calculates a CRC byte wise + */ + +#define NEW_CRC(byte, crc) factor[(byte) ^ ((crc) & 0xFF)] ^ (((crc) >> 8) & 0xFF) + +/* ---- + CalcCRC + + Calculates the CRC value of a block of memory +*/ + +rtems_unsigned16 calc_crc(void* vdata, /* pointer to memory block */ + rtems_unsigned32 count) /* length of block in bytes */ +{ + register rtems_unsigned8 *data = vdata; + register rtems_unsigned16 crc; + register rtems_unsigned32 byte; + + /* initialise to either 0x0 or 0xffff depending on the + CRC implementation */ + + crc = 0; + + for (byte = count; byte > 0; byte--) + { + WATCHDOG_TOGGLE(); + crc = NEW_CRC(*data++, crc); + } + + return crc; +} diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/debugger b/c/src/lib/libbsp/m68k/ods68302/startup/debugger new file mode 100644 index 0000000000..6009868468 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/debugger @@ -0,0 +1,54 @@ +/* + * $Id$ + * + * MC68302 Linker command file + * + */ + +SECTIONS +{ + .text . : + { + text_start = .; + *(.text) + etext = .; + . = ALIGN(4); + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + . = ALIGN(4); + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + } + + .vtable (ADDR(.text) + SIZEOF(.text)) : + { + vtable_start = .; + *(.vtable) + evtable = .; + } + .data (ADDR(.vtable) + SIZEOF(.vtable)) : + { + data_start = .; + *(.data) + edata = .; + } + .bss (ADDR(.data) + SIZEOF(.data)) : + { + bss_start = .; + *(.bss) + *(COMMON) + end = . ; + _end = . ; + } +} + +m302 = MC68302_BASE; +_VBR = 0; /* location of the VBR table (in RAM) */ + +ENTRY(start); diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/debugport.c b/c/src/lib/libbsp/m68k/ods68302/startup/debugport.c new file mode 100644 index 0000000000..b4616152a3 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/debugport.c @@ -0,0 +1,163 @@ +/*****************************************************************************/ +/* + High Level Debug Port Functions + + $Id$ + + */ +/*****************************************************************************/ + +#include +#include + +#include "debugport.h" +#include "m68302scc.h" +#include "bsp.h" + +static int initialised; + +void debug_port_initialise(void) +{ + scc_initialise(CONSOLE_PORT, CONSOLE_BAUD, FALSE); +#if defined(DEBUG_PORT) + scc_initialise(DEBUG_PORT, DEBUG_BAUD, FALSE); +#endif +} + +unsigned char debug_port_status(const unsigned char status) +{ + if (!initialised) + { + initialised = 1; + debug_port_initialise(); + } + + return scc_status(CONSOLE_PORT, status); +} + +unsigned char debug_port_in(void) +{ + if (!initialised) + { + initialised = 1; + debug_port_initialise(); + } + + return scc_in(CONSOLE_PORT); +} + +void debug_port_out(const unsigned char character) +{ + if (!initialised) + { + initialised = 1; + debug_port_initialise(); + } + + scc_out(CONSOLE_PORT, character); +} + +void debug_port_write(const char *buffer) +{ + while (*buffer != '\0') + { + debug_port_out(*buffer++); + } +} + +void debug_port_write_buffer(const char *buffer, unsigned int size) +{ + unsigned int count; + for (count = 0; count < size; count++) + { + debug_port_out(buffer[count]); + } +} + +void debug_port_write_hex_uint(const unsigned int value) +{ + unsigned int bits = sizeof(value) * 8; + unsigned char c; + + do + { + bits -= 4; + c = (unsigned char) ((value >> bits) & 0x0F); + if (c < 10) + { + c += '0'; + } + else + { + c += 'a' - 10; + } + debug_port_out((char) c); + } + while (bits); +} + +void debug_port_write_hex_ulong(const unsigned long value) +{ + unsigned int bits = sizeof(value) * 8; + unsigned char c; + + do + { + bits -= 4; + c = (unsigned char) ((value >> bits) & 0x0F); + if (c < 10) + { + c += '0'; + } + else + { + c += 'a' - 10; + } + debug_port_out((char) c); + } + while (bits); +} + +#define BUFFER_SIZE (256) +static char buffer[BUFFER_SIZE]; + +void debug_port_printf(const char *format, ...) +{ + va_list args; + int written; + + /* gain access to the argument list */ + va_start(args, format); + + /* set the trap */ + buffer[BUFFER_SIZE - 2] = '\xAA'; + buffer[BUFFER_SIZE - 1] = '\x55'; + + /* format the string and send to stdout */ + written = vsprintf(buffer, format, args); + + /* try an trap format buffer overflows */ + if ((buffer[BUFFER_SIZE - 2] != '\xAA') || + (buffer[BUFFER_SIZE - 1] != '\x55')) + { + debug_port_write("debug port buffer overflow, halting..."); + DISABLE_WATCHDOG(); + while (1 == 1); + } + + /* see if an error occurred, if not flush the output buffer */ + if (written != -1) + { + debug_port_write_buffer(buffer, written); + } +} + +void debug_port_banner(void) +{ +#define CARD_LABEL "ods68302-" #VARIANT + + debug_port_write("\n\n\r"); + debug_port_write(_Copyright_Notice); + debug_port_write("\n\r " CARD_ID "\n\r"); +} + diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/gdb-hooks.c b/c/src/lib/libbsp/m68k/ods68302/startup/gdb-hooks.c new file mode 100644 index 0000000000..64d220219f --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/gdb-hooks.c @@ -0,0 +1,76 @@ +/*****************************************************************************/ +/* + $Id$ + + Hooks for GDB + + */ +/*****************************************************************************/ + + +#include +#include +#include + +static int initialised = 0; + +void putDebugChar(char ch) +{ + if (!initialised) + { + scc_initialise(DEBUG_PORT, DEBUG_BAUD, 0); + initialised = 1; + } + + scc_out(DEBUG_PORT, ch); +} + +char getDebugChar(void) +{ + if (!initialised) + { + scc_initialise(DEBUG_PORT, DEBUG_BAUD, 0); + initialised = 1; + } + + while (!scc_status(DEBUG_PORT, 0)); + + return scc_in(DEBUG_PORT); +} + +/* + * Need to create yet another jump table for gdb this time + */ + +void (*exceptionHook)(unsigned int) = 0; + +typedef struct { + rtems_unsigned16 move_a7; /* move #FORMAT_ID,%a7@- */ + rtems_unsigned16 format_id; + rtems_unsigned16 jmp; /* jmp _ISR_Handlers */ + rtems_unsigned32 isr_handler; +} GDB_HANDLER_ENTRY; + +#if !defined(M68K_MOVE_A7) +#define M68K_MOVE_A7 0x3F3C +#endif + +#if !defined(M68K_JMP) +#define M68K_JMP 0x4EF9 +#endif + +/* points to jsr-exception-table in targets wo/ VBR register */ +static GDB_HANDLER_ENTRY gdb_jump_table[256]; + +void exceptionHandler(unsigned int vector, void *handler) +{ + rtems_unsigned32 *interrupt_table = 0; + + gdb_jump_table[vector].move_a7 = M68K_MOVE_A7; + gdb_jump_table[vector].format_id = vector; + gdb_jump_table[vector].jmp = M68K_JMP; + gdb_jump_table[vector].isr_handler = (rtems_unsigned32) handler; + + interrupt_table[vector] = (rtems_unsigned32) &gdb_jump_table[vector]; +} + diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/linkcmds b/c/src/lib/libbsp/m68k/ods68302/startup/linkcmds new file mode 100644 index 0000000000..225cc92f26 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/linkcmds @@ -0,0 +1,55 @@ +/* + * $Id$ + * + * MC68302 Linker command file + * + */ + +SECTIONS +{ + .text . : + { + text_start = .; + *(.text) + etext = .; + . = ALIGN(4); + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + . = ALIGN(4); + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + } + + .vtable 0 : + { + vtable_start = .; + *(.vtable) + evtable = .; + } + + .data (ADDR(.vtable) + SIZEOF(.vtable)) : + AT (ADDR(.text) + SIZEOF(.text)) + { + data_start = .; + *(.data) + edata = .; + } + .bss (ADDR(.data) + SIZEOF(.data)) : + { + bss_start = .; + *(.bss) + *(COMMON) + end = . ; + _end = . ; + } +} + +m302 = MC68302_BASE; +_VBR = ADDR(.vtable); /* location of the VBR table (in RAM) */ + diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c b/c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c new file mode 100644 index 0000000000..77d7867a21 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/m68302scc.c @@ -0,0 +1,159 @@ +/*****************************************************************************/ +/* + $Id$ + + M68302 SCC Polled Driver + + */ +/*****************************************************************************/ + + +#include +#include +#include + +#define M68302_SCC_COUNT (3) + +static volatile m302_SCC_t *scc[M68302_SCC_COUNT] = { 0, 0, 0 }; +static volatile m302_SCC_Registers_t *scc_reg[M68302_SCC_COUNT] = { 0, 0, 0 }; +static int scc_translate[M68302_SCC_COUNT] = { 0, 0, 0 }; + +static const rtems_unsigned16 baud_clocks[] = +{ + (SYSTEM_CLOCK / ( 4800 * 16)), + (SYSTEM_CLOCK / ( 9600 * 16)), + (SYSTEM_CLOCK / ( 19200 * 16)), + (SYSTEM_CLOCK / ( 38400 * 16)), + (SYSTEM_CLOCK / ( 57600 * 16)), + (SYSTEM_CLOCK / (115700 * 16)) +}; + +void scc_initialise(int channel, int baud, int translate) +{ + rtems_unsigned16 scon; + + if (channel < M68302_SCC_COUNT) + { + scc[channel] = &m302.scc1 + channel; + scc_reg[channel] = &m302.reg.scc[channel]; + scc_translate[channel] = translate; + + scon = (baud_clocks[baud] & 0xF800) == 0 ? 0 : 1; + scon |= (((baud_clocks[baud] / (1 + scon * 3)) - 1) << 1) & 0x0FFE; + + scc_reg[channel]->scon = scon; + scc_reg[channel]->scm = 0x0171; + + scc[channel]->bd.tx[0].status = 0x2000; + scc[channel]->bd.tx[0].length = 0; + scc[channel]->bd.tx[0].buffer = + (rtems_unsigned8*) &(scc[channel]->bd.tx[1].buffer); + + scc[channel]->bd.rx[0].status = 0x2000; + scc[channel]->bd.rx[0].length = 0; + scc[channel]->bd.rx[0].buffer = + (rtems_unsigned8*) &(scc[channel]->bd.rx[1].buffer); + + scc[channel]->parm.rfcr = 0x50; + scc[channel]->parm.tfcr = 0x50; + + scc[channel]->parm.mrblr = 0x0001; + scc[channel]->prot.uart.max_idl = 0x0004; + scc[channel]->prot.uart.brkcr = 1; + scc[channel]->prot.uart.parec = 0; + scc[channel]->prot.uart.frmec = 0; + scc[channel]->prot.uart.nosec = 0; + scc[channel]->prot.uart.brkec = 0; + scc[channel]->prot.uart.uaddr1 = 0; + scc[channel]->prot.uart.uaddr2 = 0; + scc[channel]->prot.uart.character[0] = 0x0003; + scc[channel]->prot.uart.character[1] = 0x8000; + + scc_reg[channel]->scce = 0xFF; + scc_reg[channel]->sccm = 0x15; + + scc_reg[channel]->scm = 0x17d; + } +} + +unsigned char scc_status(int channel, unsigned char status) +{ + rtems_unsigned16 rx_status; + + m302.reg.wcn = 0; + + if ((channel < M68302_SCC_COUNT) && scc[channel]) + { + rx_status = scc[channel]->bd.rx[0].status; + + if ((rx_status & 0x8000) == 0) + { + if (rx_status & 0x003B) + { + return 2; + } + if (status == 0) + { + return 1; + } + } + } + + return 0; +} + +unsigned char scc_in(int channel) +{ + m302.reg.wcn = 0; + + if ((channel < M68302_SCC_COUNT) && scc[channel]) + { + if ((scc[channel]->bd.rx[0].status & 0x8000) == 0) + { + unsigned char c; + + c = *(scc[channel]->bd.rx[0].buffer); + + scc[channel]->bd.rx[0].status = 0xa000; + + return c; + } + } + + return 0; +} + +void scc_out(int channel, unsigned char character) +{ + if ((channel < M68302_SCC_COUNT) && scc[channel]) + { + do + { + m302.reg.wcn = 0; + } + while (scc[channel]->bd.tx[0].status & 0x8000); + + *(scc[channel]->bd.tx[0].buffer) = character; + + scc[channel]->bd.tx[0].length = 1; + scc[channel]->bd.tx[0].status = 0xa000; + + if (scc_translate[channel]) + { + if (character == '\n') + { + scc_out(channel, '\r'); + } + } + } +} + + + + + + + + + + diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/m68k-stub.c b/c/src/lib/libbsp/m68k/ods68302/startup/m68k-stub.c new file mode 100644 index 0000000000..f9172f4c9f --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/m68k-stub.c @@ -0,0 +1,1084 @@ +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. The breakpoint instruction + * is hardwired to trap #1 because not to do so is a compatibility problem-- + * there either should be a standard breakpoint instruction, or the protocol + * should be extended to provide some means to communicate which breakpoint + * instruction is in use (or have the stub insert the breakpoint). + * + * Some explanation is probably necessary to explain how exceptions are + * handled. When an exception is encountered the 68000 pushes the current + * program counter and status register onto the supervisor stack and then + * transfers execution to a location specified in it's vector table. + * The handlers for the exception vectors are hardwired to jmp to an address + * given by the relation: (exception - 256) * 6. These are decending + * addresses starting from -6, -12, -18, ... By allowing 6 bytes for + * each entry, a jsr, jmp, bsr, ... can be used to enter the exception + * handler. Using a jsr to handle an exception has an added benefit of + * allowing a single handler to service several exceptions and use the + * return address as the key differentiation. The vector number can be + * computed from the return address by [ exception = (addr + 1530) / 6 ]. + * The sole purpose of the routine _catchException is to compute the + * exception number and push it on the stack in place of the return address. + * The external function exceptionHandler() is + * used to attach a specific handler to a specific m68k exception. + * For 68020 machines, the ability to have a return address around just + * so the vector can be determined is not necessary because the '020 pushes an + * extra word onto the stack containing the vector offset + * + * Because gdb will sometimes write to the stack area to execute function + * calls, this program cannot rely on using the supervisor stack so it + * uses it's own stack area reserved in the int array remcomStack. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include +#include +#include + +#include +#include + +/************************************************************************ + * + * external low-level support routines + */ +typedef void (*ExceptionHook)(int); /* pointer to function with int parm */ +typedef void (*Function)(void); /* pointer to a function */ + +/* assign an exception handler */ +Function exceptionHandler(int vector, Function handler); +extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */ + +int putDebugChar(char ch); +char getDebugChar(void); + +/************************/ +/* FORWARD DECLARATIONS */ +/************************/ +static int hex(char ch); +static void getpacket(char *buffer); +static void putpacket(char *buffer); +static char* mem2hex(char *mem, char *buf, int count); +static char* hex2mem(char *buf, char *mem, int count); +static void handle_buserror(void); +static int computeSignal(int exceptionVector); +static int hexToInt(char **ptr, int *intValue); + void handle_exception(int exceptionVector); +static void initializeRemcomErrorFrame(void); + +void set_debug_traps(void); +void breakpoint(void); + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 400 + +static char initialized; /* boolean flag. != 0 means we've been initialized */ + +int remote_debug; +/* debug > 0 prints ill-formed commands in valid packets & checksum errors */ + +static const char hexchars[]="0123456789abcdef"; + +/* there are 180 bytes of registers on a 68020 w/68881 */ +/* many of the fpa registers are 12 byte (96 bit) registers */ +#define NUMREGBYTES 180 +enum regnames {D0,D1,D2,D3,D4,D5,D6,D7, + A0,A1,A2,A3,A4,A5,A6,A7, + PS,PC, + FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7, + FPCONTROL,FPSTATUS,FPIADDR + }; + + +/* We keep a whole frame cache here. "Why?", I hear you cry, "doesn't + GDB handle that sort of thing?" Well, yes, I believe the only + reason for this cache is to save and restore floating point state + (fsave/frestore). A cleaner way to do this would be to make the + fsave data part of the registers which GDB deals with like any + other registers. This should not be a performance problem if the + ability to read individual registers is added to the protocol. */ + +typedef struct FrameStruct +{ + struct FrameStruct *previous; + int exceptionPC; /* pc value when this frame created */ + int exceptionVector; /* cpu vector causing exception */ + short frameSize; /* size of cpu frame in words */ + short sr; /* for 68000, this not always sr */ + int pc; + short format; + int fsaveHeader; + int morejunk[0]; /* exception frame, fp save... */ +} Frame; + +#define FRAMESIZE 500 +int gdbFrameStack[FRAMESIZE]; +static Frame *lastFrame; + +/* + * these should not be static cuz they can be used outside this module + */ +int registers[NUMREGBYTES/4]; +int superStack; + +#define STACKSIZE 10000 +int remcomStack[STACKSIZE/sizeof(int)]; +static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1]; + +/* + * In many cases, the system will want to continue exception processing + * when a continue command is given. + * oldExceptionHook is a function to invoke in this case. + */ + +static ExceptionHook oldExceptionHook; + +#if defined(__mc68020__) +/* the size of the exception stack on the 68020 varies with the type of + * exception. The following table is the number of WORDS used + * for each exception format. + */ +const short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,12,4,4,4 }; +#endif + +#if defined(__mc68332__) +static const short exceptionSize[] = { 4,4,6,4,4,4,4,4,4,4,4,4,16,4,4,4 }; +#endif + +/************* jump buffer used for setjmp/longjmp **************************/ +jmp_buf remcomEnv; + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* */ + +#if defined(__HAVE_68881__) + +/* do an fsave, then remember the address to begin a restore from */ +#define SAVE_FP_REGS() \ + asm(" fsave %a0@-"); \ + asm(" fmovemx %fp0-%fp7,registers+72"); \ + asm(" fmoveml %fpcr/%fpsr/%fpi,registers+168"); + +#define RESTORE_FP_REGS() \ +asm(" \n\ + fmoveml registers+168,%fpcr/%fpsr/%fpi \n\ + fmovemx registers+72,%fp0-%fp7 \n\ + cmpl #-1,%a0@ | skip frestore flag set ? \n\ + beq skip_frestore \n\ + frestore %a0@+ \n\ +skip_frestore: \n\ +"); + +#else + +#define SAVE_FP_REGS() +#define RESTORE_FP_REGS() + +#endif /* __HAVE_68881__ */ + +void return_to_super(void); +void return_to_user(void); + +asm(" + .text + + .globl return_to_super + .align 4 +return_to_super: + movel registers+60,%sp /* get new stack pointer */ + movel lastFrame,%a0 /* get last frame info */ + bra return_to_any + + .globl return_to_user + .align 4 + +return_to_user: + movel registers+60,%a0 /* get usp */ + movel %a0,%usp /* set usp */ + movel superStack,%sp /* get original stack pointer */ + +return_to_any: + movel lastFrame,%a0 /* get last frame info */ + movel %a0@+,lastFrame /* link in previous frame */ + addql #8,%a0 /* skip over pc, vector#*/ + movew %a0@+,%d0 /* get # of words in cpu frame */ + addw %d0,%a0 /* point to end of data */ + addw %d0,%a0 /* point to end of data */ + movel %a0,%a1 +# +# copy the stack frame + subql #1,%d0 + +copyUserLoop: + movew %a1@-,%sp@- + dbf %d0,copyUserLoop +"); + RESTORE_FP_REGS() +asm(" + moveml registers,%d0-%d7/%a0-%a6 + rte /* pop and go! */ +"); + +#define DISABLE_INTERRUPTS() asm(" oriw #0x0700,%sr"); +#define BREAKPOINT() asm(" trap #1"); + +/* this function is called immediately when a level 7 interrupt occurs */ +/* if the previous interrupt level was 7 then we're already servicing */ +/* this interrupt and an rte is in order to return to the debugger. */ +/* For the 68000, the offset for sr is 6 due to the jsr return address */ +asm(" + .text + .globl _debug_level7 + .align 4 + +_debug_level7: + movew %d0,%sp@- +"); + +#if defined(__mc68020__) || defined(__mc68332__) +asm(" + movew %sp@(2),%d0 +"); +#else +asm(" + movew %sp@(6),%d0 +"); +#endif +asm(" + andiw #0x700,%d0 + cmpiw #0x700,%d0 + beq _already7 + movew %sp@+,%d0 + bra _catchException +_already7: + movew %sp@+,%d0 +"); +#if defined (__m68000__) && !defined(__mc68020__) +asm(" + lea %sp@(4),%sp"); /* pull off 68000 return address */ +#endif +asm(" + rte +"); + +extern void _catchException(void); + +#if defined(__mc68020__) || defined(__mc68332__) +/* This function is called when a 68020 exception occurs. It saves + * all the cpu and fpcp regs in the _registers array, creates a frame on a + * linked list of frames which has the cpu and fpcp stack frames needed + * to properly restore the context of these processors, and invokes + * an exception handler (remcom_handler). + * + * stack on entry: stack on exit: + * N bytes of junk exception # MSWord + * Exception Format Word exception # MSWord + * Program counter LSWord + * Program counter MSWord + * Status Register + * + * + */ +asm(" + .text + + .globl _catchException + .align 4 +_catchException: +"); + +DISABLE_INTERRUPTS(); + +asm(" + moveml %d0-%d7/%a0-%a6,registers /* save registers */ + movel lastFrame,%a0 /* last frame pointer */ +"); +SAVE_FP_REGS(); +asm(" + lea registers,%a5 /* get address of registers */ + movew %sp@,%d1 /* get status register */ + movew %d1,%a5@(66) /* save sr */ + movel %sp@(2),%a4 /* save pc in %a4 for later use */ + movel %a4,%a5@(68) /* save pc in _regisers[] */ + +# +# figure out how many bytes in the stack frame +# + movew %sp@(6),%d0 /* get '020 exception format */ + movew %d0,%d2 /* make a copy of format word */ + andiw #0xf000,%d0 /* mask off format type */ + rolw #5,%d0 /* rotate into the low byte *2 */ + lea exceptionSize,%a1 + addw %d0,%a1 /* index into the table */ + movew %a1@,%d0 /* get number of words in frame */ + movew %d0,%d3 /* save it */ + subw %d0,%a0 /* adjust save pointer */ + subw %d0,%a0 /* adjust save pointer(bytes) */ + movel %a0,%a1 /* copy save pointer */ + subql #1,%d0 /* predecrement loop counter */ +# +# copy the frame +# +saveFrameLoop: + movew %sp@+,%a1@+ + dbf %d0,saveFrameLoop +# +# now that the stack has been clenaed, +# save the %a7 in use at time of exception + + movel %sp,superStack /* save supervisor %sp */ + andiw #0x2000,%d1 /* were we in supervisor mode ? */ + beq userMode + movel %a7,%a5@(60) /* save %a7 */ + bra a7saveDone +userMode: + movel %usp,%a1 + movel %a1,%a5@(60) /* save user stack pointer */ +a7saveDone: + +# +# save size of frame + movew %d3,%a0@- + +# +# compute exception number + andl #0xfff,%d2 /* mask off vector offset */ + lsrw #2,%d2 /* divide by 4 to get vect num */ + movel %d2,%a0@- /* save it */ +# +# save pc causing exception + movel %a4,%a0@- +# +# save old frame link and set the new value + movel lastFrame,%a1 /* last frame pointer */ + movel %a1,%a0@- /* save pointer to prev frame */ + movel %a0,lastFrame + + movel %d2,%sp@- /* push exception num */ + movel exceptionHook,%a0 /* get address of handler */ + jbsr %a0@ /* and call it */ + clrl %sp@ /* replace exception num parm with frame ptr */ + jbsr _returnFromException /* jbsr, but never returns */ + +"); + +#else /* mc68000 */ + +/* This function is called when an exception occurs. It translates the + * return address found on the stack into an exception vector # which + * is then handled by either handle_exception or a system handler. + * _catchException provides a front end for both. + * + * stack on entry: stack on exit: + * Program counter MSWord exception # MSWord + * Program counter LSWord exception # MSWord + * Status Register + * Return Address MSWord + * Return Address LSWord + */ +asm(" + .text + .globl _catchException + .align 4 +_catchException: +"); +DISABLE_INTERRUPTS(); +asm(" + moveml %d0-%d7/%a0-%a6,registers /* save registers */ + movel lastFrame,%a0 /* last frame pointer */ +"); + +SAVE_FP_REGS(); +asm(" + moveq.l #0,%d2 + movew %sp@+,%d2 + lea registers,%a5 /* get address of registers */ + + moveql #3,%d3 /* assume a three word frame */ + + cmpiw #3,%d2 /* bus error or address error ? */ + bgt normal /* if >3 then normal error */ + movel %sp@+,%a0@- /* copy error info to frame buff*/ + movel %sp@+,%a0@- /* these are never used */ + moveql #7,%d3 /* this is a 7 word frame */ + +normal: + movew %sp@+,%d1 /* pop status register */ + movel %sp@+,%a4 /* pop program counter */ + + cmpiw #33,%d2 /* trap #1, breakpoint ? */ + bne not_breakpoint + + subql #2,%a4 /* trap leaves the pc after the trap */ + +not_breakpoint: + movew %d1,%a5@(66) /* save sr */ + movel %a4,%a5@(68) /* save pc in _regisers[] */ + movel %a4,%a0@- /* copy pc to frame buffer */ + movew %d1,%a0@- /* copy sr to frame buffer */ + + movel %sp,superStack /* save supervisor %sp */ + + andiw #0x2000,%d1 /* were we in supervisor mode ? */ + beq userMode + movel %a7,%a5@(60) /* save %a7 */ + bra saveDone +userMode: + movel %usp,%a1 /* save user stack pointer */ + movel %a1,%a5@(60) /* save user stack pointer */ +saveDone: + + movew %d3,%a0@- /* push frame size in words */ + movel %d2,%a0@- /* push vector number */ + movel %a4,%a0@- /* push exception pc */ + +# +# save old frame link and set the new value +# + movel lastFrame,%a1 /* last frame pointer */ + movel %a1,%a0@- /* save pointer to prev frame */ + movel %a0,lastFrame + + movel %d2,%sp@- /* push exception num */ + movel exceptionHook,%a0 /* get address of handler */ + + jbsr %a0@ /* and call it */ + clrl %sp@ /* replace exception num parm with frame ptr */ + jbsr _returnFromException /* jbsr, but never returns */ +"); +#endif + + +/* + * remcomHandler is a front end for handle_exception. It moves the + * stack pointer into an area reserved for debugger use in case the + * breakpoint happened in supervisor mode. + */ +asm("remcomHandler:"); +asm(" addl #4,%sp"); /* pop off return address */ +asm(" movel %sp@+,%d0"); /* get the exception number */ +asm(" movel stackPtr,%sp"); /* move to remcom stack area */ +asm(" movel %d0,%sp@-"); /* push exception onto stack */ +asm(" jbsr handle_exception"); /* this never returns */ +asm(" rts"); /* return */ + +void _returnFromException(Frame *frame) +{ + /* if no passed in frame, use the last one */ + if (! frame) + { + frame = lastFrame; + frame->frameSize = 4; + frame->format = 0; + frame->fsaveHeader = -1; /* restore regs, but we dont have fsave info*/ + } + +#if defined(__m68000__) && !defined(__mc68020__) + /* a 68000 cannot use the internal info pushed onto a bus error + * or address error frame when doing an RTE so don't put this info + * onto the stack or the stack will creep every time this happens. + */ + frame->frameSize=3; +#endif + + /* throw away any frames in the list after this frame */ + lastFrame = frame; + + frame->sr = registers[(int) PS]; + frame->pc = registers[(int) PC]; + + if (registers[(int) PS] & 0x2000) + { + /* return to supervisor mode... */ + return_to_super(); + } + else + { /* return to user mode */ + return_to_user(); + } +} + +int hex(char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10); + if ((ch >= '0') && (ch <= '9')) return (ch-'0'); + if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10); + return (-1); +} + +/* scan for the sequence $# */ +void getpacket(char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + char ch; + + do { + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar() & 0x7f)) != '$'); + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) { + ch = getDebugChar() & 0x7f; + if (ch == '#') break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + buffer[count] = 0; + + if (ch == '#') { + xmitcsum = hex(getDebugChar() & 0x7f) << 4; + xmitcsum += hex(getDebugChar() & 0x7f); + if ((remote_debug ) && (checksum != xmitcsum)) { + debug_port_printf ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", + checksum,xmitcsum,buffer); + } + + if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */ + else { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') { + putDebugChar( buffer[0] ); + putDebugChar( buffer[1] ); + /* remove sequence chars from buffer */ + count = strlen(buffer); + for (i=3; i <= count; i++) buffer[i-3] = buffer[i]; + } + } + } + } while (checksum != xmitcsum); +} + +/* send the packet in buffer. The host get's one chance to read it. + This routine does not wait for a positive acknowledge. */ + + +void +putpacket(char *buffer) +{ + unsigned char checksum; + int count; + char ch; + + /* $#. */ + do { + putDebugChar('$'); + checksum = 0; + count = 0; + + while ((ch=buffer[count])) { + if (! putDebugChar(ch)) return; + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum % 16]); + + } while (1 == 0); /* (getDebugChar() != '+'); */ + +} + +char remcomInBuffer[BUFMAX]; +char remcomOutBuffer[BUFMAX]; +static short error; + +/* convert the memory pointed to by mem into hex, placing result in buf */ +/* return a pointer to the last char put in buf (null) */ +char *mem2hex(char *mem, char *buf, int count) +{ + int i; + unsigned char ch; + + if (remote_debug) + debug_port_printf("mem=0x%x, count=0x%x\n", mem, count); + + for (i=0;i> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + return(buf); +} + +/* convert the hex array pointed to by buf into binary to be placed in mem */ +/* return a pointer to the character AFTER the last byte written */ +char *hex2mem(char *buf, char *mem, int count) +{ + int i; + unsigned char ch; + + if (remote_debug) + debug_port_printf("mem=0x%x, count=0x%x\n", mem, count); + + for (i=0;i=0) + { + *intValue = (*intValue <<4) | hexValue; + numChars ++; + } + else + break; + + (*ptr)++; + } + + return (numChars); +} + +/* + * This function does all command procesing for interfacing to gdb. + */ +void handle_exception(int exceptionVector) +{ + int sigval; + int addr, length; + char * ptr; + int newPC; + Frame *frame; + + if (remote_debug) + printf("vector=%d, sr=0x%x, pc=0x%x\n", + exceptionVector, + registers[ PS ], + registers[ PC ]); + + /* reply to host that an exception has occurred */ + sigval = computeSignal( exceptionVector ); + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval % 16]; + remcomOutBuffer[3] = 0; + + putpacket(remcomOutBuffer); + + while (1==1) { + error = 0; + remcomOutBuffer[0] = 0; + getpacket(remcomInBuffer); + switch (remcomInBuffer[0]) { + case '?' : remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval % 16]; + remcomOutBuffer[3] = 0; + break; + case 'd' : + remote_debug = !(remote_debug); /* toggle debug flag */ + debug_port_printf("debug mode "); + if (remote_debug) + { + debug_port_printf("on\n"); + } + else + { + debug_port_printf("off\n"); + } + break; + case 'g' : /* return the value of the CPU registers */ + mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES); + break; + case 'G' : /* set the value of the CPU registers - return OK */ + hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES); + strcpy(remcomOutBuffer,"OK"); + break; + + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + case 'm' : + if (setjmp(remcomEnv) == 0) + { + exceptionHandler(2,handle_buserror); + + /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr,&addr)) + if (*(ptr++) == ',') + if (hexToInt(&ptr,&length)) + { + ptr = 0; + mem2hex((char*) addr, remcomOutBuffer, length); + } + + if (ptr) + { + strcpy(remcomOutBuffer,"E01"); + if (remote_debug) + printf("malformed read memory command: %s",remcomInBuffer); + } + } + else { + exceptionHandler(2,_catchException); + strcpy(remcomOutBuffer,"E03"); + if (remote_debug) + printf("bus error"); + } + + /* restore handler for bus error */ + exceptionHandler(2,_catchException); + break; + + /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + case 'M' : + if (setjmp(remcomEnv) == 0) { + exceptionHandler(2,handle_buserror); + + /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr,&addr)) + if (*(ptr++) == ',') + if (hexToInt(&ptr,&length)) + if (*(ptr++) == ':') + { + hex2mem(ptr, (char*) addr, length); + ptr = 0; + strcpy(remcomOutBuffer,"OK"); + } + if (ptr) + { + strcpy(remcomOutBuffer,"E02"); + if (remote_debug) + printf("malformed write memory command: %s",remcomInBuffer); + } + } + else { + exceptionHandler(2,_catchException); + strcpy(remcomOutBuffer,"E03"); + if (remote_debug) + printf("bus error"); + } + + /* restore handler for bus error */ + exceptionHandler(2,_catchException); + break; + + /* cAA..AA Continue at address AA..AA(optional) */ + /* sAA..AA Step one instruction from AA..AA(optional) */ + case 'c' : + case 's' : + /* try to read optional parameter, pc unchanged if no parm */ + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr,&addr)) + registers[ PC ] = addr; + + newPC = registers[ PC]; + + /* clear the trace bit */ + registers[ PS ] &= 0x7fff; + + /* set the trace bit if we're stepping */ + if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x8000; + + /* + * look for newPC in the linked list of exception frames. + * if it is found, use the old frame it. otherwise, + * fake up a dummy frame in returnFromException(). + */ + if (remote_debug) debug_port_printf("new pc = 0x%x\n",newPC); + + frame = lastFrame; + while (frame) + { + if (remote_debug) + debug_port_printf("frame at 0x%x has pc=0x%x, except#=%d\n", + frame,frame->exceptionPC, + (unsigned int) frame->exceptionVector); + if (frame->exceptionPC == newPC) break; /* bingo! a match */ + /* + * for a breakpoint instruction, the saved pc may + * be off by two due to re-executing the instruction + * replaced by the trap instruction. Check for this. + */ + if ((frame->exceptionVector == 33) && + (frame->exceptionPC == newPC)) break; + if (frame == frame->previous) + { + frame = 0; /* no match found */ + break; + } + frame = frame->previous; + } + + /* + * If we found a match for the PC AND we are not returning + * as a result of a breakpoint (33), + * trace exception (9), nmi (31), jmp to + * the old exception handler as if this code never ran. + */ + if (frame) + { + if ((frame->exceptionVector != 9) && + (frame->exceptionVector != 31) && + (frame->exceptionVector != 33)) + { + /* + * invoke the previous handler. + */ + if (oldExceptionHook) + (*oldExceptionHook) (frame->exceptionVector); + newPC = registers[ PC ]; /* pc may have changed */ + if (newPC != frame->exceptionPC) + { + if (remote_debug) + debug_port_printf("frame at 0x%x has pc=0x%x, except#=%d\n", + frame,frame->exceptionPC, + (unsigned int) frame->exceptionVector); + /* re-use the last frame, we're skipping it (longjump?)*/ + frame = (Frame *) 0; + _returnFromException( frame ); /* this is a jump */ + } + } + } + + /* if we couldn't find a frame, create one */ + if (frame == 0) + { + frame = lastFrame -1 ; + + /* by using a bunch of print commands with breakpoints, + it's possible for the frame stack to creep down. If it creeps + too far, give up and reset it to the top. Normal use should + not see this happen. + */ + if ((unsigned int) (frame-2) < (unsigned int) &gdbFrameStack) + { + initializeRemcomErrorFrame(); + frame = lastFrame; + } + frame->previous = lastFrame; + lastFrame = frame; + frame = 0; /* null so _return... will properly initialize it */ + } + + _returnFromException( frame ); /* this is a jump */ + + break; + + /* kill the program */ + case 'k' : + /* reset the board */ + WATCHDOG_TRIGGER(); + while (1 == 1); + break; + + } /* switch */ + + /* reply to the request */ + putpacket(remcomOutBuffer); + } +} + + +void initializeRemcomErrorFrame() +{ + lastFrame = ((Frame *) &gdbFrameStack[FRAMESIZE-1]) - 1; + lastFrame->previous = lastFrame; +} + +/* this function is used to set up exception handlers for tracing and + breakpoints */ +void set_debug_traps() +{ + extern void _debug_level7(void); + extern void remcomHandler(void); + + int exception; + + initializeRemcomErrorFrame(); + stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1]; + + registers[ PC ] = 0x400; + registers[ PS ] = 0x2700; + + for (exception = 2; exception <= 30; exception++) + exceptionHandler(exception,_catchException); + + /* level 7 interrupt */ + exceptionHandler(31,_debug_level7); + + for (exception = 32; exception <= 47; exception++) + exceptionHandler(exception,_catchException); + + /* exclude the unassigned, reserved vector locations */ + + for (exception = 64; exception <= 255; exception++) + exceptionHandler(exception,_catchException); + + if (oldExceptionHook != (ExceptionHook) remcomHandler) + { + oldExceptionHook = exceptionHook; + exceptionHook = (ExceptionHook) remcomHandler; + } + + initialized = 1; + +#if defined(UPDATE_DISPLAY) + UPDATE_DISPLAY("gdb "); +#endif +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +void breakpoint() +{ + if (initialized) BREAKPOINT(); +} diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/memcheck.c b/c/src/lib/libbsp/m68k/ods68302/startup/memcheck.c new file mode 100644 index 0000000000..4341a88e37 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/memcheck.c @@ -0,0 +1,33 @@ +/*****************************************************************************/ +/* + $Id$ + + Memory check routines. + + The production test is a destrucive full test. + The boot test is a minimal, non-desctructive. + The partial memory test performs a scetion at a time, and gets + called in a repeated fashion to completely check the memory, + + */ +/*****************************************************************************/ + +void +production_memory_test() +{ +} + +void +boot_memory_test() +{ +} + +void +reset_partial_memory_test() +{ +} + +void +partial_memory_test() +{ +} diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/rom b/c/src/lib/libbsp/m68k/ods68302/startup/rom new file mode 100644 index 0000000000..a8533e08b0 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/rom @@ -0,0 +1,56 @@ +/* + * $Id$ + * + * MC68302 Linker command file + * + */ + +SECTIONS +{ + .text . : + { + text_start = .; + *(.text) + etext = .; + . = ALIGN(4); + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + . = ALIGN(4); + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + } + + .vtable 0 : + { + vtable_start = .; + *(.vtable) + evtable = .; + } + + .data (ADDR(.vtable) + SIZEOF(.vtable)) : + AT (ADDR(.text) + SIZEOF(.text)) + { + data_start = .; + *(.data) + edata = .; + } + .bss (ADDR(.data) + SIZEOF(.data)) : + { + bss_start = .; + *(.bss) + *(COMMON) + end = . ; + _end = . ; + } +} + +m302 = MC68302_BASE; +_VBR = 0; /* location of the VBR table (in RAM) */ + + diff --git a/c/src/lib/libbsp/m68k/ods68302/startup/trace.c b/c/src/lib/libbsp/m68k/ods68302/startup/trace.c new file mode 100644 index 0000000000..bfc2b699e7 --- /dev/null +++ b/c/src/lib/libbsp/m68k/ods68302/startup/trace.c @@ -0,0 +1,175 @@ +/*****************************************************************************/ +/* + $Id$ + + Trace Exception dumps a back trace to the debug serial port + + */ +/*****************************************************************************/ + +#include +#include + +#ifdef 0 +/* FIXME : could get the string to print when in the BSP */ +static const char *exception_names[] = +{ + "RESET STACK TOP", + "RESET", + "BUS ERROR", + "ADDRESS ERROR", + "ILLEGAL OPCODE", + "ZERO DIVIDE", + "CHK", + "OVERFLOW", + "PRIVILEGE", + "TRACE", + "LINE 1010 EMULATOR", + "LINE 1111 EMULATOR", + "UNASSIGNED 12", + "UNASSIGNED 13", + "FORMAT ERROR", + "UNINITIALISED INTERRUPT", + "UNASSIGNED 16", + "NODE ANCHOR", + "SYSTEM ANCHOR", + "UNASSIGNED 19", + "UNASSIGNED 20", + "UNASSIGNED 21", + "UNASSIGNED 22", + "UNASSIGNED 23", + "SPURIOUS HANDLER", + "LEVEL 1", + "LEVEL 2", + "LEVEL 3", + "LEVEL 4", + "LEVEL 5", + "LEVEL 6", + "LEVEL 7", + "TRAP 0", + "TRAP 1", + "TRAP 2", + "TRAP 3", + "TRAP 4", + "TRAP 5", + "TRAP 6", + "TRAP 7", + "TRAP 8", + "TRAP 9", + "TRAP 10", + "TRAP 11", + "TRAP 12", + "TRAP 13", + "TRAP 14", + "TRAP 15" +}; +#endif + +void trace_exception(unsigned long d0, + unsigned long d1, + unsigned long d2, + unsigned long d3, + unsigned long d4, + unsigned long d5, + unsigned long d6, + unsigned long d7, + unsigned long a0, + unsigned long a1, + unsigned long a2, + unsigned long a3, + unsigned long a4, + unsigned long a5, + unsigned long a6, + unsigned long a7, + unsigned long sr_pch, + unsigned long pcl_format) +{ + unsigned int sr = sr_pch >> 16; + unsigned long pc = (sr_pch << 16) | (pcl_format >> 16); + unsigned int format = pcl_format & 0xFFFF; + unsigned int index; + unsigned char ch; + + asm volatile(" orw #0x0700,%sr"); + + debug_port_banner(); + + debug_port_write("unhandled exception="); + debug_port_write_hex_uint(format >> 2); + debug_port_write("\n"); + + debug_port_write("sr="); + debug_port_write_hex_uint(sr); + debug_port_write(", pc="); + debug_port_write_hex_ulong(pc); + debug_port_write("\n"); + + for (index = 0; index < 16; index++) + { + if (index == 8) + { + debug_port_write("\n\r"); + } + if (index < 8) + { + debug_port_out('d'); + debug_port_out('0' + index); + } + else + { + debug_port_out('a'); + debug_port_out('0' + index - 8); + } + debug_port_out('='); + debug_port_write_hex_ulong(*(((unsigned long*) &d0) + index)); + debug_port_out(' '); + } + + for (index = 0; index < (16 * 10); index++) + { + if ((index % 16) == 0) + { + debug_port_write("\n"); + debug_port_write_hex_ulong((unsigned long) (((char*) &index) + index)); + debug_port_write(" : "); + } + else + { + debug_port_out(' '); + } + + ch = (*(((char*) &index) + index) >> 4) & 0x0F; + + if (ch < 10) + { + ch += '0'; + } + else + { + ch += 'a' - 10; + } + + debug_port_out((char) ch); + + ch = *(((char*) &index) + index) & 0x0F; + + if (ch < 10) + { + ch += '0'; + } + else + { + ch += 'a' - 10; + } + debug_port_out((char) ch); + } + + debug_port_write("\nhalting cpu..."); + +#if defined(UPDATE_DISPLAY) + UPDATE_DISPLAY("HALT"); +#endif + + WATCHDOG_TRIGGER(); + while (1 == 1); +} -- cgit v1.2.3