diff --git a/components/driver/test/test_pwm.c b/components/driver/test/test_pwm.c index fb9b01588c..fb34bacc25 100644 --- a/components/driver/test/test_pwm.c +++ b/components/driver/test/test_pwm.c @@ -472,21 +472,20 @@ TEST_CASE("MCPWM timer swsync test", "[mcpwm]") } // ------------------------------------------------------------------------------------- +typedef struct { + mcpwm_unit_t unit; + TaskHandle_t task_hdl; +} test_capture_callback_data_t; + +static bool test_mcpwm_intr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, void *arg) { + BaseType_t high_task_wakeup = pdFALSE; + test_capture_callback_data_t *cb_data = (test_capture_callback_data_t *)arg; + vTaskNotifyGiveFromISR(cb_data->task_hdl, &high_task_wakeup); + return high_task_wakeup == pdTRUE; +} static void mcpwm_capture_test(mcpwm_unit_t unit, mcpwm_capture_signal_t cap_chan) { - typedef struct { - mcpwm_unit_t unit; - TaskHandle_t task_hdl; - } test_capture_callback_data_t; - - bool test_mcpwm_intr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, void *arg) { - BaseType_t high_task_wakeup = pdFALSE; - test_capture_callback_data_t *cb_data = (test_capture_callback_data_t *)arg; - vTaskNotifyGiveFromISR(cb_data->task_hdl, &high_task_wakeup); - return high_task_wakeup == pdTRUE; - } - test_capture_callback_data_t callback_data = { .unit = unit, .task_hdl = xTaskGetCurrentTaskHandle(), diff --git a/components/esp_system/test/test_sleep.c b/components/esp_system/test/test_sleep.c index 8e85187d38..b742e6486e 100644 --- a/components/esp_system/test/test_sleep.c +++ b/components/esp_system/test/test_sleep.c @@ -111,13 +111,13 @@ TEST_CASE("light sleep stress test", "[deepsleep]") vSemaphoreDelete(done); } +static void timer_func(void* arg) +{ + esp_rom_delay_us(50); +} + TEST_CASE("light sleep stress test with periodic esp_timer", "[deepsleep]") { - void timer_func(void* arg) - { - esp_rom_delay_us(50); - } - SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0); esp_sleep_enable_timer_wakeup(1000); esp_timer_handle_t timer; diff --git a/components/esp_timer/test/test_esp_timer.c b/components/esp_timer/test/test_esp_timer.c index bd0150331c..3ac57d848c 100644 --- a/components/esp_timer/test/test_esp_timer.c +++ b/components/esp_timer/test/test_esp_timer.c @@ -57,12 +57,12 @@ static void teardown_overflow(void) #endif // CONFIG_ESP_TIMER_IMPL_FRC2 +static void dummy_cb(void* arg) +{ +} + TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") { - void dummy_cb(void* arg) - { - } - uint64_t timeouts[] = { 10000, 1000, 10000, 5000, 20000, 1000 }; size_t indices[] = { 3, 0, 4, 2, 5, 1 }; const size_t num_timers = sizeof(timeouts)/sizeof(timeouts[0]); @@ -116,28 +116,28 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") fclose(stream); } +static const int test_time_sec = 10; + +static void set_alarm_task(void* arg) +{ + SemaphoreHandle_t done = (SemaphoreHandle_t) arg; + + int64_t start = esp_timer_impl_get_time(); + int64_t now = start; + int count = 0; + const int delays[] = {50, 5000, 10000000}; + const int delays_count = sizeof(delays)/sizeof(delays[0]); + while (now - start < test_time_sec * 1000000) { + now = esp_timer_impl_get_time(); + esp_timer_impl_set_alarm(now + delays[count % delays_count]); + ++count; + } + xSemaphoreGive(done); + vTaskDelete(NULL); +} + TEST_CASE("esp_timer_impl_set_alarm stress test", "[esp_timer]") { - const int test_time_sec = 10; - - void set_alarm_task(void* arg) - { - SemaphoreHandle_t done = (SemaphoreHandle_t) arg; - - int64_t start = esp_timer_impl_get_time(); - int64_t now = start; - int count = 0; - const int delays[] = {50, 5000, 10000000}; - const int delays_count = sizeof(delays)/sizeof(delays[0]); - while (now - start < test_time_sec * 1000000) { - now = esp_timer_impl_get_time(); - esp_timer_impl_set_alarm(now + delays[count % delays_count]); - ++count; - } - xSemaphoreGive(done); - vTaskDelete(NULL); - } - SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0); setup_overflow(); xTaskCreatePinnedToCore(&set_alarm_task, "set_alarm_0", 4096, done, UNITY_FREERTOS_PRIORITY, NULL, 0); @@ -153,18 +153,18 @@ TEST_CASE("esp_timer_impl_set_alarm stress test", "[esp_timer]") vSemaphoreDelete(done); } +static void test_correct_delay_timer_func(void* arg) +{ + int64_t* p_end = (int64_t*) arg; + *p_end = ref_clock_get(); +} + TEST_CASE("esp_timer produces correct delay", "[esp_timer]") { - void timer_func(void* arg) - { - int64_t* p_end = (int64_t*) arg; - *p_end = ref_clock_get(); - } - int64_t t_end; esp_timer_handle_t timer1; esp_timer_create_args_t args = { - .callback = &timer_func, + .callback = &test_correct_delay_timer_func, .arg = &t_end, .name = "timer1" }; @@ -196,41 +196,41 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]") esp_timer_delete(timer1); } -TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") -{ - // no, we can't make this a const size_t (§6.7.5.2) +// no, we can't make this a const size_t (§6.7.5.2) #define NUM_INTERVALS 16 - typedef struct { - esp_timer_handle_t timer; - size_t cur_interval; - int intervals[NUM_INTERVALS]; - int64_t t_start; - SemaphoreHandle_t done; - } test_args_t; +typedef struct { + esp_timer_handle_t timer; + size_t cur_interval; + int intervals[NUM_INTERVALS]; + int64_t t_start; + SemaphoreHandle_t done; +} test_periodic_correct_delays_args_t; - void timer_func(void* arg) - { - test_args_t* p_args = (test_args_t*) arg; - int64_t t_end = ref_clock_get(); - int32_t ms_diff = (t_end - p_args->t_start) / 1000; - printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); - p_args->intervals[p_args->cur_interval++] = ms_diff; - // Deliberately make timer handler run longer. - // We check that this doesn't affect the result. - esp_rom_delay_us(10*1000); - if (p_args->cur_interval == NUM_INTERVALS) { - printf("done\n"); - TEST_ESP_OK(esp_timer_stop(p_args->timer)); - xSemaphoreGive(p_args->done); - } +static void test_periodic_correct_delays_timer_func(void* arg) +{ + test_periodic_correct_delays_args_t* p_args = (test_periodic_correct_delays_args_t*) arg; + int64_t t_end = ref_clock_get(); + int32_t ms_diff = (t_end - p_args->t_start) / 1000; + printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); + p_args->intervals[p_args->cur_interval++] = ms_diff; + // Deliberately make timer handler run longer. + // We check that this doesn't affect the result. + esp_rom_delay_us(10*1000); + if (p_args->cur_interval == NUM_INTERVALS) { + printf("done\n"); + TEST_ESP_OK(esp_timer_stop(p_args->timer)); + xSemaphoreGive(p_args->done); } +} +TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") +{ const int delay_ms = 100; - test_args_t args = {0}; + test_periodic_correct_delays_args_t args = {0}; esp_timer_handle_t timer1; esp_timer_create_args_t create_args = { - .callback = &timer_func, + .callback = &test_periodic_correct_delays_timer_func, .arg = &args, .name = "timer1", }; @@ -254,58 +254,58 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") TEST_ESP_OK( esp_timer_delete(timer1) ); vSemaphoreDelete(args.done); +} #undef NUM_INTERVALS + + +#define N 5 + +typedef struct { + const int order[N * 3]; + size_t count; +} test_timers_ordered_correctly_common_t; + +typedef struct { + int timer_index; + const int intervals[N]; + size_t intervals_count; + esp_timer_handle_t timer; + test_timers_ordered_correctly_common_t* common; + bool pass; + SemaphoreHandle_t done; + int64_t t_start; +} test_timers_ordered_correctly_args_t; + +static void test_timers_ordered_correctly_timer_func(void* arg) +{ + test_timers_ordered_correctly_args_t* p_args = (test_timers_ordered_correctly_args_t*) arg; + // check order + size_t count = p_args->common->count; + int expected_index = p_args->common->order[count]; + int ms_since_start = (ref_clock_get() - p_args->t_start) / 1000; + printf("Time %dms, at count %d, expected timer %d, got timer %d\n", + ms_since_start, count, expected_index, p_args->timer_index); + if (expected_index != p_args->timer_index) { + p_args->pass = false; + esp_timer_stop(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + p_args->common->count++; + if (++p_args->intervals_count == N) { + esp_timer_stop(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + int next_interval = p_args->intervals[p_args->intervals_count]; + printf("starting timer %d interval #%d, %d ms\n", + p_args->timer_index, p_args->intervals_count, next_interval); + esp_timer_start_once(p_args->timer, next_interval * 1000); } TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") { -#define N 5 - - typedef struct { - const int order[N * 3]; - size_t count; - } test_common_t; - - typedef struct { - int timer_index; - const int intervals[N]; - size_t intervals_count; - esp_timer_handle_t timer; - test_common_t* common; - bool pass; - SemaphoreHandle_t done; - int64_t t_start; - } test_args_t; - - void timer_func(void* arg) - { - test_args_t* p_args = (test_args_t*) arg; - // check order - size_t count = p_args->common->count; - int expected_index = p_args->common->order[count]; - int ms_since_start = (ref_clock_get() - p_args->t_start) / 1000; - printf("Time %dms, at count %d, expected timer %d, got timer %d\n", - ms_since_start, count, expected_index, p_args->timer_index); - if (expected_index != p_args->timer_index) { - p_args->pass = false; - esp_timer_stop(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - p_args->common->count++; - if (++p_args->intervals_count == N) { - esp_timer_stop(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - int next_interval = p_args->intervals[p_args->intervals_count]; - printf("starting timer %d interval #%d, %d ms\n", - p_args->timer_index, p_args->intervals_count, next_interval); - esp_timer_start_once(p_args->timer, next_interval * 1000); - } - - - test_common_t common = { + test_timers_ordered_correctly_common_t common = { .order = {1, 2, 3, 2, 1, 3, 1, 2, 1, 3, 2, 1, 3, 3, 2}, .count = 0 }; @@ -315,7 +315,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") ref_clock_init(); int64_t now = ref_clock_get(); - test_args_t args1 = { + test_timers_ordered_correctly_args_t args1 = { .timer_index = 1, .intervals = {10, 40, 20, 40, 30}, .common = &common, @@ -324,7 +324,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") .t_start = now }; - test_args_t args2 = { + test_timers_ordered_correctly_args_t args2 = { .timer_index = 2, .intervals = {20, 20, 60, 30, 40}, .common = &common, @@ -333,7 +333,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") .t_start = now }; - test_args_t args3 = { + test_timers_ordered_correctly_args_t args3 = { .timer_index = 3, .intervals = {30, 30, 60, 30, 10}, .common = &common, @@ -344,7 +344,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") esp_timer_create_args_t create_args = { - .callback = &timer_func, + .callback = &test_timers_ordered_correctly_timer_func, .arg = &args1, .name = "1" }; @@ -378,8 +378,14 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") TEST_ESP_OK( esp_timer_delete(args1.timer) ); TEST_ESP_OK( esp_timer_delete(args2.timer) ); TEST_ESP_OK( esp_timer_delete(args3.timer) ); - +} #undef N + + +static void test_short_intervals_timer_func(void* arg) { + SemaphoreHandle_t done = (SemaphoreHandle_t) arg; + xSemaphoreGive(done); + printf("."); } /* Create two timers, start them around the same time, and search through @@ -390,14 +396,8 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]") { SemaphoreHandle_t semaphore = xSemaphoreCreateCounting(2, 0); - void timer_func(void* arg) { - SemaphoreHandle_t done = (SemaphoreHandle_t) arg; - xSemaphoreGive(done); - printf("."); - } - esp_timer_create_args_t timer_args = { - .callback = &timer_func, + .callback = &test_short_intervals_timer_func, .arg = (void*) semaphore, .name = "foo" }; @@ -444,68 +444,68 @@ static int64_t IRAM_ATTR __attribute__((noinline)) get_clock_diff(void) return hs_time - ref_time; } +typedef struct { + SemaphoreHandle_t done; + bool pass; + int test_cnt; + int error_cnt; + int64_t max_error; + int64_t avg_diff; + int64_t dummy; +} test_monotonic_values_state_t; + +static void timer_test_monotonic_values_task(void* arg) { + test_monotonic_values_state_t* state = (test_monotonic_values_state_t*) arg; + state->pass = true; + + /* make sure both functions are in cache */ + state->dummy = get_clock_diff(); + + /* calculate the difference between the two clocks */ + portDISABLE_INTERRUPTS(); + int64_t delta = get_clock_diff(); + portENABLE_INTERRUPTS(); + int64_t start_time = ref_clock_get(); + int error_repeat_cnt = 0; + while (ref_clock_get() - start_time < 10000000) { /* 10 seconds */ + /* Get values of both clocks again, and check that they are close to 'delta'. + * We don't disable interrupts here, because esp_timer_get_time doesn't lock + * interrupts internally, so we check if it can get "broken" by a well placed + * interrupt. + */ + int64_t diff = get_clock_diff() - delta; + /* Allow some difference due to rtos tick interrupting task between + * getting 'hs_now' and 'now'. + */ + if (abs(diff) > 100) { + error_repeat_cnt++; + state->error_cnt++; + } else { + error_repeat_cnt = 0; + } + if (error_repeat_cnt > 2) { + printf("diff=%lld\n", diff); + state->pass = false; + } + state->avg_diff += diff; + state->max_error = MAX(state->max_error, abs(diff)); + state->test_cnt++; + } + state->avg_diff /= state->test_cnt; + xSemaphoreGive(state->done); + vTaskDelete(NULL); + } + TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer]") { - typedef struct { - SemaphoreHandle_t done; - bool pass; - int test_cnt; - int error_cnt; - int64_t max_error; - int64_t avg_diff; - int64_t dummy; - } test_state_t; - - void timer_test_task(void* arg) { - test_state_t* state = (test_state_t*) arg; - state->pass = true; - - /* make sure both functions are in cache */ - state->dummy = get_clock_diff(); - - /* calculate the difference between the two clocks */ - portDISABLE_INTERRUPTS(); - int64_t delta = get_clock_diff(); - portENABLE_INTERRUPTS(); - int64_t start_time = ref_clock_get(); - int error_repeat_cnt = 0; - while (ref_clock_get() - start_time < 10000000) { /* 10 seconds */ - /* Get values of both clocks again, and check that they are close to 'delta'. - * We don't disable interrupts here, because esp_timer_get_time doesn't lock - * interrupts internally, so we check if it can get "broken" by a well placed - * interrupt. - */ - int64_t diff = get_clock_diff() - delta; - /* Allow some difference due to rtos tick interrupting task between - * getting 'hs_now' and 'now'. - */ - if (abs(diff) > 100) { - error_repeat_cnt++; - state->error_cnt++; - } else { - error_repeat_cnt = 0; - } - if (error_repeat_cnt > 2) { - printf("diff=%lld\n", diff); - state->pass = false; - } - state->avg_diff += diff; - state->max_error = MAX(state->max_error, abs(diff)); - state->test_cnt++; - } - state->avg_diff /= state->test_cnt; - xSemaphoreGive(state->done); - vTaskDelete(NULL); - } - ref_clock_init(); setup_overflow(); - test_state_t states[portNUM_PROCESSORS] = {0}; + test_monotonic_values_state_t states[portNUM_PROCESSORS] = {0}; SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0); for (int i = 0; i < portNUM_PROCESSORS; ++i) { states[i].done = done; - xTaskCreatePinnedToCore(&timer_test_task, "test", 4096, &states[i], 6, NULL, i); + xTaskCreatePinnedToCore(&timer_test_monotonic_values_task, "test", 4096, &states[i], 6, NULL, i); } for (int i = 0; i < portNUM_PROCESSORS; ++i) { @@ -530,27 +530,27 @@ TEST_CASE("Can dump esp_timer stats", "[esp_timer]") esp_timer_dump(stdout); } +typedef struct { + SemaphoreHandle_t notify_from_timer_cb; + esp_timer_handle_t timer; +} test_delete_from_callback_arg_t; + +static void test_delete_from_callback_timer_func(void* varg) +{ + test_delete_from_callback_arg_t arg = *(test_delete_from_callback_arg_t*) varg; + esp_timer_delete(arg.timer); + printf("Timer %p is deleted\n", arg.timer); + xSemaphoreGive(arg.notify_from_timer_cb); +} + TEST_CASE("Can delete timer from callback", "[esp_timer]") { - typedef struct { - SemaphoreHandle_t notify_from_timer_cb; - esp_timer_handle_t timer; - } test_arg_t; - - void timer_func(void* varg) - { - test_arg_t arg = *(test_arg_t*) varg; - esp_timer_delete(arg.timer); - printf("Timer %p is deleted\n", arg.timer); - xSemaphoreGive(arg.notify_from_timer_cb); - } - - test_arg_t args = { + test_delete_from_callback_arg_t args = { .notify_from_timer_cb = xSemaphoreCreateBinary(), }; esp_timer_create_args_t timer_args = { - .callback = &timer_func, + .callback = &test_delete_from_callback_timer_func, .arg = &args, .name = "self_deleter" }; @@ -630,24 +630,23 @@ TEST_CASE("esp_timer_impl_advance moves time base correctly", "[esp_timer]") TEST_ASSERT_INT_WITHIN(1000, diff_us, (int) t_delta); } +typedef struct { + int64_t cb_time; +} test_run_when_expected_state_t; + +static void test_run_when_expected_timer_func(void* varg) { + test_run_when_expected_state_t* arg = (test_run_when_expected_state_t*) varg; + arg->cb_time = ref_clock_get(); +} TEST_CASE("after esp_timer_impl_advance, timers run when expected", "[esp_timer]") { - typedef struct { - int64_t cb_time; - } test_state_t; - - void timer_func(void* varg) { - test_state_t* arg = (test_state_t*) varg; - arg->cb_time = ref_clock_get(); - } - ref_clock_init(); - test_state_t state = { 0 }; + test_run_when_expected_state_t state = { 0 }; esp_timer_create_args_t timer_args = { - .callback = &timer_func, + .callback = &test_run_when_expected_timer_func, .arg = &state }; esp_timer_handle_t timer; @@ -695,15 +694,15 @@ static void IRAM_ATTR test_tick_hook(void) } } +static void test_start_stop_timer_func(void* arg) +{ + printf("timer cb\n"); +} + TEST_CASE("Can start/stop timer from ISR context", "[esp_timer]") { - void timer_func(void* arg) - { - printf("timer cb\n"); - } - esp_timer_create_args_t create_args = { - .callback = &timer_func, + .callback = &test_start_stop_timer_func, }; TEST_ESP_OK(esp_timer_create(&create_args, &timer1)); sem = xSemaphoreCreateBinary(); diff --git a/components/esp_timer/test/test_ets_timer.c b/components/esp_timer/test/test_ets_timer.c index e32077024b..ac266dcca6 100644 --- a/components/esp_timer/test/test_ets_timer.c +++ b/components/esp_timer/test/test_ets_timer.c @@ -20,14 +20,14 @@ #include "esp32h2/rom/ets_sys.h" #endif +static void test_correct_delay_timer_func(void* arg) +{ + struct timeval* ptv = (struct timeval*) arg; + gettimeofday(ptv, NULL); +} + TEST_CASE("ets_timer produces correct delay", "[ets_timer]") { - void timer_func(void* arg) - { - struct timeval* ptv = (struct timeval*) arg; - gettimeofday(ptv, NULL); - } - ETSTimer timer1 = {0}; const int delays_ms[] = {20, 100, 200, 250}; @@ -36,7 +36,7 @@ TEST_CASE("ets_timer produces correct delay", "[ets_timer]") for (size_t i = 0; i < delays_count; ++i) { struct timeval tv_end = {0}; - ets_timer_setfn(&timer1, &timer_func, &tv_end); + ets_timer_setfn(&timer1, &test_correct_delay_timer_func, &tv_end); struct timeval tv_start; gettimeofday(&tv_start, NULL); @@ -54,42 +54,43 @@ TEST_CASE("ets_timer produces correct delay", "[ets_timer]") ets_timer_done(&timer1); } -TEST_CASE("periodic ets_timer produces correct delays", "[ets_timer]") -{ - // no, we can't make this a const size_t (§6.7.5.2) +// no, we can't make this a const size_t (§6.7.5.2) #define NUM_INTERVALS 16 - typedef struct { - ETSTimer *timer; - size_t cur_interval; - int intervals[NUM_INTERVALS]; - struct timeval tv_start; - } test_args_t; +typedef struct { + ETSTimer *timer; + size_t cur_interval; + int intervals[NUM_INTERVALS]; + struct timeval tv_start; +} test_periodic_correct_delays_args_t; - void timer_func(void *arg) { - test_args_t *p_args = (test_args_t *) arg; - struct timeval tv_now; - gettimeofday(&tv_now, NULL); - int32_t ms_diff = (tv_now.tv_sec - p_args->tv_start.tv_sec) * 1000 + - (tv_now.tv_usec - p_args->tv_start.tv_usec) / 1000; - printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); - p_args->intervals[p_args->cur_interval++] = ms_diff; - // Deliberately make timer handler run longer. - // We check that this doesn't affect the result. - esp_rom_delay_us(10 * 1000); - if (p_args->cur_interval == NUM_INTERVALS) { - printf("done\n"); - ets_timer_disarm(p_args->timer); - } +static void test_periodic_correct_delays_timer_func(void* arg) +{ + test_periodic_correct_delays_args_t *p_args = (test_periodic_correct_delays_args_t *) arg; + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + int32_t ms_diff = (tv_now.tv_sec - p_args->tv_start.tv_sec) * 1000 + + (tv_now.tv_usec - p_args->tv_start.tv_usec) / 1000; + printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); + p_args->intervals[p_args->cur_interval++] = ms_diff; + // Deliberately make timer handler run longer. + // We check that this doesn't affect the result. + esp_rom_delay_us(10 * 1000); + if (p_args->cur_interval == NUM_INTERVALS) { + printf("done\n"); + ets_timer_disarm(p_args->timer); } +} +TEST_CASE("periodic ets_timer produces correct delays", "[ets_timer]") +{ const int delay_ms = 100; ETSTimer timer1 = {0}; - test_args_t args = {0}; + test_periodic_correct_delays_args_t args = {0}; args.timer = &timer1; gettimeofday(&args.tv_start, NULL); - ets_timer_setfn(&timer1, &timer_func, &args); + ets_timer_setfn(&timer1, &test_periodic_correct_delays_timer_func, &args); ets_timer_arm(&timer1, delay_ms, true); vTaskDelay(delay_ms * (NUM_INTERVALS + 1)); @@ -98,67 +99,66 @@ TEST_CASE("periodic ets_timer produces correct delays", "[ets_timer]") TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * delay_ms, args.intervals[i]); } ets_timer_done(&timer1); - +} #undef NUM_INTERVALS + +#define N 5 + +typedef struct { + const int order[N * 3]; + size_t count; +} test_timers_ordered_correctly_common_t; + +typedef struct { + int timer_index; + const int intervals[N]; + size_t intervals_count; + ETSTimer* timer; + test_timers_ordered_correctly_common_t* common; + bool pass; + SemaphoreHandle_t done; +} test_timers_ordered_correctly_args_t; + +static void test_timers_ordered_correctly_timer_func(void* arg) +{ + test_timers_ordered_correctly_args_t* p_args = (test_timers_ordered_correctly_args_t*) arg; + // check order + size_t count = p_args->common->count; + int expected_index = p_args->common->order[count]; + printf("At count %d, expected timer %d, got timer %d\n", + count, expected_index, p_args->timer_index); + if (expected_index != p_args->timer_index) { + p_args->pass = false; + ets_timer_disarm(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + p_args->common->count++; + if (++p_args->intervals_count == N) { + ets_timer_disarm(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + int next_interval = p_args->intervals[p_args->intervals_count]; + printf("timer %d interval #%d, %d ms\n", + p_args->timer_index, p_args->intervals_count, next_interval); + ets_timer_arm(p_args->timer, next_interval, false); } TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") { -#define N 5 - - typedef struct { - const int order[N * 3]; - size_t count; - } test_common_t; - - typedef struct { - int timer_index; - const int intervals[N]; - size_t intervals_count; - ETSTimer* timer; - test_common_t* common; - bool pass; - SemaphoreHandle_t done; - } test_args_t; - - void timer_func(void* arg) - { - test_args_t* p_args = (test_args_t*) arg; - // check order - size_t count = p_args->common->count; - int expected_index = p_args->common->order[count]; - printf("At count %d, expected timer %d, got timer %d\n", - count, expected_index, p_args->timer_index); - if (expected_index != p_args->timer_index) { - p_args->pass = false; - ets_timer_disarm(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - p_args->common->count++; - if (++p_args->intervals_count == N) { - ets_timer_disarm(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - int next_interval = p_args->intervals[p_args->intervals_count]; - printf("timer %d interval #%d, %d ms\n", - p_args->timer_index, p_args->intervals_count, next_interval); - ets_timer_arm(p_args->timer, next_interval, false); - } - ETSTimer timer1; ETSTimer timer2; ETSTimer timer3; - test_common_t common = { + test_timers_ordered_correctly_common_t common = { .order = {1, 2, 3, 2, 1, 3, 1, 2, 1, 3, 2, 1, 3, 3, 2}, .count = 0 }; SemaphoreHandle_t done = xSemaphoreCreateCounting(3, 0); - test_args_t args1 = { + test_timers_ordered_correctly_args_t args1 = { .timer_index = 1, .intervals = {10, 40, 20, 40, 30}, .timer = &timer1, @@ -167,7 +167,7 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") .done = done }; - test_args_t args2 = { + test_timers_ordered_correctly_args_t args2 = { .timer_index = 2, .intervals = {20, 20, 60, 30, 40}, .timer = &timer2, @@ -176,7 +176,7 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") .done = done }; - test_args_t args3 = { + test_timers_ordered_correctly_args_t args3 = { .timer_index = 3, .intervals = {30, 30, 60, 30, 10}, .timer = &timer3, @@ -185,9 +185,9 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") .done = done }; - ets_timer_setfn(&timer1, &timer_func, &args1); - ets_timer_setfn(&timer2, &timer_func, &args2); - ets_timer_setfn(&timer3, &timer_func, &args3); + ets_timer_setfn(&timer1, &test_timers_ordered_correctly_timer_func, &args1); + ets_timer_setfn(&timer2, &test_timers_ordered_correctly_timer_func, &args2); + ets_timer_setfn(&timer3, &test_timers_ordered_correctly_timer_func, &args3); ets_timer_arm(&timer1, args1.intervals[0], false); ets_timer_arm(&timer2, args2.intervals[0], false); @@ -204,25 +204,24 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") ets_timer_done(&timer1); ets_timer_done(&timer2); ets_timer_done(&timer3); - +} #undef N + +static void IRAM_ATTR test_iram_timer_func(void* arg) +{ + volatile bool *b = (volatile bool *)arg; + *b = true; } /* WiFi/BT coexistence will sometimes arm/disarm timers from an ISR where flash may be disabled. */ IRAM_ATTR TEST_CASE("ETSTimers arm & disarm run from IRAM", "[ets_timer]") { - void timer_func(void* arg) - { - volatile bool *b = (volatile bool *)arg; - *b = true; - } - volatile bool flag = false; ETSTimer timer1; const int INTERVAL = 5; - ets_timer_setfn(&timer1, &timer_func, (void *)&flag); + ets_timer_setfn(&timer1, &test_iram_timer_func, (void *)&flag); /* arm a disabled timer, then disarm a live timer */ diff --git a/components/newlib/test/test_time.c b/components/newlib/test/test_time.c index c97a08d723..b0f139b87c 100644 --- a/components/newlib/test/test_time.c +++ b/components/newlib/test/test_time.c @@ -46,26 +46,26 @@ #if portNUM_PROCESSORS == 2 +// This runs on APP CPU: +static void time_adc_test_task(void* arg) +{ + for (int i = 0; i < 200000; ++i) { + // wait for 20us, reading one of RTC registers + uint32_t ccount = xthal_get_ccount(); + while (xthal_get_ccount() - ccount < 20 * TARGET_DEFAULT_CPU_FREQ_MHZ) { + volatile uint32_t val = REG_READ(RTC_CNTL_STATE0_REG); + (void) val; + } + } + SemaphoreHandle_t * p_done = (SemaphoreHandle_t *) arg; + xSemaphoreGive(*p_done); + vTaskDelay(1); + vTaskDelete(NULL); +} + // https://github.com/espressif/arduino-esp32/issues/120 TEST_CASE("Reading RTC registers on APP CPU doesn't affect clock", "[newlib]") { - // This runs on APP CPU: - void time_adc_test_task(void* arg) - { - for (int i = 0; i < 200000; ++i) { - // wait for 20us, reading one of RTC registers - uint32_t ccount = xthal_get_ccount(); - while (xthal_get_ccount() - ccount < 20 * TARGET_DEFAULT_CPU_FREQ_MHZ) { - volatile uint32_t val = REG_READ(RTC_CNTL_STATE0_REG); - (void) val; - } - } - SemaphoreHandle_t * p_done = (SemaphoreHandle_t *) arg; - xSemaphoreGive(*p_done); - vTaskDelay(1); - vTaskDelete(NULL); - } - SemaphoreHandle_t done = xSemaphoreCreateBinary(); xTaskCreatePinnedToCore(&time_adc_test_task, "time_adc", 4096, &done, 5, NULL, 1); diff --git a/components/vfs/test/test_vfs_uart.c b/components/vfs/test/test_vfs_uart.c index 4c3506179f..60903eade1 100644 --- a/components/vfs/test/test_vfs_uart.c +++ b/components/vfs/test/test_vfs_uart.c @@ -131,38 +131,38 @@ TEST_CASE("CRs are removed from the stdin correctly", "[vfs]") TEST_ASSERT_EQUAL_UINT8_ARRAY("4\n", dst, 2); } +struct read_task_arg_t { + char* out_buffer; + size_t out_buffer_len; + SemaphoreHandle_t ready; + SemaphoreHandle_t done; +}; + +struct write_task_arg_t { + const char* str; + SemaphoreHandle_t done; +}; + +static void read_task_fn(void* varg) +{ + struct read_task_arg_t* parg = (struct read_task_arg_t*) varg; + parg->out_buffer[0] = 0; + + fgets(parg->out_buffer, parg->out_buffer_len, stdin); + xSemaphoreGive(parg->done); + vTaskDelete(NULL); +} + +static void write_task_fn(void* varg) +{ + struct write_task_arg_t* parg = (struct write_task_arg_t*) varg; + fwrite_str_loopback(parg->str, strlen(parg->str)); + xSemaphoreGive(parg->done); + vTaskDelete(NULL); +} + TEST_CASE("can write to UART while another task is reading", "[vfs]") { - struct read_task_arg_t { - char* out_buffer; - size_t out_buffer_len; - SemaphoreHandle_t ready; - SemaphoreHandle_t done; - }; - - struct write_task_arg_t { - const char* str; - SemaphoreHandle_t done; - }; - - void read_task_fn(void* varg) - { - struct read_task_arg_t* parg = (struct read_task_arg_t*) varg; - parg->out_buffer[0] = 0; - - fgets(parg->out_buffer, parg->out_buffer_len, stdin); - xSemaphoreGive(parg->done); - vTaskDelete(NULL); - } - - void write_task_fn(void* varg) - { - struct write_task_arg_t* parg = (struct write_task_arg_t*) varg; - fwrite_str_loopback(parg->str, strlen(parg->str)); - xSemaphoreGive(parg->done); - vTaskDelete(NULL); - } - char out_buffer[32]; size_t out_buffer_len = sizeof(out_buffer); diff --git a/tools/unit-test-app/components/test_utils/include/test_utils.h b/tools/unit-test-app/components/test_utils/include/test_utils.h index 029a0eeb34..c9a5122a81 100644 --- a/tools/unit-test-app/components/test_utils/include/test_utils.h +++ b/tools/unit-test-app/components/test_utils/include/test_utils.h @@ -78,7 +78,7 @@ extern "C" { * @param value : the performance value. */ #define IDF_LOG_PERFORMANCE(item, value_fmt, value, ...) \ - printf("[Performance][%s]: "value_fmt"\n", item, value, ##__VA_ARGS__) + printf("[Performance][%s]: " value_fmt "\n", item, value, ##__VA_ARGS__) /* Some definitions applicable to Unity running in FreeRTOS */