diff --git a/components/freertos/test/test_isr_latency.c b/components/freertos/test/test_isr_latency.c index 10c5d3069e..7ee22bbfe0 100644 --- a/components/freertos/test/test_isr_latency.c +++ b/components/freertos/test/test_isr_latency.c @@ -21,7 +21,20 @@ static uint32_t cycle_before_exit; static uint32_t delta_enter_cycles = 0; static uint32_t delta_exit_cycles = 0; -static void software_isr(void *arg) { +static void software_isr_using_parameter_vportyield(void *arg) { + (void)arg; + BaseType_t yield; + delta_enter_cycles += portGET_RUN_TIME_COUNTER_VALUE() - cycle_before_trigger; + + xt_set_intclear(1 << SW_ISR_LEVEL_1); + + xSemaphoreGiveFromISR(sync, &yield); + portYIELD_FROM_ISR(yield); + + cycle_before_exit = portGET_RUN_TIME_COUNTER_VALUE(); +} + +static void software_isr_using_no_argument_vportyield(void *arg) { (void)arg; BaseType_t yield; delta_enter_cycles += portGET_RUN_TIME_COUNTER_VALUE() - cycle_before_trigger; @@ -32,17 +45,11 @@ static void software_isr(void *arg) { if(yield) { portYIELD_FROM_ISR(); } - cycle_before_exit = portGET_RUN_TIME_COUNTER_VALUE(); } static void test_task(void *arg) { - (void)arg; - - intr_handle_t handle; - - esp_err_t err = esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, &software_isr, NULL, &handle); - TEST_ASSERT_EQUAL_HEX32(ESP_OK, err); + (void) arg; for(int i = 0;i < 10000; i++) { cycle_before_trigger = portGET_RUN_TIME_COUNTER_VALUE(); @@ -54,13 +61,36 @@ static void test_task(void *arg) { delta_enter_cycles /= 10000; delta_exit_cycles /= 10000; - esp_intr_free(handle); xSemaphoreGive(end_sema); vTaskDelete(NULL); } -TEST_CASE("isr latency test", "[freertos] [ignore]") +TEST_CASE("isr latency test vport-yield-from-isr with no parameter", "[freertos] [ignore]") { + intr_handle_t handle; + esp_err_t err = esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, &software_isr_using_no_argument_vportyield, NULL, &handle); + TEST_ASSERT_EQUAL_HEX32(ESP_OK, err); + + sync = xSemaphoreCreateBinary(); + TEST_ASSERT(sync != NULL); + end_sema = xSemaphoreCreateBinary(); + TEST_ASSERT(end_sema != NULL); + xTaskCreatePinnedToCore(test_task, "tst" , 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0); + vTaskDelay(100); + BaseType_t result = xSemaphoreTake(end_sema, portMAX_DELAY); + TEST_ASSERT_EQUAL_HEX32(pdTRUE, result); + TEST_PERFORMANCE_LESS_THAN(ISR_ENTER_CYCLES, "%d cycles" ,delta_enter_cycles); + TEST_PERFORMANCE_LESS_THAN(ISR_EXIT_CYCLES, "%d cycles" ,delta_exit_cycles); + + esp_intr_free(handle); +} + +TEST_CASE("isr latency test vport-yield-from-isr with parameter", "[freertos][ignore]") +{ + intr_handle_t handle; + esp_err_t err = esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, &software_isr_using_parameter_vportyield, NULL, &handle); + TEST_ASSERT_EQUAL_HEX32(ESP_OK, err); + sync = xSemaphoreCreateBinary(); TEST_ASSERT(sync != NULL); end_sema = xSemaphoreCreateBinary(); @@ -70,4 +100,6 @@ TEST_CASE("isr latency test", "[freertos] [ignore]") TEST_ASSERT_EQUAL_HEX32(pdTRUE, result); TEST_PERFORMANCE_LESS_THAN(ISR_ENTER_CYCLES, "%d cycles" ,delta_enter_cycles); TEST_PERFORMANCE_LESS_THAN(ISR_EXIT_CYCLES, "%d cycles" ,delta_exit_cycles); -} \ No newline at end of file + + esp_intr_free(handle); +} diff --git a/components/freertos/xtensa/include/freertos/portmacro.h b/components/freertos/xtensa/include/freertos/portmacro.h index 9c00fa16d9..e4d2c057b0 100644 --- a/components/freertos/xtensa/include/freertos/portmacro.h +++ b/components/freertos/xtensa/include/freertos/portmacro.h @@ -75,7 +75,7 @@ extern "C" { #include #include #include - +#include #include #include #include /* required for XSHAL_CLIB */ @@ -321,13 +321,27 @@ static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint #define portALT_GET_RUN_TIME_COUNTER_VALUE(x) x = (uint32_t)esp_timer_get_time() #endif - -/* Kernel utilities. */ void vPortYield( void ); +void vPortEvaluateYieldFromISR(int argc, ...); void _frxt_setup_switch( void ); -#define portYIELD() vPortYield() -#define portYIELD_FROM_ISR() {traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch();} +/** + * Macro to count number of arguments of a __VA_ARGS__ used to support portYIELD_FROM_ISR with, + * or without arguments. + */ +#define portGET_ARGUMENT_COUNT(...) portGET_ARGUMENT_COUNT_INNER(0, ##__VA_ARGS__,1,0) +#define portGET_ARGUMENT_COUNT_INNER(zero, one, count, ...) count +_Static_assert(portGET_ARGUMENT_COUNT() == 0, "portGET_ARGUMENT_COUNT() result does not match for 0 arguments"); +_Static_assert(portGET_ARGUMENT_COUNT(1) == 1, "portGET_ARGUMENT_COUNT() result does not match for 1 argument"); + +#define portYIELD() vPortYield() + +/** + * @note The macro below could be used when passing a single argument, or without any argument, + * it was developed to support both usages of portYIELD inside of an ISR. Any other usage form + * might result in undesired behaviour + */ +#define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR(portGET_ARGUMENT_COUNT(__VA_ARGS__), ##__VA_ARGS__) /* Yielding within an API call (when interrupts are off), means the yield should be delayed until interrupts are re-enabled. diff --git a/components/freertos/xtensa/port.c b/components/freertos/xtensa/port.c index 62eb61fdf5..597d1d6471 100644 --- a/components/freertos/xtensa/port.c +++ b/components/freertos/xtensa/port.c @@ -387,6 +387,30 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) return (port_interruptNesting[xPortGetCoreID()] != 0); } +void IRAM_ATTR vPortEvaluateYieldFromISR(int argc, ...) +{ + BaseType_t xYield; + va_list ap; + va_start(ap, argc); + + if(argc) { + xYield = (BaseType_t)va_arg(ap, int); + va_end(ap); + } else { + //it is a empty parameter vPortYieldFromISR macro call: + va_end(ap); + traceISR_EXIT_TO_SCHEDULER(); + _frxt_setup_switch(); + return; + } + + //Yield exists, so need evaluate it first then switch: + if(xYield == pdTRUE) { + traceISR_EXIT_TO_SCHEDULER(); + _frxt_setup_switch(); + } +} + void vPortAssertIfInISR(void) { configASSERT(xPortInIsrContext()); diff --git a/components/freertos/xtensa/portmacro_priv.h b/components/freertos/xtensa/portmacro_priv.h index 9c6ad2a3e9..e75c1f6b87 100644 --- a/components/freertos/xtensa/portmacro_priv.h +++ b/components/freertos/xtensa/portmacro_priv.h @@ -75,6 +75,4 @@ #define portVALID_STACK_MEM(ptr) esp_ptr_byte_accessible(ptr) #else #define portVALID_STACK_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr)) -#endif - - +#endif \ No newline at end of file