diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 756c36eaa..20cda3558 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -875,6 +875,12 @@ UT_001_29: - ESP32_IDF - UT_T1_1 +UT_001_30: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + UT_002_01: <<: *unit_test_template tags: @@ -973,6 +979,13 @@ UT_004_09: - ESP32_IDF - UT_T1_1 - psram + +UT_004_10: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - psram UT_005_01: <<: *unit_test_template diff --git a/components/driver/test/test_timer.c b/components/driver/test/test_timer.c new file mode 100644 index 000000000..7f1d3c37f --- /dev/null +++ b/components/driver/test/test_timer.c @@ -0,0 +1,870 @@ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "unity.h" +#include "nvs_flash.h" +#include "driver/timer.h" + +#define TIMER_DIVIDER 16 +#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */ +#define TIMER_DELTA 0.001 +static bool alarm_flag; + +// group0 interruption +static void test_timer_group0_isr(void *para) +{ + int timer_idx = (int) para; + uint64_t timer_val; + double time; + uint64_t alarm_value; + alarm_flag = true; + if (TIMERG0.hw_timer[timer_idx].config.autoreload == 1) { + if (timer_idx == 0) { + TIMERG0.int_clr_timers.t0 = 1; + } else { + TIMERG0.int_clr_timers.t1 = 1; + } + ets_printf("This is TG0 timer[%d] reload-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_0, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_0, timer_idx, &time); + ets_printf("time: %.8f S\n", time); + } else { + if (timer_idx == 0) { + TIMERG0.int_clr_timers.t0 = 1; + } else { + TIMERG0.int_clr_timers.t1 = 1; + } + ets_printf("This is TG0 timer[%d] count-up-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_0, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_0, timer_idx, &time); + timer_get_alarm_value(TIMER_GROUP_0, timer_idx, &alarm_value); + ets_printf("time: %.8f S\n", time); + double alarm_time = (double) alarm_value / TIMER_SCALE; + ets_printf("alarm_time: %.8f S\n", alarm_time); + } +} + +// group1 interruption +static void test_timer_group1_isr(void *para) +{ + int timer_idx = (int) para; + uint64_t timer_val; + double time; + uint64_t alarm_value; + alarm_flag = true; + if (TIMERG1.hw_timer[timer_idx].config.autoreload == 1) { + if (timer_idx == 0) { + TIMERG1.int_clr_timers.t0 = 1; + } else { + TIMERG1.int_clr_timers.t1 = 1; + } + ets_printf("This is TG1 timer[%d] reload-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_1, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_1, timer_idx, &time); + ets_printf("time: %.8f S\n", time); + } else { + if (timer_idx == 0) { + TIMERG1.int_clr_timers.t0 = 1; + } else { + TIMERG1.int_clr_timers.t1 = 1; + } + ets_printf("This is TG1 timer[%d] count-up-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_1, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_1, timer_idx, &time); + timer_get_alarm_value(TIMER_GROUP_1, timer_idx, &alarm_value); + ets_printf("time: %.8f S\n", time); + double alarm_time = (double) alarm_value / TIMER_SCALE; + ets_printf("alarm_time: %.8f S\n", alarm_time); + } +} + +// initialize exact timer group +static void tg_timer_init(int timer_group, int timer_idx, double alarm_time) +{ + timer_pause(timer_group, timer_idx); + timer_set_counter_value(timer_group, timer_idx, 0x0); + timer_set_alarm_value(timer_group, timer_idx, alarm_time * TIMER_SCALE); + timer_enable_intr(timer_group, timer_idx); + if (timer_group == 0) { + timer_isr_register(timer_group, timer_idx, test_timer_group0_isr, + (void *) timer_idx, ESP_INTR_FLAG_LOWMED, NULL); + } else { + timer_isr_register(timer_group, timer_idx, test_timer_group1_isr, + (void *) timer_idx, ESP_INTR_FLAG_LOWMED, NULL); + } + timer_start(timer_group, timer_idx); +} + +// initialize all timer +static void all_timer_init(timer_config_t config, bool flag) +{ + esp_err_t ret; + ret = timer_init(TIMER_GROUP_0, TIMER_0, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } + ret = timer_init(TIMER_GROUP_0, TIMER_1, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } + ret = timer_init(TIMER_GROUP_1, TIMER_0, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } + ret = timer_init(TIMER_GROUP_1, TIMER_1, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } +} + +// start all of timer +static void all_timer_start() +{ + esp_err_t ret; + ret = timer_start(TIMER_GROUP_0, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_start(TIMER_GROUP_0, TIMER_1); + TEST_ASSERT(ret == ESP_OK); + ret = timer_start(TIMER_GROUP_1, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_start(TIMER_GROUP_1, TIMER_1); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_set_counter_value(uint64_t set_timer_val) +{ + esp_err_t ret; + ret = timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_value(TIMER_GROUP_0, TIMER_1, set_timer_val); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_value(TIMER_GROUP_1, TIMER_0, set_timer_val); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_pause() +{ + esp_err_t ret; + ret = timer_pause(TIMER_GROUP_0, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_pause(TIMER_GROUP_0, TIMER_1); + TEST_ASSERT(ret == ESP_OK); + ret = timer_pause(TIMER_GROUP_1, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_pause(TIMER_GROUP_1, TIMER_1); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_get_counter_value(uint64_t set_timer_val, bool flag, + uint64_t *counter_val) +{ + esp_err_t ret; + uint64_t time_val; + ret = timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag == true) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[0] = time_val; + } + } + ret = timer_get_counter_value(TIMER_GROUP_0, TIMER_1, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[1] = time_val; + } + } + ret = timer_get_counter_value(TIMER_GROUP_1, TIMER_0, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[2] = time_val; + } + } + ret = timer_get_counter_value(TIMER_GROUP_1, TIMER_1, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[3] = time_val; + } + } +} + +static void all_timer_get_counter_time_sec(bool flag, int delay_time) +{ + double time; + esp_err_t ret; + ret = timer_get_counter_time_sec(TIMER_GROUP_0, TIMER_0, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } + ret = timer_get_counter_time_sec(TIMER_GROUP_0, TIMER_1, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } + ret = timer_get_counter_time_sec(TIMER_GROUP_1, TIMER_0, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } + ret = timer_get_counter_time_sec(TIMER_GROUP_1, TIMER_1, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } +} + +static void all_timer_set_counter_mode(timer_count_dir_t counter_dir) +{ + esp_err_t ret; + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, counter_dir); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_1, counter_dir); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_mode(TIMER_GROUP_1, TIMER_0, counter_dir); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_mode(TIMER_GROUP_1, TIMER_1, counter_dir); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_set_divider(uint32_t divider) +{ + esp_err_t ret; + ret = timer_set_divider(TIMER_GROUP_0, TIMER_0, divider); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_divider(TIMER_GROUP_0, TIMER_1, divider); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_divider(TIMER_GROUP_1, TIMER_0, divider); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_divider(TIMER_GROUP_1, TIMER_1, divider); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_set_alarm_value(double alarm_time) +{ + esp_err_t ret; + ret = timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_alarm_value(TIMER_GROUP_0, TIMER_1, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_alarm_value(TIMER_GROUP_1, TIMER_0, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); +} + +TEST_CASE("Timer init", "[hw_timer]") +{ + esp_err_t ret; + + // Test init 1:config para + // empty para + timer_config_t config0 = { }; + all_timer_init(config0, false); + + // only one para + timer_config_t config1 = { + .auto_reload = 1 + }; + all_timer_init(config1, false); + + // lack one para + timer_config_t config2 = { + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config2, true); + + config2.counter_en = 0; + all_timer_init(config2, true); + + + // error config para + timer_config_t config3 = { + .alarm_en = 3, //error para + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config3, true); + timer_config_t get_config; + timer_get_config(TIMER_GROUP_1, TIMER_1, &get_config); + printf("Error config alarm_en is %d\n", get_config.alarm_en); + TEST_ASSERT(config3.alarm_en != get_config.alarm_en); + + // Test init 2: init + uint64_t set_timer_val = 0x0; + timer_config_t config = { + .alarm_en = 0, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + + // judge get config parameters + timer_init(TIMER_GROUP_0, TIMER_0, &config); + timer_get_config(TIMER_GROUP_0, TIMER_0, &get_config); + TEST_ASSERT(config.alarm_en == get_config.alarm_en); + TEST_ASSERT(config.auto_reload == get_config.auto_reload); + TEST_ASSERT(config.counter_dir == get_config.counter_dir); + TEST_ASSERT(config.counter_en == get_config.counter_en); + TEST_ASSERT(config.intr_type == get_config.intr_type); + TEST_ASSERT(config.divider == get_config.divider); + + all_timer_init(config, true); + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + all_timer_get_counter_value(set_timer_val, false, NULL); + + // Test init 3: wrong para + ret = timer_init(-1, TIMER_1, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_init(TIMER_GROUP_1, 2, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_init(TIMER_GROUP_1, -1, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_init(2, TIMER_1, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + +} + +/** + * read count case: + * 1. start timer compare value + * 2. pause timer compare value + * 3. delay some time */ +TEST_CASE("Timer read counter value", "[hw_timer]") +{ + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + + all_timer_init(config, true); + + // Test read value 1: start timer get counter value + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + all_timer_get_counter_value(set_timer_val, false, NULL); + + // Test read value 2: pause timer get counter value + all_timer_pause(); + set_timer_val = 0x30405000ULL; + all_timer_set_counter_value(set_timer_val); + all_timer_get_counter_value(set_timer_val, true, NULL); + + // Test read value 3:delay 1s get counter value + set_timer_val = 0x0; + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_time_sec(true, 1); +} + +/** + * start timer case: + * 1. normal start + * 2. error start para + * */ +TEST_CASE("Timer start", "[hw_timer]") +{ + esp_err_t ret; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + + //Test start 1: normal start + all_timer_start(); + all_timer_set_counter_value(set_timer_val); + all_timer_get_counter_value(set_timer_val, false, NULL); + + //Test start 2:wrong para + ret = timer_start(2, TIMER_1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_start(-1, TIMER_1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_start(TIMER_GROUP_1, 2); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_start(TIMER_GROUP_1, -1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); +} + +/** + * pause timer case: + * 1. normal pause, read value + * 2. error pause error + */ +TEST_CASE("Timer pause", "[hw_timer]") +{ + esp_err_t ret; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + + //Test pause 1: right para + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_get_counter_value(set_timer_val, true, NULL); + + //Test pause 2: wrong para + ret = timer_pause(-1, TIMER_0); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_pause(TIMER_GROUP_0, -1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_pause(2, TIMER_0); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_pause(TIMER_GROUP_1, 2); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); +} + +// positive mode and negative mode +TEST_CASE("Timer counter mode (up / down)", "[hw_timer]") +{ + esp_err_t ret; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + all_timer_pause(); + + // Test counter mode 1: TIMER_COUNT_UP + all_timer_set_counter_mode(TIMER_COUNT_UP); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_time_sec(true, 1); + + // Test counter mode 2: TIMER_COUNT_DOWN + all_timer_pause(); + set_timer_val = 0x00E4E1C0ULL; // 3s clock counter value + all_timer_set_counter_mode(TIMER_COUNT_DOWN); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_time_sec(true, 2); + + // Test counter mode 3 : wrong para + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, -1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, 2); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); +} + +/** + * divider case: + * 1. different divider, read value + * Note: divide 0 = divide max, divide 1 = divide 2 + * 2. error para + * + * the frequency(timer counts in one sec): + * 80M/divider = 800*100000 + * max divider value is 65536, its frequency is 1220 (nearly about 1KHz) + */ +TEST_CASE("Timer divider", "[hw_timer]") +{ + int i; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0; + uint64_t time_val[4]; + uint64_t comp_time_val[4]; + all_timer_init(config, true); + + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_value(set_timer_val, false, time_val); + + // compare divider 16 and 8, value should be double + all_timer_pause(); + all_timer_set_divider(8); + all_timer_set_counter_value(set_timer_val); + + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(10000, 10000000, comp_time_val[i]); + } + + // divider is 256, value should be 2^4 + all_timer_pause(); + all_timer_set_divider(256); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(3126, 312500, comp_time_val[i]); + } + + // extrem value test + all_timer_pause(); + all_timer_set_divider(2); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(40000 , 40000000, comp_time_val[i]); + } + + all_timer_pause(); + all_timer_set_divider(65536); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(2 , 1220, comp_time_val[i]); + } + + // divider is 1 should be equal with 2 + all_timer_pause(); + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_0, 1) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_0, 1) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_1, 1) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_1, 1) == ESP_ERR_INVALID_ARG) ; + + all_timer_pause(); + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_0, 65537) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_0, 65537) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_1, 65537) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_1, 65537) == ESP_ERR_INVALID_ARG) ; +} + +/** + * enable alarm case: + * 1. enable alarm ,set alarm value and get value + * 2. disable alarm ,set alarm value and get value + */ +TEST_CASE("Timer enable alarm", "[hw_timer]") +{ + timer_config_t config_test = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config_test, true); + + // enable alarm + alarm_flag = false; + tg_timer_init(TIMER_GROUP_0, TIMER_1, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); + + // disable alarm + alarm_flag = false; + timer_set_alarm(TIMER_GROUP_0, TIMER_1, TIMER_ALARM_DIS); + tg_timer_init(TIMER_GROUP_0, TIMER_1, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); + + // enable alarm + alarm_flag = false; + timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); + + // disable alarm + alarm_flag = false; + timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_DIS); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); +} + +/** + * alarm value case: + * 1. set alarm value and get value + * 2. interrupt test time + */ +TEST_CASE("Timer set alarm value", "[hw_timer]") +{ + esp_err_t ret; + int i; + uint64_t alarm_val[4]; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 0, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config, true); + + // set and get alarm value + all_timer_set_alarm_value(3); + ret = timer_get_alarm_value(TIMER_GROUP_0, TIMER_0, &alarm_val[0]); + TEST_ASSERT(ret == ESP_OK); + ret = timer_get_alarm_value(TIMER_GROUP_0, TIMER_1, &alarm_val[1]); + TEST_ASSERT(ret == ESP_OK); + ret = timer_get_alarm_value(TIMER_GROUP_1, TIMER_0, &alarm_val[2]); + TEST_ASSERT(ret == ESP_OK); + ret = timer_get_alarm_value(TIMER_GROUP_1, TIMER_1, &alarm_val[3]); + TEST_ASSERT(ret == ESP_OK); + for (i = 0; i < 4; i++) { + TEST_ASSERT_EQUAL_UINT32(alarm_val[i] , TIMER_SCALE * 3); + } + + // set interrupt read alarm value + tg_timer_init(TIMER_GROUP_0, TIMER_1, 2.4); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.4); + vTaskDelay(3000 / portTICK_PERIOD_MS); +} + +/** + * auto reload case: + * 1. no reload + * 2. auto reload + */ +TEST_CASE("Timer auto reload", "[hw_timer]") +{ + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config, true); + + // test disable auto_reload + tg_timer_init(TIMER_GROUP_0, TIMER_0, 1.14); + tg_timer_init(TIMER_GROUP_1, TIMER_1, 1.14); + vTaskDelay(2000 / portTICK_PERIOD_MS); + + //test enable auto_reload + timer_set_auto_reload(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_0, TIMER_1, 1.4); + timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.4); + vTaskDelay(2000 / portTICK_PERIOD_MS); +} + +/** + * timer_enable_intr case: + * 1. enable timer_intr + * 2. disable timer_intr + */ +TEST_CASE("Timer enable timer interrupt", "[hw_timer]") +{ + alarm_flag = false; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = TIMER_PAUSE, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_set_alarm_value(1.2); + + // enable timer_intr0 + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1.2 * TIMER_SCALE); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr, + (void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true) + + // disable timer_intr0 + alarm_flag = false; + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1.2 * TIMER_SCALE); + timer_disable_intr(TIMER_GROUP_0, TIMER_0); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false) + + // enable timer_intr1 + timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); + timer_isr_register(TIMER_GROUP_1, TIMER_1, test_timer_group1_isr, + (void *) TIMER_1, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_1, TIMER_1); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true) + + // disable timer_intr1 + alarm_flag = false; + timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); + timer_disable_intr(TIMER_GROUP_1, TIMER_1); + timer_start(TIMER_GROUP_1, TIMER_1); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); + + //enable timer_intr1 again + timer_init(TIMER_GROUP_1, TIMER_1, &config); + timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); + timer_enable_intr(TIMER_GROUP_1, TIMER_1); + timer_start(TIMER_GROUP_1, TIMER_1); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true) +} + +/** + * enable timer group case: + * 1. enable timer group + * 2. disable timer group + */ +TEST_CASE("Timer enable timer group interrupt", "[hw_timer][ignore]") +{ + alarm_flag = false; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 0, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_set_alarm_value(1.2); + + // enable timer group + timer_group_intr_enable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr, + (void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); + + //test enable auto_reload + alarm_flag = false; + timer_group_intr_disable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); + + timer_group_intr_enable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr, + (void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); +} + +/** + * isr_register case: + * Cycle register 15 times, compare the heap size to ensure no memory leaks + */ +TEST_CASE("Timer interrupt register", "[hw_timer]") +{ + int i; + int heap_size = 0; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = TIMER_PAUSE, + .intr_type = TIMER_INTR_LEVEL + }; + + for (i = 0; i < 15; i++) { + all_timer_init(config, true); + tg_timer_init(TIMER_GROUP_0, TIMER_0, 0.54); + tg_timer_init(TIMER_GROUP_1, TIMER_1, 0.34); + + timer_set_auto_reload(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_0, TIMER_1, 0.4); + timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 0.6); + vTaskDelay(1000 / portTICK_PERIOD_MS); + if (heap_size == 0) { + heap_size = esp_get_free_heap_size(); + } + } + TEST_ASSERT_INT_WITHIN(100, heap_size, esp_get_free_heap_size()); +}