Skip to content

Commit bac101c

Browse files
Fix/clear MIE bit in initial RISC-V mstatus register. (#57)
* fix: CLEAR MIE BIT IN INITIAL RISC-V MSTATUS VALUE The MIE bit in the RISC-V MSTATUS register is used to globally enable or disable interrupts. It is copied into the MPIE bit and cleared on entry to an interrupt, and then copied back from the MPIE bit on exit from an interrupt. When a task is created it is given an initial MSTATUS value that is derived from the current MSTATUS value with the MPIE bit force to 1, but the MIE bit is not forced into any state. This change forces the MIE bit to 0 (interrupts disabled). Why: If a task is created before the scheduler is started the MIE bit will happen to be 0 (interrupts disabled), which is fine. If a task is created after the scheduler has been started the MIE bit is set (interrupts enabled), causing interrupts to unintentionally become enabled inside the interrupt in which the task is first moved to the running state - effectively breaking a critical section which in turn could cause a crash if enabling interrupts causes interrupts to nest. It is only an issue when starting a newly created task that was created after the scheduler was started. Related Issues: https://forums.freertos.org/t/risc-v-port-pxportinitialisestack-issue-about-mstatus-value-onto-the-stack/9622 Co-authored-by: Cobus van Eeden <[email protected]>
1 parent eac2b9a commit bac101c

File tree

2 files changed

+13
-10
lines changed

2 files changed

+13
-10
lines changed

portable/GCC/RISC-V/portASM.S

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,6 @@ xPortStartFirstTask:
313313

314314
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
315315

316-
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
317-
addi t0, t0, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
318-
csrrw x0, mstatus, t0 /* Interrupts enabled from here! */
319-
320-
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
321316
load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */
322317
load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */
323318
load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */
@@ -344,6 +339,12 @@ xPortStartFirstTask:
344339
load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */
345340
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */
346341
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */
342+
343+
load_x x5, 29 * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0) */
344+
addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
345+
csrrw x0, mstatus, x5 /* Interrupts enabled from here! */
346+
load_x x5, 2 * portWORD_SIZE( sp ) /* Initial x5 (t0) value. */
347+
347348
addi sp, sp, portCONTEXT_SIZE
348349
ret
349350
.endfunc
@@ -416,6 +417,7 @@ xPortStartFirstTask:
416417
pxPortInitialiseStack:
417418

418419
csrr t0, mstatus /* Obtain current mstatus value. */
420+
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. */
419421
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
420422
slli t1, t1, 4
421423
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */

portable/IAR/RISC-V/portASM.s

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,6 @@ xPortStartFirstTask:
320320

321321
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
322322

323-
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
324-
addi t0, t0, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
325-
csrrw x0, CSR_MSTATUS, t0 /* Interrupts enabled from here! */
326-
327-
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
328323
load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */
329324
load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */
330325
load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */
@@ -351,6 +346,11 @@ xPortStartFirstTask:
351346
load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */
352347
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */
353348
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */
349+
350+
load_x x5, 29 * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0) */
351+
addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
352+
csrrw x0, CSR_MSTATUS, x5 /* Interrupts enabled from here! */
353+
load_x x5, 2 * portWORD_SIZE( sp ) /* Initial x5 (t0) value. */
354354
addi sp, sp, portCONTEXT_SIZE
355355
ret
356356

@@ -421,6 +421,7 @@ xPortStartFirstTask:
421421
pxPortInitialiseStack:
422422

423423
csrr t0, CSR_MSTATUS /* Obtain current mstatus value. */
424+
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. */
424425
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
425426
slli t1, t1, 4
426427
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */

0 commit comments

Comments
 (0)