diff --git a/libcpu/risc-v/nuclei/context_gcc.S b/libcpu/risc-v/nuclei/context_gcc.S index 1f1d96220f..fda453940d 100644 --- a/libcpu/risc-v/nuclei/context_gcc.S +++ b/libcpu/risc-v/nuclei/context_gcc.S @@ -11,12 +11,12 @@ #include "riscv_encoding.h" #ifndef __riscv_32e -#define portRegNum 30 +#define RT_SAVED_REGNUM 30 #else -#define portRegNum 14 +#define RT_SAVED_REGNUM 14 #endif -#define portCONTEXT_SIZE ( portRegNum * REGBYTES ) +#define RT_CONTEXT_SIZE (RT_SAVED_REGNUM * REGBYTES) .extern rt_interrupt_from_thread .extern rt_interrupt_to_thread @@ -25,7 +25,6 @@ .section .text - /* * void rt_hw_context_switch_to(rt_ubase_t to); * a0 --> to_thread @@ -51,7 +50,7 @@ rt_hw_context_switch_to: LOAD t0, 0 * REGBYTES(sp) csrw CSR_MEPC, t0 /* Pop mstatus from stack and set it */ - LOAD t0, (portRegNum - 1) * REGBYTES(sp) + LOAD t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp) csrw CSR_MSTATUS, t0 /* Interrupt still disable here */ /* Restore Registers from Stack */ @@ -86,14 +85,14 @@ rt_hw_context_switch_to: LOAD x31, 28 * REGBYTES(sp) #endif - addi sp, sp, portCONTEXT_SIZE + addi sp, sp, RT_CONTEXT_SIZE mret .align 2 .global eclic_msip_handler eclic_msip_handler: - addi sp, sp, -portCONTEXT_SIZE + addi sp, sp, -RT_CONTEXT_SIZE STORE x1, 1 * REGBYTES(sp) /* RA */ STORE x5, 2 * REGBYTES(sp) STORE x6, 3 * REGBYTES(sp) @@ -126,7 +125,7 @@ eclic_msip_handler: #endif /* Push mstatus to stack */ csrr t0, CSR_MSTATUS - STORE t0, (portRegNum - 1) * REGBYTES(sp) + STORE t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp) /* Push additional registers */ @@ -137,7 +136,7 @@ eclic_msip_handler: csrr t0, CSR_MEPC STORE t0, 0(sp) - jal xPortTaskSwitch + jal rt_hw_taskswitch /* Switch task context */ LOAD t0, rt_interrupt_to_thread @@ -146,10 +145,11 @@ eclic_msip_handler: /* Pop PC from stack and set MEPC */ LOAD t0, 0 * REGBYTES(sp) csrw CSR_MEPC, t0 + /* Pop additional registers */ /* Pop mstatus from stack and set it */ - LOAD t0, (portRegNum - 1) * REGBYTES(sp) + LOAD t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp) csrw CSR_MSTATUS, t0 /* Interrupt still disable here */ /* Restore Registers from Stack */ @@ -184,5 +184,5 @@ eclic_msip_handler: LOAD x31, 28 * REGBYTES(sp) #endif - addi sp, sp, portCONTEXT_SIZE + addi sp, sp, RT_CONTEXT_SIZE mret diff --git a/libcpu/risc-v/nuclei/cpuport.c b/libcpu/risc-v/nuclei/cpuport.c index c347109cb3..fad9afdf4c 100644 --- a/libcpu/risc-v/nuclei/cpuport.c +++ b/libcpu/risc-v/nuclei/cpuport.c @@ -16,57 +16,68 @@ #include "cpuport.h" -#define SYSTICK_TICK_CONST (SOC_TIMER_FREQ / RT_TICK_PER_SECOND) +#define SYSTICK_TICK_CONST (SOC_TIMER_FREQ / RT_TICK_PER_SECOND) -#ifndef configKERNEL_INTERRUPT_PRIORITY - #define configKERNEL_INTERRUPT_PRIORITY 1 -#endif +/* Interrupt level for kernel systimer interrupt and software timer interrupt */ +#define RT_KERNEL_INTERRUPT_LEVEL 1 -#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY - // See function prvCheckMaxSysCallPrio and prvCalcMaxSysCallMTH - #define configMAX_SYSCALL_INTERRUPT_PRIORITY 255 -#endif - -#define portINITIAL_MSTATUS ( MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL) +/* Initial CSR MSTATUS value when thread created */ +#define RT_INITIAL_MSTATUS (MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL) +/** + * @brief from thread used interrupt context switch + * + */ volatile rt_ubase_t rt_interrupt_from_thread = 0; +/** + * @brief to thread used interrupt context switch + * + */ volatile rt_ubase_t rt_interrupt_to_thread = 0; +/** + * @brief flag to indicate context switch in interrupt or not + * + */ volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0; +/** + * @brief thread stack frame of saved context + * + */ struct rt_hw_stack_frame { - rt_ubase_t epc; /* epc - epc - program counter */ - rt_ubase_t ra; /* x1 - ra - return address for jumps */ - 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 epc; /*!< epc - epc - program counter */ + rt_ubase_t ra; /*!< x1 - ra - return address for jumps */ + 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 */ #ifndef __riscv_32e - 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 */ + 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 */ #endif - rt_ubase_t mstatus; /* - machine status register */ + rt_ubase_t mstatus; /*!< - machine status register */ }; /** @@ -103,13 +114,16 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, frame->a0 = (rt_ubase_t)parameter; frame->epc = (rt_ubase_t)tentry; - frame->mstatus = portINITIAL_MSTATUS; + frame->mstatus = RT_INITIAL_MSTATUS; return stk; } -/* - * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); +/** + * @brief Do rt-thread context switch in interrupt context + * + * @param from thread sp of from thread + * @param to thread sp of to thread */ void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to) { @@ -118,17 +132,26 @@ void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to) rt_interrupt_to_thread = to; rt_thread_switch_interrupt_flag = 1; - portYIELD(); + RT_YIELD(); } +/** + * @brief Do rt-thread context switch in task context + * + * @param from thread sp of from thread + * @param to thread sp of to thread + */ void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to) { rt_interrupt_from_thread = from; rt_interrupt_to_thread = to; - portYIELD(); + RT_YIELD(); } -/** shutdown CPU */ +/** + * @brief shutdown CPU + * + */ void rt_hw_cpu_shutdown() { rt_uint32_t level; @@ -141,14 +164,31 @@ void rt_hw_cpu_shutdown() } } -void xPortTaskSwitch( void ) +/** + * @brief Do extra task switch code + * + * @details + * + * - Clear software timer interrupt request flag + * - clear rt_thread_switch_interrupt_flag to 0 + */ +void rt_hw_taskswitch(void) { /* Clear Software IRQ, A MUST */ SysTimer_ClearSWIRQ(); rt_thread_switch_interrupt_flag = 0; } -void vPortSetupTimerInterrupt( void ) +/** + * @brief Setup systimer and software timer interrupt + * + * @details + * + * - Set Systimer interrupt as NON-VECTOR interrupt with lowest interrupt level + * - Set software timer interrupt as VECTOR interrupt with lowest interrupt level + * - Enable these two interrupts + */ +void rt_hw_ticksetup(void) { uint64_t ticks = SYSTICK_TICK_CONST; @@ -156,23 +196,31 @@ void vPortSetupTimerInterrupt( void ) /* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */ SysTick_Config(ticks); ECLIC_DisableIRQ(SysTimer_IRQn); - ECLIC_SetLevelIRQ(SysTimer_IRQn, configKERNEL_INTERRUPT_PRIORITY); + ECLIC_SetLevelIRQ(SysTimer_IRQn, RT_KERNEL_INTERRUPT_LEVEL); ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT); ECLIC_EnableIRQ(SysTimer_IRQn); /* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */ ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT); - ECLIC_SetLevelIRQ(SysTimerSW_IRQn, configKERNEL_INTERRUPT_PRIORITY); + ECLIC_SetLevelIRQ(SysTimerSW_IRQn, RT_KERNEL_INTERRUPT_LEVEL); ECLIC_EnableIRQ(SysTimerSW_IRQn); } - +/** + * systimer interrupt handler eclic_mtip_handler + * is hard coded in startup_.S + * We define SysTick_Handler as eclic_mtip_handler + * for easy understanding + */ #define SysTick_Handler eclic_mtip_handler -/* This is the timer interrupt service routine. */ +/** + * @brief This is the timer interrupt service routine. + * + */ void SysTick_Handler(void) { - // Reload timer + /* Reload systimer */ SysTick_Reload(SYSTICK_TICK_CONST); /* enter interrupt */ @@ -185,21 +233,26 @@ void SysTick_Handler(void) rt_interrupt_leave(); } -extern ssize_t _write(int fd, const void* ptr, size_t len); - -void rt_hw_console_output(const char *str) -{ - rt_size_t size = 0; - - size = rt_strlen(str); - _write(STDOUT_FILENO, str, size); -} - +/** + * @brief Disable cpu interrupt + * + * @details + * + * - Disable cpu interrupt by clear MIE bit in MSTATUS + * - Return the previous value in MSTATUS before clear MIE bit + * + * @return the previous value in MSTATUS before clear MIE bit + */ rt_base_t rt_hw_interrupt_disable(void) { return __RV_CSR_READ_CLEAR(CSR_MSTATUS, MSTATUS_MIE); } +/** + * @brief Restore previous saved interrupt status + * + * @param level previous saved MSTATUS value + */ void rt_hw_interrupt_enable(rt_base_t level) { __RV_CSR_WRITE(CSR_MSTATUS, level); diff --git a/libcpu/risc-v/nuclei/cpuport.h b/libcpu/risc-v/nuclei/cpuport.h index d5b6c82b9a..3736f0078a 100644 --- a/libcpu/risc-v/nuclei/cpuport.h +++ b/libcpu/risc-v/nuclei/cpuport.h @@ -6,7 +6,7 @@ * * Change Logs: * Date Author Notes - * 2020/03/26 Huaqi Nuclei RISC-V Core porting code. + * 2020/03/26 hqfang Nuclei RISC-V Core porting code. */ #ifndef __CPUPORT_H__ @@ -20,16 +20,18 @@ extern "C" { #endif /* Scheduler utilities. */ -#define portYIELD() \ -{ \ - /* Set a software interrupt(SWI) request to request a context switch. */ \ - SysTimer_SetSWIRQ(); \ - /* Barriers are normally not required but do ensure the code is completely \ - within the specified behaviour for the architecture. */ \ - __RWMB(); \ - __FENCE_I(); \ +#define RT_YIELD() \ +{ \ + /* Set a software interrupt(SWI) request to request a context switch. */ \ + SysTimer_SetSWIRQ(); \ + /* Barriers are normally not required but do ensure the code is completely \ + within the specified behaviour for the architecture. */ \ + __RWMB(); \ + __FENCE_I(); \ } +extern void rt_hw_ticksetup(void); +extern void rt_hw_taskswitch(void); #ifdef __cplusplus } diff --git a/libcpu/risc-v/nuclei/interrupt_gcc.S b/libcpu/risc-v/nuclei/interrupt_gcc.S index baeb04ebff..02a3e3e760 100644 --- a/libcpu/risc-v/nuclei/interrupt_gcc.S +++ b/libcpu/risc-v/nuclei/interrupt_gcc.S @@ -5,7 +5,7 @@ * * Change Logs: * Date Author Notes - * 2020/03/26 Huaqi First Nuclei RISC-V porting implementation + * 2020/03/26 hqfang First Nuclei RISC-V porting implementation */ #include "riscv_encoding.h"