Xtensa: First cat at context switching functions

This commit is contained in:
Gregory Nutt
2016-10-21 10:43:59 -06:00
parent 363fe19ff6
commit f07601a067
13 changed files with 1250 additions and 155 deletions
-1
View File
@@ -157,7 +157,6 @@ struct xcptcontext
/* These are saved copies of registers used during signal processing. */
uint32_t saved_pc;
uint32_t saved_cpsr;
#endif
/* Register save area */
+5 -5
View File
@@ -248,15 +248,15 @@ void xtensa_dumpstate(void);
uint32_t *xtensa_int_decode(uint32_t *regs);
uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs);
void xtensa_context_save(uint32_t *regs);
void xtensa_full_context_save(uint32_t *regs);
void xtensa_context_restore(uint32_t *regs);
void xtensa_full_context_restore(uint32_t *regs);
/* Software interrupt handler */
int xtensa_swint(int irq, FAR void *context);
/* Synchronous context switching */
int xtensa_context_save(uint32_t *regs);
int xtensa_context_restore(uint32_t *regs);
/* Signals */
void xtensa_sigdeliver(void);
+175
View File
@@ -0,0 +1,175 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_blocktask.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <stdbool.h>
#include <sched.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include "sched/sched.h"
#include "group/group.h"
#include "xtensa.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_block_task
*
* Description:
* The currently executing task at the head of
* the ready to run list must be stopped. Save its context
* and move it to the inactive list specified by task_state.
*
* Inputs:
* tcb: Refers to a task in the ready-to-run list (normally
* the task at the head of the list). It most be
* stopped, its context saved and moved into one of the
* waiting task lists. It it was the task at the head
* of the ready-to-run list, then a context to the new
* ready to run task must be performed.
* task_state: Specifies which waiting task list should be
* hold the blocked task TCB.
*
****************************************************************************/
void up_block_task(struct tcb_s *tcb, tstate_t task_state)
{
struct tcb_s *rtcb = this_task();
bool switch_needed;
/* Verify that the context switch can be performed */
ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) &&
(tcb->task_state <= LAST_READY_TO_RUN_STATE));
/* Remove the tcb task from the ready-to-run list. If we
* are blocking the task at the head of the task list (the
* most likely case), then a context switch to the next
* ready-to-run task is needed. In this case, it should
* also be true that rtcb == tcb.
*/
switch_needed = sched_removereadytorun(tcb);
/* Add the task to the specified blocked task list */
sched_addblocked(tcb, (tstate_t)task_state);
/* If there are any pending tasks, then add them to the ready-to-run
* task list now
*/
if (g_pendingtasks.head)
{
switch_needed |= sched_mergepending();
}
/* Now, perform the context switch if one is needed */
if (switch_needed)
{
/* Update scheduler parameters */
sched_suspend_scheduler(rtcb);
/* Are we in an interrupt handler? */
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
xtensa_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Reset scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
xtensa_restorestate(rtcb->xcp.regs);
}
/* Copy the user C context into the TCB at the (old) head of the
* ready-to-run Task list. if up_saveusercontext returns a non-zero
* value, then this is really the previously running task restarting!
*/
else if (!xtensa_context_save(rtcb->xcp.regs))
{
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
(void)group_addrenv(rtcb);
#endif
/* Reset scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts */
xtensa_context_restore(rtcb->xcp.regs);
}
}
}
+215 -130
View File
@@ -76,95 +76,76 @@
.text
/****************************************************************************
* Name: xtensa_context_save
* xtensa_full_context_save
* Name: _xtensa_context_save
*
* Description:
*
* NOTE: MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION!
*
* These functions save Xtensa processor state:
* This function saves Xtensa processor state: xtensa_context_save
* saves all registers except PC, PS, A0, A1 (SP), and A2
*
* - xtensa_full_context_save saves all registers except PC, PS, A0, and
* A1 (SP)
* - xtensa_context_save, in addition, does not save A12-A15 which
* are preserved by the callee).
* This function is called directly by interrupt handling logic and from
* xtensa_context_save() below with interrupts disabled. In either calling
* context, caller saves saves PC, PS, A0, A1 (SP), and A2. This
* logic also executes indirectly from xtena_context_save() by falling
* through from above.
*
* Caller is expected to have saved PC, PS, A0, and A1 (SP).
*
* The counterparts to these functions are xtensa_context_restore() and
* xtensa_full_context_restore().
* The counterpart to this function is _xtensa_context_restore().
*
* Entry Conditions:
* - A0 = Return address in caller.
* - A1 = Stack pointer of calling thread or interrupt handler.
* - Other processor state except PC, PS, A0, and A1 (SP) are as at
* - A0 = Return address to caller.
* - A2 = Pointer to the processor state save area
* - Other processor state except PC, PS, A0, A1 (SP), and A2 are as at
* the point of interruption.
* - If windowed ABI, PS.EXCM = 1 (exceptions disabled).
*
* Exit conditions:
* Exit conditions:
* - A0 = Return address in caller.
* - A1 = Stack pointer of interrupted thread or handler ("interruptee").
* - A12-A15 as at entry (preserved).
* - A2, A12-A15 as at entry (preserved).
*
* Assumptions:
* - Caller is expected to have saved PC, PS, A0, A1 (SP), and A2.
* - If windowed ABI, PS.EXCM = 1 (exceptions disabled).
*
****************************************************************************/
.global xtensa_full_context_save
.global xtensa_context_save
.type xtensa_full_context_save, @function
.type xtensa_context_save, @function
.global _xtensa_context_save
.type _xtensa_context_save, @function
.align 4
.literal_position
.align 4
xtensa_full_context_save:
_xtensa_context_save:
#ifndef CONFIG_XTENSA_CALL0_ABI
/* Save Call0 ABI callee-saved regs a12-15. */
s32i a2, a2, (4 * REG_A2)
s32i a3, a2, (4 * REG_A3)
s32i a4, a2, (4 * REG_A4)
s32i a5, a2, (4 * REG_A5)
s32i a6, a2, (4 * REG_A6)
s32i a7, a2, (4 * REG_A7)
s32i a8, a2, (4 * REG_A8)
s32i a9, a2, (4 * REG_A9)
s32i a10, a2, (4 * REG_A10)
s32i a11, a2, (4 * REG_A11)
s32i a12, sp, (4 * REG_A12)
s32i a13, sp, (4 * REG_A13)
s32i a14, sp, (4 * REG_A14)
s32i a15, sp, (4 * REG_A15)
#endif
/* Call0 ABI callee-saved regs a12-15 */
xtensa_context_save:
s32i a2, sp, (4 * REG_A2)
s32i a3, sp, (4 * REG_A3)
s32i a4, sp, (4 * REG_A4)
s32i a5, sp, (4 * REG_A5)
s32i a6, sp, (4 * REG_A6)
s32i a7, sp, (4 * REG_A7)
s32i a8, sp, (4 * REG_A8)
s32i a9, sp, (4 * REG_A9)
s32i a10, sp, (4 * REG_A10)
s32i a11, sp, (4 * REG_A11)
/* Call0 ABI callee-saved regs a12-15 do not need to be saved here.
* a12-13 are the caller's responsibility so it can use them as scratch.
* So only need to save a14-a15 here for Windowed ABI (not Call0).
*/
#ifndef CONFIG_XTENSA_CALL0_ABI
s32i a12, sp, (4 * REG_A12)
s32i a13, sp, (4 * REG_A13)
s32i a14, sp, (4 * REG_A14)
s32i a15, sp, (4 * REG_A15)
#endif
s32i a12, a2, (4 * REG_A12)
s32i a13, a2, (4 * REG_A13)
s32i a14, a2, (4 * REG_A14)
s32i a15, a2, (4 * REG_A15)
rsr a3, SAR
s32i a3, sp, (4 * REG_SAR)
s32i a3, a2, (4 * REG_SAR)
#ifdef XTENSA_HAVE_LOOPS
rsr a3, LBEG
s32i a3, sp, (4 * REG_LBEG)
s32i a3, a2, (4 * REG_LBEG)
rsr a3, LEND
s32i a3, sp, (4 * REG_LEND)
s32i a3, a2, (4 * REG_LEND)
rsr a3, LCOUNT
s32i a3, sp, (4 * REG_LCOUNT)
s32i a3, a2, (4 * REG_LCOUNT)
#endif
#ifdef CONFIG_XTENSA_USE_SWPRI
@@ -172,7 +153,7 @@ xtensa_context_save:
movi a3, _xtensa_vprimask
l32i a3, a3, 0
s32i a3, sp, (4 * REG_VPRI)
s32i a3, a2, (4 * REG_VPRI)
#endif
#if XTENSA_EXTRA_SA_SIZE > 0 || !defined(CONFIG_XTENSA_CALL0_ABI)
@@ -187,9 +168,9 @@ xtensa_context_save:
* disabled (assured by PS.EXCM == 1).
*/
s32i a12, sp, (4 * REG_TMP0) /* Temp. save stuff in stack frame */
s32i a13, sp, (4 * REG_TMP1)
s32i a9, sp, (4 * REG_TMP2)
s32i a12, a2, (4 * REG_TMP0) /* Temp. save stuff in stack frame */
s32i a13, a2, (4 * REG_TMP1)
s32i a9, a2, (4 * REG_TMP2)
/* Save the overlay state if we are supporting overlays. Since we just
* saved three registers, we can conveniently use them here. Note that
@@ -197,14 +178,16 @@ xtensa_context_save:
*/
#ifdef CONFIG_XTENSA_USE_OVLY
l32i a9, sp, (4 * REG_PC) /* Recover saved PC */
l32i a9, a2, (4 * REG_PC) /* Recover saved PC */
_xt_overlay_get_state a9, a12, a13
s32i a9, sp, (4 * REG_OVLY) /* Save overlay state */
s32i a9, a2, (4 * REG_OVLY) /* Save overlay state */
#endif
l32i a12, sp, (4 * REG_A12) /* Recover original a9,12,13 */
l32i a13, sp, (4 * REG_A13)
l32i a9, sp, (4 * REG_A9)
l32i a12, a2, (4 * REG_A12) /* Recover original a9,12,13 */
l32i a13, a2, (4 * REG_A13)
l32i a9, a2, (4 * REG_A9)
#warning REVISIT: The following is probably not correct due to changes in registers
addi sp, sp, (4 * XCPTCONTEXT_SIZE) /* Restore the interruptee's SP */
call0 xthal_window_spill_nw /* Preserves only a4,5,8,9,12,13 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE)
@@ -223,7 +206,7 @@ xtensa_context_save:
* Future Xtensa tools releases might limit the regs that can be affected.
*/
addi a2, sp, (4 * REG_EXTRA) /* Where to save it */
addi a2, a2, (4 * REG_EXTRA) /* Where to save it */
#if XTENSA_EXTRA_SA_ALIGN > 16
movi a3, -XTENSA_EXTRA_SA_ALIGN
and a2, a2, a3 /* Align dynamically >16 bytes */
@@ -238,58 +221,99 @@ xtensa_context_save:
ret
/****************************************************************************
* Name: xtensa_context_restore
* xtensa_full_context_restore
* Name: xtensa_context_save
*
* Description:
*
* NOTE: MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION!
*
* This functions implements the moral equivalent of setjmp(). It is
* called from user code (with interrupts disabled) to save the current
* state of the running thread. This function always returns zero.
* However, it sets the saved value of the return address (A2) to 1.
* If the thread is restarted via _xtensa_contest_restore or
* xtensa_context_restore, it will appear as a second return from
* xtensa_context_save but with the returned value of 1 to distinguish
* the two cases.
*
* The counterpart to this function is xtensa_context_restore().
*
* Entry Conditions:
* - A0 = Return address to caller.
* - A2 = Pointer to the processor state save area
*
* Exit conditions:
* - A0 = Return address in caller.
* - A2 = 0
*
* Assumptions:
* - Interrupts are disabled.
*
****************************************************************************/
.global xtensa_context_save
.type xtensa_context_save, @function
.align 4
.literal_position
.align 4
xtensa_context_save:
/* Set up for call to _xtensa_context_save() */
rsr a12, EPS_2 /* Save callee's PS */
s32i a12, a2, (4 * REG_PS)
s32i a0, a2, (4 * REG_PC) /* Save Return address as PC */
s32i a0, a2, (4 * REG_A0) /* Save callee's a0 */
s32i sp, a2, (4 * REG_A1) /* Save callee's SP */
movi a12, 1 /* Set saved A2 to 1 */
s32i a12, a2, (4 * REG_A2)
/* Save the rest of the processor state */
call0 _xtensa_context_save /* Save full register state */
/* Recover the return address and return zero */
l32i a0, a2, (4 * REG_A0) /* Recover return addess */
movi a2, 0 /* Return zero */
ret
/****************************************************************************
* Name: _xtensa_context_restore
*
* Description:
*
* NOTE: MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION!
*
* These functions restores Xtensa processor state and differ in which
* registers are saved:
* registers are saved: _xtensa_context_restore() restores all registers
* except PC, PS, and A0
*
* - xtensa_full_context_restore restores all registers except PC, PS,
* A0, and A1 (SP)
* - xtensa_context_restore, in addition, does not restore A12-A15 which
* are preserved by the callee).
* The caller is responsible for restoring PC, PS, and A0 in both cases.
*
* The caller is responsible for restoring PC, PS, A0, A1 (SP) in both cases.
*
* xtensa_context_save and xtensa_full_context_save are the counterparts
* to these functions.
* _xtensa_context_save is the counterpart to this function.
*
* Entry Conditions:
* - A0 = Return address in caller.
* - A1 = Stack pointer of calling thread or interrupt handler.
* - A2 = Pointer to the processor state save area
*
* Exit conditions:
* - A0 = Return address in caller.
* - A1 = Stack pointer of calling thread or interrupt handler.
* - Other registers are restored as detailed above.
* - Other registers are restored as detailed above (including A1 and A2).
*
****************************************************************************/
.global xtensa_full_context_restore
.global xtensa_context_restore
.type xtensa_full_context_restore,@function
.type xtensa_context_restore,@function
.global _xtensa_context_restore
.type _xtensa_context_restore,@function
.align 4
.literal_position
.align 4
xtensa_full_context_restore:
#ifndef CONFIG_XTENSA_CALL0_ABI
/* Restore Call0 ABI callee-saved regs a12-15. */
l32i a12, sp, (4 * REG_A12)
l32i a13, sp, (4 * REG_A13)
l32i a14, sp, (4 * REG_A14)
l32i a15, sp, (4 * REG_A15)
#endif
xtensa_context_restore:
_xtensa_context_restore:
#if XTENSA_EXTRA_SA_SIZE > 0
/* NOTE: Normally the xthal_restore_extra_nw macro only affects address
@@ -302,7 +326,7 @@ xtensa_context_restore:
*/
mov a13, a0 /* Preserve ret addr */
addi a2, sp, (4 * REG_EXTRA) /* Where to find it */
addi a2, a2, (4 * REG_EXTRA) /* Where to find it */
#if XTENSA_EXTRA_SA_ALIGN > 16
movi a3, -XTENSA_EXTRA_SA_ALIGN
@@ -313,10 +337,10 @@ xtensa_context_restore:
#endif
#ifdef XTENSA_HAVE_LOOPS
l32i a2, sp, (4 * REG_LBEG)
l32i a3, sp, (4 * REG_LEND)
l32i a2, a2, (4 * REG_LBEG)
l32i a3, a2, (4 * REG_LEND)
wsr a2, LBEG
l32i a2, sp, (4 * REG_LCOUNT)
l32i a2, a2, (4 * REG_LCOUNT)
wsr a3, LEND
wsr a2, LCOUNT
#endif
@@ -329,13 +353,13 @@ xtensa_context_restore:
* to be restored.
*/
l32i a2, sp, (4 * REG_PC) /* Retrieve PC */
l32i a3, sp, (4 * REG_PS) /* Retrieve PS */
l32i a4, sp, (4 * REG_OVLY) /* Retrieve overlay state */
l32i a5, sp, (4 * REG_A1) /* Retrieve stack ptr */
l32i a2, a2, (4 * REG_PC) /* Retrieve PC */
l32i a3, a2, (4 * REG_PS) /* Retrieve PS */
l32i a4, a2, (4 * REG_OVLY) /* Retrieve overlay state */
l32i a5, a2, (4 * REG_A1) /* Retrieve stack ptr */
_xt_overlay_check_map a2, a3, a4, a5, a6
s32i a2, sp, (4 * REG_PC) /* Save updated PC */
s32i a3, sp, (4 * REG_PS) /* Save updated PS */
s32i a2, a2, (4 * REG_PC) /* Save updated PC */
s32i a3, a2, (4 * REG_PS) /* Save updated PS */
#endif
#ifdef CONFIG_XTENSA_USE_SWPRI
@@ -343,35 +367,96 @@ xtensa_context_restore:
movi a3, _xtensa_intdata
l32i a4, a3, 0 /* a4 = _xtensa_intenable */
l32i a5, sp, (4 * REG_VPRI) /* a5 = saved _xtensa_vprimask */
l32i a5, a2, (4 * REG_VPRI) /* a5 = saved _xtensa_vprimask */
and a4, a4, a5
wsr a4, INTENABLE /* Update INTENABLE */
s32i a5, a3, 4 /* Restore _xtensa_vprimask */
#endif
l32i a3, sp, (4 * REG_SAR)
l32i a2, sp, (4 * REG_A2)
l32i a3, a2, (4 * REG_SAR)
l32i sp, a2, (4 * REG_A1)
wsr a3, SAR
l32i a3, sp, (4 * REG_A3)
l32i a4, sp, (4 * REG_A4)
l32i a5, sp, (4 * REG_A5)
l32i a6, sp, (4 * REG_A6)
l32i a7, sp, (4 * REG_A7)
l32i a8, sp, (4 * REG_A8)
l32i a9, sp, (4 * REG_A9)
l32i a10, sp, (4 * REG_A10)
l32i a11, sp, (4 * REG_A11)
l32i a3, a2, (4 * REG_A3)
l32i a4, a2, (4 * REG_A4)
l32i a5, a2, (4 * REG_A5)
l32i a6, a2, (4 * REG_A6)
l32i a7, a2, (4 * REG_A7)
l32i a8, a2, (4 * REG_A8)
l32i a9, a2, (4 * REG_A9)
l32i a10, a2, (4 * REG_A10)
l32i a11, a2, (4 * REG_A11)
/* Call0 ABI callee-saved regs a12-15 do not need to be restored here.
* However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(),
* so need to be restored anyway, despite being callee-saved in Call0.
*/
/* Call0 ABI callee-saved regs a12-15 */
#ifndef CONFIG_XTENSA_CALL0_ABI
l32i a12, sp, (4 * REG_A12)
l32i a13, sp, (4 * REG_A13)
l32i a14, sp, (4 * REG_A14)
l32i a15, sp, (4 * REG_A15)
#endif
l32i a12, a2, (4 * REG_A12)
l32i a13, a2, (4 * REG_A13)
l32i a14, a2, (4 * REG_A14)
l32i a15, a2, (4 * REG_A15)
/* Finally, restore A2 with the correct value */
l32i a2, a2, (4 * REG_A2)
ret
/****************************************************************************
* Name: xtensa_context_restore
*
* Description:
*
* NOTE: MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION!
*
* This functions implements the moral equivalent of longjmp(). It is
* called from user code (with interrupts disabled) to restor the current
* state of the running thread. This function always returns 1 because
* the saved value of A2 was set to 1 in xtensa_context_save().
*
* The counterpart to this function is xtensa_context_save().
*
* Entry Conditions:
* - A0 = Return address to caller.
* - A2 = Pointer to the processor state save area
*
* Exit conditions:
* - A0 = Return address in caller.
* - A2 = 1
*
* NOTE: That this function does NOT return to the caller but rather
* to a new threading context.
*
* Assumptions:
* - Interrupts are disabled.
*
****************************************************************************/
.global xtensa_context_restore
.type xtensa_context_restore, @function
.align 4
.literal_position
.align 4
xtensa_context_restore:
/* Restore the processor state */
call0 _xtensa_context_restore /* Restore full register state */
/* Restore PC, PS, and A0. */
s32i a0, sp, (4 * REG_PS)
rsr a12, EPS_2 /* Save callee's PS */
s32i a12, sp, (4 * REG_PS)
s32i a0, a2, (4 * REG_PC) /* Save Return address as PC */
s32i a0, a2, (4 * REG_A0) /* Save callee's a0 */
s32i sp, a2, (4 * REG_A1) /* Save callee's SP */
movi a12, 1 /* Set saved A2 to 1 */
s32i a12, a2, (4 * REG_A2)
l32i a0, a2, (4 * REG_A0) /* Recover return addess */
movi a2, 0 /* Return zero */
ret
+1 -1
View File
@@ -49,7 +49,7 @@
****************************************************************************/
/****************************************************************************
* Name: up_copystate
* Name: xtensa_copystate
****************************************************************************/
/* A little faster than most memcpy's */
+31 -14
View File
@@ -272,7 +272,7 @@
* a CALL0 instruction. See "NOTES on the use of call0 ..." above.
*
* The corresponding handler sets up the appropriate stack frame, saves
* a few vector-specific registers and calls xtensa_full_context_save()
* a few vector-specific registers and calls _xtensa_context_save()
* to save the rest of the interrupted context. It then calls the C
* logic to decode the specific interrupt source and dispatch to the
* appropriate C interrupt handler.
@@ -283,7 +283,9 @@
.section .iram1,"ax"
.type _xtensa_level2_handler,@function
.align 4
_xtensa_level2_handler:
mov a0, sp /* sp == a1 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
@@ -296,7 +298,9 @@ _xtensa_level2_handler:
/* Save rest of interrupt context and enter RTOS. */
call0 xtensa_full_context_save /* Save full register state */
s32i a2, sp, (4 * REG_A2)
movi a2, sp /* Address of state save on stack */
call0 _xtensa_context_save /* Save full register state */
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
@@ -317,16 +321,17 @@ _xtensa_level2_handler:
/* Restore registers in preparation to return from interrupt */
call0 _xtensa_int_exit
call0 _xtensa_context_restore
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* retrieve interruptee's PS */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, EPS_2
l32i a0, sp, (4 * REG_PC) /* retrieve interruptee's PC */
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_2
l32i a0, sp, (4 * REG_A0) /* retrieve interruptee's A0 */
l32i sp, sp, (4 * REG_A1) /* remove interrupt stack frame */
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
rsync /* Ensure EPS and EPC written */
/* Return from interrupt. RFI restores the PS from EPS_2 and jumps to
@@ -381,6 +386,7 @@ documentation: "Microprocessor Programmer's Guide".
.section .iram1,"ax"
.type _xtensa_level2_handler, @function
.align 4
_xtensa_level2_handler:
#ifdef XT_INTEXC_HOOKS
@@ -389,8 +395,11 @@ _xtensa_level2_handler:
movi a0, _xt_intexc_hooks
l32i a0, a0, 2<<2
beqz a0, 1f
.Ln_xtensa_level2_handler_call_hook:
callx0 a0 /* Must NOT disturb stack! */
1:
#endif
@@ -399,7 +408,7 @@ _xtensa_level2_handler:
*/
.align 4
.L_xtensa_level2_handler_exit:
rsr a0, EXCSAVE_2 /* Restore a0 */
rfi 2
@@ -409,6 +418,7 @@ _xtensa_level2_handler:
.section .iram1,"ax"
.type _xtensa_level3_handler, @function
.align 4
_xtensa_level3_handler:
#ifdef XT_INTEXC_HOOKS
@@ -417,7 +427,9 @@ _xtensa_level3_handler:
movi a0, _xt_intexc_hooks
l32i a0, a0, 3<<2
beqz a0, 1f
.Ln_xtensa_level3_handler_call_hook:
callx0 a0 /* Must NOT disturb stack! */
1:
#endif
@@ -427,7 +439,7 @@ _xtensa_level3_handler:
*/
.align 4
.L_xtensa_level3_handler_exit:
rsr a0, EXCSAVE_3 /* Restore a0 */
rfi 3
@@ -437,6 +449,7 @@ _xtensa_level3_handler:
.section .iram1,"ax"
.type _xtensa_level4_handler,@function
.align 4
_xtensa_level4_handler:
#ifdef XT_INTEXC_HOOKS
@@ -445,7 +458,9 @@ _xtensa_level4_handler:
movi a0, _xt_intexc_hooks
l32i a0, a0, 4 << 2
beqz a0, 1f
.Ln_xtensa_level4_handler_call_hook:
callx0 a0 /* Must NOT disturb stack! */
1:
#endif
@@ -455,7 +470,7 @@ _xtensa_level4_handler:
*/
.align 4
.L_xtensa_level4_handler_exit:
rsr a0, EXCSAVE_4 /* Restore a0 */
rfi 4
@@ -465,6 +480,7 @@ _xtensa_level4_handler:
.section .iram1,"ax"
.type _xtensa_level5_handler,@function
.align 4
_xtensa_level5_handler:
#ifdef XT_INTEXC_HOOKS
@@ -473,7 +489,9 @@ _xtensa_level5_handler:
movi a0, _xt_intexc_hooks
l32i a0, a0, 5 << 2
beqz a0, 1f
.Ln_xtensa_level5_handler_call_hook:
callx0 a0 /* Must NOT disturb stack! */
1:
#endif
@@ -482,8 +500,6 @@ _xtensa_level5_handler:
* ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
*/
.align 4
.L_xtensa_level5_handler_exit:
rsr a0, EXCSAVE_5 /* restore a0 */
rfi 5
@@ -493,6 +509,7 @@ _xtensa_level5_handler:
.section .iram1,"ax"
.type _xtensa_level6_handler, @function
.align 4
_xtensa_level6_handler:
#ifdef XT_INTEXC_HOOKS
@@ -501,7 +518,9 @@ _xtensa_level6_handler:
movi a0, _xt_intexc_hooks
l32i a0, a0, 6 << 2
beqz a0, 1f
.Ln_xtensa_level6_handler_call_hook:
callx0 a0 /* Must NOT disturb stack! */
1:
#endif
@@ -510,8 +529,6 @@ _xtensa_level6_handler:
* ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
*/
.align 4
.L_xtensa_level6_handler_exit:
rsr a0, EXCSAVE_6 /* Restore a0 */
rfi 6
@@ -0,0 +1,144 @@
/****************************************************************************
* arch/xtensa/src/common/arm_releasepending.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sched.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include "sched/sched.h"
#include "group/group.h"
#include "xtensa.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_release_pending
*
* Description:
* Release and ready-to-run tasks that have
* collected in the pending task list. This can call a
* context switch if a new task is placed at the head of
* the ready to run list.
*
****************************************************************************/
void up_release_pending(void)
{
struct tcb_s *rtcb = this_task();
sinfo("From TCB=%p\n", rtcb);
/* Merge the g_pendingtasks list into the ready-to-run task list */
/* sched_lock(); */
if (sched_mergepending())
{
/* The currently active task has changed! We will need to
* switch contexts.
*/
/* Update scheduler parameters */
sched_suspend_scheduler(rtcb);
/* Are we operating in interrupt context? */
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
xtensa_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
xtensa_restorestate(rtcb->xcp.regs);
}
/* Copy the exception context into the TCB of the task that
* was currently active. if up_saveusercontext returns a non-zero
* value, then this is really the previously running task
* restarting!
*/
else if (!xtensa_context_save(rtcb->xcp.regs))
{
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
(void)group_addrenv(rtcb);
#endif
/* Update scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts */
xtensa_context_restore(rtcb->xcp.regs);
}
}
}
@@ -0,0 +1,198 @@
/****************************************************************************
* arch/xtensa/src/common/arm_reprioritizertr.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <sched.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include "sched/sched.h"
#include "group/group.h"
#include "xtensa.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_reprioritize_rtr
*
* Description:
* Called when the priority of a running or
* ready-to-run task changes and the reprioritization will
* cause a context switch. Two cases:
*
* 1) The priority of the currently running task drops and the next
* task in the ready to run list has priority.
* 2) An idle, ready to run task's priority has been raised above the
* the priority of the current, running task and it now has the
* priority.
*
* Inputs:
* tcb: The TCB of the task that has been reprioritized
* priority: The new task priority
*
****************************************************************************/
void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority)
{
/* Verify that the caller is sane */
if (tcb->task_state < FIRST_READY_TO_RUN_STATE ||
tcb->task_state > LAST_READY_TO_RUN_STATE
#if SCHED_PRIORITY_MIN > 0
|| priority < SCHED_PRIORITY_MIN
#endif
#if SCHED_PRIORITY_MAX < UINT8_MAX
|| priority > SCHED_PRIORITY_MAX
#endif
)
{
PANIC();
}
else
{
struct tcb_s *rtcb = this_task();
bool switch_needed;
sinfo("TCB=%p PRI=%d\n", tcb, priority);
/* Remove the tcb task from the ready-to-run list.
* sched_removereadytorun will return true if we just
* remove the head of the ready to run list.
*/
switch_needed = sched_removereadytorun(tcb);
/* Setup up the new task priority */
tcb->sched_priority = (uint8_t)priority;
/* Return the task to the specified blocked task list.
* sched_addreadytorun will return true if the task was
* added to the new list. We will need to perform a context
* switch only if the EXCLUSIVE or of the two calls is non-zero
* (i.e., one and only one the calls changes the head of the
* ready-to-run list).
*/
switch_needed ^= sched_addreadytorun(tcb);
/* Now, perform the context switch if one is needed */
if (switch_needed)
{
/* If we are going to do a context switch, then now is the right
* time to add any pending tasks back into the ready-to-run list.
* task list now
*/
if (g_pendingtasks.head)
{
sched_mergepending();
}
/* Update scheduler parameters */
sched_suspend_scheduler(rtcb);
/* Are we in an interrupt handler? */
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
xtensa_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
xtensa_restorestate(rtcb->xcp.regs);
}
/* Copy the exception context into the TCB at the (old) head of the
* ready-to-run Task list. if up_saveusercontext returns a non-zero
* value, then this is really the previously running task restarting!
*/
else if (!xtensa_context_save(rtcb->xcp.regs))
{
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
(void)group_addrenv(rtcb);
#endif
/* Update scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts */
xtensa_context_restore(rtcb->xcp.regs);
}
}
}
}
@@ -0,0 +1,190 @@
/****************************************************************************
* arch/xtensa/src/common/arm_schedulesigaction.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <stdint.h>
#include <sched.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include "sched/sched.h"
#include "xtensa.h"
#ifndef CONFIG_DISABLE_SIGNALS
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_schedule_sigaction
*
* Description:
* This function is called by the OS when one or more
* signal handling actions have been queued for execution.
* The architecture specific code must configure things so
* that the 'sigdeliver' callback is executed on the thread
* specified by 'tcb' as soon as possible.
*
* This function may be called from interrupt handling logic.
*
* This operation should not cause the task to be unblocked
* nor should it cause any immediate execution of sigdeliver.
* Typically, a few cases need to be considered:
*
* (1) This function may be called from an interrupt handler
* During interrupt processing, all xcptcontext structures
* should be valid for all tasks. That structure should
* be modified to invoke sigdeliver() either on return
* from (this) interrupt or on some subsequent context
* switch to the recipient task.
* (2) If not in an interrupt handler and the tcb is NOT
* the currently executing task, then again just modify
* the saved xcptcontext structure for the recipient
* task so it will invoke sigdeliver when that task is
* later resumed.
* (3) If not in an interrupt handler and the tcb IS the
* currently executing task -- just call the signal
* handler now.
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
{
irqstate_t flags;
sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver);
/* Make sure that interrupts are disabled */
flags = enter_critical_section();
/* Refuse to handle nested signal actions */
if (!tcb->xcp.sigdeliver)
{
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/
sinfo("rtcb=0x%p CURRENT_REGS=0x%p\n", this_task(), CURRENT_REGS);
if (tcb == this_task())
{
/* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
*/
if (!CURRENT_REGS)
{
/* In this case just deliver the signal now. */
sigdeliver(tcb);
}
/* CASE 2: We are in an interrupt handler AND the interrupted
* task is the same as the one that must receive the signal, then
* we will have to modify the return state as well as the state
* in the TCB.
*
* Hmmm... there looks like a latent bug here: The following logic
* would fail in the strange case where we are in an interrupt
* handler, the thread is signalling itself, but a context switch
* to another task has occurred so that CURRENT_REGS does not
* refer to the thread of this_task()!
*/
else
{
/* Save the return lr and cpsr and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.sigdeliver = sigdeliver;
tcb->xcp.saved_pc = CURRENT_REGS[REG_PC];
#warning REVISIT: Missing logic... need to save interrupt state
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
#warning REVISIT: Missing logic... need to set interrupt state with interrupts disabled
/* And make sure that the saved context in the TCB is the same
* as the interrupt return context.
*/
xtensa_savestate(tcb->xcp.regs);
}
}
/* Otherwise, we are (1) signaling a task is not running from an
* interrupt handler or (2) we are not in an interrupt handler and the
* running task is signalling some non-running task.
*/
else
{
/* Save the return lr and cpsr and one scratch register. These
* will be restored by the signal trampoline after the signals
* have been delivered.
*/
tcb->xcp.sigdeliver = sigdeliver;
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
#warning REVISIT: Missing logic... need to save interrupt state
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
#warning REVISIT: Missing logic... need to set interrupt state with interrupts disabled
}
}
leave_critical_section(flags);
}
#endif /* !CONFIG_DISABLE_SIGNALS */
+126
View File
@@ -0,0 +1,126 @@
/****************************************************************************
* arch/xtensa/src/common/arm_sigdeliver.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <stdint.h>
#include <sched.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include "sched/sched.h"
#include "xtensa.h"
#ifndef CONFIG_DISABLE_SIGNALS
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_sigdeliver
*
* Description:
* This is the a signal handling trampoline. When a signal action was
* posted. The task context was mucked with and forced to branch to this
* location with interrupts disabled.
*
****************************************************************************/
void up_sigdeliver(void)
{
struct tcb_s *rtcb = this_task();
uint32_t regs[XCPTCONTEXT_REGS];
sig_deliver_t sigdeliver;
/* Save the errno. This must be preserved throughout the signal handling
* so that the user code final gets the correct errno value (probably
* EINTR).
*/
int saved_errno = rtcb->pterrno;
board_autoled_on(LED_SIGNAL);
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
ASSERT(rtcb->xcp.sigdeliver != NULL);
/* Save the real return state on the stack. */
xtensa_copystate(regs, rtcb->xcp.regs);
regs[REG_PC] = rtcb->xcp.saved_pc;
#warbing Missing Logic... Need to restore the correct interrupt here
/* Get a local copy of the sigdeliver function pointer. we do this so that
* we can nullify the sigdeliver function pointer in the TCB and accept
* more signal deliveries while processing the current pending signals.
*/
sigdeliver = rtcb->xcp.sigdeliver;
rtcb->xcp.sigdeliver = NULL;
/* Then restore the task interrupt state */
up_irq_restore(regs[REG_CPSR]);
/* Deliver the signals */
sigdeliver(rtcb);
/* Output any debug messages BEFORE restoring errno (because they may
* alter errno), then disable interrupts again and restore the original
* errno that is needed by the user logic (it is probably EINTR).
*/
sinfo("Resuming\n");
(void)up_irq_save();
rtcb->pterrno = saved_errno;
/* Then restore the correct state for this thread of execution. */
board_autoled_off(LED_SIGNAL);
xtensa_context_restore(regs);
}
#endif /* !CONFIG_DISABLE_SIGNALS */
+159
View File
@@ -0,0 +1,159 @@
/****************************************************************************
* arch/xtensa/src/common/arm_unblocktask.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sched.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include "sched/sched.h"
#include "group/group.h"
#include "clock/clock.h"
#include "xtensa.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
*
* Inputs:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
{
struct tcb_s *rtcb = this_task();
/* Verify that the context switch can be performed */
ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Remove the task from the blocked task list */
sched_removeblocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (sched_addreadytorun(tcb))
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
*/
/* Update scheduler parameters */
sched_suspend_scheduler(rtcb);
/* Are we in an interrupt handler? */
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
xtensa_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
xtensa_restorestate(rtcb->xcp.regs);
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
*/
else if (!xtensa_context_save(rtcb->xcp.regs))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
rtcb = this_task();
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
(void)group_addrenv(rtcb);
#endif
/* Update scheduler parameters */
sched_resume_scheduler(rtcb);
/* Then switch contexts */
xtensa_context_restore(rtcb->xcp.regs);
}
}
}
+5 -3
View File
@@ -41,13 +41,15 @@ HEAD_CSRC = esp32_start.c
# Common XTENSA files (arch/xtensa/src/common)
CMN_ASRCS = xtensa_context.S xtensa_irq.S xtensa_intvectors.S
CMN_CSRCS = xtensa_assert.c xtensa_copystate.c
CMN_CSRCS = xtensa_assert.c xtensa_blocktask.c xtensa_copystate.c
CMN_CSRCS += xtensa_createstack.c xtensa_exit.c xtensa_idle.c
CMN_CSRCS += xtensa_initialize.c xtensa_initialstate.c
CMN_CSRCS += xtensa_interruptcontext.c xtensa_irqdispatch.c xtensa_lowputs.c
CMN_CSRCS += xtensa_mdelay.c xtensa_modifyreg8.c xtensa_modifyreg16.c
CMN_CSRCS += xtensa_modifyreg32.c xtensa_puts.c xtensa_releasestack.c
CMN_CSRCS += xtensa_stackframe.c xtensa_udelay.c xtensa_usestack.c
CMN_CSRCS += xtensa_modifyreg32.c xtensa_puts.c xtensa_releasepending.c
CMN_CSRCS += xtensa_releasestack.c xtensa_reprioritizertr.c
CMN_CSRCS += xtensa_schedsigaction.c xtensa_sigdeliver.c xtensa_stackframe.c
CMN_CSRCS += xtensa_udelay.c xtensa_unblocktask.c xtensa_usestack.c
# Configuration-dependent common XTENSA files
+1 -1
View File
@@ -137,7 +137,7 @@ int xtensa_start_handler(int irq, FAR void *context)
* be the CPUs NULL task.
*/
up_restorestate(tcb->xcp.regs);
xtensa_context_restore(tcb->xcp.regs);
return OK;
}