mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-21 10:36:04 +08:00
[bsp][synopsys] add the support of synopsys arc emsk
* the initial support of synopsys designware arc processor * the initial support of synospsy ARC EM Starter Kit * the bsp code is based on embarc which is a common SDK for all synopsys ARC-based boards * use "scons --gdb" to debug emsk with em9d configuration * for detailed board information, pls go embarc.org Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
|
||||
if rtconfig.PLATFORM == 'gcc':
|
||||
src += Glob('*_gcc.S')
|
||||
|
||||
group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Synopsys, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#define __ASSEMBLY__
|
||||
#include "inc/arc/arc.h"
|
||||
#include "inc/arc/arc_asm_common.h"
|
||||
|
||||
.global rt_interrupt_enter; .type rt_interrupt_enter, %function
|
||||
.global rt_interrupt_leave; .type rt_interrupt_leave, %function
|
||||
.global context_switch_reqflg; .type context_switch_reqflg, %object
|
||||
.global rt_interrupt_from_thread; .type rt_interrupt_from_thread, %object
|
||||
.global rt_interrupt_to_thread; .type rt_interrupt_to_thread, %object
|
||||
|
||||
.text
|
||||
.align 4
|
||||
dispatcher:
|
||||
st sp, [r0]
|
||||
ld sp, [r1]
|
||||
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
|
||||
.type rt_hw_interrupt_disable, %function
|
||||
rt_hw_interrupt_disable:
|
||||
clri r0
|
||||
j [blink]
|
||||
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.global rt_hw_interrupt_enable
|
||||
.type rt_hw_interrupt_enable, %function
|
||||
rt_hw_interrupt_enable:
|
||||
seti r0
|
||||
j [blink]
|
||||
|
||||
|
||||
.global rt_hw_context_switch_interrupt
|
||||
.type rt_hw_context_switch_interrupt, %function
|
||||
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
|
||||
.type rt_hw_context_switch, %function
|
||||
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
|
||||
.type rt_hw_context_switch_to, %function
|
||||
rt_hw_context_switch_to:
|
||||
ld sp, [r0]
|
||||
pop r0
|
||||
j [r0]
|
||||
|
||||
.global start_r
|
||||
.type start_r, %function
|
||||
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, [exc_nest_count]
|
||||
add r1, r0, 1
|
||||
st r1, [exc_nest_count]
|
||||
cmp r0, 0
|
||||
bne 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
|
||||
cmp r0, 0
|
||||
bne.d ret_exc_1
|
||||
st r0, [r1]
|
||||
|
||||
ld r0, [context_switch_reqflg]
|
||||
cmp r0, 0
|
||||
bne 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 */
|
||||
|
||||
cmp r3, 0
|
||||
bne irq_handler_1
|
||||
/* change to exception stack if interrupt happened in task context */
|
||||
mov sp, _e_stack
|
||||
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
|
||||
cmp r0, 0
|
||||
bne.d ret_int_1
|
||||
st r0, [r1]
|
||||
|
||||
ld r0, [context_switch_reqflg]
|
||||
cmp r0, 0
|
||||
bne 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
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Synopsys, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "inc/arc/arc_exception.h"
|
||||
|
||||
/* enable interrupt and set interrupt priority mask */
|
||||
#define ARC_INIT_STATUS (AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1))
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user