Merge branch 'refactor/add_peripheral_signal_description' into 'master'

timer_group: driver on ESP32-S3

Closes IDF-1774

See merge request espressif/esp-idf!10833
This commit is contained in:
Michael (XIAO Xufeng)
2020-11-04 10:45:49 +08:00
16 changed files with 260 additions and 164 deletions

View File

@@ -7,10 +7,9 @@
#include "nvs_flash.h" #include "nvs_flash.h"
#include "driver/timer.h" #include "driver/timer.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/soc_caps.h"
#include "esp_rom_sys.h" #include "esp_rom_sys.h"
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
#define TIMER_DIVIDER 16 #define TIMER_DIVIDER 16
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */ #define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */
#define TIMER_DELTA 0.001 #define TIMER_DELTA 0.001
@@ -38,13 +37,15 @@ static timer_info_t timer_info[4] = {
TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_1), TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_1),
}; };
#define GET_TIMER_INFO(TG, TID) (&timer_info[(TG)*2+(TID)]) static intr_handle_t timer_isr_handles[SOC_TIMER_GROUP_TOTAL_TIMERS];
#define GET_TIMER_INFO(TG, TID) (&timer_info[(TG)*SOC_TIMER_GROUP_TIMERS_PER_GROUP+(TID)])
// timer group interruption handle callback // timer group interruption handle callback
static bool test_timer_group_isr_cb(void *arg) static bool test_timer_group_isr_cb(void *arg)
{ {
bool is_awoken = false; bool is_awoken = false;
timer_info_t* info = (timer_info_t*) arg; timer_info_t *info = (timer_info_t *) arg;
const timer_group_t timer_group = info->timer_group; const timer_group_t timer_group = info->timer_group;
const timer_idx_t timer_idx = info->timer_idx; const timer_idx_t timer_idx = info->timer_idx;
uint64_t timer_val; uint64_t timer_val;
@@ -74,7 +75,9 @@ static bool test_timer_group_isr_cb(void *arg)
BaseType_t awoken = pdFALSE; BaseType_t awoken = pdFALSE;
BaseType_t ret = xQueueSendFromISR(timer_queue, &evt, &awoken); BaseType_t ret = xQueueSendFromISR(timer_queue, &evt, &awoken);
TEST_ASSERT_EQUAL(pdTRUE, ret); TEST_ASSERT_EQUAL(pdTRUE, ret);
if (awoken) is_awoken = true; if (awoken) {
is_awoken = true;
}
} }
return is_awoken; return is_awoken;
} }
@@ -90,8 +93,8 @@ static void test_timer_group_isr(void *arg)
// initialize all timer // initialize all timer
static void all_timer_init(timer_config_t *config, bool expect_init) static void all_timer_init(timer_config_t *config, bool expect_init)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ASSERT_EQUAL((expect_init ? ESP_OK : ESP_ERR_INVALID_ARG), timer_init(tg_idx, timer_idx, config)); TEST_ASSERT_EQUAL((expect_init ? ESP_OK : ESP_ERR_INVALID_ARG), timer_init(tg_idx, timer_idx, config));
} }
} }
@@ -103,8 +106,8 @@ static void all_timer_init(timer_config_t *config, bool expect_init)
// deinitialize all timer // deinitialize all timer
static void all_timer_deinit(void) static void all_timer_deinit(void)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_deinit(tg_idx, timer_idx)); TEST_ESP_OK(timer_deinit(tg_idx, timer_idx));
} }
} }
@@ -117,8 +120,8 @@ static void all_timer_deinit(void)
// start all of timer // start all of timer
static void all_timer_start(void) static void all_timer_start(void)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_start(tg_idx, timer_idx)); TEST_ESP_OK(timer_start(tg_idx, timer_idx));
} }
} }
@@ -126,8 +129,8 @@ static void all_timer_start(void)
static void all_timer_set_counter_value(uint64_t set_cnt_val) static void all_timer_set_counter_value(uint64_t set_cnt_val)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_set_counter_value(tg_idx, timer_idx, set_cnt_val)); TEST_ESP_OK(timer_set_counter_value(tg_idx, timer_idx, set_cnt_val));
} }
} }
@@ -135,8 +138,8 @@ static void all_timer_set_counter_value(uint64_t set_cnt_val)
static void all_timer_pause(void) static void all_timer_pause(void)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_pause(tg_idx, timer_idx)); TEST_ESP_OK(timer_pause(tg_idx, timer_idx));
} }
} }
@@ -146,15 +149,15 @@ static void all_timer_get_counter_value(uint64_t set_cnt_val, bool expect_equal_
uint64_t *actual_cnt_val) uint64_t *actual_cnt_val)
{ {
uint64_t current_cnt_val; uint64_t current_cnt_val;
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_get_counter_value(tg_idx, timer_idx, &current_cnt_val)); TEST_ESP_OK(timer_get_counter_value(tg_idx, timer_idx, &current_cnt_val));
if (expect_equal_set_val) { if (expect_equal_set_val) {
TEST_ASSERT_EQUAL(set_cnt_val, current_cnt_val); TEST_ASSERT_EQUAL(set_cnt_val, current_cnt_val);
} else { } else {
TEST_ASSERT_NOT_EQUAL(set_cnt_val, current_cnt_val); TEST_ASSERT_NOT_EQUAL(set_cnt_val, current_cnt_val);
if (actual_cnt_val != NULL) { if (actual_cnt_val != NULL) {
actual_cnt_val[tg_idx*TIMER_GROUP_MAX + timer_idx] = current_cnt_val; actual_cnt_val[tg_idx * SOC_TIMER_GROUP_TIMERS_PER_GROUP + timer_idx] = current_cnt_val;
} }
} }
} }
@@ -164,8 +167,8 @@ static void all_timer_get_counter_value(uint64_t set_cnt_val, bool expect_equal_
static void all_timer_get_counter_time_sec(int expect_time) static void all_timer_get_counter_time_sec(int expect_time)
{ {
double time; double time;
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_get_counter_time_sec(tg_idx, timer_idx, &time)); TEST_ESP_OK(timer_get_counter_time_sec(tg_idx, timer_idx, &time));
TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, expect_time, time); TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, expect_time, time);
} }
@@ -174,8 +177,8 @@ static void all_timer_get_counter_time_sec(int expect_time)
static void all_timer_set_counter_mode(timer_count_dir_t counter_dir) static void all_timer_set_counter_mode(timer_count_dir_t counter_dir)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_set_counter_mode(tg_idx, timer_idx, counter_dir)); TEST_ESP_OK(timer_set_counter_mode(tg_idx, timer_idx, counter_dir));
} }
} }
@@ -183,8 +186,8 @@ static void all_timer_set_counter_mode(timer_count_dir_t counter_dir)
static void all_timer_set_divider(uint32_t divider) static void all_timer_set_divider(uint32_t divider)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_set_divider(tg_idx, timer_idx, divider)); TEST_ESP_OK(timer_set_divider(tg_idx, timer_idx, divider));
} }
} }
@@ -192,19 +195,37 @@ static void all_timer_set_divider(uint32_t divider)
static void all_timer_set_alarm_value(uint64_t alarm_cnt_val) static void all_timer_set_alarm_value(uint64_t alarm_cnt_val)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_set_alarm_value(tg_idx, timer_idx, alarm_cnt_val)); TEST_ESP_OK(timer_set_alarm_value(tg_idx, timer_idx, alarm_cnt_val));
} }
} }
} }
static void all_timer_get_alarm_value(uint64_t *alarm_vals)
{
for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_get_alarm_value(tg_idx, timer_idx, &alarm_vals[tg_idx * SOC_TIMER_GROUP_TIMERS_PER_GROUP + timer_idx]));
}
}
}
static void all_timer_isr_reg(void) static void all_timer_isr_reg(void)
{ {
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_isr_register(tg_idx, timer_idx, test_timer_group_isr, TEST_ESP_OK(timer_isr_register(tg_idx, timer_idx, test_timer_group_isr,
GET_TIMER_INFO(tg_idx, timer_idx), ESP_INTR_FLAG_LOWMED, NULL)); GET_TIMER_INFO(tg_idx, timer_idx), ESP_INTR_FLAG_LOWMED, &timer_isr_handles[tg_idx * SOC_TIMER_GROUP_TIMERS_PER_GROUP + timer_idx]));
}
}
}
static void all_timer_isr_unreg(void)
{
for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(esp_intr_free(timer_isr_handles[tg_idx * SOC_TIMER_GROUP_TIMERS_PER_GROUP + timer_idx]));
} }
} }
} }
@@ -287,7 +308,7 @@ TEST_CASE("Timer init", "[hw_timer]")
}; };
all_timer_init(&config3, true); all_timer_init(&config3, true);
timer_config_t get_config; timer_config_t get_config;
TEST_ESP_OK(timer_get_config(TIMER_GROUP_1, TIMER_1, &get_config)); TEST_ESP_OK(timer_get_config(TIMER_GROUP_1, TIMER_0, &get_config));
printf("Error config alarm_en is %d\n", get_config.alarm_en); printf("Error config alarm_en is %d\n", get_config.alarm_en);
TEST_ASSERT_NOT_EQUAL(config3.alarm_en, get_config.alarm_en); TEST_ASSERT_NOT_EQUAL(config3.alarm_en, get_config.alarm_en);
@@ -319,10 +340,10 @@ TEST_CASE("Timer init", "[hw_timer]")
all_timer_get_counter_value(set_timer_val, false, NULL); all_timer_get_counter_value(set_timer_val, false, NULL);
// Test init 3: wrong parameter // 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(-1, TIMER_0, &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, 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(TIMER_GROUP_1, -1, &config));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_init(2, TIMER_1, &config)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_init(2, TIMER_0, &config));
all_timer_deinit(); all_timer_deinit();
} }
@@ -389,8 +410,8 @@ TEST_CASE("Timer start", "[hw_timer]")
all_timer_get_counter_value(set_timer_val, false, NULL); all_timer_get_counter_value(set_timer_val, false, NULL);
//Test start 2:wrong parameter //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(2, TIMER_0));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(-1, TIMER_1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(-1, TIMER_0));
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, 2));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(TIMER_GROUP_1, -1)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, timer_start(TIMER_GROUP_1, -1));
all_timer_deinit(); all_timer_deinit();
@@ -531,7 +552,7 @@ TEST_CASE("Timer divider", "[hw_timer]")
all_timer_get_counter_value(set_timer_val, false, comp_time_val); all_timer_get_counter_value(set_timer_val, false, comp_time_val);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]);
TEST_ASSERT_INT_WITHIN(40000 , 40000000, comp_time_val[i]); TEST_ASSERT_INT_WITHIN(40000, 40000000, comp_time_val[i]);
} }
all_timer_pause(); all_timer_pause();
@@ -542,21 +563,17 @@ TEST_CASE("Timer divider", "[hw_timer]")
all_timer_get_counter_value(set_timer_val, false, comp_time_val); all_timer_get_counter_value(set_timer_val, false, comp_time_val);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]);
TEST_ASSERT_INT_WITHIN(2 , 1220, comp_time_val[i]); TEST_ASSERT_INT_WITHIN(2, 1220, comp_time_val[i]);
} }
// divider is 1 should be equal with 2 // divider is 1 should be equal with 2
all_timer_pause(); 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_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_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(); 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_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_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(); all_timer_deinit();
} }
@@ -580,15 +597,15 @@ TEST_CASE("Timer enable alarm", "[hw_timer]")
// enable alarm of tg0_timer1 // enable alarm of tg0_timer1
alarm_flag = false; alarm_flag = false;
TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_1, TIMER_ALARM_EN)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_EN));
timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 1.2); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 1.2);
timer_isr_check(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE); timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE);
TEST_ASSERT_EQUAL(true, alarm_flag); TEST_ASSERT_EQUAL(true, alarm_flag);
// disable alarm of tg0_timer1 // disable alarm of tg0_timer1
alarm_flag = false; alarm_flag = false;
TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_1, TIMER_ALARM_DIS)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_DIS));
timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 1.2); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 1.2);
vTaskDelay(2000 / portTICK_PERIOD_MS); vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL(false, alarm_flag); TEST_ASSERT_EQUAL(false, alarm_flag);
@@ -605,6 +622,7 @@ TEST_CASE("Timer enable alarm", "[hw_timer]")
timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.2); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.2);
vTaskDelay(2000 / portTICK_PERIOD_MS); vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL(false, alarm_flag); TEST_ASSERT_EQUAL(false, alarm_flag);
all_timer_isr_unreg();
all_timer_deinit(); all_timer_deinit();
} }
@@ -615,8 +633,7 @@ TEST_CASE("Timer enable alarm", "[hw_timer]")
*/ */
TEST_CASE("Timer set alarm value", "[hw_timer]") TEST_CASE("Timer set alarm value", "[hw_timer]")
{ {
int i; uint64_t alarm_val[SOC_TIMER_GROUP_TOTAL_TIMERS];
uint64_t alarm_val[4];
timer_config_t config = { timer_config_t config = {
.alarm_en = TIMER_ALARM_EN, .alarm_en = TIMER_ALARM_EN,
.auto_reload = TIMER_AUTORELOAD_DIS, .auto_reload = TIMER_AUTORELOAD_DIS,
@@ -630,19 +647,17 @@ TEST_CASE("Timer set alarm value", "[hw_timer]")
// set and get alarm value // set and get alarm value
all_timer_set_alarm_value(3 * TIMER_SCALE); all_timer_set_alarm_value(3 * TIMER_SCALE);
TEST_ESP_OK(timer_get_alarm_value(TIMER_GROUP_0, TIMER_0, &alarm_val[0])); all_timer_get_alarm_value(alarm_val);
TEST_ESP_OK(timer_get_alarm_value(TIMER_GROUP_0, TIMER_1, &alarm_val[1])); for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
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]); TEST_ASSERT_EQUAL_UINT32(3 * TIMER_SCALE, (uint32_t)alarm_val[i]);
} }
// set interrupt read alarm value // set interrupt read alarm value
timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 2.4); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 2.4);
timer_isr_check(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_DIS, 2.4 * TIMER_SCALE); timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_DIS, 2.4 * TIMER_SCALE);
timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.4); 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); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_DIS, 1.4 * TIMER_SCALE);
all_timer_isr_unreg();
all_timer_deinit(); all_timer_deinit();
} }
@@ -667,16 +682,12 @@ TEST_CASE("Timer auto reload", "[hw_timer]")
// test disable auto_reload // test disable auto_reload
timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 1.14); 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_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 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)); 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_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 1.4);
timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN, 0); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN, 0);
all_timer_isr_unreg();
all_timer_deinit(); all_timer_deinit();
} }
@@ -702,17 +713,18 @@ TEST_CASE("Timer enable timer interrupt", "[hw_timer]")
all_timer_set_counter_value(0); all_timer_set_counter_value(0);
all_timer_isr_reg(); 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_0, TIMER_0, 1.2 * TIMER_SCALE);
timer_intr_enable_disable_test(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); timer_intr_enable_disable_test(TIMER_GROUP_1, TIMER_0, 1.2 * TIMER_SCALE);
// enable interrupt of tg1_timer1 again // enable interrupt of tg1_timer0 again
alarm_flag = false; alarm_flag = false;
TEST_ESP_OK(timer_pause(TIMER_GROUP_1, TIMER_1)); TEST_ESP_OK(timer_pause(TIMER_GROUP_1, TIMER_0));
TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_1, TIMER_1, 0)); TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_1, TIMER_0, 0));
TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN));
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_1, TIMER_1)); TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_1, TIMER_0));
TEST_ESP_OK(timer_start(TIMER_GROUP_1, TIMER_1)); TEST_ESP_OK(timer_start(TIMER_GROUP_1, TIMER_0));
timer_isr_check(TIMER_GROUP_1, TIMER_1, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE);
TEST_ASSERT_EQUAL(true, alarm_flag); TEST_ASSERT_EQUAL(true, alarm_flag);
all_timer_isr_unreg();
all_timer_deinit(); all_timer_deinit();
} }
@@ -723,6 +735,7 @@ TEST_CASE("Timer enable timer interrupt", "[hw_timer]")
*/ */
TEST_CASE("Timer enable timer group interrupt", "[hw_timer][ignore]") TEST_CASE("Timer enable timer group interrupt", "[hw_timer][ignore]")
{ {
intr_handle_t isr_handle = NULL;
alarm_flag = false; alarm_flag = false;
timer_config_t config = { timer_config_t config = {
.alarm_en = TIMER_ALARM_EN, .alarm_en = TIMER_ALARM_EN,
@@ -741,7 +754,7 @@ TEST_CASE("Timer enable timer group interrupt", "[hw_timer][ignore]")
// enable interrupt of tg0_timer0 // enable interrupt of tg0_timer0
TEST_ESP_OK(timer_group_intr_enable(TIMER_GROUP_0, TIMER_INTR_T0)); 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, 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)); GET_TIMER_INFO(TIMER_GROUP_0, TIMER_0), ESP_INTR_FLAG_LOWMED, &isr_handle));
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0)); 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); timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_DIS, 1.2 * TIMER_SCALE);
TEST_ASSERT_EQUAL(true, alarm_flag); TEST_ASSERT_EQUAL(true, alarm_flag);
@@ -753,13 +766,14 @@ TEST_CASE("Timer enable timer group interrupt", "[hw_timer][ignore]")
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0)); TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
vTaskDelay(2000 / portTICK_PERIOD_MS); vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL(false, alarm_flag); TEST_ASSERT_EQUAL(false, alarm_flag);
esp_intr_free(isr_handle);
} }
/** /**
* isr_register case: * isr_register case:
* Cycle register 15 times, compare the heap size to ensure no memory leaks * Cycle register 15 times, compare the heap size to ensure no memory leaks
*/ */
TEST_CASE("Timer interrupt register", "[hw_timer][leaks=200]") TEST_CASE("Timer interrupt register", "[hw_timer]")
{ {
timer_config_t config = { timer_config_t config = {
.alarm_en = TIMER_ALARM_DIS, .alarm_en = TIMER_ALARM_DIS,
@@ -773,37 +787,37 @@ TEST_CASE("Timer interrupt register", "[hw_timer][leaks=200]")
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++) {
all_timer_init(&config, true); all_timer_init(&config, true);
timer_isr_handle_t timer_isr_handle[TIMER_GROUP_MAX * TIMER_MAX]; timer_isr_handle_t timer_isr_handle[TIMER_GROUP_MAX * TIMER_MAX];
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(timer_isr_register(tg_idx, timer_idx, test_timer_group_isr, TEST_ESP_OK(timer_isr_register(tg_idx, timer_idx, test_timer_group_isr,
GET_TIMER_INFO(tg_idx, timer_idx), ESP_INTR_FLAG_LOWMED, &timer_isr_handle[tg_idx * TIMER_GROUP_MAX + timer_idx])); GET_TIMER_INFO(tg_idx, timer_idx), ESP_INTR_FLAG_LOWMED, &timer_isr_handle[tg_idx * SOC_TIMER_GROUP_TIMERS_PER_GROUP + timer_idx]));
} }
} }
TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_EN)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_EN));
timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 0.54); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 0.54);
TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN));
timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_1, 0.34); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 0.34);
TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_EN)); TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_EN));
TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_1, TIMER_ALARM_EN)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_EN));
timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_1, 0.4); timer_intr_enable_and_start(TIMER_GROUP_0, TIMER_0, 0.4);
TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN)); TEST_ESP_OK(timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN));
TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN)); TEST_ESP_OK(timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN));
timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 0.6); timer_intr_enable_and_start(TIMER_GROUP_1, TIMER_0, 0.6);
vTaskDelay(1000 / portTICK_PERIOD_MS); vTaskDelay(1000 / portTICK_PERIOD_MS);
// ISR hanlde function should be free before next ISR register. // ISR hanlde function should be free before next ISR register.
for (uint32_t tg_idx=0; tg_idx<TIMER_GROUP_MAX; tg_idx++) { for (uint32_t tg_idx = 0; tg_idx < TIMER_GROUP_MAX; tg_idx++) {
for (uint32_t timer_idx=0; timer_idx<TIMER_MAX; timer_idx++) { for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) {
TEST_ESP_OK(esp_intr_free(timer_isr_handle[tg_idx * TIMER_GROUP_MAX + timer_idx])); TEST_ESP_OK(esp_intr_free(timer_isr_handle[tg_idx * SOC_TIMER_GROUP_TIMERS_PER_GROUP + timer_idx]));
} }
} }
all_timer_deinit(); all_timer_deinit();
} }
} }
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK #if SOC_TIMER_GROUP_SUPPORT_XTAL
/** /**
* Timer clock source: * Timer clock source:
* 1. configure clock source as APB clock, and enable timer interrupt * 1. configure clock source as APB clock, and enable timer interrupt
@@ -829,7 +843,7 @@ TEST_CASE("Timer clock source", "[hw_timer]")
all_timer_isr_reg(); 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_0, TIMER_0, 1.2 * timer_scale);
timer_intr_enable_disable_test(TIMER_GROUP_1, TIMER_1, 1.2 * timer_scale ); timer_intr_enable_disable_test(TIMER_GROUP_1, TIMER_0, 1.2 * timer_scale );
// configure clock source as XTAL clock // configure clock source as XTAL clock
all_timer_pause(); all_timer_pause();
@@ -839,8 +853,9 @@ TEST_CASE("Timer clock source", "[hw_timer]")
all_timer_set_alarm_value(1.2 * timer_scale); all_timer_set_alarm_value(1.2 * timer_scale);
timer_intr_enable_disable_test(TIMER_GROUP_0, TIMER_0, 1.2 * timer_scale); 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 ); timer_intr_enable_disable_test(TIMER_GROUP_1, TIMER_0, 1.2 * timer_scale );
all_timer_isr_unreg();
all_timer_deinit(); all_timer_deinit();
} }
#endif #endif
@@ -867,27 +882,27 @@ TEST_CASE("Timer ISR callback", "[hw_timer]")
all_timer_set_alarm_value(alarm_cnt_val); all_timer_set_alarm_value(alarm_cnt_val);
all_timer_set_counter_value(set_timer_val); all_timer_set_counter_value(set_timer_val);
// add isr callback for tg0_timer1 // add isr callback for tg0_timer0
TEST_ESP_OK(timer_isr_callback_add(TIMER_GROUP_0, TIMER_1, test_timer_group_isr_cb, TEST_ESP_OK(timer_isr_callback_add(TIMER_GROUP_0, TIMER_0, test_timer_group_isr_cb,
GET_TIMER_INFO(TIMER_GROUP_0, TIMER_1), ESP_INTR_FLAG_LOWMED)); GET_TIMER_INFO(TIMER_GROUP_0, TIMER_0), ESP_INTR_FLAG_LOWMED));
TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_1, set_timer_val)); TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val));
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_1)); TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
timer_isr_check(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_DIS, alarm_cnt_val); timer_isr_check(TIMER_GROUP_0, TIMER_0, TIMER_AUTORELOAD_DIS, alarm_cnt_val);
TEST_ASSERT_EQUAL(true, alarm_flag); TEST_ASSERT_EQUAL(true, alarm_flag);
// remove isr callback for tg0_timer1 // remove isr callback for tg0_timer0
TEST_ESP_OK(timer_pause(TIMER_GROUP_0, TIMER_1)); TEST_ESP_OK(timer_pause(TIMER_GROUP_0, TIMER_0));
TEST_ESP_OK(timer_isr_callback_remove(TIMER_GROUP_0, TIMER_1)); TEST_ESP_OK(timer_isr_callback_remove(TIMER_GROUP_0, TIMER_0));
alarm_flag = false; alarm_flag = false;
TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_1, set_timer_val)); TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val));
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_1)); TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
vTaskDelay(2000 / portTICK_PERIOD_MS); vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL(false, alarm_flag); TEST_ASSERT_EQUAL(false, alarm_flag);
// add isr callback for tg1_timer0 // add isr callback for tg1_timer0
TEST_ESP_OK(timer_pause(TIMER_GROUP_1, TIMER_0)); TEST_ESP_OK(timer_pause(TIMER_GROUP_1, TIMER_0));
TEST_ESP_OK(timer_isr_callback_add(TIMER_GROUP_1, TIMER_0, test_timer_group_isr_cb, TEST_ESP_OK(timer_isr_callback_add(TIMER_GROUP_1, TIMER_0, test_timer_group_isr_cb,
GET_TIMER_INFO(TIMER_GROUP_1, TIMER_0), ESP_INTR_FLAG_LOWMED)); GET_TIMER_INFO(TIMER_GROUP_1, TIMER_0), ESP_INTR_FLAG_LOWMED));
TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_1, TIMER_0, set_timer_val)); TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_1, TIMER_0, set_timer_val));
TEST_ESP_OK(timer_start(TIMER_GROUP_1, TIMER_0)); TEST_ESP_OK(timer_start(TIMER_GROUP_1, TIMER_0));
timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_DIS, alarm_cnt_val); timer_isr_check(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_DIS, alarm_cnt_val);
@@ -907,7 +922,7 @@ TEST_CASE("Timer ISR callback", "[hw_timer]")
/** /**
* Timer memory test * Timer memory test
*/ */
TEST_CASE("Timer memory test", "[hw_timer][leaks=100]") TEST_CASE("Timer memory test", "[hw_timer]")
{ {
timer_config_t config = { timer_config_t config = {
.alarm_en = TIMER_ALARM_EN, .alarm_en = TIMER_ALARM_EN,
@@ -917,7 +932,7 @@ TEST_CASE("Timer memory test", "[hw_timer][leaks=100]")
.counter_en = TIMER_PAUSE, .counter_en = TIMER_PAUSE,
.intr_type = TIMER_INTR_LEVEL, .intr_type = TIMER_INTR_LEVEL,
}; };
for(uint32_t i=0; i<100; i++) { for (uint32_t i = 0; i < 100; i++) {
all_timer_init(&config, true); all_timer_init(&config, true);
all_timer_deinit(); all_timer_deinit();
} }
@@ -955,7 +970,7 @@ static void timer_group_test_first_stage(void)
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0)); TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0)); TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
//Waiting for timer_group to generate an interrupt //Waiting for timer_group to generate an interrupt
while( !(timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0) && while ( !(timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0) &&
loop_cnt++ < 100) { loop_cnt++ < 100) {
vTaskDelay(200); vTaskDelay(200);
} }
@@ -972,8 +987,6 @@ static void timer_group_test_second_stage(void)
} }
TEST_CASE_MULTIPLE_STAGES("timer_group software reset test", TEST_CASE_MULTIPLE_STAGES("timer_group software reset test",
"[intr_status][intr_status = 0]", "[intr_status][intr_status = 0]",
timer_group_test_first_stage, timer_group_test_first_stage,
timer_group_test_second_stage); timer_group_test_second_stage);
#endif

View File

@@ -17,10 +17,10 @@
#include "esp_err.h" #include "esp_err.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "driver/timer.h" #include "driver/timer.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "hal/timer_hal.h" #include "hal/timer_hal.h"
#include "soc/timer_periph.h"
#include "soc/rtc.h" #include "soc/rtc.h"
static const char *TIMER_TAG = "timer_group"; static const char *TIMER_TAG = "timer_group";
@@ -83,7 +83,7 @@ esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_
uint32_t div; uint32_t div;
timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div); timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div);
*time = (double)timer_val * div / rtc_clk_apb_freq_get(); *time = (double)timer_val * div / rtc_clk_apb_freq_get();
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK #if SOC_TIMER_GROUP_SUPPORT_XTAL
if (timer_hal_get_use_xtal(&(p_timer_obj[group_num][timer_num]->hal))) { if (timer_hal_get_use_xtal(&(p_timer_obj[group_num][timer_num]->hal))) {
*time = (double)timer_val * div / ((int)rtc_clk_xtal_freq_get() * 1000000); *time = (double)timer_val * div / ((int)rtc_clk_xtal_freq_get() * 1000000);
} }
@@ -266,36 +266,10 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
TIMER_CHECK(fn != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(fn != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG);
int intr_source = 0;
uint32_t status_reg = 0; uint32_t status_reg = 0;
uint32_t mask = 0; uint32_t mask = 0;
switch (group_num) { timer_hal_get_status_reg_mask_bit(&(p_timer_obj[group_num][timer_num]->hal), &status_reg, &mask);
case TIMER_GROUP_0: return esp_intr_alloc_intrstatus(timer_group_periph_signals.groups[group_num].t0_irq_id + timer_num, intr_alloc_flags, status_reg, mask, fn, arg, handle);
default:
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE)) {
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
}
#endif
timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_0][timer_num]->hal), &status_reg, &mask);
break;
case TIMER_GROUP_1:
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE)) {
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
}
#endif
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
} else {
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
}
timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_1][timer_num]->hal), &status_reg, &mask);
break;
}
return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle);
} }
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config) esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config)
@@ -305,11 +279,7 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(config->divider > 1 && config->divider < 65537, DIVIDER_RANGE_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(config->divider > 1 && config->divider < 65537, DIVIDER_RANGE_ERROR, ESP_ERR_INVALID_ARG);
if (group_num == TIMER_GROUP_0) { periph_module_enable(timer_group_periph_signals.groups[group_num].module);
periph_module_enable(PERIPH_TIMG0_MODULE);
} else if (group_num == TIMER_GROUP_1) {
periph_module_enable(PERIPH_TIMG1_MODULE);
}
if (p_timer_obj[group_num][timer_num] == NULL) { if (p_timer_obj[group_num][timer_num] == NULL) {
p_timer_obj[group_num][timer_num] = (timer_obj_t *) heap_caps_calloc(1, sizeof(timer_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); p_timer_obj[group_num][timer_num] = (timer_obj_t *) heap_caps_calloc(1, sizeof(timer_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -327,15 +297,12 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
timer_hal_set_divider(&(p_timer_obj[group_num][timer_num]->hal), config->divider); timer_hal_set_divider(&(p_timer_obj[group_num][timer_num]->hal), config->divider);
timer_hal_set_counter_increase(&(p_timer_obj[group_num][timer_num]->hal), config->counter_dir); timer_hal_set_counter_increase(&(p_timer_obj[group_num][timer_num]->hal), config->counter_dir);
timer_hal_set_alarm_enable(&(p_timer_obj[group_num][timer_num]->hal), config->alarm_en); timer_hal_set_alarm_enable(&(p_timer_obj[group_num][timer_num]->hal), config->alarm_en);
if (config->intr_type == TIMER_INTR_LEVEL) { timer_hal_set_level_int_enable(&(p_timer_obj[group_num][timer_num]->hal), true);
timer_hal_set_level_int_enable(&(p_timer_obj[group_num][timer_num]->hal), true); if (config->intr_type != TIMER_INTR_LEVEL) {
ESP_LOGW(TIMER_TAG, "only support Level Interrupt, switch to Level Interrupt instead");
} }
// currently edge interrupt is not supported
// if (config->intr_type == TIMER_INTR_EDGE) {
// timer_hal_set_edge_int_enable(&(p_timer_obj[group_num][timer_num]->hal), true);
// }
timer_hal_set_counter_enable(&(p_timer_obj[group_num][timer_num]->hal), config->counter_en); timer_hal_set_counter_enable(&(p_timer_obj[group_num][timer_num]->hal), config->counter_en);
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK #if SOC_TIMER_GROUP_SUPPORT_XTAL
timer_hal_set_use_xtal(&(p_timer_obj[group_num][timer_num]->hal), config->clk_src); timer_hal_set_use_xtal(&(p_timer_obj[group_num][timer_num]->hal), config->clk_src);
#endif #endif
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
@@ -450,9 +417,12 @@ uint32_t IRAM_ATTR timer_group_get_intr_status_in_isr(timer_group_t group_num)
uint32_t intr_status = 0; uint32_t intr_status = 0;
if (p_timer_obj[group_num][TIMER_0] != NULL) { if (p_timer_obj[group_num][TIMER_0] != NULL) {
timer_hal_get_intr_status(&(p_timer_obj[group_num][TIMER_0]->hal), &intr_status); timer_hal_get_intr_status(&(p_timer_obj[group_num][TIMER_0]->hal), &intr_status);
} else if (p_timer_obj[group_num][TIMER_1] != NULL) { }
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1
else if (p_timer_obj[group_num][TIMER_1] != NULL) {
timer_hal_get_intr_status(&(p_timer_obj[group_num][TIMER_1]->hal), &intr_status); timer_hal_get_intr_status(&(p_timer_obj[group_num][TIMER_1]->hal), &intr_status);
} }
#endif
return intr_status; return intr_status;
} }

View File

@@ -302,7 +302,7 @@ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t ti
*/ */
FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status)
{ {
*intr_status = hw->int_st_timers.val; *intr_status = hw->int_st_timers.val & 0x03;
} }
/** /**
@@ -316,7 +316,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_s
FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status) FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status)
{ {
timg_dev_t *hw = TIMER_LL_GET_HW(group_num); timg_dev_t *hw = TIMER_LL_GET_HW(group_num);
*intr_raw_status = hw->int_raw.val; *intr_raw_status = hw->int_raw.val & 0x03;
} }
/** /**

View File

@@ -298,7 +298,7 @@ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t ti
*/ */
FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status)
{ {
*intr_status = hw->int_st.val; *intr_status = hw->int_st.val & 0x03;
} }
/** /**
@@ -312,7 +312,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_s
FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status) FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status)
{ {
timg_dev_t *hw = TIMER_LL_GET_HW(group_num); timg_dev_t *hw = TIMER_LL_GET_HW(group_num);
*intr_raw_status = hw->int_raw.val; *intr_raw_status = hw->int_raw.val & 0x03;
} }
/** /**

View File

@@ -297,7 +297,7 @@ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t ti
*/ */
FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status)
{ {
*intr_status = hw->int_st.val; *intr_status = hw->int_st.val & 0x03;
} }
/** /**
@@ -311,7 +311,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_s
FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status) FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status)
{ {
timg_dev_t *hw = TIMER_LL_GET_HW(group_num); timg_dev_t *hw = TIMER_LL_GET_HW(group_num);
*intr_raw_status = hw->int_raw.val; *intr_raw_status = hw->int_raw.val & 0x03;
} }
/** /**

View File

@@ -29,7 +29,9 @@ extern "C" {
*/ */
typedef enum { typedef enum {
TIMER_GROUP_0 = 0, /*!<Hw timer group 0*/ TIMER_GROUP_0 = 0, /*!<Hw timer group 0*/
#if SOC_TIMER_GROUPS > 1
TIMER_GROUP_1 = 1, /*!<Hw timer group 1*/ TIMER_GROUP_1 = 1, /*!<Hw timer group 1*/
#endif
TIMER_GROUP_MAX, TIMER_GROUP_MAX,
} timer_group_t; } timer_group_t;
@@ -38,7 +40,9 @@ typedef enum {
*/ */
typedef enum { typedef enum {
TIMER_0 = 0, /*!<Select timer0 of GROUPx*/ TIMER_0 = 0, /*!<Select timer0 of GROUPx*/
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1
TIMER_1 = 1, /*!<Select timer1 of GROUPx*/ TIMER_1 = 1, /*!<Select timer1 of GROUPx*/
#endif
TIMER_MAX, TIMER_MAX,
} timer_idx_t; } timer_idx_t;
@@ -64,9 +68,13 @@ typedef enum {
*/ */
//this is compatible with the value of esp32. //this is compatible with the value of esp32.
typedef enum { typedef enum {
TIMER_INTR_T0 = BIT(0), /*!< interrupt of timer 0 */ TIMER_INTR_T0 = BIT(0), /*!< interrupt of timer 0 */
TIMER_INTR_T1 = BIT(1), /*!< interrupt of timer 1 */ #if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1
TIMER_INTR_T1 = BIT(1), /*!< interrupt of timer 1 */
TIMER_INTR_WDT = BIT(2), /*!< interrupt of watchdog */ TIMER_INTR_WDT = BIT(2), /*!< interrupt of watchdog */
#else
TIMER_INTR_WDT = BIT(1), /*!< interrupt of watchdog */
#endif
TIMER_INTR_NONE = 0 TIMER_INTR_NONE = 0
} timer_intr_t; } timer_intr_t;
FLAG_ATTR(timer_intr_t) FLAG_ATTR(timer_intr_t)
@@ -85,7 +93,6 @@ typedef enum {
*/ */
typedef enum { typedef enum {
TIMER_INTR_LEVEL = 0, /*!< Interrupt mode: level mode*/ TIMER_INTR_LEVEL = 0, /*!< Interrupt mode: level mode*/
//TIMER_INTR_EDGE = 1, /*!< Interrupt mode: edge mode, Not supported Now*/
TIMER_INTR_MAX TIMER_INTR_MAX
} timer_intr_mode_t; } timer_intr_mode_t;

View File

@@ -14,6 +14,7 @@ set(srcs
"sigmadelta_periph.c" "sigmadelta_periph.c"
"soc_memory_layout.c" "soc_memory_layout.c"
"spi_periph.c" "spi_periph.c"
"timer_periph.c"
"touch_sensor_periph.c" "touch_sensor_periph.c"
"uart_periph.c") "uart_periph.c")

View File

@@ -186,7 +186,11 @@
#define SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUTPUT 0 #define SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUTPUT 0
/*-------------------------- TIMER GROUP CAPS --------------------------------*/ /*-------------------------- TIMER GROUP CAPS --------------------------------*/
// No contents here #define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (64)
#define SOC_TIMER_GROUP_PRESCALE_BIT_WIDTH (16)
#define SOC_TIMER_GROUPS (2)
#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (2)
#define SOC_TIMER_GROUP_TOTAL_TIMERS (SOC_TIMER_GROUPS * SOC_TIMER_GROUP_TIMERS_PER_GROUP)
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
#define SOC_TOUCH_SENSOR_NUM (10) #define SOC_TOUCH_SENSOR_NUM (10)

View File

@@ -0,0 +1,29 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/soc.h"
#include "soc/timer_periph.h"
const timer_group_signal_conn_t timer_group_periph_signals = {
.groups = {
[0] = {
.module = PERIPH_TIMG0_MODULE,
.t0_irq_id = ETS_TG0_T0_LEVEL_INTR_SOURCE
},
[1] = {
.module = PERIPH_TIMG1_MODULE,
.t0_irq_id = ETS_TG1_T0_LEVEL_INTR_SOURCE,
}
}
};

View File

@@ -13,6 +13,7 @@ set(srcs
"sigmadelta_periph.c" "sigmadelta_periph.c"
"soc_memory_layout.c" "soc_memory_layout.c"
"spi_periph.c" "spi_periph.c"
"timer_periph.c"
"touch_sensor_periph.c" "touch_sensor_periph.c"
"uart_periph.c" "uart_periph.c"
"usb_periph.c") "usb_periph.c")

View File

@@ -190,7 +190,12 @@
#define SOC_SYSTIMER_BIT_WIDTH_HI (32) // Bit width of systimer high part #define SOC_SYSTIMER_BIT_WIDTH_HI (32) // Bit width of systimer high part
/*-------------------------- TIMER GROUP CAPS --------------------------------*/ /*-------------------------- TIMER GROUP CAPS --------------------------------*/
#define SOC_TIMER_GROUP_SUPPORT_XTAL 1 #define SOC_TIMER_GROUP_SUPPORT_XTAL (1)
#define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (64)
#define SOC_TIMER_GROUP_PRESCALE_BIT_WIDTH (16)
#define SOC_TIMER_GROUPS (2)
#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (2)
#define SOC_TIMER_GROUP_TOTAL_TIMERS (SOC_TIMER_GROUPS * SOC_TIMER_GROUP_TIMERS_PER_GROUP)
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
#define SOC_TOUCH_SENSOR_NUM (15) /*! 15 Touch channels */ #define SOC_TOUCH_SENSOR_NUM (15) /*! 15 Touch channels */

View File

@@ -1,4 +1,4 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#pragma once #include "soc/timer_periph.h"
#define SOC_TIMER_GROUP_SUPPORT_XTAL 1 const timer_group_signal_conn_t timer_group_periph_signals = {
.groups = {
[0] = {
.module = PERIPH_TIMG0_MODULE,
.t0_irq_id = ETS_TG0_T0_LEVEL_INTR_SOURCE
},
[1] = {
.module = PERIPH_TIMG1_MODULE,
.t0_irq_id = ETS_TG1_T0_LEVEL_INTR_SOURCE,
}
}
};

View File

@@ -15,6 +15,7 @@ set(srcs
"sigmadelta_periph.c" "sigmadelta_periph.c"
"soc_memory_layout.c" "soc_memory_layout.c"
"spi_periph.c" "spi_periph.c"
"timer_periph.c"
"touch_sensor_periph.c" "touch_sensor_periph.c"
"uart_periph.c") "uart_periph.c")

View File

@@ -69,7 +69,12 @@
#include "systimer_caps.h" #include "systimer_caps.h"
/*-------------------------- TIMER GROUP CAPS --------------------------------*/ /*-------------------------- TIMER GROUP CAPS --------------------------------*/
#include "timer_group_caps.h" #define SOC_TIMER_GROUP_SUPPORT_XTAL (1)
#define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54)
#define SOC_TIMER_GROUP_PRESCALE_BIT_WIDTH (16)
#define SOC_TIMER_GROUPS (2)
#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (2)
#define SOC_TIMER_GROUP_TOTAL_TIMERS (SOC_TIMER_GROUPS * SOC_TIMER_GROUP_TIMERS_PER_GROUP)
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
#include "touch_sensor_caps.h" #include "touch_sensor_caps.h"

View File

@@ -0,0 +1,28 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/timer_periph.h"
const timer_group_signal_conn_t timer_group_periph_signals = {
.groups = {
[0] = {
.module = PERIPH_TIMG0_MODULE,
.t0_irq_id = ETS_TG0_T0_LEVEL_INTR_SOURCE
},
[1] = {
.module = PERIPH_TIMG1_MODULE,
.t0_irq_id = ETS_TG1_T0_LEVEL_INTR_SOURCE,
}
}
};

View File

@@ -13,5 +13,26 @@
// limitations under the License. // limitations under the License.
#pragma once #pragma once
#include <stdint.h>
#include "soc/timer_group_reg.h" #include "soc/timer_group_reg.h"
#include "soc/timer_group_struct.h" #include "soc/timer_group_struct.h"
#include "soc/soc_caps.h"
#include "soc/periph_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
struct {
const periph_module_t module; // Peripheral module
const int t0_irq_id; // Interrupt ID of the first timer in the group
} groups[SOC_TIMER_GROUPS];
} timer_group_signal_conn_t;
extern const timer_group_signal_conn_t timer_group_periph_signals;
#ifdef __cplusplus
}
#endif