diff options
| author | yangjie11 <[email protected]> | 2020-11-18 09:56:35 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-11-18 09:56:35 +0800 |
| commit | d4a682e8d97fa131e5a8d795f8c5451d55cdd5b0 (patch) | |
| tree | 4773b40cb012475c5daf74bfd55707e141477669 /libcpu/arc/em | |
| parent | 2b98f4720c827ae1850df78299f6b273d568c8c7 (diff) | |
| parent | 2ef3c9d861f55253620996a94831a4be31ca6620 (diff) | |
Merge pull request #3 from RT-Thread/master
sync
Diffstat (limited to 'libcpu/arc/em')
| -rw-r--r-- | libcpu/arc/em/SConscript | 15 | ||||
| -rw-r--r-- | libcpu/arc/em/contex_gcc_mw.S | 364 | ||||
| -rw-r--r-- | libcpu/arc/em/cpuport.c | 87 |
3 files changed, 466 insertions, 0 deletions
diff --git a/libcpu/arc/em/SConscript b/libcpu/arc/em/SConscript new file mode 100644 index 0000000000..ff1d8c134d --- /dev/null +++ b/libcpu/arc/em/SConscript @@ -0,0 +1,15 @@ +# RT-Thread building script for component + +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +src += Glob('*.S') + +group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/arc/em/contex_gcc_mw.S b/libcpu/arc/em/contex_gcc_mw.S new file mode 100644 index 0000000000..81b291c1c8 --- /dev/null +++ b/libcpu/arc/em/contex_gcc_mw.S @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define __ASSEMBLY__ +#include "include/arc/arc.h" +#include "include/arc/arc_asm_common.h" + +.global rt_interrupt_enter; +.global rt_interrupt_leave; +.global context_switch_reqflg; +.global rt_interrupt_from_thread; +.global rt_interrupt_to_thread; +.global exc_nest_count; +.global set_hw_stack_check; + + .text + .align 4 +dispatcher: + st sp, [r0] + ld sp, [r1] +#if ARC_FEATURE_STACK_CHECK +#if ARC_FEATURE_SEC_PRESENT + lr r0, [AUX_SEC_STAT] + bclr r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 +#else + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_SC + kflag r0 +#endif + jl set_hw_stack_check +#if ARC_FEATURE_SEC_PRESENT + lr r0, [AUX_SEC_STAT] + bset r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 +#else + lr r0, [AUX_STATUS32] + bset r0, r0, AUX_STATUS_BIT_SC + kflag r0 +#endif +#endif + pop r0 + j [r0] + +/* return routine when task dispatch happened in task context */ +dispatch_r: + RESTORE_NONSCRATCH_REGS + j [blink] + +/* + * rt_base_t rt_hw_interrupt_disable(); + */ + .global rt_hw_interrupt_disable + .align 4 +rt_hw_interrupt_disable: + clri r0 + j [blink] + + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ + .global rt_hw_interrupt_enable + .align 4 +rt_hw_interrupt_enable: + seti r0 + j [blink] + + + .global rt_hw_context_switch_interrupt + .align 4 +rt_hw_context_switch_interrupt: + st r0, [rt_interrupt_from_thread] + st r1, [rt_interrupt_to_thread] + mov r0, 1 + st r0, [context_switch_reqflg] + j [blink] + + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); + * r0 --> from + * r1 --> to + */ + .global rt_hw_context_switch + .align 4 +rt_hw_context_switch: + SAVE_NONSCRATCH_REGS + mov r2, dispatch_r + push r2 + b dispatcher + + +/* + * void rt_hw_context_switch_to(rt_uint32 to); + * r0 --> to + */ + .global rt_hw_context_switch_to + .align 4 +rt_hw_context_switch_to: + ld sp, [r0] +#if ARC_FEATURE_STACK_CHECK + mov r1, r0 +#if ARC_FEATURE_SEC_PRESENT + lr r0, [AUX_SEC_STAT] + bclr r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 +#else + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_SC + kflag r0 +#endif + jl set_hw_stack_check +#if ARC_FEATURE_SEC_PRESENT + lr r0, [AUX_SEC_STAT] + bset r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 +#else + lr r0, [AUX_STATUS32] + bset r0, r0, AUX_STATUS_BIT_SC + kflag r0 +#endif +#endif + pop r0 + j [r0] + + .global start_r + .align 4 +start_r: + pop blink; + pop r1 + pop r2 + pop r0 + + j_s.d [r1] + kflag r2 + +/* + * int __rt_ffs(int value); + * r0 --> value + */ + .global __rt_ffs + .align 4 +__rt_ffs: + breq r0, 0, __rt_ffs_return + ffs r1, r0 + add r0, r1, 1 +__rt_ffs_return: + j [blink] + +/****** exceptions and interrupts handing ******/ +/****** entry for exception handling ******/ + .global exc_entry_cpu + .align 4 +exc_entry_cpu: + + EXCEPTION_PROLOGUE + + mov blink, sp + mov r3, sp /* as exception handler's para(p_excinfo) */ + + ld r0, [exc_nest_count] + add r1, r0, 1 + st r1, [exc_nest_count] + brne r0, 0, exc_handler_1 +/* change to exception stack if interrupt happened in task context */ + mov sp, _e_stack +exc_handler_1: + PUSH blink + + lr r0, [AUX_ECR] + lsr r0, r0, 16 + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] + + mov r0, r3 + jl [r2] + +/* interrupts are not allowed */ +ret_exc: + POP sp + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + st r0, [r1] + brne r0, 0, ret_exc_1 /* nest exception case */ + lr r1, [AUX_IRQ_ACT] /* nest interrupt case */ + brne r1, 0, ret_exc_1 + + ld r0, [context_switch_reqflg] + brne r0, 0, ret_exc_2 +ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */ + EXCEPTION_EPILOGUE + rtie + +/* there is a dispatch request */ +ret_exc_2: + /* clear dispatch request */ + mov r0, 0 + st r0, [context_switch_reqflg] + + SAVE_CALLEE_REGS /* save callee save registers */ + + /* clear exception bit to do exception exit by SW */ + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_AE + kflag r0 + + mov r1, ret_exc_r /* save return address */ + PUSH r1 + + ld r0, [rt_interrupt_from_thread] + ld r1, [rt_interrupt_to_thread] + b dispatcher + +ret_exc_r: + /* recover exception status */ + lr r0, [AUX_STATUS32] + bset r0, r0, AUX_STATUS_BIT_AE + kflag r0 + + RESTORE_CALLEE_REGS + EXCEPTION_EPILOGUE + rtie + +/****** entry for normal interrupt exception handling ******/ + .global exc_entry_int /* entry for interrupt handling */ + .align 4 +exc_entry_int: +#if ARC_FEATURE_FIRQ == 1 +/* check whether it is P0 interrupt */ +#if ARC_FEATURE_RGF_NUM_BANKS > 1 + lr r0, [AUX_IRQ_ACT] + btst r0, 0 + jnz exc_entry_firq +#else + PUSH r10 + lr r10, [AUX_IRQ_ACT] + btst r10, 0 + POP r10 + jnz exc_entry_firq +#endif +#endif + INTERRUPT_PROLOGUE + + mov blink, sp + + clri /* disable interrupt */ + ld r3, [exc_nest_count] + add r2, r3, 1 + st r2, [exc_nest_count] + seti /* enable higher priority interrupt */ + + brne r3, 0, irq_handler_1 +/* change to exception stack if interrupt happened in task context */ + mov sp, _e_stack +#if ARC_FEATURE_STACK_CHECK +#if ARC_FEATURE_SEC_PRESENT + lr r0, [AUX_SEC_STAT] + bclr r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 +#else + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_SC + kflag r0 +#endif +#endif +irq_handler_1: + PUSH blink + + jl rt_interrupt_enter + + lr r0, [AUX_IRQ_CAUSE] + sr r0, [AUX_IRQ_SELECT] + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */ +/* handle software triggered interrupt */ + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d irq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] +irq_hint_handled: + lr r3, [AUX_IRQ_PRIORITY] + PUSH r3 /* save irq priority */ + + jl [r2] /* jump to interrupt handler */ + jl rt_interrupt_leave +ret_int: + clri /* disable interrupt */ + POP r3 /* irq priority */ + POP sp + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + st r0, [r1] +/* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */ + lr r0, [AUX_IRQ_CAUSE] + sr r0, [AUX_IRQ_SELECT] + lr r3, [AUX_IRQ_PRIORITY] + lr r1, [AUX_IRQ_ACT] + bclr r2, r1, r3 + brne r2, 0, ret_int_1 + + ld r0, [context_switch_reqflg] + brne r0, 0, ret_int_2 +ret_int_1: /* return from non-task context */ + INTERRUPT_EPILOGUE + rtie +/* there is a dispatch request */ +ret_int_2: + /* clear dispatch request */ + mov r0, 0 + st r0, [context_switch_reqflg] + + /* interrupt return by SW */ + lr r10, [AUX_IRQ_ACT] + PUSH r10 + bclr r10, r10, r3 /* clear related bits in IRQ_ACT */ + sr r10, [AUX_IRQ_ACT] + + SAVE_CALLEE_REGS /* save callee save registers */ + mov r1, ret_int_r /* save return address */ + PUSH r1 + + ld r0, [rt_interrupt_from_thread] + ld r1, [rt_interrupt_to_thread] + b dispatcher + +ret_int_r: + RESTORE_CALLEE_REGS + /* recover AUX_IRQ_ACT to restore the interrup status */ + POPAX AUX_IRQ_ACT + INTERRUPT_EPILOGUE + rtie + +/****** entry for fast irq exception handling ******/ + .global exc_entry_firq + .weak exc_entry_firq + .align 4 +exc_entry_firq: + SAVE_FIQ_EXC_REGS + + lr r0, [AUX_IRQ_CAUSE] + mov r1, exc_int_handler_table +/* r2 = _kernel_exc_tbl + irqno *4 */ + ld.as r2, [r1, r0] + +/* for the case of software triggered interrupt */ + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d firq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] +firq_hint_handled: +/* jump to interrupt handler */ + mov r0, sp + jl [r2] + +firq_return: + RESTORE_FIQ_EXC_REGS + rtie diff --git a/libcpu/arc/em/cpuport.c b/libcpu/arc/em/cpuport.c new file mode 100644 index 0000000000..34f538881f --- /dev/null +++ b/libcpu/arc/em/cpuport.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include <rtthread.h> + +#include "arc/arc_exception.h" + +#if ARC_FEATURE_STACK_CHECK +#define ARC_INIT_STATUS ((1 << AUX_STATUS_BIT_SC) | AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE) +#else +#define ARC_INIT_STATUS (AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE) +#endif + +extern void start_r(void); + + +rt_uint32_t context_switch_reqflg; +rt_uint32_t rt_interrupt_from_thread; +rt_uint32_t rt_interrupt_to_thread; +rt_uint32_t exc_nest_count; + +struct init_stack_frame { + rt_uint32_t pc; + rt_uint32_t blink; + rt_uint32_t task; + rt_uint32_t status32; + rt_uint32_t r0; +}; + +/** + * shutdown CPU + */ +void rt_hw_cpu_shutdown(void) +{ + +} + +rt_uint8_t *rt_hw_stack_init(void *tentry, + void *parameter, + rt_uint8_t *stack_addr, + void *texit) +{ + struct init_stack_frame *stack_frame; + rt_uint8_t *stk; + + stk = stack_addr + sizeof(rt_uint32_t); + stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8); + stk -= sizeof(struct init_stack_frame); + + stack_frame = (struct init_stack_frame *)stk; + + stack_frame->pc = (rt_uint32_t)start_r; + stack_frame->blink = (rt_uint32_t)texit; + stack_frame->task = (rt_uint32_t)tentry; + stack_frame->status32 = ARC_INIT_STATUS; + stack_frame->r0 = (rt_uint32_t)parameter; + + return stk; +} + + +/** + * This function set the hook, which is invoked on fault exception handling. + * + * @param exception_handle the exception handling hook function. + */ +void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context)) +{ + exception_handle = exception_handle; +} + +void set_hw_stack_check(rt_uint32_t *from, rt_uint32_t *to) +{ + struct rt_thread *rt_thread_to; + if (to != NULL) { + rt_thread_to = rt_container_of(to, struct rt_thread, sp); +#if ARC_FEATURE_SEC_PRESENT + arc_aux_write(AUX_S_KSTACK_TOP, (uint32_t)(rt_thread_to->stack_addr)); + arc_aux_write(AUX_S_KSTACK_BASE, (uint32_t)(rt_thread_to->stack_addr)+rt_thread_to->stack_size); +#else + arc_aux_write(AUX_KSTACK_TOP, (uint32_t)(rt_thread_to->stack_addr)); + arc_aux_write(AUX_KSTACK_BASE, (uint32_t)(rt_thread_to->stack_addr)+rt_thread_to->stack_size); +#endif + } +} |
