#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "esp_system.h" #include "unity.h" #include "nvs_flash.h" #include "driver/timer.h" #include "soc/rtc.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; static xQueueHandle timer_queue; typedef struct { timer_group_t timer_group; timer_idx_t timer_idx; } timer_info_t; typedef struct { timer_autoreload_t type; // the type of timer's event timer_group_t timer_group; timer_idx_t timer_idx; uint64_t timer_counter_value; } timer_event_t; #define TIMER_INFO_INIT(TG, TID) {.timer_group = (TG), .timer_idx = (TID),} static timer_info_t timer_info[4] = { TIMER_INFO_INIT(TIMER_GROUP_0, TIMER_0), TIMER_INFO_INIT(TIMER_GROUP_0, TIMER_1), TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_0), TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_1), }; #define GET_TIMER_INFO(TG, TID) (&timer_info[(TG)*2+(TID)]) // timer group interruption handle callback static bool test_timer_group_isr_cb(void *arg) { bool is_awoken = false; timer_info_t* info = (timer_info_t*) arg; const timer_group_t timer_group = info->timer_group; const timer_idx_t timer_idx = info->timer_idx; uint64_t timer_val; double time; uint64_t alarm_value; timer_event_t evt; alarm_flag = true; if (timer_group_get_auto_reload_in_isr(timer_group, timer_idx)) { // For autoreload mode, the counter value has been cleared timer_group_clr_intr_status_in_isr(timer_group, timer_idx); ets_printf("This is TG%d timer[%d] reload-timer alarm!\n", timer_group, timer_idx); timer_get_counter_value(timer_group, timer_idx, &timer_val); timer_get_counter_time_sec(timer_group, timer_idx, &time); evt.type = TIMER_AUTORELOAD_EN; } else { timer_group_clr_intr_status_in_isr(timer_group, timer_idx); ets_printf("This is TG%d timer[%d] count-up-timer alarm!\n", timer_group, timer_idx); timer_get_counter_value(timer_group, timer_idx, &timer_val); timer_get_counter_time_sec(timer_group, timer_idx, &time); timer_get_alarm_value(timer_group, timer_idx, &alarm_value); timer_set_counter_value(timer_group, timer_idx, 0); evt.type = TIMER_AUTORELOAD_DIS; } evt.timer_group = timer_group; evt.timer_idx = timer_idx; evt.timer_counter_value = timer_val; if (timer_queue != NULL) { BaseType_t awoken = pdFALSE; BaseType_t ret = xQueueSendFromISR(timer_queue, &evt, &awoken); TEST_ASSERT_EQUAL(pdTRUE, ret); if (awoken) is_awoken = true; } return is_awoken; } // timer group interruption handle static void test_timer_group_isr(void *arg) { if (test_timer_group_isr_cb(arg)) { portYIELD_FROM_ISR(); } } // initialize all timer static void all_timer_init(timer_config_t *config, bool expect_init) { for (uint32_t tg_idx=0; tg_idx> 32), (uint32_t)(evt.timer_counter_value >> 32)); TEST_ASSERT_UINT32_WITHIN(1000, (uint32_t)(alarm_cnt_val), (uint32_t)(evt.timer_counter_value)); } static void timer_intr_enable_disable_test(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_cnt_val) { alarm_flag = false; TEST_ESP_OK(timer_set_counter_value(group_num, timer_num, 0)); TEST_ESP_OK(timer_set_alarm(group_num, timer_num, TIMER_ALARM_EN)); TEST_ESP_OK(timer_enable_intr(group_num, timer_num)); TEST_ESP_OK(timer_start(group_num, timer_num)); timer_isr_check(group_num, timer_num, TIMER_AUTORELOAD_DIS, alarm_cnt_val); TEST_ASSERT_EQUAL(true, alarm_flag); // disable interrupt of tg0_timer0 alarm_flag = false; TEST_ESP_OK(timer_pause(group_num, timer_num)); TEST_ESP_OK(timer_set_counter_value(group_num, timer_num, 0)); TEST_ESP_OK(timer_disable_intr(group_num, timer_num)); TEST_ESP_OK(timer_start(group_num, timer_num)); vTaskDelay(2000 / portTICK_PERIOD_MS); TEST_ASSERT_EQUAL(false, alarm_flag); } TEST_CASE("Timer init", "[hw_timer]") { // Test init 1:config parameter // empty parameter timer_config_t config0 = { }; all_timer_init(&config0, false); // only one parameter timer_config_t config1 = { .auto_reload = TIMER_AUTORELOAD_EN }; all_timer_init(&config1, false); // lack one parameter timer_config_t config2 = { .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .intr_type = TIMER_INTR_LEVEL }; all_timer_init(&config2, true); config2.counter_en = TIMER_PAUSE; all_timer_init(&config2, true); // error config parameter timer_config_t config3 = { .alarm_en = 3, //error parameter .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .intr_type = TIMER_INTR_LEVEL }; all_timer_init(&config3, true); timer_config_t get_config; TEST_ESP_OK(timer_get_config(TIMER_GROUP_1, TIMER_1, &get_config)); printf("Error config alarm_en is %d\n", get_config.alarm_en); TEST_ASSERT_NOT_EQUAL(config3.alarm_en, get_config.alarm_en); // Test init 2: init uint64_t set_timer_val = 0x0; timer_config_t config = { .alarm_en = TIMER_ALARM_DIS, .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .intr_type = TIMER_INTR_LEVEL }; // judge get config parameters TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &config)); TEST_ESP_OK(timer_get_config(TIMER_GROUP_0, TIMER_0, &get_config)); TEST_ASSERT_EQUAL(config.alarm_en, get_config.alarm_en); TEST_ASSERT_EQUAL(config.auto_reload, get_config.auto_reload); TEST_ASSERT_EQUAL(config.counter_dir, get_config.counter_dir); TEST_ASSERT_EQUAL(config.counter_en, get_config.counter_en); TEST_ASSERT_EQUAL(config.intr_type, get_config.intr_type); TEST_ASSERT_EQUAL(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 parameter TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_init(-1, TIMER_1, &config)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_init(TIMER_GROUP_1, 2, &config)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_init(TIMER_GROUP_1, -1, &config)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_init(2, TIMER_1, &config)); all_timer_deinit(); } /** * 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 = TIMER_ALARM_EN, .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .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(1); all_timer_deinit(); } /** * start timer case: * 1. normal start * 2. error start parameter * */ TEST_CASE("Timer start", "[hw_timer]") { timer_config_t config = { .alarm_en = TIMER_ALARM_EN, .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .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 parameter TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(2, TIMER_1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(-1, TIMER_1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(TIMER_GROUP_1, 2)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(TIMER_GROUP_1, -1)); all_timer_deinit(); } /** * pause timer case: * 1. normal pause, read value * 2. error pause error */ TEST_CASE("Timer pause", "[hw_timer]") { timer_config_t config = { .alarm_en = TIMER_ALARM_EN, .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .intr_type = TIMER_INTR_LEVEL }; uint64_t set_timer_val = 0x0; all_timer_init(&config, true); //Test pause 1: right parameter 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 parameter TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_pause(-1, TIMER_0)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_pause(TIMER_GROUP_0, -1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_pause(2, TIMER_0)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_pause(TIMER_GROUP_1, 2)); all_timer_deinit(); } // positive mode and negative mode TEST_CASE("Timer counter mode (up / down)", "[hw_timer]") { timer_config_t config = { .alarm_en = TIMER_ALARM_EN, .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .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(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(2); // Test counter mode 3 : wrong parameter TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, -1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, 2)); all_timer_deinit(); } /** * divider case: * 1. different divider, read value * Note: divide 0 = divide max, divide 1 = divide 2 * 2. error parameter * * 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 = TIMER_ALARM_EN, .auto_reload = TIMER_AUTORELOAD_EN, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_START, .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_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_0, TIMER_0, 1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_1, TIMER_0, 1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_0, TIMER_1, 1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_1, TIMER_1, 1)); all_timer_pause(); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_0, TIMER_0, 65537)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_1, TIMER_0, 65537)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_0, TIMER_1, 65537)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_set_divider(TIMER_GROUP_1, TIMER_1, 65537)); all_timer_deinit(); } /** * 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 = TIMER_ALARM_DIS, .auto_reload = TIMER_AUTORELOAD_DIS, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_PAUSE, .intr_type = TIMER_INTR_LEVEL }; all_timer_init(&config_test, true); all_timer_isr_reg(); // enable alarm of tg0_timer1 alarm_flag = false; TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_1, TIMER_ALARM_EN)); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 1.2); timer_isr_check(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE); TEST_ASSERT_EQUAL(true, alarm_flag); // disable alarm of tg0_timer1 alarm_flag = false; TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_1, TIMER_ALARM_DIS)); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 1.2); vTaskDelay(2000 / portTICK_PERIOD_MS); TEST_ASSERT_EQUAL(false, alarm_flag); // enable alarm of tg1_timer0 alarm_flag = false; TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN)); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.2); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE); TEST_ASSERT_EQUAL(true, alarm_flag); // disable alarm of tg1_timer0 alarm_flag = false; TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_DIS)); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.2); vTaskDelay(2000 / portTICK_PERIOD_MS); TEST_ASSERT_EQUAL(false, alarm_flag); all_timer_deinit(); } /** * alarm value case: * 1. set alarm value and get value * 2. interrupt test time */ TEST_CASE("Timer set alarm value", "[hw_timer]") { int i; uint64_t alarm_val[4]; timer_config_t config = { .alarm_en = TIMER_ALARM_EN, .auto_reload = TIMER_AUTORELOAD_DIS, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_PAUSE, .intr_type = TIMER_INTR_LEVEL }; all_timer_init(&config, true); all_timer_isr_reg(); // set and get alarm value all_timer_set_alarm_value(3 * TIMER_SCALE); TEST_ESP_OK(timer_get_alarm_value(TIMER_GROUP_0, TIMER_0, &alarm_val[0])); TEST_ESP_OK(timer_get_alarm_value(TIMER_GROUP_0, TIMER_1, &alarm_val[1])); TEST_ESP_OK(timer_get_alarm_value(TIMER_GROUP_1, TIMER_0, &alarm_val[2])); TEST_ESP_OK(timer_get_alarm_value(TIMER_GROUP_1, TIMER_1, &alarm_val[3])); for (i = 0; i < 4; i++) { TEST_ASSERT_EQUAL_UINT32(3 * TIMER_SCALE, (uint32_t)alarm_val[i]); } // set interrupt read alarm value timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 2.4); timer_isr_check(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_DIS, 2.4 * TIMER_SCALE); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.4); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_DIS, 1.4 * TIMER_SCALE); all_timer_deinit(); } /** * auto reload case: * 1. no reload * 2. auto reload */ TEST_CASE("Timer auto reload", "[hw_timer]") { timer_config_t config = { .alarm_en = TIMER_ALARM_EN, .auto_reload = TIMER_AUTORELOAD_DIS, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_PAUSE, .intr_type = TIMER_INTR_LEVEL }; all_timer_init(&config, true); all_timer_isr_reg(); // test disable auto_reload timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 1.14); timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_DIS, 1.14 * TIMER_SCALE); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_1, 1.14); timer_isr_check(TIMER_GROUP_1, TIMER_1, TIMER_AUTORELOAD_DIS, 1.14 * TIMER_SCALE); //test enable auto_reload TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_EN)); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 1.4); timer_isr_check(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_EN, 0); TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN)); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.4); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN, 0); all_timer_deinit(); } /** * timer_enable_intr case: * 1. enable timer_intr * 2. disable timer_intr */ TEST_CASE("Timer enable timer interrupt", "[hw_timer]") { timer_config_t config = { .alarm_en = TIMER_ALARM_DIS, .counter_dir = TIMER_COUNT_UP, .auto_reload = TIMER_AUTORELOAD_DIS, .divider = TIMER_DIVIDER, .counter_en = TIMER_PAUSE, .intr_type = TIMER_INTR_LEVEL }; all_timer_init(&config, true); all_timer_pause(); all_timer_set_alarm_value(1.2 * TIMER_SCALE); all_timer_set_counter_value(0); all_timer_isr_reg(); timer_intr_enable_disable_test(TIMER_GROUP_0, TIMER_0, 1.2 * TIMER_SCALE); timer_intr_enable_disable_test(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); // enable interrupt of tg1_timer1 again alarm_flag = false; TEST_ESP_OK(timer_pause(TIMER_GROUP_1, TIMER_1)); TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_1, TIMER_1, 0)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN)); TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_1, TIMER_1)); TEST_ESP_OK(timer_start(TIMER_GROUP_1, TIMER_1)); timer_isr_check(TIMER_GROUP_1, TIMER_1, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE); TEST_ASSERT_EQUAL(true, alarm_flag); all_timer_deinit(); } /** * 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 = TIMER_ALARM_EN, .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 * TIMER_SCALE); // enable interrupt of tg0_timer0 TEST_ESP_OK(timer_group_intr_enable(TIMER_GROUP_0, TIMER_INTR_T0)); TEST_ESP_OK(timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group_isr, GET_TIMER_INFO(TIMER_GROUP_0, TIMER_0), ESP_INTR_FLAG_LOWMED, NULL)); TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0)); timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE); TEST_ASSERT_EQUAL(true, alarm_flag); // disable interrupt of tg0_timer0 alarm_flag = false; TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val)); TEST_ESP_OK(timer_group_intr_disable(TIMER_GROUP_0, TIMER_INTR_T0)); TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0)); vTaskDelay(2000 / portTICK_PERIOD_MS); TEST_ASSERT_EQUAL(false, alarm_flag); } /** * isr_register case: * Cycle register 15 times, compare the heap size to ensure no memory leaks */ TEST_CASE("Timer interrupt register", "[hw_timer][leaks=200]") { timer_config_t config = { .alarm_en = TIMER_ALARM_DIS, .auto_reload = TIMER_AUTORELOAD_DIS, .counter_dir = TIMER_COUNT_UP, .divider = TIMER_DIVIDER, .counter_en = TIMER_PAUSE, .intr_type = TIMER_INTR_LEVEL }; for (int i = 0; i < 15; i++) { all_timer_init(&config, true); timer_isr_handle_t timer_isr_handle[TIMER_GROUP_MAX * TIMER_MAX]; for (uint32_t tg_idx=0; tg_idx