mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 10:58:49 +08:00
tlsr82/tc32: optimize the irq process
1. using armv6-m arm_irq(); 2. simplify the interrupt number get process; 3. To improve the performance, move common exception code to ram_code. Signed-off-by: wangbowen6 <wangbowen6@xiaomi.com>
This commit is contained in:
parent
6caa8f1075
commit
c39d3fa9e4
4 changed files with 253 additions and 317 deletions
|
@ -68,11 +68,9 @@
|
|||
.global __LOAD_DUT
|
||||
.global __LOAD_FLASH
|
||||
|
||||
.extern g_current_regs
|
||||
|
||||
__start: @ MUST, referenced by boot.link
|
||||
|
||||
.extern irq_handler
|
||||
.extern tc32_exception
|
||||
|
||||
.extern firmwareVersion
|
||||
|
||||
|
@ -388,176 +386,20 @@ IDLE_STACK:
|
|||
@ src code for the irq proc part .
|
||||
|
||||
__irq:
|
||||
/* Save R0 ~ R3, these registers will be used */
|
||||
/* Save R0 ~ R3, these registers will be used before saved */
|
||||
|
||||
tpush {r0}
|
||||
tpush {r1}
|
||||
tpush {r2}
|
||||
tpush {r3}
|
||||
|
||||
/* Switch to SVC mode to get the SVC mode SP, then save context
|
||||
* into the interrupted task stack.
|
||||
*/
|
||||
|
||||
/* Disable interrupt, because cpu will switch into SVC mode, interrupt
|
||||
* nested should be prevented, this is not supported by tc32
|
||||
* architecture.
|
||||
*/
|
||||
|
||||
tloadr r0, _REG_IRQ_EN @ disable irq
|
||||
tloadrb r1, [r0] @ get irq state in R1
|
||||
tmov r2, #0 @ disable irq
|
||||
tstorerb r2, [r0] @ disable irq
|
||||
|
||||
/* Switch to SVC mode and get the LR and SP in SVC mode */
|
||||
|
||||
tloadr r0, _REG_IRQ_EN + 4 @ switch to SVC mode
|
||||
tnop
|
||||
tmcsr r0 @ switch to SVC mode
|
||||
tnop
|
||||
tmov r2, r14 @ get SVC mode LR in R2
|
||||
tmov r3, r13 @ get SVC mode SP in R3
|
||||
tloadr r0, _REG_IRQ_EN + 8 @ return to IRQ mode
|
||||
tnop
|
||||
tmcsr r0 @ return to IRQ mode
|
||||
tnop
|
||||
|
||||
/* R0 = the interrupted task SP after context save */
|
||||
|
||||
tmov r0, #XCPTCONTEXT_SIZE
|
||||
tsub r0, r3, r0
|
||||
|
||||
/* Save IRQ_STATE, SVC mode SP and SVC mode LR as PC */
|
||||
|
||||
tstorer r1, [r0, #(4 * REG_IRQ_EN)]
|
||||
tstorer r3, [r0, #(4 * REG_SP)]
|
||||
tstorer r2, [r0, #(4 * REG_PC)]
|
||||
|
||||
/* Get SPSR and save as CPSR */
|
||||
|
||||
tmrss r1
|
||||
tstorer r1, [r0, #(4 * REG_CPSR)]
|
||||
|
||||
/* Save IRQ mode LR as LR */
|
||||
|
||||
tmov r1, r14
|
||||
tstorer r1, [r0, #(4 * REG_LR)]
|
||||
|
||||
/* Pop the saved R1 ~ R3 (pushed in beginning of irq),
|
||||
* then save R1 ~ R7.
|
||||
*/
|
||||
|
||||
tpop {r3}
|
||||
tpop {r2}
|
||||
tpop {r1}
|
||||
tstorer r1, [r0, #(4 * REG_R1)]
|
||||
tstorer r2, [r0, #(4 * REG_R2)]
|
||||
tstorer r3, [r0, #(4 * REG_R3)]
|
||||
tstorer r4, [r0, #(4 * REG_R4)]
|
||||
tstorer r5, [r0, #(4 * REG_R5)]
|
||||
tstorer r6, [r0, #(4 * REG_R6)]
|
||||
tstorer r7, [r0, #(4 * REG_R7)]
|
||||
|
||||
/* Pop R0 and save it */
|
||||
|
||||
tpop {r1}
|
||||
tstorer r1, [r0, #(4 * REG_R0)]
|
||||
|
||||
/* Save R8 ~ R12 */
|
||||
|
||||
tmov r1, r8
|
||||
tstorer r1, [r0, #(4 * REG_R8)]
|
||||
tmov r1, r9
|
||||
tstorer r1, [r0, #(4 * REG_R9)]
|
||||
tmov r1, r10
|
||||
tstorer r1, [r0, #(4 * REG_R10)]
|
||||
tmov r1, r11
|
||||
tstorer r1, [r0, #(4 * REG_R11)]
|
||||
tmov r1, r12
|
||||
tstorer r1, [r0, #(4 * REG_R12)]
|
||||
|
||||
/* R0 = interrupted task SP after the context save */
|
||||
|
||||
tjl irq_handler
|
||||
|
||||
/* R0 = interrupted task SP after the context save (no context switch)
|
||||
* = next task tcb->regs (with context switch)
|
||||
* Restore all the register according to R0
|
||||
*/
|
||||
|
||||
/* Dsiable interrupt to protect the SVC mode */
|
||||
|
||||
tloadr r2, _REG_IRQ_EN @ disable irq
|
||||
tmov r3, #0 @ disable irq
|
||||
tstorerb r3, [r2] @ disable irq
|
||||
|
||||
/* Restore SVC mode SP (R13), SVC mode LR (R14, based saved PC)
|
||||
* PC is not need to retore */
|
||||
|
||||
tloadr r2, [r0, #(4 * REG_SP)]
|
||||
tloadr r3, [r0, #(4 * REG_PC)]
|
||||
|
||||
tloadr r1, _REG_IRQ_EN + 4 @ switch to SVC mode
|
||||
tnop
|
||||
tmcsr r1 @ switch to SVC mode
|
||||
tnop
|
||||
tmov r14, r3 @ restore SVC mode LR
|
||||
tmov r13, r2 @ restore SVC mode SP
|
||||
tloadr r1, _REG_IRQ_EN + 8 @ return to IRQ mode
|
||||
tnop
|
||||
tmcsr r1 @ return to IRQ mode
|
||||
tnop
|
||||
|
||||
/* Restore CPSR to SPSR, IRQ_STATE */
|
||||
|
||||
tloadr r2, [r0, #(4 * REG_CPSR)]
|
||||
tloadr r3, [r0, #(4 * REG_IRQ_EN)]
|
||||
|
||||
tmssr r2 @ restore CPSR to SPSR
|
||||
|
||||
tloadr r1, _REG_IRQ_EN @ restore IRQ enable flag
|
||||
tstorerb r3, [r1] @ restore IRQ enable flag
|
||||
|
||||
/* Restore R8 ~ R12, IRQ mode LR */
|
||||
|
||||
tloadr r2, [r0, #(4 * REG_R8)]
|
||||
tloadr r3, [r0, #(4 * REG_R9)]
|
||||
tloadr r4, [r0, #(4 * REG_R10)]
|
||||
tloadr r5, [r0, #(4 * REG_R11)]
|
||||
tloadr r6, [r0, #(4 * REG_R12)]
|
||||
tloadr r7, [r0, #(4 * REG_LR)]
|
||||
|
||||
tmov r8, r2
|
||||
tmov r9, r3
|
||||
tmov r10, r4
|
||||
tmov r11, r5
|
||||
tmov r12, r6
|
||||
tmov r14, r7
|
||||
|
||||
/* Restore R1 ~ R7 */
|
||||
|
||||
tloadr r1, [r0, #(4 * REG_R1)]
|
||||
tloadr r2, [r0, #(4 * REG_R2)]
|
||||
tloadr r3, [r0, #(4 * REG_R3)]
|
||||
tloadr r4, [r0, #(4 * REG_R4)]
|
||||
tloadr r5, [r0, #(4 * REG_R5)]
|
||||
tloadr r6, [r0, #(4 * REG_R6)]
|
||||
tloadr r7, [r0, #(4 * REG_R7)]
|
||||
|
||||
/* Restore R0 */
|
||||
|
||||
tloadr r0, [r0, #(4 * REG_R0)]
|
||||
|
||||
/* Return to interrupted task or next task */
|
||||
/* Save LR, LR will change after tjl instruction */
|
||||
|
||||
tpush {r14}
|
||||
treti {r15}
|
||||
|
||||
.align 4
|
||||
_REG_IRQ_EN:
|
||||
.word 0x00800643
|
||||
.word 0x00000093
|
||||
.word 0x00000092
|
||||
/* Call tc32_exception */
|
||||
|
||||
tjl tc32_exception
|
||||
|
||||
ASMEND:
|
||||
.section .bss
|
||||
|
|
|
@ -42,11 +42,12 @@ CMN_CSRCS := $(filter-out $(TC32_CSRCS_FILTER), $(CMN_CSRCS))
|
|||
|
||||
# Common files in arch/arm/src/armv6-m
|
||||
|
||||
CMN_CSRCS += arm_sigdeliver.c
|
||||
CMN_CSRCS += arm_sigdeliver.c arm_doirq.c
|
||||
|
||||
# Common files in arch/arm/src/tlsr82/tc32
|
||||
|
||||
CMN_ASRCS += tc32_fullcontextrestore.S tc32_switchcontext.S tc32_saveusercontext.S
|
||||
CMN_ASRCS += tc32_fullcontextrestore.S tc32_switchcontext.S
|
||||
CMN_ASRCS += tc32_saveusercontext.S tc32_exception.S
|
||||
|
||||
CMN_CSRCS += tc32_doirq.c tc32_initialstate.c tc32_schedulesigaction.c
|
||||
CMN_CSRCS += tc32_syscall.c tc32_udelay.c
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
#include "arm_internal.h"
|
||||
|
||||
#include "group/group.h"
|
||||
|
||||
#include "hardware/tlsr82_irq.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -53,75 +51,10 @@
|
|||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const uint8_t tc32_lowbit_bitmap[] =
|
||||
{
|
||||
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 00 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 10 */
|
||||
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 20 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 30 */
|
||||
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 40 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 50 */
|
||||
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 60 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 70 */
|
||||
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 80 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 90 */
|
||||
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* A0 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* B0 */
|
||||
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* C0 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* D0 */
|
||||
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* E0 */
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* F0 */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tc32_ffs
|
||||
*
|
||||
* Description:
|
||||
* This function finds the first bit set (beginning with the least
|
||||
* significant bit) in value and return the index of that bit.
|
||||
* TC32 archtecture does not support clz instruction.
|
||||
*
|
||||
* Parameters:
|
||||
* uint32_t - value
|
||||
*
|
||||
* Return Value:
|
||||
* [1, 32] - On Success.
|
||||
* 0 - No set bit in value (value = 0).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int locate_code(".ram_code") tc32_ffs(uint32_t value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
else if (value & 0xff)
|
||||
{
|
||||
ret = (int)tc32_lowbit_bitmap[value & 0xff] + 1;
|
||||
}
|
||||
else if (value & 0xff00)
|
||||
{
|
||||
ret = (int)tc32_lowbit_bitmap[(value & 0xff00) >> 8] + 9;
|
||||
}
|
||||
else if (value & 0xff0000)
|
||||
{
|
||||
ret = (int)tc32_lowbit_bitmap[(value & 0xff0000) >> 16] + 17;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (int)tc32_lowbit_bitmap[(value & 0xff000000) >> 24] + 25;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tc32_getirq
|
||||
*
|
||||
|
@ -141,22 +74,17 @@ static inline int locate_code(".ram_code") tc32_ffs(uint32_t value)
|
|||
static int locate_code(".ram_code") tc32_getirq(void)
|
||||
{
|
||||
int irq;
|
||||
uint32_t value;
|
||||
|
||||
/* Only detect the enable interrupt */
|
||||
value = IRQ_SRC_REG & IRQ_MASK_REG;
|
||||
|
||||
irq = tc32_ffs(IRQ_SRC_REG & IRQ_MASK_REG);
|
||||
|
||||
if (irq > 0 && irq <= NR_IRQS)
|
||||
if (value == 0)
|
||||
{
|
||||
/* Minus one to obatin the correct irq number */
|
||||
|
||||
irq = irq - 1;
|
||||
irq = NR_IRQS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid irq number */
|
||||
|
||||
irq = NR_IRQS;
|
||||
irq = __builtin_ctz(value);
|
||||
}
|
||||
|
||||
return irq;
|
||||
|
@ -166,82 +94,16 @@ static int locate_code(".ram_code") tc32_getirq(void)
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function serves to handle the interrupt of MCU
|
||||
* @param[in] none
|
||||
* @return none
|
||||
*/
|
||||
/****************************************************************************
|
||||
* Name: arm_ack_irq
|
||||
*
|
||||
* Description:
|
||||
* Acknowledge the IRQ
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
void arm_ack_irq(int irq)
|
||||
{
|
||||
board_autoled_on(LED_INIRQ);
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
PANIC();
|
||||
#else
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* g_current_regs is also used to manage interrupt level context switches.
|
||||
*
|
||||
* Nested interrupts are not supported
|
||||
*/
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
CURRENT_REGS = regs;
|
||||
|
||||
/* Disable further occurrences of this interrupt (until the interrupt
|
||||
* sources have been clear by the driver).
|
||||
*/
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* g_current_regs will have a different value than it did on entry. If an
|
||||
* interrupt level context switch has occurred, then restore the floating
|
||||
* point state and the establish the correct address environment before
|
||||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
/* Restore floating point registers */
|
||||
|
||||
riscv_restorefpu(CURRENT_REGS);
|
||||
#endif
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
||||
group_addrenv(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If a context switch occurred while processing the interrupt then
|
||||
* g_current_regs may have change value. If we return any value different
|
||||
* from the input regs, then the lower level will know that a context
|
||||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
|
||||
/* Set g_current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
|
||||
/* Unmask the last interrupt (global interrupts are still disabled) */
|
||||
|
||||
#endif
|
||||
board_autoled_off(LED_INIRQ);
|
||||
return regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
231
arch/arm/src/tlsr82/tc32/tc32_exception.S
Normal file
231
arch/arm/src/tlsr82/tc32/tc32_exception.S
Normal file
|
@ -0,0 +1,231 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/tlsr82/tc32/tc32_exception.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <arch/chip/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "tc32_exception.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Macros
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tc32_exception
|
||||
*
|
||||
* Description:
|
||||
* TC32 Common exception
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.align 2
|
||||
.code 16
|
||||
.thumb_func
|
||||
.section .ram_code,"ax"
|
||||
.extern irq_handler
|
||||
.global tc32_exception
|
||||
.type tc32_exception, function
|
||||
tc32_exception:
|
||||
|
||||
/* Restore the R14 (LR) saved in __irq */
|
||||
|
||||
tpop {r3}
|
||||
tmov r14, r3
|
||||
|
||||
/* Switch to SVC mode to get the SVC mode SP, then save context
|
||||
* into the interrupted task stack.
|
||||
*/
|
||||
|
||||
/* Disable interrupt, because cpu will switch into SVC mode, interrupt
|
||||
* nested should be prevented, this is not supported by tc32
|
||||
* architecture.
|
||||
*/
|
||||
|
||||
tloadr r0, _REG_IRQ_EN /* disable irq */
|
||||
tloadrb r1, [r0] /* get irq state in R1 */
|
||||
tmov r2, #0 /* disable irq */
|
||||
tstorerb r2, [r0] /* disable irq */
|
||||
|
||||
/* Switch to SVC mode and get the LR and SP in SVC mode */
|
||||
|
||||
tloadr r0, _REG_IRQ_EN + 4 /* switch to SVC mode */
|
||||
tnop
|
||||
tmcsr r0 /* switch to SVC mode */
|
||||
tnop
|
||||
tmov r2, r14 /* get SVC mode LR in R2 */
|
||||
tmov r3, r13 /* get SVC mode SP in R3 */
|
||||
tloadr r0, _REG_IRQ_EN + 8 /* return to IRQ mode */
|
||||
tnop
|
||||
tmcsr r0 /* return to IRQ mode */
|
||||
tnop
|
||||
|
||||
/* R0 = the interrupted task SP after context save */
|
||||
|
||||
tmov r0, #XCPTCONTEXT_SIZE
|
||||
tsub r0, r3, r0
|
||||
|
||||
/* Save IRQ_STATE, SVC mode SP and SVC mode LR as PC */
|
||||
|
||||
tstorer r1, [r0, #(4 * REG_IRQ_EN)]
|
||||
tstorer r3, [r0, #(4 * REG_SP)]
|
||||
tstorer r2, [r0, #(4 * REG_PC)]
|
||||
|
||||
/* Get SPSR and save as CPSR */
|
||||
|
||||
tmrss r1
|
||||
tstorer r1, [r0, #(4 * REG_CPSR)]
|
||||
|
||||
/* Save IRQ mode LR as LR */
|
||||
|
||||
tmov r1, r14
|
||||
tstorer r1, [r0, #(4 * REG_LR)]
|
||||
|
||||
/* Pop the saved R1 ~ R3 (pushed in beginning of irq),
|
||||
* then save R1 ~ R7.
|
||||
*/
|
||||
|
||||
tpop {r3}
|
||||
tpop {r2}
|
||||
tpop {r1}
|
||||
tstorer r1, [r0, #(4 * REG_R1)]
|
||||
tstorer r2, [r0, #(4 * REG_R2)]
|
||||
tstorer r3, [r0, #(4 * REG_R3)]
|
||||
tstorer r4, [r0, #(4 * REG_R4)]
|
||||
tstorer r5, [r0, #(4 * REG_R5)]
|
||||
tstorer r6, [r0, #(4 * REG_R6)]
|
||||
tstorer r7, [r0, #(4 * REG_R7)]
|
||||
|
||||
/* Pop R0 and save it */
|
||||
|
||||
tpop {r1}
|
||||
tstorer r1, [r0, #(4 * REG_R0)]
|
||||
|
||||
/* Save R8 ~ R12 */
|
||||
|
||||
tmov r1, r8
|
||||
tstorer r1, [r0, #(4 * REG_R8)]
|
||||
tmov r1, r9
|
||||
tstorer r1, [r0, #(4 * REG_R9)]
|
||||
tmov r1, r10
|
||||
tstorer r1, [r0, #(4 * REG_R10)]
|
||||
tmov r1, r11
|
||||
tstorer r1, [r0, #(4 * REG_R11)]
|
||||
tmov r1, r12
|
||||
tstorer r1, [r0, #(4 * REG_R12)]
|
||||
|
||||
/* R0 = interrupted task SP after the context save */
|
||||
|
||||
tjl irq_handler
|
||||
|
||||
/* R0 = interrupted task SP after the context save (no context switch)
|
||||
* = next task tcb->regs (with context switch)
|
||||
* Restore all the register according to R0
|
||||
*/
|
||||
|
||||
/* Dsiable interrupt to protect the SVC mode */
|
||||
|
||||
tloadr r2, _REG_IRQ_EN /* disable irq */
|
||||
tmov r3, #0 /* disable irq */
|
||||
tstorerb r3, [r2] /* disable irq */
|
||||
|
||||
/* Restore SVC mode SP (R13), SVC mode LR (R14, based saved PC)
|
||||
* PC is not need to retore */
|
||||
|
||||
tloadr r2, [r0, #(4 * REG_SP)]
|
||||
tloadr r3, [r0, #(4 * REG_PC)]
|
||||
|
||||
tloadr r1, _REG_IRQ_EN + 4 /* switch to SVC mode */
|
||||
tnop
|
||||
tmcsr r1 /* switch to SVC mode */
|
||||
tnop
|
||||
tmov r14, r3 /* restore SVC mode LR */
|
||||
tmov r13, r2 /* restore SVC mode SP */
|
||||
tloadr r1, _REG_IRQ_EN + 8 /* return to IRQ mode */
|
||||
tnop
|
||||
tmcsr r1 /* return to IRQ mode */
|
||||
tnop
|
||||
|
||||
/* Restore CPSR to SPSR, IRQ_STATE */
|
||||
|
||||
tloadr r2, [r0, #(4 * REG_CPSR)]
|
||||
tloadr r3, [r0, #(4 * REG_IRQ_EN)]
|
||||
|
||||
tmssr r2 /* restore CPSR to SPSR */
|
||||
|
||||
tloadr r1, _REG_IRQ_EN /* restore IRQ enable flag */
|
||||
tstorerb r3, [r1] /* restore IRQ enable flag */
|
||||
|
||||
/* Restore R8 ~ R12, IRQ mode LR */
|
||||
|
||||
tloadr r2, [r0, #(4 * REG_R8)]
|
||||
tloadr r3, [r0, #(4 * REG_R9)]
|
||||
tloadr r4, [r0, #(4 * REG_R10)]
|
||||
tloadr r5, [r0, #(4 * REG_R11)]
|
||||
tloadr r6, [r0, #(4 * REG_R12)]
|
||||
tloadr r7, [r0, #(4 * REG_LR)]
|
||||
|
||||
tmov r8, r2
|
||||
tmov r9, r3
|
||||
tmov r10, r4
|
||||
tmov r11, r5
|
||||
tmov r12, r6
|
||||
tmov r14, r7
|
||||
|
||||
/* Restore R1 ~ R7 */
|
||||
|
||||
tloadr r1, [r0, #(4 * REG_R1)]
|
||||
tloadr r2, [r0, #(4 * REG_R2)]
|
||||
tloadr r3, [r0, #(4 * REG_R3)]
|
||||
tloadr r4, [r0, #(4 * REG_R4)]
|
||||
tloadr r5, [r0, #(4 * REG_R5)]
|
||||
tloadr r6, [r0, #(4 * REG_R6)]
|
||||
tloadr r7, [r0, #(4 * REG_R7)]
|
||||
|
||||
/* Restore R0 */
|
||||
|
||||
tloadr r0, [r0, #(4 * REG_R0)]
|
||||
|
||||
/* Return to interrupted task or next task */
|
||||
|
||||
tpush {r14}
|
||||
treti {r15}
|
||||
|
||||
.align 4
|
||||
_REG_IRQ_EN:
|
||||
.word 0x00800643
|
||||
.word 0x00000093
|
||||
.word 0x00000092
|
||||
.size tc32_exception, .-tc32_exception
|
||||
.end
|
Loading…
Reference in a new issue