mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 09:18:00 +08:00
Xtensa: First cat at context switching functions
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_copystate
|
||||
* Name: xtensa_copystate
|
||||
****************************************************************************/
|
||||
|
||||
/* A little faster than most memcpy's */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user