From df359100dc856a77a469665fe6f08757ae38ec41 Mon Sep 17 00:00:00 2001 From: Kedar Chitnis Date: Wed, 7 Jun 2023 16:36:24 +0530 Subject: [PATCH 1/6] feature: add ISR profiling support - add logic to stop measuring task cycles when ISR is entered - add logic to resume measuring task cycles when ISR is exited - add logic to avoid getting negative value for cycles in corner case of 32b timestamp overflow --- Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c | 6 ++++-- Source/os_core.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c b/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c index ceab816..a84cf6e 100644 --- a/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c +++ b/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c @@ -513,8 +513,10 @@ void OSTaskSwHook (void) #if OS_CFG_TASK_PROFILE_EN > 0u ts = OS_TS_GET(); if (OSTCBCurPtr != OSTCBHighRdyPtr) { - OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart; - OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta; + if (ts > OSTCBCurPtr->CyclesStart) { + OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart; + OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta; + } } OSTCBHighRdyPtr->CyclesStart = ts; diff --git a/Source/os_core.c b/Source/os_core.c index 737e72d..5c9ee3e 100644 --- a/Source/os_core.c +++ b/Source/os_core.c @@ -272,6 +272,18 @@ void OSIntEnter (void) return; /* Yes */ } +#if OS_CFG_TASK_PROFILE_EN > 0u + if(OSIntNestingCtr==0) { + CPU_TS ts; + + ts = OS_TS_GET(); + if(ts > OSTCBCurPtr->CyclesStart) { + OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart; + OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta; + } + } +#endif + OSIntNestingCtr++; /* Increment ISR nesting level */ } @@ -339,6 +351,10 @@ void OSIntExit (void) #endif #endif +#if OS_CFG_TASK_PROFILE_EN > 0u + OSTCBCurPtr->CyclesStart = OS_TS_GET(); +#endif + OSPrioHighRdy = OS_PrioGetHighest(); /* Find highest priority */ #if (OS_CFG_TASK_IDLE_EN > 0u) OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr; /* Get highest priority task ready-to-run */ From b592804b92bcf809bc98229cdf85042b28126798 Mon Sep 17 00:00:00 2001 From: Don Dominic Date: Mon, 3 Jul 2023 17:29:10 +0530 Subject: [PATCH 2/6] feat: add ISR context check API Signed-off-by: Don Dominic --- Source/os.h | 1 + Source/os_core.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Source/os.h b/Source/os.h index a9ffb3b..0d8e079 100644 --- a/Source/os.h +++ b/Source/os.h @@ -1897,6 +1897,7 @@ void OSInit (OS_ERR *p_err); void OSIntEnter (void); void OSIntExit (void); +CPU_BOOLEAN OSIntIsInIsr (void); #if (OS_CFG_SCHED_ROUND_ROBIN_EN > 0u) void OSSchedRoundRobinCfg (CPU_BOOLEAN en, diff --git a/Source/os_core.c b/Source/os_core.c index 5c9ee3e..8a05f3c 100644 --- a/Source/os_core.c +++ b/Source/os_core.c @@ -403,6 +403,35 @@ void OSIntExit (void) } +/* +************************************************************************************************************************ +* ISR CHECK +* +* Description: This function is called to check if the current context is in an ISR or not. +* +* Arguments : none +* +* Returns : If current context is in iSR (OS_TRUE) or not (OS_FALSE). +* +* Note(s) : none +************************************************************************************************************************ +*/ + +CPU_BOOLEAN OSIntIsInIsr (void) +{ + CPU_BOOLEAN in_isr; + + if (OSIntNestingCtr > 0u) { + in_isr = OS_TRUE; + } + else { + in_isr = OS_FALSE; + } + + return (in_isr); +} + + /* ************************************************************************************************************************ * INDICATE THAT IT'S NO LONGER SAFE TO CREATE OBJECTS From c306bc7b3619f8c65bb4a2ec53e321653d39326a Mon Sep 17 00:00:00 2001 From: Don Dominic Date: Thu, 13 Jul 2023 14:26:49 +0530 Subject: [PATCH 3/6] feat: add task message queue check API Add a new API to check if the task message queue is full or not. Signed-off-by: Don Dominic --- Source/os.h | 3 +++ Source/os_msg.c | 26 ++++++++++++++++++++++++++ Source/os_task.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/Source/os.h b/Source/os.h index 0d8e079..ccbd160 100644 --- a/Source/os.h +++ b/Source/os.h @@ -1672,6 +1672,7 @@ void OSTaskQPost (OS_TCB *p_tcb, OS_OPT opt, OS_ERR *p_err); +CPU_BOOLEAN OSTaskQIsFull (OS_TCB *p_tcb); #endif #if (OS_CFG_TASK_REG_TBL_SIZE > 0u) @@ -2010,6 +2011,8 @@ void OS_MsgQPut (OS_MSG_Q *p_msg_q, CPU_TS ts, OS_ERR *p_err); +CPU_BOOLEAN OS_MsgQIsFull (OS_MSG_Q *p_msg_q); + /* ---------------------------------------------- PEND/POST MANAGEMENT ---------------------------------------------- */ void OS_Pend (OS_PEND_OBJ *p_obj, diff --git a/Source/os_msg.c b/Source/os_msg.c index cd4836e..5852492 100644 --- a/Source/os_msg.c +++ b/Source/os_msg.c @@ -346,4 +346,30 @@ void OS_MsgQPut (OS_MSG_Q *p_msg_q, #endif *p_err = OS_ERR_NONE; } + + +/* +************************************************************************************************************************ +* CHECK MESSAGE QUEUE +* +* Description: This function checks if the message queue is full or not +* +* Arguments : p_msg_q is a pointer to the message queue +* ------- +* +* Returns : == OS_FALSE if message queue is not full. +* == OS_TRUE if message queue is full. +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. +************************************************************************************************************************ +*/ + +CPU_BOOLEAN OS_MsgQIsFull (OS_MSG_Q *p_msg_q) +{ + if (p_msg_q->NbrEntries >= p_msg_q->NbrEntriesSize) { + return(OS_TRUE); + } else { + return(OS_FALSE); + } +} #endif diff --git a/Source/os_task.c b/Source/os_task.c index cf85f83..6cb2095 100644 --- a/Source/os_task.c +++ b/Source/os_task.c @@ -1170,6 +1170,34 @@ void OSTaskQPost (OS_TCB *p_tcb, #endif +/* +************************************************************************************************************************ +* TASK MESSAGE Q CHECK +* +* Description: This function checks if the task message queue is full or not. +* +* Arguments : p_tcb is a pointer to the TCB of the task. If you specify a NULL pointer then the check is +* performed for the queue of the calling task. +* +* Returns : == OS_FALSE if task message queue is not full. +* == OS_TRUE if task message queue is full. +* +* Note(s) : none +************************************************************************************************************************ +*/ + +#if (OS_CFG_TASK_Q_EN > 0u) +CPU_BOOLEAN OSTaskQIsFull (OS_TCB *p_tcb) +{ + if (p_tcb == (OS_TCB *)0) { /* Check for 'self'? */ + p_tcb = OSTCBCurPtr; + } + + return (OS_MsgQIsFull(&p_tcb->MsgQ)); +} +#endif + + /* ************************************************************************************************************************ * GET THE CURRENT VALUE OF A TASK REGISTER From ed1b308c1ae3e82190bd1b5fd8064618935d03c7 Mon Sep 17 00:00:00 2001 From: Kedar Chitnis Date: Thu, 5 Oct 2023 13:57:09 +0530 Subject: [PATCH 4/6] chore: add a volatile keyword to keep a error check in OSInitHook OSInitHook has a error check to make sure the M4F FPU is in correct mode. As such the FPU in STM32G4 M4F is in correct state on reset and this check will always pass. However making sure the error check stays active in the final binary could help catch issues in some other platforms --- Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c b/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c index a84cf6e..3016422 100644 --- a/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c +++ b/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c @@ -114,7 +114,7 @@ void OSIdleTaskHook (void) void OSInitHook (void) { #if (OS_CPU_ARM_FP_EN > 0u) - CPU_INT32U reg_val; + volatile CPU_INT32U reg_val; #endif /* 8-byte align the ISR stack. */ OS_CPU_ExceptStkBase = (CPU_STK *)(OSCfg_ISRStkBasePtr + OSCfg_ISRStkSize); From 5be7f3b60a7e2b678ba35a3a6376df590bfc8a7e Mon Sep 17 00:00:00 2001 From: iontra-gaurav <162095343+iontra-gaurav@users.noreply.github.com> Date: Fri, 26 Apr 2024 12:00:09 +0530 Subject: [PATCH 5/6] feat: uCOS3 port for Sifive E2x RISC-V (#5) -This commit contains changes for enabling interrupt(including timer interrupt) in uC-OS RISC V port. -Saving and restoring of registers during context switch (task to task, interrupt to task, task to interrupt) -Removed systick handler as we are directly calling OSTimeTick() from timer ISR. -Added comments in os_cpu_a.S file for better understanding of assembly line instruction. Signed-off-by: Gaurav --- Ports/RISC-V/RV32/GCC/os_cpu_a.S | 166 +++++++++++++++++++++---------- Ports/RISC-V/RV32/GCC/os_cpu_c.c | 30 ------ 2 files changed, 116 insertions(+), 80 deletions(-) diff --git a/Ports/RISC-V/RV32/GCC/os_cpu_a.S b/Ports/RISC-V/RV32/GCC/os_cpu_a.S index ab66d9a..1736af6 100644 --- a/Ports/RISC-V/RV32/GCC/os_cpu_a.S +++ b/Ports/RISC-V/RV32/GCC/os_cpu_a.S @@ -35,7 +35,6 @@ .extern OSPrioHighRdy .extern OSTCBCurPtr .extern OSTCBHighRdyPtr - .extern OSIntExit .extern OSTaskSwHook @@ -43,17 +42,18 @@ .global OSCtxSw .global OSIntCtxSw .global Software_IRQHandler + .global ucos_intr_exception_handler #******************************************************************************************************** # EQUATES #******************************************************************************************************** - .equ RISCV_MSTATUS_MIE, 0x08 + .equ RISCV_MSTATUS_MIE, 0x08 - .equ RISCV_MIE_MSIE, 0x08 # M Soft Interrupt bit + .equ ARCH_CPU_MCAUSE_INTR_MASK, 0x80000000 - .equ RISCV_PRCI_BASE_ADDR, 0x44000000 + .equ ARCH_CPU_MCAUSE_CAUSE_MASK, 0x000003FF #******************************************************************************************************** @@ -78,27 +78,38 @@ OSStartHighRdy: # Disable interrupts + # load immediately "RISCV_MSTATUS_MIE" into t0 register li t0, RISCV_MSTATUS_MIE + # mstatus = mstatus & ~t0 csrrc zero, mstatus, t0 # Execute OS task switch hook. + # jump to OSTaskSwHook function(address) and store the next instruction + # into link register + # this function will get called each time when the context switch happens jal OSTaskSwHook # OSRunning = TRUE; li t0, 0x01 + # load address of OSRunning into t1 register la t1, OSRunning + # store byte value of t0 into memory address pointed by t1 with 0 offset sb t0, 0(t1) # SWITCH TO HIGHEST PRIORITY TASK la t0, OSTCBHighRdyPtr + # load word from address stored in [t0 + 0(offset)] to t1 lw t1, 0(t0) + # load word from address stored in [t1+ 0(offset)] into sp lw sp, 0(t1) # Retrieve the location where to jump lw t0, 31 * 4(sp) + # value stored in t0 is stored into mepc csrw mepc, t0 # Restore x1 to x31 registers + # load word from memory addres [(0 * 4) + sp] into ra register lw ra, 0 * 4(sp) lw t0, 4 * 4(sp) lw t1, 5 * 4(sp) @@ -129,6 +140,7 @@ OSStartHighRdy: lw t6, 30 * 4(sp) # Compensate for the stack pointer + # sp = sp + 32 * 4 addi sp, sp, 32 * 4 # Use register t6 to jump to HIGHEST priority @@ -147,66 +159,116 @@ OSStartHighRdy: # PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() # # Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function -# triggers a synchronous software interrupt by writing into the MSIP register +# triggers a ecall. # # 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as -# the result of an interrupt. This function triggers a synchronous software interrupt by -# writing into the MSIP register +# the result of an interrupt. This function just return back as the context switch after interrupt +# is executed just before exiting the interrupt handler. #******************************************************************************************************** +OSIntCtxSw: + ret OSCtxSw: -OSIntCtxSw: -# MIE_MSIE -- enable software interrupt bit - li t0, RISCV_MIE_MSIE - csrrs zero, mie, t0 - -# This will trigger a synchronous software interrupt; PRCI->MSIP[0] = 0x01; - li t0, RISCV_PRCI_BASE_ADDR - li t1, 0x1 - sw t1, 0x0(t0) + ecall ret +# Exception handler should be 256 bytes aligned +.align 8 +ucos_intr_exception_handler: + # save regs to current sp + addi sp, sp, -4*32 + # store contents of register ra into memory [(0 * 4) + sp] + sw ra, 0 * 4(sp) + sw t0, 4 * 4(sp) + sw t1, 5 * 4(sp) + sw t2, 6 * 4(sp) + sw s0, 7 * 4(sp) + sw s1, 8 * 4(sp) + sw a0, 9 * 4(sp) + sw a1, 10 * 4(sp) + sw a2, 11 * 4(sp) + sw a3, 12 * 4(sp) + sw a4, 13 * 4(sp) + sw a5, 14 * 4(sp) + sw a6, 15 * 4(sp) + sw a7, 16 * 4(sp) + sw s2, 17 * 4(sp) + sw s3, 18 * 4(sp) + sw s4, 19 * 4(sp) + sw s5, 20 * 4(sp) + sw s6, 21 * 4(sp) + sw s7, 22 * 4(sp) + sw s8, 23 * 4(sp) + sw s9, 24 * 4(sp) + sw s10, 25 * 4(sp) + sw s11, 26 * 4(sp) + sw t3, 27 * 4(sp) + sw t4, 28 * 4(sp) + sw t5, 29 * 4(sp) + sw t6, 30 * 4(sp) + + # If it is a ecall, do not add 4 in mepc + # otherwise add 4 in mepc + li t1, ARCH_CPU_MCAUSE_CAUSE_MASK + csrr t0, mcause + # t3 = t1 & t0 + and t3, t1, t0 + li t1, 11 + csrr t0, mepc + # If t1 != t3 jump to DONTADD: + bne t1, t3, DONTADD + addi t0, t0, 4 + +DONTADD: # for interrupt do not add 4 in mepc + sw t0, 31*4(sp) + # load address of OSTCBCurPtr into t0 register + la t0, OSTCBCurPtr + # load word from register [t0 + 0] address into t1 + lw t1, 0(t0) + # store value stored in sp to [t1 + 0] address + sw sp, 0(t1) + + li t1, ARCH_CPU_MCAUSE_INTR_MASK + csrr t0, mcause + and t2, t1, t0 + bne t1, t2, run_exception_handler + # it is a interrupt + j run_interrupt_exception_handler + +run_exception_handler: + li t1, ARCH_CPU_MCAUSE_CAUSE_MASK + csrr t0, mcause + and t3, t1, t0 + li t1, 11 + bne t1, t3, run_interrupt_exception_handler + # it is a ecall + j run_ecall_handler + +run_interrupt_exception_handler: + jal osa_intr_master_isr + +run_ecall_handler: + j Software_IRQHandler + + + #******************************************************************************************************** # void Software_IRQHandler (void) # -# Note(s) : 1) This function is defined with weak linking in 'riscv_hal_stubs.c' so that it can be -# overridden by the kernel port with same prototype. -# -# 2) Pseudo-code is: -# a) Disable global interrupts. -# b) Clear soft interrupt for hart0. -# c) Save the process SP in its TCB, OSTCBCurPtr->StkPtr = SP; -# d) Call OSTaskSwHook(); -# e) Get current high priority, OSPrioCur = OSPrioHighRdy; -# f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr; -# g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->StkPtr; -# h) Retrieve the address at which exception happened -# i) Restore x1-x31 from new process stack; x0 is always zero. -# j) Perform exception return which will restore remaining context. +# 1) Pseudo-code is: +# a) Call OSTaskSwHook(); +# b) Get current high priority, OSPrioCur = OSPrioHighRdy; +# c) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr; +# d) Get new process SP from TCB, SP = OSTCBHighRdyPtr->StkPtr; +# e) Retrieve the address at which exception happened. +# f) Restore x1-x31 from new process stack; x0 is always zero. +# g) set MPIE = 1 to enable interrupt before returning. +# h) Perform exception return which will restore remaining context. # -# 3) On entry into Software_IRQHandler: -# a) The initial register context save is being done by 'entry.S' -# b) Stack pointer was passed by 'entry.s' in register a2. -# c) OSTCBCurPtr points to the OS_TCB of the task to suspend -# OSTCBHighRdyPtr points to the OS_TCB of the task to resume #******************************************************************************************************** Software_IRQHandler: -# Disable interrupts globally and prevent interruption during context switch - li t0, RISCV_MSTATUS_MIE - csrrc zero, mstatus, t0 - -# Clear soft interrupt for hart0, PRCI->MSIP[0] = 0x00; - li t0, RISCV_PRCI_BASE_ADDR - sw zero, 0x0(t0) - -# Stack pointer was passed by 'entry.s' in register a2. -# OSTCBCurPtr->StkPtr = SP; - la t0, OSTCBCurPtr - lw t1, 0(t0) - sw a2, 0(t1) - # Execute OS task switch hook. jal OSTaskSwHook @@ -259,12 +321,16 @@ Software_IRQHandler: lw t5, 29 * 4(sp) lw t6, 30 * 4(sp) +# Compensate for the stack pointer addi sp, sp, 4 * 32 # Exception return will restore remaining context + # set MPIE = 1 + # interrupts will be enabled from here onwards + li t0, 0x80 + csrrs zero, mstatus, t0 mret - #******************************************************************************************************** # MODULE END #********************************************************************************************************* diff --git a/Ports/RISC-V/RV32/GCC/os_cpu_c.c b/Ports/RISC-V/RV32/GCC/os_cpu_c.c index f9d83cd..52a9809 100644 --- a/Ports/RISC-V/RV32/GCC/os_cpu_c.c +++ b/Ports/RISC-V/RV32/GCC/os_cpu_c.c @@ -443,36 +443,6 @@ void OSTimeTickHook (void) #endif } - -/* -********************************************************************************************************* -* SYS TICK HANDLER -* -* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-III tick -* interrupt. -* -* Arguments : None. -* -* Note(s) : This function is defined with weak linking in 'riscv_hal_stubs.c' so that it can be -* overridden by the kernel port with same prototype -********************************************************************************************************* -*/ - -void SysTick_Handler (void) -{ - CPU_SR_ALLOC(); /* Allocate storage for CPU status register */ - - - CPU_CRITICAL_ENTER(); - OSIntEnter(); /* Tell uC/OS-III that we are starting an ISR */ - CPU_CRITICAL_EXIT(); - - OSTimeTick(); /* Call uC/OS-III's OSTimeTick() */ - - OSIntExit(); /* Tell uC/OS-III that we are leaving the ISR */ -} - - /* ********************************************************************************************************* * EXTERNAL C LANGUAGE LINKAGE END From 845c86b8c8fac0c51dfb3a3f53967d21d0aeae60 Mon Sep 17 00:00:00 2001 From: Gaurav Date: Mon, 6 May 2024 11:20:17 +0530 Subject: [PATCH 6/6] feat : enable FPU in UCOS This change enable the saving and restoring of FPU registers during context switch. [ISDK-60](https://iontra.atlassian.net/browse/ISDK-60) Signed-off-by: Gaurav --- Ports/RISC-V/RV32/GCC/os_cpu_a.S | 118 ++++++++++++++++++++++++++++--- Ports/RISC-V/RV32/GCC/os_cpu_c.c | 7 +- 2 files changed, 115 insertions(+), 10 deletions(-) diff --git a/Ports/RISC-V/RV32/GCC/os_cpu_a.S b/Ports/RISC-V/RV32/GCC/os_cpu_a.S index 1736af6..fd0724e 100644 --- a/Ports/RISC-V/RV32/GCC/os_cpu_a.S +++ b/Ports/RISC-V/RV32/GCC/os_cpu_a.S @@ -23,7 +23,6 @@ # For : RISC-V RV32 # Toolchain : GNU C Compiler #******************************************************************************************************** -# Note(s) : Hardware FP is not supported. #******************************************************************************************************** #******************************************************************************************************** @@ -71,7 +70,7 @@ # a) Call OSTaskSwHook() then, # b) Set OSRunning to TRUE, # c) Set OSTCBHighRdyPtr->StkPtr = SP -# d) Restore x1-x31; There is no need to restore x0 since it is always zero. +# d) Restore x1-x31 and f0-f31; There is no need to restore x0 since it is always zero. # e) Enable interrupts (tasks will run with interrupts enabled). # f) Switch to highest priority task. #******************************************************************************************************** @@ -108,7 +107,7 @@ OSStartHighRdy: # value stored in t0 is stored into mepc csrw mepc, t0 -# Restore x1 to x31 registers +# Restore x1 to x31 registers (base registers) # load word from memory addres [(0 * 4) + sp] into ra register lw ra, 0 * 4(sp) lw t0, 4 * 4(sp) @@ -139,9 +138,43 @@ OSStartHighRdy: lw t5, 29 * 4(sp) lw t6, 30 * 4(sp) + #Restore f0 to f31 registers (FP registers) + flw f0, 32 * 4(sp) + flw f1, 33 * 4(sp) + flw f2, 34 * 4(sp) + flw f3, 35 * 4(sp) + flw f4, 36 * 4(sp) + flw f5, 37 * 4(sp) + flw f6, 38 * 4(sp) + flw f7, 39 * 4(sp) + flw f8, 40 * 4(sp) + flw f9, 41 * 4(sp) + flw f10, 42 * 4(sp) + flw f11, 43 * 4(sp) + flw f12, 44 * 4(sp) + flw f13, 45 * 4(sp) + flw f14, 46 * 4(sp) + flw f15, 47 * 4(sp) + flw f16, 48 * 4(sp) + flw f17, 49 * 4(sp) + flw f18, 50 * 4(sp) + flw f19, 51 * 4(sp) + flw f20, 52 * 4(sp) + flw f21, 53 * 4(sp) + flw f22, 54 * 4(sp) + flw f23, 55 * 4(sp) + flw f24, 56 * 4(sp) + flw f25, 57 * 4(sp) + flw f26, 58 * 4(sp) + flw f27, 59 * 4(sp) + flw f28, 60 * 4(sp) + flw f29, 61 * 4(sp) + flw f30, 62 * 4(sp) + flw f31, 63 * 4(sp) + # Compensate for the stack pointer - # sp = sp + 32 * 4 - addi sp, sp, 32 * 4 + # sp = sp + 64 * 4 + addi sp, sp, 64 * 4 # Use register t6 to jump to HIGHEST priority csrr t6, mepc @@ -176,7 +209,7 @@ OSCtxSw: .align 8 ucos_intr_exception_handler: # save regs to current sp - addi sp, sp, -4*32 + addi sp, sp, -4*64 # store contents of register ra into memory [(0 * 4) + sp] sw ra, 0 * 4(sp) sw t0, 4 * 4(sp) @@ -207,6 +240,40 @@ ucos_intr_exception_handler: sw t5, 29 * 4(sp) sw t6, 30 * 4(sp) + # save f0 to f31 registers (FPU registers) + fsw f0, 32 * 4(sp) + fsw f1, 33 * 4(sp) + fsw f2, 34 * 4(sp) + fsw f3, 35 * 4(sp) + fsw f4, 36 * 4(sp) + fsw f5, 37 * 4(sp) + fsw f6, 38 * 4(sp) + fsw f7, 39 * 4(sp) + fsw f8, 40 * 4(sp) + fsw f9, 41 * 4(sp) + fsw f10, 42 * 4(sp) + fsw f11, 43 * 4(sp) + fsw f12, 44 * 4(sp) + fsw f13, 45 * 4(sp) + fsw f14, 46 * 4(sp) + fsw f15, 47 * 4(sp) + fsw f16, 48 * 4(sp) + fsw f17, 49 * 4(sp) + fsw f18, 50 * 4(sp) + fsw f19, 51 * 4(sp) + fsw f20, 52 * 4(sp) + fsw f21, 53 * 4(sp) + fsw f22, 54 * 4(sp) + fsw f23, 55 * 4(sp) + fsw f24, 56 * 4(sp) + fsw f25, 57 * 4(sp) + fsw f26, 58 * 4(sp) + fsw f27, 59 * 4(sp) + fsw f28, 60 * 4(sp) + fsw f29, 61 * 4(sp) + fsw f30, 62 * 4(sp) + fsw f31, 63 * 4(sp) + # If it is a ecall, do not add 4 in mepc # otherwise add 4 in mepc li t1, ARCH_CPU_MCAUSE_CAUSE_MASK @@ -262,7 +329,8 @@ run_ecall_handler: # c) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr; # d) Get new process SP from TCB, SP = OSTCBHighRdyPtr->StkPtr; # e) Retrieve the address at which exception happened. -# f) Restore x1-x31 from new process stack; x0 is always zero. +# f) Restore x1-x31(base registers) and f0-f31(FP registers) +# from new process stack; x0 is always zero. # g) set MPIE = 1 to enable interrupt before returning. # h) Perform exception return which will restore remaining context. # @@ -321,8 +389,42 @@ Software_IRQHandler: lw t5, 29 * 4(sp) lw t6, 30 * 4(sp) + # Restore f0 to f31 registers (FPU registers) + flw f0, 32 * 4(sp) + flw f1, 33 * 4(sp) + flw f2, 34 * 4(sp) + flw f3, 35 * 4(sp) + flw f4, 36 * 4(sp) + flw f5, 37 * 4(sp) + flw f6, 38 * 4(sp) + flw f7, 39 * 4(sp) + flw f8, 40 * 4(sp) + flw f9, 41 * 4(sp) + flw f10, 42 * 4(sp) + flw f11, 43 * 4(sp) + flw f12, 44 * 4(sp) + flw f13, 45 * 4(sp) + flw f14, 46 * 4(sp) + flw f15, 47 * 4(sp) + flw f16, 48 * 4(sp) + flw f17, 49 * 4(sp) + flw f18, 50 * 4(sp) + flw f19, 51 * 4(sp) + flw f20, 52 * 4(sp) + flw f21, 53 * 4(sp) + flw f22, 54 * 4(sp) + flw f23, 55 * 4(sp) + flw f24, 56 * 4(sp) + flw f25, 57 * 4(sp) + flw f26, 58 * 4(sp) + flw f27, 59 * 4(sp) + flw f28, 60 * 4(sp) + flw f29, 61 * 4(sp) + flw f30, 62 * 4(sp) + flw f31, 63 * 4(sp) + # Compensate for the stack pointer - addi sp, sp, 4 * 32 + addi sp, sp, 4 * 64 # Exception return will restore remaining context # set MPIE = 1 diff --git a/Ports/RISC-V/RV32/GCC/os_cpu_c.c b/Ports/RISC-V/RV32/GCC/os_cpu_c.c index 52a9809..b9c6cf5 100644 --- a/Ports/RISC-V/RV32/GCC/os_cpu_c.c +++ b/Ports/RISC-V/RV32/GCC/os_cpu_c.c @@ -306,8 +306,12 @@ CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task, p_stk = &p_stk_base[stk_size]; /* Load stack pointer and align it to 16-bytes */ p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF0u); + /* make space for floating point registers */ + for(int i = 0; i < 32; i++) { + *(--p_stk) = (CPU_STK)0; + } + /* make space for base registers */ *(--p_stk) = (CPU_STK) p_task; /* Entry Point */ - *(--p_stk) = (CPU_STK) 0x31313131uL; /* t6 */ *(--p_stk) = (CPU_STK) 0x30303030uL; /* t5 */ *(--p_stk) = (CPU_STK) 0x29292929uL; /* t4 */ @@ -344,7 +348,6 @@ CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task, *(--p_stk) = (CPU_STK) 0x03030303uL; /* gp: Global pointer */ *(--p_stk) = (CPU_STK) 0x02020202uL; /* sp: Stack pointer */ *(--p_stk) = (CPU_STK) OS_TaskReturn; /* ra: return address */ - return (p_stk); }