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:
Watson Zeng
2020-03-25 17:11:52 +08:00
committed by Jingru
parent 13eaef3d46
commit 0d4593ee5e
169 changed files with 871 additions and 46371 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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_ */

View File

@@ -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;

View File

@@ -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]