/**************************************************************************** * arch/z80/src/z8/z8_saveirqcontext.c * * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include "chip/switch.h" #include "up_internal.h" /**************************************************************************** * Definitions ****************************************************************************/ /**************************************************************************** * Private Data ****************************************************************************/ /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: z8_saveirqcontext * * Description: * In order to provide faster interrupt handling, the interrupt logic does * "lazy" context saving as described below: * * (1) At the time of the interrupt, minimum information is saved and the * register pointer is changed so that the interrupt logic does not * alter the state of the interrupted task's registers. * (2) If no context switch occurs during the interrupt processing, then * the return from interrupt is also simple. * (3) If a context switch occurs during interrupt processing, then * (a) The full context of the interrupt task is saved, and * (b) A full context switch is performed when the interrupt exits * (see z8_vector.S). * * This function implements the full-context switch of bullet 3a. * ****************************************************************************/ void z8_saveirqcontext(FAR chipreg_t *regs) { /* If we have already saved the interrupted task's registers in the TCB, * then we do not need to do anything. */ if (g_z8irqstate.state == Z8_IRQSTATE_ENTRY) { /* Calculate the source address based on the saved RP value */ uint16_t rp = g_z8irqstate.regs[Z8_IRQSAVE_RPFLAGS] >> 8; FAR chipreg_t *src = (FAR uint16_t*)(rp & 0xf0); FAR chipreg_t *dest = ®s[XCPT_RR0]; /* Copy the interrupted tasks register into the TCB register save area. */ int i; for (i = 0; i < XCPTCONTEXT_REGS; i++) { *dest++ = *src++; } /* Since the task was interrupted, we know that interrupts were enabled */ regs[XCPT_IRQCTL] = 0x0080; /* IRQE bit will enable interrupts */ /* The g_z8irqstate.regs pointer is the value of the stack pointer at * the time that up_doirq() was called. Therefore, we can calculate * the correct value for the stack pointer on return from interrupt: */ regs[XCPT_SP] = ((chipreg_t)g_z8irqstate.regs) + Z8_IRQSAVE_SIZE; /* Copy the PC, RP, and FLAGS information from the lazy save to the TCB * register save area. */ regs[XCPT_RPFLAGS] = g_z8irqstate.regs[Z8_IRQSAVE_RPFLAGS]; regs[XCPT_PC] = g_z8irqstate.regs[Z8_IRQSAVE_PC]; /* Now update the IRQ save area so that we will know that we have already * done this. */ g_z8irqstate.state = Z8_IRQSTATE_SAVED; g_z8irqstate.regs = regs; } }