Merge branch 'feature/re-enable_suspend_test_esp32c3_v4.3' into 'release/v4.3'

freertos: Workaround delay between interrupt request and trigger on RISC-V (backport v4.3)

See merge request espressif/esp-idf!12679
This commit is contained in:
Angus Gratton 2021-03-11 07:12:56 +00:00
commit a8e0989648
2 changed files with 29 additions and 4 deletions

View File

@ -178,6 +178,24 @@ void prvTaskExitError(void)
void vPortClearInterruptMask(int mask)
{
REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, mask);
/**
* The delay between the moment we unmask the interrupt threshold register
* and the moment the potential requested interrupt is triggered is not
* null: up to three machine cycles/instructions can be executed.
*
* When compilation size optimization is enabled, this function and its
* callers returning void will have NO epilogue, thus the instruction
* following these calls will be executed.
*
* If the requested interrupt is a context switch to a higher priority
* task then the one currently running, we MUST NOT execute any instruction
* before the interrupt effectively happens.
* In order to prevent this, force this routine to have a 3-instruction
* delay before exiting.
*/
asm volatile ( "nop" );
asm volatile ( "nop" );
asm volatile ( "nop" );
}
/* Set interrupt mask and return current interrupt enable register */
@ -188,6 +206,17 @@ int vPortSetInterruptMask(void)
ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL);
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
/**
* In theory, this function should not return immediately as there is a
* delay between the moment we mask the interrupt threshold register and
* the moment a potential lower-priority interrupt is triggered (as said
* above), it should have a delay of 2 machine cycles/instructions.
*
* However, in practice, this function has an epilogue of one instruction,
* thus the instruction masking the interrupt threshold register is
* followed by two instructions: `ret` and `csrrs` (RV_SET_CSR).
* That's why we don't need any additional nop instructions here.
*/
return ret;
}

View File

@ -89,9 +89,6 @@ TEST_CASE("Suspend/resume task on other core", "[freertos]")
}
#endif
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
// TODO ESP32C3 IDF-2588
/* Task suspends itself, then sets a flag and deletes itself */
static void task_suspend_self(void *vp_resumed)
{
@ -118,7 +115,6 @@ TEST_CASE("Suspend the current running task", "[freertos]")
// Shouldn't need any delay here, as task should resume on this CPU immediately
TEST_ASSERT_TRUE(resumed);
}
#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
volatile bool timer_isr_fired;