Skip to content

RISC-V: Add support for RV32E extension in GCC port #543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions portable/GCC/RISC-V/portASM.S
Original file line number Diff line number Diff line change
Expand Up @@ -98,35 +98,35 @@ definitions. */
/*-----------------------------------------------------------*/

.macro portUPDATE_MTIMER_COMPARE_REGISTER
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 @@ -206,7 +206,12 @@ 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. */

#ifdef __riscv_32e
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x11-x15. */
#else
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-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. */
load_x t0, xTaskReturnAddress
Expand Down Expand Up @@ -241,6 +246,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 @@ -257,12 +263,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, mstatus, x5 /* Interrupts enabled from here! */

Expand Down
25 changes: 20 additions & 5 deletions portable/GCC/RISC-V/portContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,16 @@
* 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
Expand All @@ -71,6 +80,7 @@
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 +97,15 @@
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 @@ -133,10 +146,10 @@
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 +165,7 @@
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 +182,7 @@
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/GCC/RISC-V/portmacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,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 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no doubt the reduced alignment requirement is correct, but for my own records would like to know where it is documented. Grateful for a link.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#else
#define portBYTE_ALIGNMENT 16
#endif
/*-----------------------------------------------------------*/

/* Scheduler utilities. */
Expand Down