kopia lustrzana https://github.com/espressif/esp-idf
freertos: Fix delay between interrupt request and trigger on RISC-V
NOP instructions have been added in order to prevent the code from executing code it shouldn't execute. This is due to a delay between the moment an interrupt is requested and the moment it is fired. It only happens on RISC-V SoC.pull/6718/head
rodzic
daf429c67f
commit
78a94dbb6c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Ładowanie…
Reference in New Issue