From c471cce26c8e496ba602fe158884e896483b67b4 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Tue, 4 Aug 2020 16:16:33 -0300 Subject: [PATCH] freertos/tests: added isr latency test with no parameter and parameter based yield from ISR --- components/freertos/test/test_isr_latency.c | 52 +++++++++++++++---- .../xtensa/include/freertos/portmacro.h | 22 +++++--- components/freertos/xtensa/port.c | 6 +-- 3 files changed, 62 insertions(+), 18 deletions(-) diff --git a/components/freertos/test/test_isr_latency.c b/components/freertos/test/test_isr_latency.c index ab626633e6..7ee22bbfe0 100644 --- a/components/freertos/test/test_isr_latency.c +++ b/components/freertos/test/test_isr_latency.c @@ -21,7 +21,7 @@ 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; @@ -34,13 +34,22 @@ static void software_isr(void *arg) { cycle_before_exit = portGET_RUN_TIME_COUNTER_VALUE(); } -static void test_task(void *arg) { +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; - 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); + xt_set_intclear(1 << SW_ISR_LEVEL_1); + + xSemaphoreGiveFromISR(sync, &yield); + if(yield) { + portYIELD_FROM_ISR(); + } + cycle_before_exit = portGET_RUN_TIME_COUNTER_VALUE(); +} + +static void test_task(void *arg) { + (void) arg; for(int i = 0;i < 10000; i++) { cycle_before_trigger = portGET_RUN_TIME_COUNTER_VALUE(); @@ -52,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(); @@ -68,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 bc58e75052..e4d2c057b0 100644 --- a/components/freertos/xtensa/include/freertos/portmacro.h +++ b/components/freertos/xtensa/include/freertos/portmacro.h @@ -322,16 +322,26 @@ static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint #endif void vPortYield( void ); -void xEvaluateYieldFromISR(int argc, ...); +void vPortEvaluateYieldFromISR(int argc, ...); void _frxt_setup_switch( void ); +/** + * 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 -//Macro to count number of arguments of a __VA_ARGS__ used to support portYIELD_FROM_ISR with, -//or without arguments. -#define GET_ARGUMENT_COUNT(...) GET_ARGUMENT_COUNT_INNER(0, ##__VA_ARGS__,1,0) -#define GET_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() -#define portYIELD_FROM_ISR(...) xEvaluateYieldFromISR(GET_ARGUMENT_COUNT(__VA_ARGS__), ##__VA_ARGS__) + +/** + * @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 4dbb647284..597d1d6471 100644 --- a/components/freertos/xtensa/port.c +++ b/components/freertos/xtensa/port.c @@ -387,7 +387,7 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) return (port_interruptNesting[xPortGetCoreID()] != 0); } -void IRAM_ATTR xEvaluateYieldFromISR(int argc, ...) +void IRAM_ATTR vPortEvaluateYieldFromISR(int argc, ...) { BaseType_t xYield; va_list ap; @@ -397,7 +397,7 @@ void IRAM_ATTR xEvaluateYieldFromISR(int argc, ...) xYield = (BaseType_t)va_arg(ap, int); va_end(ap); } else { - //Yield does not exist, it is a empty vPortYieldFromISR macro: + //it is a empty parameter vPortYieldFromISR macro call: va_end(ap); traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch(); @@ -405,7 +405,7 @@ void IRAM_ATTR xEvaluateYieldFromISR(int argc, ...) } //Yield exists, so need evaluate it first then switch: - if(xYield) { + if(xYield == pdTRUE) { traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch(); }