summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2017-10-06 11:03:02 +0800
committerGitHub <[email protected]>2017-10-06 11:03:02 +0800
commitea18ef60eda8d06f918bc76194afb4e7c62de407 (patch)
treec17b556f94a6c1bbc134036e2d77473a3a3d4713 /libcpu
parent49aa0c468ab59bc7467add5596fc0b711990a3f4 (diff)
parent9bbf53875349c1fa6d5ff64526064b088e4d8c04 (diff)
Merge pull request #826 from ArcherChang/master
[BSP] Add Andes N1068 porting and simple bsp.
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/nds32/context_gcc.S188
-rw-r--r--libcpu/nds32/cpuport.c221
2 files changed, 409 insertions, 0 deletions
diff --git a/libcpu/nds32/context_gcc.S b/libcpu/nds32/context_gcc.S
new file mode 100644
index 0000000000..8d5f3287e9
--- /dev/null
+++ b/libcpu/nds32/context_gcc.S
@@ -0,0 +1,188 @@
+#include "nds32.h"
+#include "os_cpu_common.h"
+#include "config.h"
+
+ .align 4
+! void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+! R0 --> from
+! R1 --> to
+ .section .text
+ .global rt_hw_context_switch_interrupt
+ .global rt_hw_context_switch
+rt_hw_context_switch_interrupt:
+rt_hw_context_switch:
+ push25 $r6,#8 ! {$r6, $fp, $gp, $lp}
+
+ la $r2, rt_thread_switch_interrupt_flag
+ lw $r3, [$r2]
+ movi $r4, #1
+ beq $r3, $r4, _reswitch
+ sw $r4, [$r2] ! set rt_thread_switch_interrupt_flag to 1
+
+ la $r2, rt_interrupt_from_thread
+ sw $r0, [$r2] ! set rt_interrupt_from_thread
+_reswitch:
+ la $r2, rt_interrupt_to_thread
+ sw $r1, [$r2] ! set rt_interrupt_to_thread
+ bal hal_intc_swi_trigger ! trigger the swi exception (causes context switch)
+
+ pop25 $r6,#8 ! {$r6, $fp, $gp, $lp}
+
+! R0 --> switch from thread stack
+! R1 --> switch to thread stack
+! psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack
+
+ .align 4
+ .global OS_Trap_Interrupt_SWI
+OS_Trap_Interrupt_SWI:
+! pushm $r0, $r5
+ setgie.d ! disable interrupt to protect context switch
+ dsb
+
+ IntlDescend ! Descend interrupt level
+
+ movi $r0, 0x0
+ mtsr $r0, $INT_PEND ! clean SWI pending
+
+ la $r0, rt_thread_switch_interrupt_flag ! get rt_thread_switch_interrupt_flag
+ lw $r1, [$r0]
+ beqz $r1, pendsv_exit ! swi has already been handled
+
+ movi $r1, #0
+ sw $r1, [$r0] ! clear rt_thread_switch_interrupt_flag to 0
+
+ la $r0, rt_interrupt_from_thread
+ lw $r1, [$r0]
+ beqz $r1, switch_to_thread ! skip register save at the first time(os startup phase)
+
+ SAVE_ALL
+
+ move $r1, $sp
+ la $r0, rt_interrupt_from_thread
+ lw $r0, [$r0]
+ sw $r1, [$r0]
+
+switch_to_thread:
+ la $r1, rt_interrupt_to_thread
+ lw $r1, [$r1]
+ lw $r1, [$r1] ! load thread stack pointer
+ move $sp, $r1 ! update stack pointer
+ RESTORE_ALL ! pop registers
+
+pendsv_exit:
+ setgie.e
+ iret
+
+ .align 4
+! void rt_hw_context_switch_to(rt_uint32 to);
+! R0 --> to
+ .global rt_hw_context_switch_to
+rt_hw_context_switch_to:
+ la $r1, rt_interrupt_to_thread
+ sw $r0, [$r1]
+
+ ! set from thread to 0
+ la $r1, rt_interrupt_from_thread
+ movi $r0, #0
+ sw $r0, [$r1]
+
+ ! set interrupt flag to 1
+ la $r1, rt_thread_switch_interrupt_flag
+ movi $r0, #1
+ sw $r0, [$r1]
+
+ ! set the SWI exception priority(must be the lowest level)
+ ! todo
+
+ ! trigger the SWI exception (causes context switch)
+ jal hal_intc_swi_trigger
+
+ setgie.e ! enable interrupts at processor level
+
+1:
+ b 1b ! never reach here
+
+#ifndef VECTOR_NUMINTRS
+#define VECTOR_NUMINTRS 32
+#endif
+
+ .global OS_Trap_Int_Common
+
+ ! Set up Interrupt vector ISR
+ ! HW#IRQ_SWI_VECTOR : OS_Trap_Interrupt_SWI (SWI)
+ ! HW#n : OS_Trap_Int_Common
+
+ .macro SET_HWISR num
+ .global OS_Trap_Interrupt_HW\num
+ .if \num == IRQ_SWI_VECTOR
+ .set OS_Trap_Interrupt_HW\num, OS_Trap_Interrupt_SWI
+ .else
+ .set OS_Trap_Interrupt_HW\num, OS_Trap_Int_Common
+ .endif
+ .endm
+
+ .altmacro
+ .set irqno, 0
+ .rept VECTOR_NUMINTRS
+ SET_HWISR %irqno
+ .set irqno, irqno+1
+ .endr
+ .noaltmacro
+
+! .global OS_Trap_Int_Common
+OS_Trap_Int_Common:
+#ifdef MPU_SUPPORT
+ mfsr $p1, $PSW
+ ori $p1, $p1, (PSW_mskIT | PSW_mskDT)
+ mtsr $p1, $PSW ! enable IT/DT
+ dsb
+ pushm $r0, $r5
+ move $r0, $p0 ! IRQ number
+#endif
+ ! $r0 : HW Interrupt vector number
+ SAVE_CALLER
+
+ IntlDescend ! Descend interrupt level
+
+ mfsr $r1, $IPSW ! Use IPSW.CPL to check come from thread or ISR
+ srli45 $r1, #PSW_offCPL
+ fexti33 $r1, #0x2 ! IPSW.CPL
+ bnec $r1, #0x7, 2f ! IPSW.CPL != 7, come form ISR, reentrant
+
+ move $fp, $sp ! save old stack pointer
+ la $sp, __OS_Int_Stack ! switch to interrupt stack
+2:
+ setgie.e ! allow nested now
+
+ ! The entire CPU state is now stashed on the stack,
+ ! and the stack is also 8-byte alignment.
+ ! We can call C program based interrupt handler now.
+ la $r1, OS_CPU_Vector_Table
+ lw $r1, [$r1+($r0<<2)] ! ISR function pointer
+ jral $r1 ! Call ISR
+
+ la $r1, __OS_Int_Stack ! Check for nested interruption return
+ bne $r1, $sp, 3f ! $sp != __OS_Int_Stack?
+
+ move $sp, $fp ! Move back to the thread stack
+3:
+ RESTORE_CALLER
+
+ iret
+
+! .set OS_Trap_Interrupt_HW9, OS_Trap_Interrupt_SWI
+! .set OS_Trap_Interrupt_HW19, OS_Trap_Int_Common
+
+!*********************************************
+! POINTERS TO VARIABLES
+!*********************************************
+#ifdef MPU_SUPPORT
+ .section privileged_data
+#else
+ .section .bss
+#endif
+ .skip IRQ_STACK_SIZE
+ .align 3
+__OS_Int_Stack:
+
+ .end
diff --git a/libcpu/nds32/cpuport.c b/libcpu/nds32/cpuport.c
new file mode 100644
index 0000000000..17523f2430
--- /dev/null
+++ b/libcpu/nds32/cpuport.c
@@ -0,0 +1,221 @@
+/*
+ * File : cpuport.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2009-01-05 Bernard first version
+ * 2011-02-14 onelife Modify for EFM32
+ * 2011-06-17 onelife Merge all of the C source code into cpuport.c
+ * 2012-12-23 aozima stack addr align to 8byte.
+ * 2012-12-29 Bernard Add exception hook.
+ * 2013-07-09 aozima enhancement hard fault exception handler.
+ */
+
+#include <rtthread.h>
+
+#include "nds32.h"
+
+/*
+ * Initialise the stack of a task to look exactly as if a call to
+ * SAVE_CONTEXT had been called.
+ *
+ * See header file for description.
+ *
+ *
+ * Stack Layout:
+ * High |-----------------|
+ * | $R5 |
+ * |-----------------|
+ * | . |
+ * | . |
+ * |-----------------|
+ * | $R0 |
+ * |-----------------|
+ * | $R30 (LP) |
+ * |-----------------|
+ * | $R29 (GP) |
+ * |-----------------|
+ * | $R28 (FP) |
+ * |-----------------|
+ * | $R15 $R27 |
+ * |-----------------|
+ * | $R10 $R26 |
+ * |-----------------|
+ * | . |
+ * | . |
+ * |-----------------|
+ * | $R6 |
+ * |-----------------|
+ * | $IFC_LP | (Option)
+ * |-----------------|
+ * | $LC/$LE/$LB | (Option)
+ * | (ZOL) |
+ * |-----------------|
+ * | $IPSW |
+ * |-----------------|
+ * | $IPC |
+ * |-----------------|
+ * | Dummy word | (Option, only exist when IFC & ZOL both configured)
+ * |-----------------|
+ * | $FPU | (Option)
+ * |-----------------|
+ * Low
+ *
+ */
+
+struct stack_frame
+{
+ rt_uint32_t topOfStack[34];
+};
+
+/* flag in interrupt handling */
+rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
+rt_uint32_t rt_thread_switch_interrupt_flag;
+/* exception hook */
+static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;
+
+rt_base_t rt_hw_interrupt_disable(void)
+{
+ rt_base_t level = __nds32__mfsr(NDS32_SR_PSW);
+
+ GIE_DISABLE();
+
+ return level;
+}
+
+void rt_hw_interrupt_enable(rt_base_t level)
+{
+ if (level & PSW_mskGIE)
+ GIE_ENABLE();
+}
+
+/* For relax support, must initial $gp at task init*/
+extern uint32_t _SDA_BASE_ __attribute__ ((weak));
+
+/**************************************************************
+ * This function will initialize thread stack
+ *
+ * @param tentry the entry of thread
+ * @param parameter the parameter of entry
+ * @param stack_addr the beginning stack address
+ * @param texit the function will be called when thread exit
+ *
+ * @return stack address
+ **************************************************************/
+rt_uint8_t *rt_hw_stack_init(void *tentry,
+ void *parameter,
+ rt_uint8_t *stack_addr,
+ void *texit)
+{
+ rt_int32_t i;
+ rt_uint32_t *pxTopOfStack;
+
+ pxTopOfStack = (rt_uint32_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 4);
+
+ /* Simulate the stack frame as it would be created by a context switch */
+ /* R0 ~ R5 registers */
+ for (i = 5; i >= 1; i--) /* R5, R4, R3, R2 and R1. */
+ *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
+ *--pxTopOfStack = (rt_uint32_t)parameter; /* R0 : Argument */
+
+ /* R6 ~ R30 registers */
+ *--pxTopOfStack = (rt_uint32_t)texit; /* R30: $LP */
+ *--pxTopOfStack = (rt_uint32_t)&_SDA_BASE_; /* R29: $GP */
+ *--pxTopOfStack = (rt_uint32_t)0x2828282828; /* R28: $FP */
+#ifdef __NDS32_REDUCE_REGS__
+ *--pxTopOfStack = (rt_uint32_t)0x1515151515; /* R15 */
+ for (i = 10; i >= 6; i--) /* R10 ~ R6 */
+ *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
+#else
+ for (i = 27; i >= 6; i--) /* R27 ~ R6 */
+ *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
+#endif
+
+ /* IFC system register */
+#ifdef __TARGET_IFC_EXT
+ *--pxTopOfStack = (rt_uint32_t)0x0; /* $IFC_LP */
+#endif
+
+ /* ZOL system registers */
+#ifdef __TARGET_ZOL_EXT
+ *--pxTopOfStack = (rt_uint32_t)0x0; /* $LC */
+ *--pxTopOfStack = (rt_uint32_t)0x0; /* $LE */
+ *--pxTopOfStack = (rt_uint32_t)0x0; /* $LB */
+#endif
+
+ /* IPSW and IPC system registers */
+ /* Default IPSW: enable GIE, set CPL to 7, clear IFCON */
+ i = (__nds32__mfsr(NDS32_SR_PSW) | PSW_mskGIE | PSW_mskCPL) & ~PSW_mskIFCON;
+ *--pxTopOfStack = (rt_uint32_t)i; /* $IPSW */
+ *--pxTopOfStack = (rt_uint32_t)tentry; /* $IPC */
+
+ /* Dummy word for 8-byte stack alignment */
+#if defined(__TARGET_IFC_EXT) && defined(__TARGET_ZOL_EXT)
+ *--pxTopOfStack = (rt_uint32_t)0xFFFFFFFF; /* Dummy */
+#endif
+
+ /* FPU registers */
+#ifdef __TARGET_FPU_EXT
+ for (i = 0; i < FPU_REGS; i++)
+ *--pxTopOfStack = (rt_uint32_t)0x0; /* FPU */
+#endif
+
+ return (rt_uint8_t *)pxTopOfStack;
+}
+
+/**
+ * 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))
+{
+ rt_exception_hook = exception_handle;
+}
+
+#ifdef RT_USING_CPU_FFS
+/**
+ * This function finds the first bit set (beginning with the least significant bit)
+ * in value and return the index of that bit.
+ *
+ * Bits are numbered starting at 1 (the least significant bit). A return value of
+ * zero from any of these functions means that the argument was zero.
+ *
+ * @return return the index of the first bit set. If value is 0, then this function
+ * shall return 0.
+ */
+#if defined(__CC_ARM)
+__asm int __rt_ffs(int value)
+{
+ CMP r0, #0x00
+ BEQ exit
+ RBIT r0, r0
+ CLZ r0, r0
+ ADDS r0, r0, #0x01
+
+ exit
+ BX lr
+}
+#elif defined(__IAR_SYSTEMS_ICC__)
+int __rt_ffs(int value)
+{
+ if (value == 0) return value;
+
+ __ASM("RBIT r0, r0");
+ __ASM("CLZ r0, r0");
+ __ASM("ADDS r0, r0, #0x01");
+}
+#elif defined(__GNUC__)
+int __rt_ffs(int value)
+{
+ return __builtin_ffs(value);
+}
+#endif
+
+#endif