diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h
index 40a7d8562b..724426b1d5 100644
--- a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h
+++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h
@@ -107,6 +107,7 @@
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
@@ -142,7 +143,4 @@ to exclude the API function. */
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); __asm volatile( "ebreak" ); for( ;; ); }
-#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
-
-
#endif /* FREERTOS_CONFIG_H */
diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch
index 8f9f92c989..3a67cbcc16 100644
--- a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch
+++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch
@@ -57,6 +57,6 @@
-
+
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h
index 0252ecda59..a5544b0614 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h
@@ -44,7 +44,7 @@
* base set of RISC-V registers. There are additional
* freertos_risc_v_port_specific_extensions.h files for RISC-V implementations
* that do not include a standard CLINT or do add to the base set of RISC-V
- * regiters.
+ * registers.
*
* CARE MUST BE TAKEN TO INCLDUE THE CORRECT
* freertos_risc_v_port_specific_extensions.h HEADER FILE FOR THE CHIP
@@ -62,5 +62,15 @@
#define __FREERTOS_RISC_V_EXTENSIONS_H__
#define portasmHAS_CLINT 1
+#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
+
+.macro portasmSAVE_ADDITIONAL_REGISTERS
+ /* No additional registers to save, so this macro does nothing. */
+ .endm
+
+/* Restore the additional registers found on the Pulpino. */
+.macro portasmRESTORE_ADDITIONAL_REGISTERS
+ /* No additional registers to restore, so this macro does nothing. */
+ .endm
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h
index e106b72233..2448d8a783 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h
@@ -44,7 +44,7 @@
* base set of RISC-V registers. There are additional
* freertos_risc_v_port_specific_extensions.h files for RISC-V implementations
* that do not include a standard CLINT or do add to the base set of RISC-V
- * regiters.
+ * registers.
*
* CARE MUST BE TAKEN TO INCLDUE THE CORRECT
* freertos_risc_v_port_specific_extensions.h HEADER FILE FOR THE CHIP
@@ -62,12 +62,49 @@
#define portasmHAS_CLINT 0
+/* Constants to define the additional registers found on the Pulpino RI5KY. */
+#define lpstart0 0x7b0
+#define lpend0 0x7b1
+#define lpcount0 0x7b2
+#define lpstart1 0x7b4
+#define lpend1 0x7b5
+#define lpcount1 0x7b6
+
+/* Six additional registers to save and restore, as per the #defines above. */
+#define portasmADDITIONAL_CONTEXT_SIZE 6 /* Must be even number on 32-bit cores. */
+
+/* Save additional registers found on the Pulpino. */
.macro portasmSAVE_ADDITIONAL_REGISTERS
+ addi sp, sp, -portasmADDITIONAL_CONTEXT_SIZE /* Make room for the additional registers. */
+ csrr t0, lpstart0 /* Load additional registers into accessable temporary registers. */
+ csrr t1, lpend0
+ csrr t2, lpcount0
+ csrr t3, lpstart1
+ csrr t4, lpend1
+ csrr t5, lpcount1
+ sw t0, 1 * portWORD_SIZE( sp )
+ sw t1, 2 * portWORD_SIZE( sp )
+ sw t2, 3 * portWORD_SIZE( sp )
+ sw t3, 4 * portWORD_SIZE( sp )
+ sw t4, 5 * portWORD_SIZE( sp )
+ sw t5, 6 * portWORD_SIZE( sp )
.endm
+/* Restore the additional registers found on the Pulpino. */
.macro portasmRESTORE_ADDITIONAL_REGISTERS
- /* This file is for use with chips that do not add to the standard RISC-V
- * register set, so there is nothing to do here. */
+ lw t0, 1 * portWORD_SIZE( sp ) /* Load additional registers into accessable temporary registers. */
+ lw t1, 2 * portWORD_SIZE( sp )
+ lw t2, 3 * portWORD_SIZE( sp )
+ lw t3, 4 * portWORD_SIZE( sp )
+ lw t4, 5 * portWORD_SIZE( sp )
+ lw t5, 6 * portWORD_SIZE( sp )
+ csrw lpstart0, t0
+ csrw lpend0, t1
+ csrw lpcount0, t2
+ csrw lpstart1, t3
+ csrw lpend1, t4
+ csrw lpcount1, t5
+ addi sp, sp, -portasmADDITIONAL_CONTEXT_SIZE /* Remove space added for additional registers. */
.endm
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
index 3f9a981477..a8b4928987 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
@@ -34,13 +34,28 @@
#include "task.h"
#include "portmacro.h"
-#ifdef configISR_STACK_SIZE
- /* The stack used by interrupt service routines. */
- static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 };
- const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & ~portBYTE_ALIGNMENT_MASK ) - 1 ] );
+/* Let the user override the pre-loading of the initial LR with the address of
+prvTaskExitError() in case it messes up unwinding of the stack in the
+debugger. */
+#ifdef configTASK_RETURN_ADDRESS
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
+#else
+ #define portTASK_RETURN_ADDRESS prvTaskExitError
+#endif
+
+/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS
+to use a statically allocated array as the interrupt stack. Alternative leave
+configISR_STACK_SIZE_WORDS undefined and update the linker script so that a
+linker variable names __freertos_irq_stack_top has the same value as the top
+of the stack used by main. Using the linker script method will repurpose the
+stack that was used by main before the scheduler was started for use as the
+interrupt stack after the scheduler has started. */
+#ifdef configISR_STACK_SIZE_WORDS
+ static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
+ const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ ( configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ) - 1 ] );
#else
extern const uint32_t __freertos_irq_stack_top[];
- const uint32_t xISRStackTop = ( uint32_t ) __freertos_irq_stack_top;
+ const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
#endif
/*
@@ -89,10 +104,10 @@ task stack, not the ISR stack). */
/*-----------------------------------------------------------*/
-void prvTaskExitError( void )
+static void prvTaskExitError( void )
{
volatile uint32_t ulx = 0;
-
+#warning Not currently used
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
@@ -105,107 +120,6 @@ volatile uint32_t ulx = 0;
}
/*-----------------------------------------------------------*/
-/*
- * See header file for description.
- */
-StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
-{
-uint32_t mstatus;
-const uint32_t ulMPIE_Bit = 0x80, ulMPP_Bits = 0x1800;
- /*
- X1 to X31 integer registers for the 'I' profile, X1 to X15 for the 'E' profile.
-
- Register ABI Name Description Saver
- x0 zero Hard-wired zero -
- x1 ra Return address Caller
- x2 sp Stack pointer Callee
- x3 gp Global pointer -
- x4 tp Thread pointer -
- x5-7 t0-2 Temporaries Caller
- x8 s0/fp Saved register/Frame pointer Callee
- x9 s1 Saved register Callee
- x10-11 a0-1 Function Arguments/return values Caller
- x12-17 a2-7 Function arguments Caller
- x18-27 s2-11 Saved registers Callee
- x28-31 t3-6 Temporaries Caller
- */
-
- /* Start task with interrupt enabled. */
- __asm volatile ("csrr %0, mstatus" : "=r"(mstatus));
- mstatus |= ulMPIE_Bit | ulMPP_Bits;
- pxTopOfStack--;
- *pxTopOfStack = mstatus;
-
- /* Numbers correspond to the x register number. */
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 31;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 30;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 29;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 28;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 27;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 26;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 25;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 24;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 23;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 22;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 21;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 20;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 19;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 18;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 17;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 16;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 15;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 14;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 13;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 12;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 11;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) pvParameters;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 9;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 8;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 7;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 6;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 5;
- pxTopOfStack--;
-// *pxTopOfStack = ( StackType_t ) 4; /* Thread pointer. */
-// pxTopOfStack--;
-// *pxTopOfStack = ( StackType_t ) 3; /* Global pointer. */
-// pxTopOfStack--;
-// *pxTopOfStack = ( StackType_t ) 2; /* Stack pointer. */
-// pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) prvTaskExitError;
- pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) pxCode;
-
- return pxTopOfStack;
-}
-/*-----------------------------------------------------------*/
-
#if( configCLINT_BASE_ADDRESS != 0 )
void vPortSetupTimerInterrupt( void )
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
index 2abafd461d..12cc49b4d0 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
@@ -25,6 +25,15 @@
* 1 tab == 4 spaces!
*/
+#if __riscv_xlen == 64
+ #error Not implemented yet - change lw to ld, and sw to sd.
+ #define portWORD_SIZE 8
+#elif __riscv_xlen == 32
+ #define portWORD_SIZE 4
+#else
+ #error Assembler did not define __riscv_xlen
+#endif
+
/*
* The FreeRTOS kernel's RISC-V port is split between the the code that is
* common across all currently supported RISC-V chips (implementations of the
@@ -42,7 +51,7 @@
* base set of RISC-V registers. There are additional
* freertos_risc_v_port_specific_extensions.h files for RISC-V implementations
* that do not include a standard CLINT or do add to the base set of RISC-V
- * regiters.
+ * registers.
*
* CARE MUST BE TAKEN TO INCLDUE THE CORRECT
* freertos_risc_v_port_specific_extensions.h HEADER FILE FOR THE CHIP
@@ -67,27 +76,6 @@ definitions. */
#error portasmHANDLE_INTERRUPT must be defined to the function to be called to handle external/peripheral interrupts. portasmHANDLE_INTERRUPT can be defined on the assmbler command line or in the appropriate freertos_risc_v_port_specific_extensions.h header file.
#endif
-#ifndef portasmSAVE_ADDITIONAL_REGISTERS
- /* portasmSAVE_ADDITIONAL_REGISTERS is not defined so assume no additional
- registers need to be saved. */
- #define portasmSAVE_ADDITIONAL_REGISTERS
-#endif
-
-#ifndef portasmRESTORE_ADDITIONAL_REGISTERS
- /* portasmRESTORE_ADDITIONAL_REGISTERS is not defined so assume no
- additional registers need to be restored. */
- #define portasmRESTORE_ADDITIONAL_REGISTERS
-#endif
-
-#if __riscv_xlen == 64
- #error Not implemented yet - change lw to ld, and sw to sd.
- #define portWORD_SIZE 8
-#elif __riscv_xlen == 32
- #define portWORD_SIZE 4
-#else
- #error Assembler did not define __riscv_xlen
-#endif
-
/* Only the standard core registers are stored by default. Any additional
registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and
portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip
@@ -97,6 +85,7 @@ at the top of this file. */
.global xPortStartFirstTask
.global vFreeRTOSPortTrapHandler
+.global pxPortInitialiseStack
.extern pxCurrentTCB
.extern ulPortTrapHandler
.extern vTaskSwitchContext
@@ -105,11 +94,11 @@ at the top of this file. */
.extern pullNextTime
.extern ulTimerIncrementsForOneTick
.extern xISRStackTop
-.extern vPortHandleInterrupt
/*-----------------------------------------------------------*/
-.align 16
+.align 8
+.func
vFreeRTOSPortTrapHandler:
addi sp, sp, -portCONTEXT_SIZE
sw x1, 1 * portWORD_SIZE( sp )
@@ -141,11 +130,11 @@ vFreeRTOSPortTrapHandler:
sw x30, 27 * portWORD_SIZE( sp )
sw x31, 28 * portWORD_SIZE( sp )
- portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to save any registers unique to the RISC-V implementation. */
-
csrr t0, mstatus /* Required for MPIE bit. */
sw t0, 29 * portWORD_SIZE( sp )
+ portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to save any registers unique to the RISC-V implementation. */
+
lw t0, pxCurrentTCB /* Load pxCurrentTCB. */
sw sp, 0( t0 ) /* Write sp to first TCB member. */
@@ -217,16 +206,16 @@ processed_source:
lw sp, pxCurrentTCB /* Load pxCurrentTCB. */
lw sp, 0( sp ) /* Read sp from first TCB member. */
- /* Load mret with the address of the next task. */
+ /* Load mret with the address of the next instruction in the task to run next. */
lw t0, 0( sp )
csrw mepc, t0
+ portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
+
/* Load mstatus with the interrupt enable bits used by the task. */
lw t0, 29 * portWORD_SIZE( sp )
csrw mstatus, t0 /* Required for MPIE bit. */
- portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
-
lw x1, 1 * portWORD_SIZE( sp )
lw x5, 2 * portWORD_SIZE( sp ) /* t0 */
lw x6, 3 * portWORD_SIZE( sp ) /* t1 */
@@ -255,12 +244,14 @@ processed_source:
lw x29, 26 * portWORD_SIZE( sp ) /* t4 */
lw x30, 27 * portWORD_SIZE( sp ) /* t5 */
lw x31, 28 * portWORD_SIZE( sp ) /* t6 */
- addi sp, sp, portCONTEXT_SIZE
+ addi sp, sp, portCONTEXT_SIZE
mret
+ .endfunc
/*-----------------------------------------------------------*/
-.align 16
+.align 8
+.func
xPortStartFirstTask:
#if( portasmHAS_CLINT != 0 )
@@ -275,6 +266,12 @@ xPortStartFirstTask:
lw sp, 0( sp ) /* Read sp from first TCB member. */
lw x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
+
+ portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
+
+ lw t0, 29 * portWORD_SIZE( sp ) /* mstatus */
+ csrrw x0, mstatus, t0 /* Interrupts enabled from here! */
+
lw x5, 2 * portWORD_SIZE( sp ) /* t0 */
lw x6, 3 * portWORD_SIZE( sp ) /* t1 */
lw x7, 4 * portWORD_SIZE( sp ) /* t2 */
@@ -303,8 +300,98 @@ xPortStartFirstTask:
lw x30, 27 * portWORD_SIZE( sp ) /* t5 */
lw x31, 28 * portWORD_SIZE( sp ) /* t6 */
addi sp, sp, portCONTEXT_SIZE
- csrs mstatus, 8 /* Enable machine interrupts. */
ret
-
+ .endfunc
/*-----------------------------------------------------------*/
+/*
+ * Unlike other ports pxPortInitialiseStack() is written in assembly code as it
+ * needs access to the portasmADDITIONAL_CONTEXT_SIZE constant. The prototype
+ * for the function is as per the other ports:
+ * StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters );
+ *
+ * As per the standard RISC-V ABI pxTopcOfStack is passed in in a0, pxCode in
+ * a1, and pvParameters in a2. The new top of stack is passed out in a0.
+ *
+ * RISC-V maps registers to ABI names as follows (X1 to X31 integer registers
+ * for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed).
+ *
+ * Register ABI Name Description Saver
+ * x0 zero Hard-wired zero -
+ * x1 ra Return address Caller
+ * x2 sp Stack pointer Callee
+ * x3 gp Global pointer -
+ * x4 tp Thread pointer -
+ * x5-7 t0-2 Temporaries Caller
+ * x8 s0/fp Saved register/Frame pointer Callee
+ * x9 s1 Saved register Callee
+ * x10-11 a0-1 Function Arguments/return values Caller
+ * x12-17 a2-7 Function arguments Caller
+ * x18-27 s2-11 Saved registers Callee
+ * x28-31 t3-6 Temporaries Caller
+ *
+ * The RISC-V context is saved t FreeRTOS tasks in the following stack frame,
+ * where the global and thread pointers are currently assumed to be constant so
+ * are not saved:
+ *
+ * mstatus
+ * x31
+ * x30
+ * x29
+ * x28
+ * x27
+ * x26
+ * x25
+ * x24
+ * x23
+ * x22
+ * x21
+ * x20
+ * x19
+ * x18
+ * x17
+ * x16
+ * x15
+ * x14
+ * x13
+ * x12
+ * x11
+ * pvParameters
+ * x9
+ * x8
+ * x7
+ * x6
+ * x5
+ * portTASK_RETURN_ADDRESS
+ * pxCode
+ */
+.align 8
+.func
+pxPortInitialiseStack:
+
+ addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
+
+chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */
+ beq t0, x0, standard_stack_frame /* No more chip specific registers to save. */
+ addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */
+ sw x0, 0(a0) /* Give the chip specific register an initial value of zero. */
+ addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */
+ j chip_specific_stack_frame /* Until no more chip specific registers. */
+
+standard_stack_frame: /* Now create the stack frame for the standard registers. */
+ csrr t0, mstatus /* Obtain current mstatus value. */
+ addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
+ slli t1, t1, 4
+ or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */
+
+ addi a0, a0, -portWORD_SIZE
+ sw t0, 0(a0) /* mstatus onto the stack. */
+ addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-x31. */
+ sw a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */
+ addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9. */
+ sw x0, 0(a0) /* Return address onto the stack, could be portTASK_RETURN_ADDRESS */
+ addi a0, a0, -portWORD_SIZE
+ sw a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */
+ ret
+ .endfunc
+/*-----------------------------------------------------------*/