Browse Source

[libcpu] add risc-v e310 porting

liang yongxiang 7 years ago
parent
commit
32c5b2515f

+ 13 - 0
libcpu/risc-v/e310/SConscript

@@ -0,0 +1,13 @@
+Import('rtconfig')
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+if rtconfig.PLATFORM == 'gcc':
+    src += Glob('*_gcc.S')
+
+group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 227 - 0
libcpu/risc-v/e310/context_gcc.S

@@ -0,0 +1,227 @@
+;/*
+; * File      : context_gcc.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2018, RT-Thread Development Team
+; *
+; *  This program is free software; you can redistribute it and/or modify
+; *  it under the terms of the GNU General Public License as published by
+; *  the Free Software Foundation; either version 2 of the License, or
+; *  (at your option) any later version.
+; *
+; *  This program is distributed in the hope that it will be useful,
+; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; *  GNU General Public License for more details.
+; *
+; *  You should have received a copy of the GNU General Public License along
+; *  with this program; if not, write to the Free Software Foundation, Inc.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; * 2017-07-16     zhangjun     for hifive1
+; * 2018-05-29     tanek        optimize  rt_hw_interrupt_*
+; * 2018-05-29     tanek        add mie register to context
+; */
+
+/*
+ * rt_base_t rt_hw_interrupt_disable(void);
+ */
+    .globl rt_hw_interrupt_disable
+rt_hw_interrupt_disable:
+    csrrci a0, mstatus, 8
+    ret
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level);
+ */
+    .globl rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+    csrw mstatus, a0
+    ret
+
+/*
+ * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+ * a0 --> from
+ * a1 --> to
+ */
+    .globl rt_hw_context_switch
+rt_hw_context_switch:
+
+    /* saved from thread context
+     *     x1/ra       -> sp(0)
+     *     x1/ra       -> sp(1)
+     *     mstatus.mie -> sp(2)
+     *     x(i)        -> sp(i-4)
+     */
+    addi  sp,  sp, -32 * 4
+    sw sp,  (a0)
+
+    sw x1,   0 * 4(sp)
+    sw x1,   1 * 4(sp)
+
+    csrr a0, mstatus
+    andi a0, a0, 8
+    beqz a0, save_mpie
+    li   a0, 0x80
+save_mpie:
+    sw a0,   2 * 4(sp)
+
+    sw x4,   4 * 4(sp)
+    sw x5,   5 * 4(sp)
+    sw x6,   6 * 4(sp)
+    sw x7,   7 * 4(sp)
+    sw x8,   8 * 4(sp)
+    sw x9,   9 * 4(sp)
+    sw x10, 10 * 4(sp)
+    sw x11, 11 * 4(sp)
+    sw x12, 12 * 4(sp)
+    sw x13, 13 * 4(sp)
+    sw x14, 14 * 4(sp)
+    sw x15, 15 * 4(sp)
+    sw x16, 16 * 4(sp)
+    sw x17, 17 * 4(sp)
+    sw x18, 18 * 4(sp)
+    sw x19, 19 * 4(sp)
+    sw x20, 20 * 4(sp)
+    sw x21, 21 * 4(sp)
+    sw x22, 22 * 4(sp)
+    sw x23, 23 * 4(sp)
+    sw x24, 24 * 4(sp)
+    sw x25, 25 * 4(sp)
+    sw x26, 26 * 4(sp)
+    sw x27, 27 * 4(sp)
+    sw x28, 28 * 4(sp)
+    sw x29, 29 * 4(sp)
+    sw x30, 30 * 4(sp)
+    sw x31, 31 * 4(sp)
+
+    /* restore to thread context
+     * sp(0) -> epc;
+     * sp(1) -> ra;
+     * sp(i) -> x(i+2)
+     */
+    lw sp,  (a1)
+
+    /* resw ra to mepc */
+    lw a1,   0 * 4(sp)
+    csrw mepc, a1
+    lw x1,   1 * 4(sp)
+
+    /* force to machin mode(MPP=11) */
+    li a1, 0x00001800;
+    csrs mstatus, a1
+    lw a1,   2 * 4(sp)
+    csrs mstatus, a1
+
+    lw x4,   4 * 4(sp)
+    lw x5,   5 * 4(sp)
+    lw x6,   6 * 4(sp)
+    lw x7,   7 * 4(sp)
+    lw x8,   8 * 4(sp)
+    lw x9,   9 * 4(sp)
+    lw x10, 10 * 4(sp)
+    lw x11, 11 * 4(sp)
+    lw x12, 12 * 4(sp)
+    lw x13, 13 * 4(sp)
+    lw x14, 14 * 4(sp)
+    lw x15, 15 * 4(sp)
+    lw x16, 16 * 4(sp)
+    lw x17, 17 * 4(sp)
+    lw x18, 18 * 4(sp)
+    lw x19, 19 * 4(sp)
+    lw x20, 20 * 4(sp)
+    lw x21, 21 * 4(sp)
+    lw x22, 22 * 4(sp)
+    lw x23, 23 * 4(sp)
+    lw x24, 24 * 4(sp)
+    lw x25, 25 * 4(sp)
+    lw x26, 26 * 4(sp)
+    lw x27, 27 * 4(sp)
+    lw x28, 28 * 4(sp)
+    lw x29, 29 * 4(sp)
+    lw x30, 30 * 4(sp)
+    lw x31, 31 * 4(sp)
+
+    addi sp,  sp, 32 * 4
+    mret
+
+/*
+ * void rt_hw_context_switch_to(rt_uint32 to);
+ * a0 --> to
+ */
+    .globl rt_hw_context_switch_to
+rt_hw_context_switch_to:
+    lw sp, (a0)
+
+    /* load epc from stack */
+    lw a0,   0 * 4(sp)
+    csrw mepc, a0
+    lw x1,   1 * 4(sp)
+    /* load mstatus from stack */
+    lw a0,   2 * 4(sp)
+    csrw mstatus, a0
+    lw x4,   4 * 4(sp)
+    lw x5,   5 * 4(sp)
+    lw x6,   6 * 4(sp)
+    lw x7,   7 * 4(sp)
+    lw x8,   8 * 4(sp)
+    lw x9,   9 * 4(sp)
+    lw x10, 10 * 4(sp)
+    lw x11, 11 * 4(sp)
+    lw x12, 12 * 4(sp)
+    lw x13, 13 * 4(sp)
+    lw x14, 14 * 4(sp)
+    lw x15, 15 * 4(sp)
+    lw x16, 16 * 4(sp)
+    lw x17, 17 * 4(sp)
+    lw x18, 18 * 4(sp)
+    lw x19, 19 * 4(sp)
+    lw x20, 20 * 4(sp)
+    lw x21, 21 * 4(sp)
+    lw x22, 22 * 4(sp)
+    lw x23, 23 * 4(sp)
+    lw x24, 24 * 4(sp)
+    lw x25, 25 * 4(sp)
+    lw x26, 26 * 4(sp)
+    lw x27, 27 * 4(sp)
+    lw x28, 28 * 4(sp)
+    lw x29, 29 * 4(sp)
+    lw x30, 30 * 4(sp)
+    lw x31, 31 * 4(sp)
+
+    addi sp,  sp, 32 * 4
+    mret
+
+/*
+ * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
+ */
+    .globl rt_thread_switch_interrupt_flag
+    .globl rt_interrupt_from_thread
+    .globl rt_interrupt_to_thread
+    .globl rt_hw_context_switch_interrupt
+rt_hw_context_switch_interrupt:
+    addi sp, sp, -16
+    sw   s0, 12(sp)
+    sw   a0, 8(sp)
+    sw   a5, 4(sp)
+
+    la   a0, rt_thread_switch_interrupt_flag
+    lw   a5, (a0)
+    bnez a5, _reswitch
+    li   a5, 1
+    sw   a5, (a0)
+
+    la   a5, rt_interrupt_from_thread
+    lw   a0, 8(sp)
+    sw   a0, (a5)
+
+_reswitch:
+    la   a5, rt_interrupt_to_thread
+    sw   a1, (a5)
+
+    lw   a5, 4(sp)
+    lw   a0, 8(sp)
+    lw   s0, 12(sp)
+    addi sp, sp, 16
+    ret

+ 145 - 0
libcpu/risc-v/e310/entry_gcc.S

@@ -0,0 +1,145 @@
+/*
+ * File      : context_gcc.S
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-05-29     tanek        first implementation
+ */
+
+  .section      .text.entry
+  .align 2
+  .global trap_entry
+trap_entry:
+
+    // save all from thread context
+    addi sp, sp, -32 * 4
+
+    sw x1,   1 * 4(sp)
+    li t0, 0x80
+    sw t0,   2 * 4(sp)
+
+    sw x4,   4 * 4(sp)
+    sw x5,   5 * 4(sp)
+    sw x6,   6 * 4(sp)
+    sw x7,   7 * 4(sp)
+    sw x8,   8 * 4(sp)
+    sw x9,   9 * 4(sp)
+    sw x10, 10 * 4(sp)
+    sw x11, 11 * 4(sp)
+    sw x12, 12 * 4(sp)
+    sw x13, 13 * 4(sp)
+    sw x14, 14 * 4(sp)
+    sw x15, 15 * 4(sp)
+    sw x16, 16 * 4(sp)
+    sw x17, 17 * 4(sp)
+    sw x18, 18 * 4(sp)
+    sw x19, 19 * 4(sp)
+    sw x20, 20 * 4(sp)
+    sw x21, 21 * 4(sp)
+    sw x22, 22 * 4(sp)
+    sw x23, 23 * 4(sp)
+    sw x24, 24 * 4(sp)
+    sw x25, 25 * 4(sp)
+    sw x26, 26 * 4(sp)
+    sw x27, 27 * 4(sp)
+    sw x28, 28 * 4(sp)
+    sw x29, 29 * 4(sp)
+    sw x30, 30 * 4(sp)
+    sw x31, 31 * 4(sp)
+
+    // switch to interrupt stack
+    move s0, sp
+    la   sp, _sp
+
+    // interrupt handle
+    call rt_interrupt_enter
+    csrr a0, mcause
+    csrr a1, mepc
+    mv a2, sp
+    call handle_trap
+    call rt_interrupt_leave
+
+    // switch to from thread stack
+    move sp, s0
+
+    // need to switch new thread
+    la   s0, rt_thread_switch_interrupt_flag
+    lw   s2, 0(s0)
+    beqz s2, spurious_interrupt
+    sw   zero, 0(s0)
+
+    csrr a0, mepc
+    sw a0,  0 * 4(sp)
+
+    la   s0, rt_interrupt_from_thread
+    lw   s1, 0(s0)
+    sw   sp, 0(s1)
+
+    la   s0, rt_interrupt_to_thread
+    lw   s1, 0(s0)
+    lw   sp, 0(s1)
+
+    lw  a0,  0 * 4(sp)
+    csrw mepc, a0
+
+spurious_interrupt:
+    lw x1,   1 * 4(sp)
+    
+    // Remain in M-mode after mret
+    li t0, 0x00001800
+    csrs mstatus, t0
+    lw t0,   2 * 4(sp)
+    csrs mstatus, t0 
+    
+    lw x4,   4 * 4(sp)
+    lw x5,   5 * 4(sp)
+    lw x6,   6 * 4(sp)
+    lw x7,   7 * 4(sp)
+    lw x8,   8 * 4(sp)
+    lw x9,   9 * 4(sp)
+    lw x10, 10 * 4(sp)
+    lw x11, 11 * 4(sp)
+    lw x12, 12 * 4(sp)
+    lw x13, 13 * 4(sp)
+    lw x14, 14 * 4(sp)
+    lw x15, 15 * 4(sp)
+    lw x16, 16 * 4(sp)
+    lw x17, 17 * 4(sp)
+    lw x18, 18 * 4(sp)
+    lw x19, 19 * 4(sp)
+    lw x20, 20 * 4(sp)
+    lw x21, 21 * 4(sp)
+    lw x22, 22 * 4(sp)
+    lw x23, 23 * 4(sp)
+    lw x24, 24 * 4(sp)
+    lw x25, 25 * 4(sp)
+    lw x26, 26 * 4(sp)
+    lw x27, 27 * 4(sp)
+    lw x28, 28 * 4(sp)
+    lw x29, 29 * 4(sp)
+    lw x30, 30 * 4(sp)
+    lw x31, 31 * 4(sp)
+
+    addi sp, sp, 32 * 4
+    mret
+
+.weak handle_trap
+handle_trap:
+1:
+    j 1b

+ 104 - 0
libcpu/risc-v/e310/stack.c

@@ -0,0 +1,104 @@
+/*
+ * File      : stack.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-07-31     tanek        first implementation
+ */
+
+#include <rtthread.h>
+
+/* flag in interrupt handling */
+rt_uint32_t rt_interrupt_from_thread;
+rt_uint32_t rt_interrupt_to_thread;
+rt_uint32_t rt_thread_switch_interrupt_flag;
+
+struct stack_frame
+{
+    rt_ubase_t epc;        /* epc - epc    - program counter                     */
+    rt_ubase_t ra;         /* x1  - ra     - return address for jumps            */
+    rt_ubase_t mstatus;    /*              - machine status register             */
+    rt_ubase_t gp;         /* x3  - gp     - global pointer                      */
+    rt_ubase_t tp;         /* x4  - tp     - thread pointer                      */
+    rt_ubase_t t0;         /* x5  - t0     - temporary register 0                */
+    rt_ubase_t t1;         /* x6  - t1     - temporary register 1                */
+    rt_ubase_t t2;         /* x7  - t2     - temporary register 2                */
+    rt_ubase_t s0_fp;      /* x8  - s0/fp  - saved register 0 or frame pointer   */
+    rt_ubase_t s1;         /* x9  - s1     - saved register 1                    */
+    rt_ubase_t a0;         /* x10 - a0     - return value or function argument 0 */
+    rt_ubase_t a1;         /* x11 - a1     - return value or function argument 1 */
+    rt_ubase_t a2;         /* x12 - a2     - function argument 2                 */
+    rt_ubase_t a3;         /* x13 - a3     - function argument 3                 */
+    rt_ubase_t a4;         /* x14 - a4     - function argument 4                 */
+    rt_ubase_t a5;         /* x15 - a5     - function argument 5                 */
+    rt_ubase_t a6;         /* x16 - a6     - function argument 6                 */
+    rt_ubase_t a7;         /* x17 - s7     - function argument 7                 */
+    rt_ubase_t s2;         /* x18 - s2     - saved register 2                    */
+    rt_ubase_t s3;         /* x19 - s3     - saved register 3                    */
+    rt_ubase_t s4;         /* x20 - s4     - saved register 4                    */
+    rt_ubase_t s5;         /* x21 - s5     - saved register 5                    */
+    rt_ubase_t s6;         /* x22 - s6     - saved register 6                    */
+    rt_ubase_t s7;         /* x23 - s7     - saved register 7                    */
+    rt_ubase_t s8;         /* x24 - s8     - saved register 8                    */
+    rt_ubase_t s9;         /* x25 - s9     - saved register 9                    */
+    rt_ubase_t s10;        /* x26 - s10    - saved register 10                   */
+    rt_ubase_t s11;        /* x27 - s11    - saved register 11                   */
+    rt_ubase_t t3;         /* x28 - t3     - temporary register 3                */
+    rt_ubase_t t4;         /* x29 - t4     - temporary register 4                */
+    rt_ubase_t t5;         /* x30 - t5     - temporary register 5                */
+    rt_ubase_t t6;         /* x31 - t6     - temporary register 6                */
+};
+
+/**
+ * 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)
+{
+    struct stack_frame *stack_frame;
+    rt_uint8_t         *stk;
+    int                i;
+
+    stk  = stack_addr + sizeof(rt_uint32_t);
+    stk  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
+    stk -= sizeof(struct stack_frame);
+
+    stack_frame = (struct stack_frame *)stk;
+
+    for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_ubase_t); i++)
+    {
+        ((rt_ubase_t *)stack_frame)[i] = 0xdeadbeef;
+    }
+
+    stack_frame->ra      = (rt_ubase_t)texit;
+    stack_frame->a0      = (rt_ubase_t)parameter;
+    stack_frame->epc     = (rt_ubase_t)tentry;
+
+    // force to machine mode(MPP=11) and set MPIE to 1
+    stack_frame->mstatus = 0x00001880;
+
+    return stk;
+}