diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-03-13 16:24:16 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-03-19 07:00:20 +0100 |
commit | bd1508019cfb219b41da7cb6f1a9895a69c64534 (patch) | |
tree | 6c3f15e745ef11dc3d7c3b706fde54c95dac055d /bsps/powerpc/ss555 | |
parent | bsps/powerpc: Remove unused files (diff) | |
download | rtems-bd1508019cfb219b41da7cb6f1a9895a69c64534.tar.bz2 |
bsps/powerpc: Move exceptions support to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/powerpc/ss555')
-rw-r--r-- | bsps/powerpc/ss555/start/vectors.S | 201 | ||||
-rw-r--r-- | bsps/powerpc/ss555/start/vectors_init.c | 137 |
2 files changed, 338 insertions, 0 deletions
diff --git a/bsps/powerpc/ss555/start/vectors.S b/bsps/powerpc/ss555/start/vectors.S new file mode 100644 index 0000000000..35d2f23a30 --- /dev/null +++ b/bsps/powerpc/ss555/start/vectors.S @@ -0,0 +1,201 @@ +/* + * 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 + */ + +#include <rtems/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 diff --git a/bsps/powerpc/ss555/start/vectors_init.c b/bsps/powerpc/ss555/start/vectors_init.c new file mode 100644 index 0000000000..342ca5509a --- /dev/null +++ b/bsps/powerpc/ss555/start/vectors_init.c @@ -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 the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ +#include <inttypes.h> +#include <rtems/bspIo.h> +#include <libcpu/vectors.h> +#include <libcpu/raw_exception.h> +#include <bsp/irq.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 %" PRIu32 "\n", + excPtr->_EXC_number); + printk("\t Next PC or Address of fault = %" PRIxPTR "\n", excPtr->EXC_SRR0); + printk("\t Saved MSR = %" PRIxPTR "\n", excPtr->EXC_SRR1); + printk("\t R0 = %" PRIxPTR "\n", excPtr->GPR0); + printk("\t R1 = %" PRIxPTR "\n", excPtr->GPR1); + printk("\t R2 = %" PRIxPTR "\n", excPtr->GPR2); + printk("\t R3 = %" PRIxPTR "\n", excPtr->GPR3); + printk("\t R4 = %" PRIxPTR "\n", excPtr->GPR4); + printk("\t R5 = %" PRIxPTR "\n", excPtr->GPR5); + printk("\t R6 = %" PRIxPTR "\n", excPtr->GPR6); + printk("\t R7 = %" PRIxPTR "\n", excPtr->GPR7); + printk("\t R8 = %" PRIxPTR "\n", excPtr->GPR8); + printk("\t R9 = %" PRIxPTR "\n", excPtr->GPR9); + printk("\t R10 = %" PRIxPTR "\n", excPtr->GPR10); + printk("\t R11 = %" PRIxPTR "\n", excPtr->GPR11); + printk("\t R12 = %" PRIxPTR "\n", excPtr->GPR12); + printk("\t R13 = %" PRIxPTR "\n", excPtr->GPR13); + printk("\t R14 = %" PRIxPTR "\n", excPtr->GPR14); + printk("\t R15 = %" PRIxPTR "\n", excPtr->GPR15); + printk("\t R16 = %" PRIxPTR "\n", excPtr->GPR16); + printk("\t R17 = %" PRIxPTR "\n", excPtr->GPR17); + printk("\t R18 = %" PRIxPTR "\n", excPtr->GPR18); + printk("\t R19 = %" PRIxPTR "\n", excPtr->GPR19); + printk("\t R20 = %" PRIxPTR "\n", excPtr->GPR20); + printk("\t R21 = %" PRIxPTR "\n", excPtr->GPR21); + printk("\t R22 = %" PRIxPTR "\n", excPtr->GPR22); + printk("\t R23 = %" PRIxPTR "\n", excPtr->GPR23); + printk("\t R24 = %" PRIxPTR "\n", excPtr->GPR24); + printk("\t R25 = %" PRIxPTR "\n", excPtr->GPR25); + printk("\t R26 = %" PRIxPTR "\n", excPtr->GPR26); + printk("\t R27 = %" PRIxPTR "\n", excPtr->GPR27); + printk("\t R28 = %" PRIxPTR "\n", excPtr->GPR28); + printk("\t R29 = %" PRIxPTR "\n", excPtr->GPR29); + printk("\t R30 = %" PRIxPTR "\n", excPtr->GPR30); + printk("\t R31 = %" PRIxPTR "\n", excPtr->GPR31); + printk("\t CR = %" PRIx32 "\n", excPtr->EXC_CR); + printk("\t CTR = %" PRIxPTR "\n", excPtr->EXC_CTR); + printk("\t XER = %" PRIx32 "\n", excPtr->EXC_XER); + printk("\t LR = %" PRIxPTR "\n", excPtr->EXC_LR); + 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); + } +} + +static void nop_except_enable(const rtems_raw_except_connect_data* ptr) +{ +} + +static int except_always_enabled(const rtems_raw_except_connect_data* ptr) +{ + return 1; +} + +void initialize_exceptions(void) +{ + 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"); + } +} |