From c39d3fa9e48246d0b2385df1585f60d86068f076 Mon Sep 17 00:00:00 2001 From: wangbowen6 Date: Wed, 11 May 2022 20:23:23 +0800 Subject: [PATCH] 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 --- .../src/tlsr82/chip/b87/boot/cstartup_flash.S | 170 +------------ arch/arm/src/tlsr82/tc32/Make.defs | 5 +- arch/arm/src/tlsr82/tc32/tc32_doirq.c | 164 +------------ arch/arm/src/tlsr82/tc32/tc32_exception.S | 231 ++++++++++++++++++ 4 files changed, 253 insertions(+), 317 deletions(-) create mode 100644 arch/arm/src/tlsr82/tc32/tc32_exception.S diff --git a/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S b/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S index 50656a388f..6a676565bb 100644 --- a/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S +++ b/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S @@ -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 diff --git a/arch/arm/src/tlsr82/tc32/Make.defs b/arch/arm/src/tlsr82/tc32/Make.defs index 5efb136860..bd0cc3c84a 100644 --- a/arch/arm/src/tlsr82/tc32/Make.defs +++ b/arch/arm/src/tlsr82/tc32/Make.defs @@ -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 diff --git a/arch/arm/src/tlsr82/tc32/tc32_doirq.c b/arch/arm/src/tlsr82/tc32/tc32_doirq.c index bbe178da8c..e217eb9041 100644 --- a/arch/arm/src/tlsr82/tc32/tc32_doirq.c +++ b/arch/arm/src/tlsr82/tc32/tc32_doirq.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; } /**************************************************************************** diff --git a/arch/arm/src/tlsr82/tc32/tc32_exception.S b/arch/arm/src/tlsr82/tc32/tc32_exception.S new file mode 100644 index 0000000000..1c5249f9d4 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_exception.S @@ -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 + +/**************************************************************************** + * 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