Skip to content

Commit

Permalink
Add IAR RISC-V 32 Embedded Extension Support (#588)
Browse files Browse the repository at this point in the history
Adds RV32E support to the IAR port. This is done by
reducing our register usage to the first 16 registers
only.

Influenced by changes in #543

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
  • Loading branch information
kstribrnAmzn and aggarg committed Nov 29, 2022
1 parent b213ad8 commit 1d59f65
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 31 deletions.
6 changes: 3 additions & 3 deletions portable/GCC/RISC-V/portASM.S
Expand Up @@ -208,12 +208,12 @@ pxPortInitialiseStack:
store_x x0, 0(a0) /* Critical nesting count starts at 0 for every task. */

#ifdef __riscv_32e
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x11-x15. */
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x10-x15. */
#else
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-x31. */
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x10-x31. */
#endif
store_x 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. */
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9 + taskReturnAddress. */
load_x t0, xTaskReturnAddress
store_x t0, 0(a0) /* Return address onto the stack. */
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
Expand Down
48 changes: 27 additions & 21 deletions portable/IAR/RISC-V/portASM.s
Expand Up @@ -107,35 +107,35 @@ definitions. */
CODE

portUPDATE_MTIMER_COMPARE_REGISTER MACRO
load_x t0, pullMachineTimerCompareRegister /* Load address of compare register into t0. */
load_x t1, pullNextTime /* Load the address of ullNextTime into t1. */
load_x a0, pullMachineTimerCompareRegister /* Load address of compare register into a0. */
load_x a1, pullNextTime /* Load the address of ullNextTime into a1. */

#if( __riscv_xlen == 32 )

/* Update the 64-bit mtimer compare match value in two 32-bit writes. */
li t4, -1
lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */
lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */
sw t4, 0(t0) /* Low word no smaller than old value to start with - will be overwritten below. */
sw t3, 4(t0) /* Store high word of ullNextTime into compare register. No smaller than new value. */
sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */
li a4, -1
lw a2, 0(a1) /* Load the low word of ullNextTime into a2. */
lw a3, 4(a1) /* Load the high word of ullNextTime into a3. */
sw a4, 0(a0) /* Low word no smaller than old value to start with - will be overwritten below. */
sw a3, 4(a0) /* Store high word of ullNextTime into compare register. No smaller than new value. */
sw a2, 0(a0) /* Store low word of ullNextTime into compare register. */
lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
add t4, t0, t2 /* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits). */
sltu t5, t4, t2 /* See if the sum of low words overflowed (what about the zero case?). */
add t6, t3, t5 /* Add overflow to high word of ullNextTime. */
sw t4, 0(t1) /* Store new low word of ullNextTime. */
sw t6, 4(t1) /* Store new high word of ullNextTime. */
add a4, t0, a2 /* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits). */
sltu t1, a4, a2 /* See if the sum of low words overflowed (what about the zero case?). */
add t2, a3, t1 /* Add overflow to high word of ullNextTime. */
sw a4, 0(a1) /* Store new low word of ullNextTime. */
sw t2, 4(a1) /* Store new high word of ullNextTime. */

#endif /* __riscv_xlen == 32 */

#if( __riscv_xlen == 64 )

/* Update the 64-bit mtimer compare match value. */
ld t2, 0(t1) /* Load ullNextTime into t2. */
sd t2, 0(t0) /* Store ullNextTime into compare register. */
ld t2, 0(a1) /* Load ullNextTime into t2. */
sd t2, 0(a0) /* Store ullNextTime into compare register. */
ld t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
add t4, t0, t2 /* Add ullNextTime to the timer increments for one tick. */
sd t4, 0(t1) /* Store ullNextTime. */
sd t4, 0(a1) /* Store ullNextTime. */

#endif /* __riscv_xlen == 64 */
ENDM
Expand Down Expand Up @@ -205,7 +205,7 @@ portUPDATE_MTIMER_COMPARE_REGISTER MACRO
* pxCode
*/
pxPortInitialiseStack:
csrr t0, CSR_MSTATUS /* Obtain current mstatus value. */
csrr t0, CSR_MSTATUS /* Obtain current mstatus value. */
andi t0, t0, ~0x8 /* Ensure interrupts are disabled when the stack is restored within an ISR. Required when a task is created after the schedulre has been started, otherwise interrupts would be disabled anyway. */
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
slli t1, t1, 4
Expand All @@ -215,9 +215,13 @@ pxPortInitialiseStack:
store_x t0, 0(a0) /* mstatus onto the stack. */
addi a0, a0, -portWORD_SIZE /* Space for critical nesting count. */
store_x x0, 0(a0) /* Critical nesting count starts at 0 for every task. */
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-x31. */
#ifdef __riscv_32e
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x10-15. */
#else
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x10-x31. */
#endif
store_x 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. */
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9 + taskReturnAddress. */
load_x t0, xTaskReturnAddress
store_x t0, 0(a0) /* Return address onto the stack. */
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
Expand Down Expand Up @@ -250,6 +254,7 @@ xPortStartFirstTask:
load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */
load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */
load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */
#ifndef __riscv_32e
load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */
load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */
load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */
Expand All @@ -266,12 +271,13 @@ xPortStartFirstTask:
load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */
#endif

load_x x5, 29 * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
load_x x5, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
load_x x6, pxCriticalNesting /* Load the address of xCriticalNesting into x6. */
store_x x5, 0( x6 ) /* Restore the critical nesting value for this task. */

load_x x5, 30 * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0). */
load_x x5, portMSTATUS_OFFSET * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0). */
addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
csrrw x0, CSR_MSTATUS, x5 /* Interrupts enabled from here! */

Expand Down
24 changes: 18 additions & 6 deletions portable/IAR/RISC-V/portContext.h
Expand Up @@ -48,7 +48,15 @@
* portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip
* specific version of freertos_risc_v_chip_specific_extensions.h. See the
* notes at the top of portASM.S file. */
#define portCONTEXT_SIZE ( 31 * portWORD_SIZE )
#ifdef __riscv_32e
#define portCONTEXT_SIZE ( 15 * portWORD_SIZE )
#define portCRITICAL_NESTING_OFFSET 13
#define portMSTATUS_OFFSET 14
#else
#define portCONTEXT_SIZE ( 31 * portWORD_SIZE )
#define portCRITICAL_NESTING_OFFSET 29
#define portMSTATUS_OFFSET 30
#endif

EXTERN pxCurrentTCB
EXTERN xISRStackTop
Expand All @@ -71,6 +79,7 @@ portcontextSAVE_CONTEXT_INTERNAL MACRO
store_x x13, 10 * portWORD_SIZE( sp )
store_x x14, 11 * portWORD_SIZE( sp )
store_x x15, 12 * portWORD_SIZE( sp )
#ifndef __riscv_32e
store_x x16, 13 * portWORD_SIZE( sp )
store_x x17, 14 * portWORD_SIZE( sp )
store_x x18, 15 * portWORD_SIZE( sp )
Expand All @@ -87,12 +96,13 @@ portcontextSAVE_CONTEXT_INTERNAL MACRO
store_x x29, 26 * portWORD_SIZE( sp )
store_x x30, 27 * portWORD_SIZE( sp )
store_x x31, 28 * portWORD_SIZE( sp )
#endif

load_x t0, xCriticalNesting /* Load the value of xCriticalNesting into t0. */
store_x t0, 29 * portWORD_SIZE( sp ) /* Store the critical nesting value to the stack. */
store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the critical nesting value to the stack. */

csrr t0, mstatus /* Required for MPIE bit. */
store_x t0, 30 * portWORD_SIZE( sp )
store_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp )

portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */

Expand Down Expand Up @@ -123,7 +133,7 @@ portcontextSAVE_INTERRUPT_CONTEXT MACRO

portcontextRESTORE_CONTEXT MACRO
load_x t1, pxCurrentTCB /* Load pxCurrentTCB. */
load_x sp, 0( t1 ) /* Read sp from first TCB member. */
load_x sp, 0( t1 ) /* Read sp from first TCB member. */

/* Load mepc with the address of the instruction in the task to run next. */
load_x t0, 0( sp )
Expand All @@ -133,10 +143,10 @@ portcontextRESTORE_CONTEXT MACRO
portasmRESTORE_ADDITIONAL_REGISTERS

/* Load mstatus with the interrupt enable bits used by the task. */
load_x t0, 30 * portWORD_SIZE( sp )
load_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp )
csrw mstatus, t0 /* Required for MPIE bit. */

load_x t0, 29 * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
load_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
load_x t1, pxCriticalNesting /* Load the address of xCriticalNesting into t1. */
store_x t0, 0( t1 ) /* Restore the critical nesting value for this task. */

Expand All @@ -152,6 +162,7 @@ portcontextRESTORE_CONTEXT MACRO
load_x x13, 10 * portWORD_SIZE( sp )
load_x x14, 11 * portWORD_SIZE( sp )
load_x x15, 12 * portWORD_SIZE( sp )
#ifndef __riscv_32e
load_x x16, 13 * portWORD_SIZE( sp )
load_x x17, 14 * portWORD_SIZE( sp )
load_x x18, 15 * portWORD_SIZE( sp )
Expand All @@ -168,6 +179,7 @@ portcontextRESTORE_CONTEXT MACRO
load_x x29, 26 * portWORD_SIZE( sp )
load_x x30, 27 * portWORD_SIZE( sp )
load_x x31, 28 * portWORD_SIZE( sp )
#endif
addi sp, sp, portCONTEXT_SIZE

mret
Expand Down
6 changes: 5 additions & 1 deletion portable/IAR/RISC-V/portmacro.h
Expand Up @@ -82,7 +82,11 @@ typedef portUBASE_TYPE TickType_t;
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 16
#ifdef __riscv_32e
#define portBYTE_ALIGNMENT 8 /* RV32E uses RISC-V EABI with reduced stack alignment requirements. */
#else
#define portBYTE_ALIGNMENT 16
#endif
/*-----------------------------------------------------------*/

/* Scheduler utilities. */
Expand Down

0 comments on commit 1d59f65

Please sign in to comment.