arch: arc: update the ARC port
* add basic synopsys arc em processor support * add basic arc nsim em virtual board support * add basic arc mwdt toolchain support Signed-off-by: Watson Zeng <zhiwei@synopsys.com>
This commit is contained in:
@@ -273,6 +273,8 @@ __PORT__ void port_cpsr_restore(cpu_cpsr_t cpsr);
|
||||
|
||||
__PORT__ void port_cpu_reset(void);
|
||||
|
||||
__PORT__ uint32_t port_cpu_clz(uint32_t);
|
||||
|
||||
__PORT__ void port_sched_start(void) __NO_RETURN__;
|
||||
|
||||
__PORT__ void port_context_switch(void);
|
@@ -52,7 +52,7 @@ __PORT__ void port_cpu_reset(void)
|
||||
|
||||
__PORT__ void port_systick_config(uint32_t cycle_per_tick) // Configure SysTick to generate an interrupt every cycle_per_tick
|
||||
{
|
||||
timer_int_clear(0); // nsim #define BOARD_SYS_TIMER_ID TIMER_0
|
||||
arc_timer_int_clear(0); // nsim #define BOARD_SYS_TIMER_ID TIMER_0
|
||||
board_timer_update(cycle_per_tick); // board.c
|
||||
}
|
||||
__PORT__ void port_systick_priority_set(uint32_t prio) // Sets the int priority
|
@@ -21,15 +21,10 @@
|
||||
#define TOS_CFG_CPU_ADDR_SIZE CPU_WORD_SIZE_32
|
||||
#define TOS_CFG_CPU_DATA_SIZE CPU_WORD_SIZE_32
|
||||
#define TOS_CFG_CPU_STK_GROWTH CPU_STK_GROWTH_DESCENDING
|
||||
// #define TOS_CFG_CPU_HRTIMER_SIZE CPU_WORD_SIZE_32
|
||||
#define TOS_CFG_CPU_HRTIMER_EN 0u
|
||||
#define TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT 1u
|
||||
#define TOS_CFG_CPU_HRTIMER_EN 0u
|
||||
#define TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT 0u
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
#define TOS_CFG_CPU_ARM_FPU_EN 1u
|
||||
#else
|
||||
#define TOS_CFG_CPU_ARM_FPU_EN 0u
|
||||
#endif
|
||||
#define TOS_CFG_CPU_ARM_FPU_EN 0u
|
||||
|
||||
#endif /* _PORT_CONFIG_H_ */
|
||||
|
360
arch/arc/arcem/port_s.s
Normal file
360
arch/arc/arcem/port_s.s
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Synopsys, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define __ASSEMBLY__
|
||||
#include "arc.h"
|
||||
#include "arc_asm_common.h"
|
||||
|
||||
.global k_curr_task
|
||||
.global k_next_task
|
||||
|
||||
.global g_exc_nest_count
|
||||
.global g_context_switch_reqflg
|
||||
|
||||
.global tos_knl_irq_enter
|
||||
.global tos_knl_irq_leave
|
||||
|
||||
.text
|
||||
.align 4
|
||||
dispatcher:
|
||||
st sp, [r0] // ld r0, [k_curr_task]
|
||||
ld sp, [r1] // ld r1, [k_next_task]
|
||||
# k_curr_task = k_next_task;
|
||||
st r1, [k_curr_task]
|
||||
pop r0
|
||||
j [r0]
|
||||
|
||||
/* return routine when task dispatch happened in task context */
|
||||
dispatch_r:
|
||||
RESTORE_NONSCRATCH_REGS
|
||||
j [blink]
|
||||
|
||||
/*
|
||||
* void port_int_disable(void);
|
||||
*/
|
||||
.global port_int_disable
|
||||
.align 4
|
||||
port_int_disable:
|
||||
clri
|
||||
j [blink]
|
||||
|
||||
/*
|
||||
* void port_int_enable(void);
|
||||
*/
|
||||
.global port_int_enable
|
||||
.align 4
|
||||
port_int_enable:
|
||||
seti
|
||||
j [blink]
|
||||
|
||||
/*
|
||||
* cpu_cpsr_t port_cpsr_save(void);
|
||||
*/
|
||||
.global port_cpsr_save
|
||||
.align 4
|
||||
port_cpsr_save:
|
||||
clri r0
|
||||
j [blink]
|
||||
|
||||
/*
|
||||
* void port_cpsr_restore(cpu_cpsr_t cpsr);
|
||||
*/
|
||||
.global port_cpsr_restore
|
||||
.align 4
|
||||
port_cpsr_restore:
|
||||
seti r0
|
||||
j [blink]
|
||||
|
||||
/*
|
||||
* uint32_t port_cpu_clz(uint32_t val)
|
||||
* r0 --> val
|
||||
*/
|
||||
.global port_cpu_clz
|
||||
.align 4
|
||||
port_cpu_clz:
|
||||
breq r0, 0, cpu_clz_return
|
||||
ffs r1, r0
|
||||
add r0, r1, 1
|
||||
cpu_clz_return:
|
||||
j [blink]
|
||||
|
||||
/*
|
||||
* void port_sched_start(void)
|
||||
*/
|
||||
.global port_sched_start
|
||||
.align 4
|
||||
port_sched_start:
|
||||
ld r0, [k_curr_task]
|
||||
ld sp, [r0]
|
||||
pop r0
|
||||
j [r0]
|
||||
|
||||
|
||||
/*
|
||||
* void port_context_switch(void)
|
||||
*/
|
||||
.global port_context_switch
|
||||
.align 4
|
||||
port_context_switch:
|
||||
SAVE_NONSCRATCH_REGS
|
||||
mov r2, dispatch_r
|
||||
push r2
|
||||
ld r0, [k_curr_task]
|
||||
ld r1, [k_next_task]
|
||||
b dispatcher
|
||||
|
||||
/*
|
||||
* void port_irq_context_switch(void)
|
||||
*/
|
||||
.global port_irq_context_switch
|
||||
.align 4
|
||||
port_irq_context_switch:
|
||||
mov r0, 1
|
||||
st r0, [g_context_switch_reqflg]
|
||||
j [blink]
|
||||
|
||||
|
||||
/*
|
||||
* void start_r(void)
|
||||
*/
|
||||
.global start_r
|
||||
.align 4
|
||||
start_r:
|
||||
pop blink;
|
||||
pop r1
|
||||
pop r2
|
||||
pop r0
|
||||
|
||||
j_s.d [r1]
|
||||
kflag r2
|
||||
|
||||
/****** 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, [g_exc_nest_count]
|
||||
add r1, r0, 1
|
||||
st r1, [g_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
|
||||
|
||||
jl tos_knl_irq_enter
|
||||
|
||||
lr r0, [AUX_ECR]
|
||||
lsr r0, r0, 16
|
||||
mov r1, exc_int_handler_table
|
||||
ld.as r2, [r1, r0]
|
||||
|
||||
mov r0, r3
|
||||
jl [r2]
|
||||
|
||||
jl tos_knl_irq_leave
|
||||
|
||||
/* interrupts are not allowed */
|
||||
ret_exc:
|
||||
POP sp
|
||||
mov r1, g_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, [g_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, [g_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, [k_curr_task]
|
||||
ld r1, [k_next_task]
|
||||
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, [g_exc_nest_count]
|
||||
add r2, r3, 1
|
||||
st r2, [g_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 tos_knl_irq_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 tos_knl_irq_leave
|
||||
|
||||
ret_int:
|
||||
clri /* disable interrupt */
|
||||
POP r3 /* irq priority */
|
||||
POP sp
|
||||
mov r1, g_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, [g_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, [g_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, [k_curr_task]
|
||||
ld r1, [k_next_task]
|
||||
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
|
||||
.align 4
|
||||
exc_entry_firq:
|
||||
SAVE_FIQ_EXC_REGS
|
||||
|
||||
jl tos_knl_irq_enter
|
||||
|
||||
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]
|
||||
|
||||
jl tos_knl_irq_leave
|
||||
|
||||
firq_return:
|
||||
RESTORE_FIQ_EXC_REGS
|
||||
rtie
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -140,7 +140,7 @@ __KNL__ void cpu_fault_diagnosis(void);
|
||||
/* Restore CPU status word. */
|
||||
#define TOS_CPU_INT_ENABLE() \
|
||||
do { \
|
||||
__builtin_arc_seti(cpu_cpsr); \
|
||||
tos_cpu_cpsr_restore(cpu_cpsr); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _TOS_CPU_H_ */
|
@@ -16,7 +16,13 @@
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <tos_k.h>
|
||||
#include "arc/arc_exception.h"
|
||||
#include "embARC.h"
|
||||
|
||||
void tos_cup_tick_handler(void)
|
||||
{
|
||||
arc_timer_int_clear(BOARD_OS_TIMER_ID);
|
||||
tos_tick_handler();
|
||||
}
|
||||
|
||||
__API__ uint32_t tos_cpu_clz(uint32_t val)
|
||||
{
|
||||
@@ -100,14 +106,18 @@ __KNL__ void cpu_context_switch(void)
|
||||
|
||||
__KNL__ void cpu_irq_context_switch(void)
|
||||
{
|
||||
// port_irq_context_switch();
|
||||
// DO NOTHING
|
||||
port_irq_context_switch();
|
||||
}
|
||||
|
||||
__KNL__ void cpu_systick_init(k_cycle_t cycle_per_tick)
|
||||
{
|
||||
port_systick_priority_set(TOS_CFG_CPU_SYSTICK_PRIO);
|
||||
port_systick_config(cycle_per_tick);
|
||||
int_disable(BOARD_OS_TIMER_INTNO); /* disable os timer interrupt */
|
||||
arc_timer_stop(BOARD_OS_TIMER_ID);
|
||||
arc_timer_start(BOARD_OS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cycle_per_tick);
|
||||
|
||||
int_handler_install(BOARD_OS_TIMER_INTNO, (INT_HANDLER_T)tos_cup_tick_handler);
|
||||
int_pri_set(BOARD_OS_TIMER_INTNO, INT_PRI_MIN + 1);
|
||||
int_enable(BOARD_OS_TIMER_INTNO);
|
||||
}
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
@@ -188,7 +198,18 @@ __KNL__ void cpu_standby_mode_enter(void)
|
||||
}
|
||||
|
||||
#endif /* TOS_CFG_PWR_MGR_EN */
|
||||
|
||||
uint32_t g_context_switch_reqflg;
|
||||
uint32_t g_exc_nest_count;
|
||||
|
||||
extern void start_r(void);
|
||||
|
||||
#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
|
||||
|
||||
__KNL__ k_stack_t *cpu_task_stk_init(void *entry,
|
||||
void *arg,
|
||||
void *exit,
|
||||
@@ -206,7 +227,7 @@ __KNL__ k_stack_t *cpu_task_stk_init(void *entry,
|
||||
regs->pc = (cpu_data_t)start_r;
|
||||
regs->blink = (cpu_data_t)exit;
|
||||
regs->task = (cpu_data_t)entry;
|
||||
regs->status32 = (cpu_data_t)(AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE);
|
||||
regs->status32 = ARC_INIT_STATUS;
|
||||
regs->r0 = (cpu_data_t)arg;
|
||||
|
||||
|
@@ -1,107 +0,0 @@
|
||||
.global port_int_disable
|
||||
.global port_int_enable
|
||||
|
||||
.global port_cpsr_save
|
||||
.global port_cpsr_restore
|
||||
|
||||
.global port_sched_start
|
||||
.global port_context_switch
|
||||
|
||||
.global start_r
|
||||
|
||||
|
||||
.extern k_curr_task
|
||||
.extern k_next_task
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
||||
|
||||
.type port_int_disable, %function
|
||||
port_int_disable:
|
||||
clri
|
||||
j [blink]
|
||||
|
||||
|
||||
.type port_int_enable, %function
|
||||
port_int_enable:
|
||||
seti
|
||||
j [blink]
|
||||
|
||||
.type port_cpsr_save, %function
|
||||
port_cpsr_save:
|
||||
clri r0
|
||||
j [blink]
|
||||
|
||||
|
||||
.type port_cpsr_restore, %function
|
||||
port_cpsr_restore:
|
||||
seti r0
|
||||
j [blink]
|
||||
|
||||
.type port_sched_start, %function
|
||||
port_sched_start:
|
||||
ld r0, [k_curr_task]
|
||||
ld r1, [k_next_task]
|
||||
ld r2, [r1]
|
||||
st r2, [r0] /*k_curr_task=k_next_task*/
|
||||
ld r0, [r2]
|
||||
ld sp, [r0]
|
||||
pop r3
|
||||
j [r3]
|
||||
|
||||
|
||||
.type start_r, %function
|
||||
start_r:
|
||||
pop blink;
|
||||
pop r1
|
||||
pop r2
|
||||
pop r0
|
||||
|
||||
j_s.d [r1]
|
||||
kflag r2
|
||||
|
||||
.type port_context_switch, %function
|
||||
port_context_switch:
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop blink
|
||||
pop fp
|
||||
pop gp
|
||||
j [blink]
|
||||
|
||||
|
||||
|
||||
|
||||
.type PendSV_Handler, %function
|
||||
TaskSwitchContext:
|
||||
clri
|
||||
push gp
|
||||
push fp
|
||||
push blink
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
mov r2, dispatch_r
|
||||
push r2
|
||||
mov r5, k_curr_task
|
||||
ld r6, [r5]
|
||||
st r0, [r6]
|
||||
mov r1, k_next_task
|
||||
ld r2, [r1]
|
||||
st r2, [r5]
|
||||
ld r0, [r2]
|
||||
ld sp, [r0]
|
||||
seti
|
||||
j [r0]
|
||||
|
||||
dispatch_r:
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop blink
|
||||
pop fp
|
||||
pop gp
|
||||
j [blink]
|
Reference in New Issue
Block a user