From 9f9da9ec964d4124eb799d3a5be79a020c806fac Mon Sep 17 00:00:00 2001 From: chenjianqiang Date: Mon, 15 Jul 2019 14:21:36 +0800 Subject: [PATCH] feat(timer): refator timer group driver 1. add hal and low-level layer for timer group 2. add callback functions to handle interrupt 3. add timer deinit function 4. add timer spinlock take function --- components/app_trace/test/test_trace.c | 6 +- components/driver/include/driver/timer.h | 267 ++++++++----- components/driver/test/test_timer.c | 4 +- components/driver/timer.c | 363 +++++++++++++----- components/esp32/int_wdt.c | 4 +- components/esp32/panic.c | 2 +- components/esp32/task_wdt.c | 2 +- components/esp32/test/test_intr_alloc.c | 8 +- components/esp32/test/test_reset_reason.c | 4 +- components/esp_event/test/test_event.c | 2 +- components/esp_ringbuf/test/test_ringbuf.c | 2 +- components/freemodbus/port/porttimer.c | 2 +- components/freemodbus/port/porttimer_m.c | 2 +- .../freertos/test/test_freertos_eventgroups.c | 2 +- .../freertos/test/test_freertos_task_notify.c | 2 +- .../freertos/test/test_suspend_scheduler.c | 2 +- .../freertos/test/test_task_suspend_resume.c | 3 +- components/soc/CMakeLists.txt | 1 + components/soc/esp32/include/hal/timer_ll.h | 330 +++++++++++++--- .../soc/esp32s2beta/include/hal/timer_ll.h | 357 ++++++++++++++--- components/soc/include/hal/timer_hal.h | 311 +++++++++++++++ components/soc/include/hal/timer_types.h | 78 +++- components/soc/src/hal/timer_hal.c | 22 ++ components/spi_flash/test/test_spi_flash.c | 2 +- docs/Doxyfile | 1 + .../main/timer_group_example_main.c | 10 +- .../sysview_tracing/main/sysview_tracing.c | 2 +- 27 files changed, 1460 insertions(+), 331 deletions(-) create mode 100644 components/soc/include/hal/timer_hal.h create mode 100644 components/soc/src/hal/timer_hal.c diff --git a/components/app_trace/test/test_trace.c b/components/app_trace/test/test_trace.c index 2e19e5808..da96cb37f 100644 --- a/components/app_trace/test/test_trace.c +++ b/components/app_trace/test/test_trace.c @@ -145,7 +145,7 @@ static void esp_apptrace_test_timer_isr(void *arg) } tim_arg->data.wr_cnt++; - timer_group_intr_clr_in_isr(tim_arg->group, tim_arg->id); + timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id); timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id); } @@ -153,7 +153,7 @@ static void esp_apptrace_test_timer_isr_crash(void *arg) { esp_apptrace_test_timer_arg_t *tim_arg = (esp_apptrace_test_timer_arg_t *)arg; - timer_group_intr_clr_in_isr(tim_arg->group, tim_arg->id); + timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id); timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id); if (tim_arg->data.wr_cnt < ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH) { uint32_t *ts = (uint32_t *)(tim_arg->data.buf + sizeof(uint32_t)); @@ -810,7 +810,7 @@ static void esp_sysview_test_timer_isr(void *arg) //ESP_APPTRACE_TEST_LOGI("tim-%d: IRQ %d/%d\n", tim_arg->id, tim_arg->group, tim_arg->timer); - timer_group_intr_clr_in_isr(tim_arg->group, tim_arg->id); + timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id); timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id); } diff --git a/components/driver/include/driver/timer.h b/components/driver/include/driver/timer.h index c760fb389..f99784410 100644 --- a/components/driver/include/driver/timer.h +++ b/components/driver/include/driver/timer.h @@ -1,4 +1,4 @@ -// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2010-2019 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. @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef _DRIVER_TIMER_H_ -#define _DRIVER_TIMER_H_ +#pragma once + #include "esp_err.h" #include "esp_attr.h" #include "soc/soc.h" @@ -25,79 +25,9 @@ extern "C" { #endif - #define TIMER_BASE_CLK (APB_CLK_FREQ) /*!< Frequency of the clock on the input of the timer groups */ -/** - * @brief Selects a Timer-Group out of 2 available groups - */ -typedef enum { - TIMER_GROUP_0 = 0, /*! #include "esp_log.h" #include "esp_err.h" @@ -19,10 +20,11 @@ #include "freertos/xtensa_api.h" #include "driver/timer.h" #include "driver/periph_ctrl.h" -#include "hal/timer_ll.h" +#include "hal/timer_hal.h" #include "soc/rtc.h" -static const char* TIMER_TAG = "timer_group"; +static const char *TIMER_TAG = "timer_group"; + #define TIMER_CHECK(a, str, ret_val) \ if (!(a)) { \ ESP_LOGE(TIMER_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ @@ -32,48 +34,58 @@ static const char* TIMER_TAG = "timer_group"; #define TIMER_GROUP_NUM_ERROR "TIMER GROUP NUM ERROR" #define TIMER_NUM_ERROR "HW TIMER NUM ERROR" #define TIMER_PARAM_ADDR_ERROR "HW TIMER PARAM ADDR ERROR" +#define TIMER_NEVER_INIT_ERROR "HW TIMER NEVER INIT ERROR" #define TIMER_COUNT_DIR_ERROR "HW TIMER COUNTER DIR ERROR" #define TIMER_AUTORELOAD_ERROR "HW TIMER AUTORELOAD ERROR" #define TIMER_SCALE_ERROR "HW TIMER SCALE ERROR" #define TIMER_ALARM_ERROR "HW TIMER ALARM ERROR" #define DIVIDER_RANGE_ERROR "HW TIMER divider outside of [2, 65536] range error" -DRAM_ATTR static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1}; -static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED}; #define TIMER_ENTER_CRITICAL(mux) portENTER_CRITICAL_SAFE(mux); #define TIMER_EXIT_CRITICAL(mux) portEXIT_CRITICAL_SAFE(mux); -esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* timer_val) +typedef struct { + timer_isr_t fn; /*!< isr function */ + void *args; /*!< isr function args */ + timer_isr_handle_t timer_isr_handle; /*!< interrupt handle */ + timer_group_t isr_timer_group; /*!< timer group of interrupt triggered */ +} timer_isr_func_t; + +typedef struct { + timer_hal_context_t hal; + timer_isr_func_t timer_isr_fun; +} timer_obj_t; + +static timer_obj_t *p_timer_obj[TIMER_GROUP_MAX][TIMER_MAX] = {0}; +static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED}; + +esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *timer_val) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_val != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG); - portENTER_CRITICAL_SAFE(&timer_spinlock[group_num]); -#ifdef CONFIG_IDF_TARGET_ESP32 - TG[group_num]->hw_timer[timer_num].update = 1; -#elif defined CONFIG_IDF_TARGET_ESP32S2BETA - TG[group_num]->hw_timer[timer_num].update.update = 1; -#endif - *timer_val = ((uint64_t) TG[group_num]->hw_timer[timer_num].cnt_high << 32) - | (TG[group_num]->hw_timer[timer_num].cnt_low); - portEXIT_CRITICAL_SAFE(&timer_spinlock[group_num]); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + timer_hal_get_counter_value(&(p_timer_obj[group_num][timer_num]->hal), timer_val); + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } -esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double* time) +esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double *time) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(time != 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); uint64_t timer_val; esp_err_t err = timer_get_counter_value(group_num, timer_num, &timer_val); if (err == ESP_OK) { - uint16_t div = TG[group_num]->hw_timer[timer_num].config.divider; + uint16_t div; + timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div); #ifdef CONFIG_IDF_TARGET_ESP32 *time = (double)timer_val * div / TIMER_BASE_CLK; #elif defined CONFIG_IDF_TARGET_ESP32S2BETA - if(TG[group_num]->hw_timer[timer_num].config.use_xtal) { + 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); } else { *time = (double)timer_val * div / rtc_clk_apb_freq_get(); @@ -87,10 +99,9 @@ esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32); - TG[group_num]->hw_timer[timer_num].load_low = (uint32_t) load_val; - TG[group_num]->hw_timer[timer_num].reload = 1; + timer_hal_set_counter_value(&(p_timer_obj[group_num][timer_num]->hal), load_val); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -99,8 +110,9 @@ esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->hw_timer[timer_num].config.enable = 1; + timer_hal_set_counter_enable(&(p_timer_obj[group_num][timer_num]->hal), TIMER_START); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -109,8 +121,9 @@ esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->hw_timer[timer_num].config.enable = 0; + timer_hal_set_counter_enable(&(p_timer_obj[group_num][timer_num]->hal), TIMER_PAUSE); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -120,8 +133,9 @@ esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(counter_dir < TIMER_COUNT_MAX, TIMER_COUNT_DIR_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->hw_timer[timer_num].config.increase = counter_dir; + timer_hal_set_counter_increase(&(p_timer_obj[group_num][timer_num]->hal), counter_dir); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -131,8 +145,9 @@ esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(reload < TIMER_AUTORELOAD_MAX, TIMER_AUTORELOAD_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->hw_timer[timer_num].config.autoreload = reload; + timer_hal_set_auto_reload(&(p_timer_obj[group_num][timer_num]->hal), reload); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -142,11 +157,9 @@ esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(divider > 1 && divider < 65537, DIVIDER_RANGE_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - int timer_en = TG[group_num]->hw_timer[timer_num].config.enable; - TG[group_num]->hw_timer[timer_num].config.enable = 0; - TG[group_num]->hw_timer[timer_num].config.divider = (uint16_t) divider; - TG[group_num]->hw_timer[timer_num].config.enable = timer_en; + timer_hal_set_divider(&(p_timer_obj[group_num][timer_num]->hal), (uint16_t) divider); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -155,22 +168,22 @@ esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32); - TG[group_num]->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value; + timer_hal_set_alarm_value(&(p_timer_obj[group_num][timer_num]->hal), alarm_value); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } -esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* alarm_value) +esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *alarm_value) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(alarm_value != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG); - portENTER_CRITICAL_SAFE(&timer_spinlock[group_num]); - *alarm_value = ((uint64_t) TG[group_num]->hw_timer[timer_num].alarm_high << 32) - | (TG[group_num]->hw_timer[timer_num].alarm_low); - portEXIT_CRITICAL_SAFE(&timer_spinlock[group_num]); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + timer_hal_get_alarm_value(&(p_timer_obj[group_num][timer_num]->hal), alarm_value); + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -179,42 +192,100 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_ TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(alarm_en < TIMER_ALARM_MAX, TIMER_ALARM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->hw_timer[timer_num].config.alarm_en = alarm_en; + timer_hal_set_alarm_enable(&(p_timer_obj[group_num][timer_num]->hal), alarm_en); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } +static void IRAM_ATTR timer_isr_default(void *arg) +{ + timer_obj_t *timer_obj = (timer_obj_t *)arg; + if (timer_obj == NULL) { + return; + } + if (timer_obj->timer_isr_fun.fn == NULL) { + return; + } + + TIMER_ENTER_CRITICAL(&timer_spinlock[timer_obj->timer_isr_fun.isr_timer_group]); + { + uint32_t intr_status = 0; + timer_hal_get_intr_status(&(timer_obj->hal), &intr_status); + if (intr_status & BIT(timer_obj->hal.idx)) { + timer_obj->timer_isr_fun.fn(timer_obj->timer_isr_fun.args); + //Clear intrrupt status + timer_hal_clear_intr_status(&(timer_obj->hal)); + //After the alarm has been triggered, we need enable it again, so it is triggered the next time. + timer_hal_set_alarm_enable(&(timer_obj->hal), TIMER_ALARM_EN); + } + } + TIMER_EXIT_CRITICAL(&timer_spinlock[timer_obj->timer_isr_fun.isr_timer_group]); +} + +esp_err_t timer_isr_callback_add(timer_group_t group_num, timer_idx_t timer_num, timer_isr_t isr_handler, void *args, int intr_alloc_flags) +{ + TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + + timer_disable_intr(group_num, timer_num); + p_timer_obj[group_num][timer_num]->timer_isr_fun.fn = isr_handler; + p_timer_obj[group_num][timer_num]->timer_isr_fun.args = args; + p_timer_obj[group_num][timer_num]->timer_isr_fun.isr_timer_group = group_num; + timer_isr_register(group_num, timer_num, timer_isr_default, (void *)p_timer_obj[group_num][timer_num], + intr_alloc_flags, &(p_timer_obj[group_num][timer_num]->timer_isr_fun.timer_isr_handle)); + timer_enable_intr(group_num, timer_num); + + return ESP_OK; +} + +esp_err_t timer_isr_callback_remove(timer_group_t group_num, timer_idx_t timer_num) +{ + TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + + timer_disable_intr(group_num, timer_num); + p_timer_obj[group_num][timer_num]->timer_isr_fun.fn = NULL; + p_timer_obj[group_num][timer_num]->timer_isr_fun.args = NULL; + esp_intr_free(p_timer_obj[group_num][timer_num]->timer_isr_fun.timer_isr_handle); + + return ESP_OK; +} + esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, - void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle) + void (*fn)(void *), void *arg, int intr_alloc_flags, timer_isr_handle_t *handle) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_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); int intr_source = 0; uint32_t status_reg = 0; int mask = 0; - switch(group_num) { - case TIMER_GROUP_0: - default: - if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) { - intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num; - } else { - intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num; - } - status_reg = TIMG_INT_ST_TIMERS_REG(0); - mask = 1<hal), &status_reg); + mask = 1 << timer_num; + break; + case TIMER_GROUP_1: + 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_EDGE_INTR_SOURCE + timer_num; + } + timer_hal_get_intr_status_reg(&(p_timer_obj[TIMER_GROUP_1][timer_num]->hal), &status_reg); + mask = 1 << timer_num; + break; } return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle); } @@ -226,32 +297,59 @@ 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->divider > 1 && config->divider < 65537, DIVIDER_RANGE_ERROR, ESP_ERR_INVALID_ARG); - if(group_num == 0) { + if (group_num == TIMER_GROUP_0) { periph_module_enable(PERIPH_TIMG0_MODULE); - } else if(group_num == 1) { + } else if (group_num == TIMER_GROUP_1) { periph_module_enable(PERIPH_TIMG1_MODULE); } + + 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); + if (p_timer_obj[group_num][timer_num] == NULL) { + ESP_LOGE(TIMER_TAG, "TIMER driver malloc error"); + return ESP_FAIL; + } + } + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - //Some applications use a software reset, at the reset time, timer_group happens to generate an interrupt. - //but software reset does not clear interrupt status. This is not safe for application when enable the interrupt of timer_group. - //we need to disable the interrupt and clear the interrupt status here. - TG[group_num]->int_ena.val &= (~BIT(timer_num)); -#ifdef CONFIG_IDF_TARGET_ESP32 - TG[group_num]->int_clr_timers.val = BIT(timer_num); -#elif defined CONFIG_IDF_TARGET_ESP32S2BETA - TG[group_num]->int_clr.val = BIT(timer_num); -#endif - TG[group_num]->hw_timer[timer_num].config.autoreload = config->auto_reload; - TG[group_num]->hw_timer[timer_num].config.divider = (uint16_t) config->divider; - TG[group_num]->hw_timer[timer_num].config.enable = config->counter_en; - TG[group_num]->hw_timer[timer_num].config.increase = config->counter_dir; - TG[group_num]->hw_timer[timer_num].config.alarm_en = config->alarm_en; - TG[group_num]->hw_timer[timer_num].config.level_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 1 : 0); - TG[group_num]->hw_timer[timer_num].config.edge_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 0 : 1); + timer_hal_init(&(p_timer_obj[group_num][timer_num]->hal), group_num, timer_num); + timer_hal_intr_disable(&(p_timer_obj[group_num][timer_num]->hal)); + timer_hal_clear_intr_status(&(p_timer_obj[group_num][timer_num]->hal)); + timer_hal_set_auto_reload(&(p_timer_obj[group_num][timer_num]->hal), config->auto_reload); + 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_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); + } + // 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); #ifdef CONFIG_IDF_TARGET_ESP32S2BETA - TG[group_num]->hw_timer[timer_num].config.use_xtal = config->clk_sel; + timer_hal_set_use_xtal(&(p_timer_obj[group_num][timer_num]->hal), config->clk_src); #endif TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); + + return ESP_OK; +} + +esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num) +{ + TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + timer_hal_set_counter_enable(&(p_timer_obj[group_num][timer_num]->hal), TIMER_PAUSE); + timer_hal_intr_disable(&(p_timer_obj[group_num][timer_num]->hal)); + timer_hal_clear_intr_status(&(p_timer_obj[group_num][timer_num]->hal)); + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); + + heap_caps_free(p_timer_obj[group_num][timer_num]); + p_timer_obj[group_num][timer_num] = NULL; + return ESP_OK; } @@ -260,15 +358,26 @@ esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(config != 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_ENTER_CRITICAL(&timer_spinlock[group_num]); - config->alarm_en = TG[group_num]->hw_timer[timer_num].config.alarm_en; - config->auto_reload = TG[group_num]->hw_timer[timer_num].config.autoreload; - config->counter_dir = TG[group_num]->hw_timer[timer_num].config.increase; - config->divider = (TG[group_num]->hw_timer[timer_num].config.divider == 0 ? - 65536 : TG[group_num]->hw_timer[timer_num].config.divider); - config->counter_en = TG[group_num]->hw_timer[timer_num].config.enable; - if(TG[group_num]->hw_timer[timer_num].config.level_int_en) { + config->alarm_en = timer_hal_get_alarm_enable(&(p_timer_obj[group_num][timer_num]->hal)); + config->auto_reload = timer_hal_get_auto_reload(&(p_timer_obj[group_num][timer_num]->hal)); + config->counter_dir = timer_hal_get_counter_increase(&(p_timer_obj[group_num][timer_num]->hal)); + config->counter_en = timer_hal_get_counter_enable(&(p_timer_obj[group_num][timer_num]->hal)); + + uint16_t div; + timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div); + if (div == 0) { + config->divider = 65536; + } else { + config->divider = div; + } + + if (timer_hal_get_level_int_enable(&(p_timer_obj[group_num][timer_num]->hal))) { config->intr_type = TIMER_INTR_LEVEL; + } else { + config->intr_type = TIMER_INTR_MAX; } TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; @@ -277,18 +386,28 @@ esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t en_mask) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); - portENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->int_ena.val |= en_mask; - portEXIT_CRITICAL(&timer_spinlock[group_num]); + TIMER_CHECK(p_timer_obj[group_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + for (int i = 0; i < TIMER_MAX; i++) { + if (en_mask & BIT(i)) { + timer_hal_intr_enable(&(p_timer_obj[group_num][i]->hal)); + } + } + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t disable_mask) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); - portENTER_CRITICAL(&timer_spinlock[group_num]); - TG[group_num]->int_ena.val &= (~disable_mask); - portEXIT_CRITICAL(&timer_spinlock[group_num]); + TIMER_CHECK(p_timer_obj[group_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + for (int i = 0; i < TIMER_MAX; i++) { + if (disable_mask & BIT(i)) { + timer_hal_intr_disable(&(p_timer_obj[group_num][i]->hal)); + } + } + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); return ESP_OK; } @@ -296,55 +415,99 @@ esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); - return timer_group_intr_enable(group_num, TIMER_LL_GET_INTR(timer_num)); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + timer_hal_intr_enable(&(p_timer_obj[group_num][timer_num]->hal)); + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); + return ESP_OK; } esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num) { TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG); - return timer_group_intr_disable(group_num, TIMER_LL_GET_INTR(timer_num)); + TIMER_CHECK(p_timer_obj[group_num][timer_num] != NULL, TIMER_NEVER_INIT_ERROR, ESP_ERR_INVALID_ARG); + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + timer_hal_intr_disable(&(p_timer_obj[group_num][timer_num]->hal)); + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); + return ESP_OK; } +/* This function is deprecated */ timer_intr_t IRAM_ATTR timer_group_intr_get_in_isr(timer_group_t group_num) { - return timer_ll_intr_status_get(TG[group_num]); + return timer_group_get_intr_status_in_isr(group_num); } +uint32_t IRAM_ATTR timer_group_get_intr_status_in_isr(timer_group_t group_num) +{ + uint32_t intr_status = 0; + if (p_timer_obj[group_num][TIMER_0] != NULL) { + 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) { + timer_hal_get_intr_status(&(p_timer_obj[group_num][TIMER_1]->hal), &intr_status); + } + return intr_status; +} + +/* This function is deprecated */ void IRAM_ATTR timer_group_intr_clr_in_isr(timer_group_t group_num, timer_idx_t timer_num) { - timer_ll_intr_status_clear(TG[group_num], TIMER_LL_GET_INTR(timer_num)); + timer_group_clr_intr_status_in_isr(group_num, timer_num); +} + +void IRAM_ATTR timer_group_clr_intr_status_in_isr(timer_group_t group_num, timer_idx_t timer_num) +{ + timer_hal_clear_intr_status(&(p_timer_obj[group_num][timer_num]->hal)); } void IRAM_ATTR timer_group_enable_alarm_in_isr(timer_group_t group_num, timer_idx_t timer_num) { - timer_ll_set_alarm_enable(TG[group_num], timer_num, true); + timer_hal_set_alarm_enable(&(p_timer_obj[group_num][timer_num]->hal), true); } uint64_t IRAM_ATTR timer_group_get_counter_value_in_isr(timer_group_t group_num, timer_idx_t timer_num) { uint64_t val; - timer_ll_get_counter_value(TG[group_num], timer_num, &val); + timer_hal_get_counter_value(&(p_timer_obj[group_num][timer_num]->hal), &val); return val; } void IRAM_ATTR timer_group_set_alarm_value_in_isr(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_val) { - timer_ll_set_alarm_value(TG[group_num], timer_num, alarm_val); + timer_hal_set_alarm_value(&(p_timer_obj[group_num][timer_num]->hal), alarm_val); } void IRAM_ATTR timer_group_set_counter_enable_in_isr(timer_group_t group_num, timer_idx_t timer_num, timer_start_t counter_en) { - timer_ll_set_counter_enable(TG[group_num], timer_num, counter_en); + timer_hal_set_counter_enable(&(p_timer_obj[group_num][timer_num]->hal), counter_en); } +/* This function is deprecated */ void IRAM_ATTR timer_group_clr_intr_sta_in_isr(timer_group_t group_num, timer_intr_t intr_mask) { - timer_ll_intr_status_clear(TG[group_num], intr_mask); + for (uint32_t timer_idx = 0; timer_idx < TIMER_MAX; timer_idx++) { + if (intr_mask & BIT(timer_idx)) { + timer_group_clr_intr_status_in_isr(group_num, timer_idx); + } + } } bool IRAM_ATTR timer_group_get_auto_reload_in_isr(timer_group_t group_num, timer_idx_t timer_num) { - return timer_ll_get_auto_reload(TG[group_num], timer_num); + return timer_hal_get_auto_reload(&(p_timer_obj[group_num][timer_num]->hal)); } +esp_err_t timer_spinlock_take(timer_group_t group_num) +{ + TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); + return ESP_OK; +} + +esp_err_t timer_spinlock_give(timer_group_t group_num) +{ + TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG); + TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); + return ESP_OK; +} diff --git a/components/esp32/int_wdt.c b/components/esp32/int_wdt.c index 2bfff8078..9b20dbb21 100644 --- a/components/esp32/int_wdt.c +++ b/components/esp32/int_wdt.c @@ -93,8 +93,8 @@ void esp_int_wdt_init(void) { timer_ll_wdt_feed(&TIMERG1); timer_ll_wdt_set_protect(&TIMERG1, true); - timer_ll_intr_status_clear(&TIMERG1, TIMER_INTR_WDT); - timer_group_intr_enable(TIMER_GROUP_1, TIMER_INTR_WDT); + timer_ll_wdt_clear_intr_status(&TIMERG1); + timer_ll_wdt_enable_intr(&TIMERG1); } void esp_int_wdt_cpu_init(void) diff --git a/components/esp32/panic.c b/components/esp32/panic.c index 2c45ec09f..7ad81ed32 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -313,7 +313,7 @@ void panicHandler(XtExcFrame *frame) disableAllWdts(); if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || frame->exccause == PANIC_RSN_INTWDT_CPU1) { - timer_group_clr_intr_sta_in_isr(TIMER_GROUP_1, TIMER_INTR_WDT); + timer_ll_wdt_clear_intr_status(&TIMERG1); } #if CONFIG_ESP32_APPTRACE_ENABLE #if CONFIG_SYSVIEW_ENABLE diff --git a/components/esp32/task_wdt.c b/components/esp32/task_wdt.c index 37c5b8726..6e309f32e 100644 --- a/components/esp32/task_wdt.c +++ b/components/esp32/task_wdt.c @@ -143,7 +143,7 @@ static void task_wdt_isr(void *arg) timer_ll_wdt_feed(&TIMERG0); timer_ll_wdt_set_protect(&TIMERG0, true); //Acknowledge interrupt - timer_group_clr_intr_sta_in_isr(TIMER_GROUP_0, TIMER_INTR_WDT); + timer_ll_wdt_clear_intr_status(&TIMERG0); //We are taking a spinlock while doing I/O (ESP_EARLY_LOGE) here. Normally, that is a pretty //bad thing, possibly (temporarily) hanging up the 2nd core and stopping FreeRTOS. In this case, //something bad already happened and reporting this is considered more important diff --git a/components/esp32/test/test_intr_alloc.c b/components/esp32/test/test_intr_alloc.c index a372675dd..8abd2c28f 100644 --- a/components/esp32/test/test_intr_alloc.c +++ b/components/esp32/test/test_intr_alloc.c @@ -58,19 +58,19 @@ static void timer_isr(void *arg) int timer_idx = (int)arg; count[timer_idx]++; if (timer_idx==0) { - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0); } if (timer_idx==1) { - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_1); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1); timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_1); } if (timer_idx==2) { - timer_group_intr_clr_in_isr(TIMER_GROUP_1, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_1, TIMER_0); timer_group_enable_alarm_in_isr(TIMER_GROUP_1, TIMER_0); } if (timer_idx==3) { - timer_group_intr_clr_in_isr(TIMER_GROUP_1, TIMER_1); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_1, TIMER_1); timer_group_enable_alarm_in_isr(TIMER_GROUP_1, TIMER_1); } // ets_printf("int %d\n", timer_idx); diff --git a/components/esp32/test/test_reset_reason.c b/components/esp32/test/test_reset_reason.c index 1aed30039..4f8316328 100644 --- a/components/esp32/test/test_reset_reason.c +++ b/components/esp32/test/test_reset_reason.c @@ -280,12 +280,12 @@ static void timer_group_test_first_stage(void) //Start timer timer_start(TIMER_GROUP_0, TIMER_0); //Waiting for timer_group to generate an interrupt - while( !(timer_group_intr_get_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) { vTaskDelay(200); } //TIMERG0.int_raw.t0 == 1 means an interruption has occurred - TEST_ASSERT(timer_group_intr_get_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0); + TEST_ASSERT(timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0); esp_restart(); } diff --git a/components/esp_event/test/test_event.c b/components/esp_event/test/test_event.c index f62f2c080..9e94fdf03 100644 --- a/components/esp_event/test/test_event.c +++ b/components/esp_event/test/test_event.c @@ -304,7 +304,7 @@ void IRAM_ATTR test_event_on_timer_alarm(void* para) from the timer that reported the interrupt */ uint64_t timer_counter_value = timer_group_get_counter_value_in_isr(TIMER_GROUP_0, TIMER_0); - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, TIMER_0, timer_counter_value); diff --git a/components/esp_ringbuf/test/test_ringbuf.c b/components/esp_ringbuf/test/test_ringbuf.c index 476283a0b..7e6f441af 100644 --- a/components/esp_ringbuf/test/test_ringbuf.c +++ b/components/esp_ringbuf/test/test_ringbuf.c @@ -356,7 +356,7 @@ static int iterations; static void ringbuffer_isr(void *arg) { //Clear timer interrupt - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); timer_group_enable_alarm_in_isr(TIMER_GROUP_0, xPortGetCoreID()); //Test sending to buffer from ISR from ISR diff --git a/components/freemodbus/port/porttimer.c b/components/freemodbus/port/porttimer.c index 4d1afcb31..8637e90b9 100644 --- a/components/freemodbus/port/porttimer.c +++ b/components/freemodbus/port/porttimer.c @@ -71,7 +71,7 @@ static void IRAM_ATTR vTimerGroupIsr(void *param) { assert((int)param == usTimerIndex); // Retrieve the counter value from the timer that reported the interrupt - timer_group_intr_clr_in_isr(usTimerGroupIndex, usTimerIndex); + timer_group_clr_intr_status_in_isr(usTimerGroupIndex, usTimerIndex); (void)pxMBPortCBTimerExpired(); // Timer callback function // Enable alarm timer_group_enable_alarm_in_isr(usTimerGroupIndex, usTimerIndex); diff --git a/components/freemodbus/port/porttimer_m.c b/components/freemodbus/port/porttimer_m.c index 2bf47c331..e663a2990 100644 --- a/components/freemodbus/port/porttimer_m.c +++ b/components/freemodbus/port/porttimer_m.c @@ -67,7 +67,7 @@ static void IRAM_ATTR vTimerGroupIsr(void *param) { assert((int)param == usTimerIndex); // Retrieve the the counter value from the timer that reported the interrupt - timer_group_intr_clr_in_isr(usTimerGroupIndex, usTimerIndex); + timer_group_clr_intr_status_in_isr(usTimerGroupIndex, usTimerIndex); (void)pxMBMasterPortCBTimerExpired(); // Timer expired callback function // Enable alarm timer_group_enable_alarm_in_isr(usTimerGroupIndex, usTimerIndex); diff --git a/components/freertos/test/test_freertos_eventgroups.c b/components/freertos/test/test_freertos_eventgroups.c index da4f800fa..06d9741cc 100644 --- a/components/freertos/test/test_freertos_eventgroups.c +++ b/components/freertos/test/test_freertos_eventgroups.c @@ -144,7 +144,7 @@ static bool test_clear_bits; static void IRAM_ATTR event_group_isr(void *arg) { portBASE_TYPE task_woken = pdFALSE; - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); timer_group_enable_alarm_in_isr(TIMER_GROUP_0, xPortGetCoreID()); if(test_set_bits){ diff --git a/components/freertos/test/test_freertos_task_notify.c b/components/freertos/test/test_freertos_task_notify.c index 8fb0b217c..311bfd73b 100644 --- a/components/freertos/test/test_freertos_task_notify.c +++ b/components/freertos/test/test_freertos_task_notify.c @@ -103,7 +103,7 @@ static void receiver_task (void* arg){ static void IRAM_ATTR sender_ISR (void *arg) { int curcore = xPortGetCoreID(); - timer_group_intr_clr_in_isr(TIMER_GROUP_0, curcore); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, curcore); timer_group_set_counter_enable_in_isr(TIMER_GROUP_0, curcore, TIMER_PAUSE); //Re-enable alarm timer_group_enable_alarm_in_isr(TIMER_GROUP_0, curcore); diff --git a/components/freertos/test/test_suspend_scheduler.c b/components/freertos/test/test_suspend_scheduler.c index fee9d8717..1415c3532 100644 --- a/components/freertos/test/test_suspend_scheduler.c +++ b/components/freertos/test/test_suspend_scheduler.c @@ -26,7 +26,7 @@ static volatile unsigned isr_count; mutex semaphore to wake up another counter task */ static void timer_group0_isr(void *vp_arg) { - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0); portBASE_TYPE higher_awoken = pdFALSE; isr_count++; diff --git a/components/freertos/test/test_task_suspend_resume.c b/components/freertos/test/test_task_suspend_resume.c index 01fbeee08..5dfb77b74 100644 --- a/components/freertos/test/test_task_suspend_resume.c +++ b/components/freertos/test/test_task_suspend_resume.c @@ -123,7 +123,8 @@ volatile bool timer_isr_fired; void IRAM_ATTR timer_group0_isr(void *vp_arg) { // Clear interrupt - timer_group_clr_intr_sta_in_isr(TIMER_GROUP_0, TIMER_0|TIMER_1); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1); timer_isr_fired = true; TaskHandle_t handle = vp_arg; diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index 391c46e0f..1aba1a759 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -22,6 +22,7 @@ list(APPEND srcs "src/hal/pcnt_hal.c" "src/hal/i2s_hal.c" "src/hal/sigmadelta_hal.c" + "src/hal/timer_hal.c" ) # TODO: SPI Flash HAL for ESP32S2Beta also diff --git a/components/soc/esp32/include/hal/timer_ll.h b/components/soc/esp32/include/hal/timer_ll.h index f4fa09d94..71ffb60d0 100644 --- a/components/soc/esp32/include/hal/timer_ll.h +++ b/components/soc/esp32/include/hal/timer_ll.h @@ -21,71 +21,71 @@ extern "C" { #endif +#include #include "hal/timer_types.h" #include "soc/timer_periph.h" -//Helper macro to get corresponding interrupt of a timer -#define TIMER_LL_GET_INTR(TIMER_IDX) ((TIMER_IDX)==TIMER_0? TIMER_INTR_T0: TIMER_INTR_T1) - -#define TIMER_LL_GET_HW(TIMER_GROUP) ((TIMER_GROUP)==0? &TIMERG0: &TIMERG1) - _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); _Static_assert(TIMER_INTR_T1 == TIMG_T1_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); _Static_assert(TIMER_INTR_WDT == TIMG_WDT_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); +typedef struct { + timg_dev_t *dev; + timer_idx_t idx; +} timer_ll_context_t; + +// Get timer group instance with giving group number +#define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1)) + /** - * @brief Enable timer interrupt. + * @brief Set timer clock prescale value * * @param hw Beginning address of the peripheral registers. - * @param intr_mask Interrupt enable mask + * @param timer_num The timer number + * @param divider Prescale value * * @return None */ -static inline void timer_ll_intr_enable(timg_dev_t *hw, timer_intr_t intr_mask) +static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t divider) { - hw->int_ena.val |= intr_mask; + int timer_en = hw->hw_timer[timer_num].config.enable; + hw->hw_timer[timer_num].config.enable = 0; + hw->hw_timer[timer_num].config.divider = divider; + hw->hw_timer[timer_num].config.enable = timer_en; } /** - * @brief Disable timer interrupt. + * @brief Get timer clock prescale value * * @param hw Beginning address of the peripheral registers. - * @param intr_mask Interrupt disable mask + * @param timer_num The timer number + * @param divider Pointer to accept the prescale value * * @return None */ -static inline void timer_ll_intr_disable(timg_dev_t *hw, timer_intr_t intr_mask) +static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t *divider) { - hw->int_ena.val &= (~intr_mask); + *divider = hw->hw_timer[timer_num].config.divider; } /** - * @brief Get timer interrupt status. + * @brief Load counter value into time-base counter * * @param hw Beginning address of the peripheral registers. - * - * @return Masked interrupt status - */ -static inline timer_intr_t timer_ll_intr_status_get(timg_dev_t *hw) -{ - return hw->int_raw.val; -} - -/** - * @brief Clear timer interrupt. - * - * @param hw Beginning address of the peripheral registers. - * @param intr_mask Interrupt mask to clear + * @param timer_num The timer number + * @param load_val Counter value * * @return None */ -static inline void timer_ll_intr_status_clear(timg_dev_t *hw, timer_intr_t intr_mask) +static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val) { - hw->int_clr_timers.val = intr_mask; + hw->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32); + hw->hw_timer[timer_num].load_low = (uint32_t) load_val; + hw->hw_timer[timer_num].reload = 1; } /** - * @brief Get counter vaule from time-base counter + * @brief Get counter value from time-base counter * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number @@ -93,36 +93,95 @@ static inline void timer_ll_intr_status_clear(timg_dev_t *hw, timer_intr_t intr_ * * @return None */ -static inline void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val) +FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val) { hw->hw_timer[timer_num].update = 1; *timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high << 32) | (hw->hw_timer[timer_num].cnt_low); } +/** + * @brief Set counter mode, include increment mode and decrement mode. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param increase_en True to increment mode, fasle to decrement mode + * + * @return None + */ +static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en) +{ + hw->hw_timer[timer_num].config.increase = increase_en; +} + +/** + * @brief Get counter mode, include increment mode and decrement mode. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Increment mode + * - false Decrement mode + */ +static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.increase; +} + /** * @brief Set counter status, enable or disable counter. * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param counter_en Counter enable status + * @param counter_en True to enable counter, false to disable counter * * @return None */ -static inline void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, timer_start_t counter_en) +FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en) { hw->hw_timer[timer_num].config.enable = counter_en; } +/** + * @brief Get counter status. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Enable counter + * - false Disable conuter + */ +static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.enable; +} + +/** + * @brief Set auto reload mode. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param auto_reload_en True to enable auto reload mode, flase to disable auto reload mode + * + * @return None + */ +static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en) +{ + hw->hw_timer[timer_num].config.autoreload = auto_reload_en; +} + /** * @brief Get auto reload mode. * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param reload Pointer to accept the auto reload mode * - * @return None + * @return + * - true Enable auto reload mode + * - false Disable auto reload mode */ -static inline bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num) +FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num) { return hw->hw_timer[timer_num].config.autoreload; } @@ -136,7 +195,7 @@ static inline bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_nu * * @return None */ -static inline void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value) +FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value) { hw->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32); hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value; @@ -161,11 +220,11 @@ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_nu * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param alarm_en true to enable, false to disable + * @param alarm_en True to enable alarm, false to disable alarm * * @return None */ -static inline void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en) +FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en) { hw->hw_timer[timer_num].config.alarm_en = alarm_en; } @@ -175,35 +234,158 @@ static inline void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_n * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param alarm_en Pointer to accept the alarm status + * + * @return + * - true Enable alarm + * - false Disable alarm + */ +static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.alarm_en; +} + +/** + * @brief Enable timer interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number * * @return None */ -static inline void timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool *alarm_en) +FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num) { - *alarm_en = hw->hw_timer[timer_num].config.alarm_en; + hw->int_ena.val |= BIT(timer_num); +} + +/** + * @brief Disable timer interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return None + */ +FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num) +{ + hw->int_ena.val &= (~BIT(timer_num)); +} + +/** + * @brief Disable timer interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return None + */ +FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num) +{ + hw->int_clr_timers.val |= BIT(timer_num); +} + +/** + * @brief Get interrupt status. + * + * @param hw Beginning address of the peripheral registers. + * @param intr_status Interrupt status + * + * @return None + */ +FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) +{ + *intr_status = hw->int_st_timers.val; +} + +/** + * @brief Set the level interrupt status, enable or disable the level interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param level_int_en True to enable level interrupt, false to disable level interrupt + * + * @return None + */ +static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en) +{ + hw->hw_timer[timer_num].config.level_int_en = level_int_en; +} + +/** + * @brief Get the level interrupt status. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Enable level interrupt + * - false Disable level interrupt + */ +static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.level_int_en; +} + +/** + * @brief Set the edge interrupt status, enable or disable the edge interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param edge_int_en True to enable edge interrupt, false to disable edge interrupt + * + * @return None + */ +static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool edge_int_en) +{ + hw->hw_timer[timer_num].config.edge_int_en = edge_int_en; +} + +/** + * @brief Get the edge interrupt status. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Enable edge interrupt + * - false Disable edge interrupt + */ +static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.edge_int_en; +} + +/** + * @brief Get interrupt status register address. + * + * @param hw Beginning address of the peripheral registers. + * @param intr_status_reg Interrupt status register address + * + * @return None + */ +static inline void timer_ll_get_intr_status_reg(timg_dev_t *hw, uint32_t *intr_status_reg) +{ + *intr_status_reg = (uint32_t)&(hw->int_st_timers.val); } /* WDT operations */ /** - * Unlock/lock the WDT register in case of mis-operations. + * @brief Unlock/lock the WDT register in case of mis-operations. * * @param hw Beginning address of the peripheral registers. * @param protect true to lock, false to unlock before operations. */ - FORCE_INLINE_ATTR void timer_ll_wdt_set_protect(timg_dev_t* hw, bool protect) { hw->wdt_wprotect=(protect? 0: TIMG_WDT_WKEY_VALUE); } /** - * Initialize WDT. + * @brief Initialize WDT. * * @param hw Beginning address of the peripheral registers. * - * @note Call ``timer_ll_wdt_set_protect first`` + * @note Call `timer_ll_wdt_set_protect` first */ FORCE_INLINE_ATTR void timer_ll_wdt_init(timg_dev_t* hw) { @@ -214,16 +396,34 @@ FORCE_INLINE_ATTR void timer_ll_wdt_init(timg_dev_t* hw) hw->wdt_config0.edge_int_en = 0; } +/** + * @brief Set the WDT tick time. + * + * @param hw Beginning address of the peripheral registers. + * @param tick_time_us Tick time. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_tick(timg_dev_t* hw, int tick_time_us) { hw->wdt_config1.clk_prescale=80*tick_time_us; } +/** + * @brief Feed the WDT. + * + * @param hw Beginning address of the peripheral registers. + */ FORCE_INLINE_ATTR void timer_ll_wdt_feed(timg_dev_t* hw) { hw->wdt_feed = 1; } +/** + * @brief Set the WDT timeout. + * + * @param hw Beginning address of the peripheral registers. + * @param stage Stage number of WDT. + * @param timeout_Tick tick threshold of timeout. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout(timg_dev_t* hw, int stage, uint32_t timeout_tick) { switch (stage) { @@ -249,6 +449,13 @@ _Static_assert(TIMER_WDT_INT == TIMG_WDT_STG_SEL_INT, "Add mapping to LL watchdo _Static_assert(TIMER_WDT_RESET_CPU == TIMG_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t"); _Static_assert(TIMER_WDT_RESET_SYSTEM == TIMG_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t"); +/** + * @brief Set the WDT timeout behavior. + * + * @param hw Beginning address of the peripheral registers. + * @param stage Stage number of WDT. + * @param behavior Behavior of WDT, please see enum timer_wdt_behavior_t. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout_behavior(timg_dev_t* hw, int stage, timer_wdt_behavior_t behavior) { switch (stage) { @@ -269,16 +476,47 @@ FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout_behavior(timg_dev_t* hw, int sta } } +/** + * @brief Enable/Disable the WDT enable. + * + * @param hw Beginning address of the peripheral registers. + * @param enable True to enable WDT, false to disable WDT. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_enable(timg_dev_t* hw, bool enable) { hw->wdt_config0.en = enable; } +/** + * @brief Enable/Disable the WDT flashboot mode. + * + * @param hw Beginning address of the peripheral registers. + * @param enable True to enable WDT flashboot mode, false to disable WDT flashboot mode. + */ FORCE_INLINE_ATTR void timer_ll_wdt_flashboot_en(timg_dev_t* hw, bool enable) { hw->wdt_config0.flashboot_mod_en = enable; } +/** + * @brief Clear the WDT interrupt status. + * + * @param hw Beginning address of the peripheral registers. + */ +FORCE_INLINE_ATTR void timer_ll_wdt_clear_intr_status(timg_dev_t* hw) +{ + hw->int_clr_timers.wdt = 1; +} + +/** + * @brief Enable the WDT interrupt. + * + * @param hw Beginning address of the peripheral registers. + */ +FORCE_INLINE_ATTR void timer_ll_wdt_enable_intr(timg_dev_t* hw) +{ + hw->int_ena.wdt = 1; +} #ifdef __cplusplus } diff --git a/components/soc/esp32s2beta/include/hal/timer_ll.h b/components/soc/esp32s2beta/include/hal/timer_ll.h index 20805337a..dd9cfb729 100644 --- a/components/soc/esp32s2beta/include/hal/timer_ll.h +++ b/components/soc/esp32s2beta/include/hal/timer_ll.h @@ -21,71 +21,71 @@ extern "C" { #endif +#include #include "hal/timer_types.h" #include "soc/timer_periph.h" -//Helper macro to get corresponding interrupt of a timer -#define TIMER_LL_GET_INTR(TIMER_IDX) ((TIMER_IDX)==TIMER_0? TIMER_INTR_T0: TIMER_INTR_T1) - -#define TIMER_LL_GET_HW(TIMER_GROUP) ((TIMER_GROUP)==0? &TIMERG0: &TIMERG1) - _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); _Static_assert(TIMER_INTR_T1 == TIMG_T1_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); _Static_assert(TIMER_INTR_WDT == TIMG_WDT_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); +typedef struct { + timg_dev_t *dev; + timer_idx_t idx; +} timer_ll_context_t; + +// Get timer group instance with giving group number +#define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1)) + /** - * @brief Enable timer interrupt. + * @brief Set timer clock prescale value * * @param hw Beginning address of the peripheral registers. - * @param intr_mask Interrupt enable mask + * @param timer_num The timer number + * @param divider Prescale value * * @return None */ -static inline void timer_ll_intr_enable(timg_dev_t *hw, timer_intr_t intr_mask) +static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t divider) { - hw->int_ena.val |= intr_mask; + int timer_en = hw->hw_timer[timer_num].config.enable; + hw->hw_timer[timer_num].config.enable = 0; + hw->hw_timer[timer_num].config.divider = divider; + hw->hw_timer[timer_num].config.enable = timer_en; } /** - * @brief Disable timer interrupt. + * @brief Get timer clock prescale value * * @param hw Beginning address of the peripheral registers. - * @param intr_mask Interrupt disable mask + * @param timer_num The timer number + * @param divider Pointer to accept the prescale value * * @return None */ -static inline void timer_ll_intr_disable(timg_dev_t *hw, timer_intr_t intr_mask) +static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t *divider) { - hw->int_ena.val &= (~intr_mask); + *divider = hw->hw_timer[timer_num].config.divider; } /** - * @brief Get timer interrupt status. + * @brief Load counter value into time-base counter * * @param hw Beginning address of the peripheral registers. - * - * @return Masked interrupt status - */ -static inline timer_intr_t timer_ll_intr_status_get(timg_dev_t *hw) -{ - return hw->int_raw.val; -} - -/** - * @brief Clear timer interrupt. - * - * @param hw Beginning address of the peripheral registers. - * @param intr_mask Interrupt mask to clear + * @param timer_num The timer number + * @param load_val Counter value * * @return None */ -static inline void timer_ll_intr_status_clear(timg_dev_t *hw, timer_intr_t intr_mask) +static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val) { - hw->int_clr.val = intr_mask; + hw->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32); + hw->hw_timer[timer_num].load_low = (uint32_t) load_val; + hw->hw_timer[timer_num].reload = 1; } /** - * @brief Get counter vaule from time-base counter + * @brief Get counter value from time-base counter * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number @@ -93,36 +93,95 @@ static inline void timer_ll_intr_status_clear(timg_dev_t *hw, timer_intr_t intr_ * * @return None */ -static inline void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val) +FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val) { hw->hw_timer[timer_num].update.update = 1; *timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high << 32) | (hw->hw_timer[timer_num].cnt_low); } +/** + * @brief Set counter mode, include increment mode and decrement mode. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param increase_en True to increment mode, fasle to decrement mode + * + * @return None + */ +static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en) +{ + hw->hw_timer[timer_num].config.increase = increase_en; +} + +/** + * @brief Get counter mode, include increment mode and decrement mode. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Increment mode + * - false Decrement mode + */ +static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.increase; +} + /** * @brief Set counter status, enable or disable counter. * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param counter_en Counter enable status + * @param counter_en True to enable counter, false to disable counter * * @return None */ -static inline void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, timer_start_t counter_en) +FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en) { hw->hw_timer[timer_num].config.enable = counter_en; } +/** + * @brief Get counter status. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Enable counter + * - false Disable conuter + */ +static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.enable; +} + +/** + * @brief Set auto reload mode. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param auto_reload_en True to enable auto reload mode, flase to disable auto reload mode + * + * @return None + */ +static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en) +{ + hw->hw_timer[timer_num].config.autoreload = auto_reload_en; +} + /** * @brief Get auto reload mode. * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param reload Pointer to accept the auto reload mode * - * @return None + * @return + * - true Enable auto reload mode + * - false Disable auto reload mode */ -static inline bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num) +FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num) { return hw->hw_timer[timer_num].config.autoreload; } @@ -136,7 +195,7 @@ static inline bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_nu * * @return None */ -static inline void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value) +FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value) { hw->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32); hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value; @@ -161,11 +220,11 @@ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_nu * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param alarm_en true to enable, false to disable + * @param alarm_en True to enable alarm, false to disable alarm * * @return None */ -static inline void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en) +FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en) { hw->hw_timer[timer_num].config.alarm_en = alarm_en; } @@ -175,35 +234,185 @@ static inline void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_n * * @param hw Beginning address of the peripheral registers. * @param timer_num The timer number - * @param alarm_en Pointer to accept the alarm status + * + * @return + * - true Enable alarm + * - false Disable alarm + */ +static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.alarm_en; +} + +/** + * @brief Enable timer interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number * * @return None */ -static inline void timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool *alarm_en) +FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num) { - *alarm_en = hw->hw_timer[timer_num].config.alarm_en; + hw->int_ena.val |= BIT(timer_num); +} + +/** + * @brief Disable timer interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return None + */ +FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num) +{ + hw->int_ena.val &= (~BIT(timer_num)); +} + +/** + * @brief Disable timer interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return None + */ +FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num) +{ + hw->int_clr.val |= BIT(timer_num); +} + +/** + * @brief Get interrupt status. + * + * @param hw Beginning address of the peripheral registers. + * @param intr_status Interrupt status + * + * @return None + */ +FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) +{ + *intr_status = hw->int_st.val; +} + +/** + * @brief Set the level interrupt status, enable or disable the level interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param level_int_en True to enable level interrupt, false to disable level interrupt + * + * @return None + */ +static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en) +{ + hw->hw_timer[timer_num].config.level_int_en = level_int_en; +} + +/** + * @brief Get the level interrupt status. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Enable level interrupt + * - false Disable level interrupt + */ +static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.level_int_en; +} + +/** + * @brief Set the edge interrupt status, enable or disable the edge interrupt. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * @param edge_int_en True to enable edge interrupt, false to disable edge interrupt + * + * @return None + */ +static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool edge_int_en) +{ + hw->hw_timer[timer_num].config.edge_int_en = edge_int_en; +} + +/** + * @brief Get the edge interrupt status. + * + * @param hw Beginning address of the peripheral registers. + * @param timer_num The timer number + * + * @return + * - true Enable edge interrupt + * - false Disable edge interrupt + */ +static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.edge_int_en; +} + +/** + * @brief Get interrupt status register address. + * + * @param hw Beginning address of the peripheral registers. + * @param intr_status_reg Interrupt status register address + * + * @return None + */ +static inline void timer_ll_get_intr_status_reg(timg_dev_t *hw, uint32_t *intr_status_reg) +{ + *intr_status_reg = (uint32_t)&(hw->int_st.val); +} + +/** + * @brief Set clock source. + * + * @param hal Context of the HAL layer + * @param use_xtal_en True to use XTAL clock, flase to use APB clock + * + * @return None + */ +static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, bool use_xtal_en) +{ + hw->hw_timer[timer_num].config.use_xtal = use_xtal_en; +} + +/** + * @brief Get clock source. + * + * @param hal Context of the HAL layer + * + * @return + * - true Use XTAL clock + * - false Use APB clock + */ +static inline bool timer_ll_get_use_xtal(timg_dev_t *hw, timer_idx_t timer_num) +{ + return hw->hw_timer[timer_num].config.use_xtal; } /* WDT operations */ /** - * Unlock/lock the WDT register in case of mis-operations. + * @brief Unlock/lock the WDT register in case of mis-operations. * * @param hw Beginning address of the peripheral registers. * @param protect true to lock, false to unlock before operations. */ - FORCE_INLINE_ATTR void timer_ll_wdt_set_protect(timg_dev_t* hw, bool protect) { hw->wdt_wprotect=(protect? 0: TIMG_WDT_WKEY_VALUE); } /** - * Initialize WDT. + * @brief Initialize WDT. * * @param hw Beginning address of the peripheral registers. * - * @note Call ``timer_ll_wdt_set_protect first`` + * @note Call `timer_ll_wdt_set_protect` first */ FORCE_INLINE_ATTR void timer_ll_wdt_init(timg_dev_t* hw) { @@ -214,16 +423,34 @@ FORCE_INLINE_ATTR void timer_ll_wdt_init(timg_dev_t* hw) hw->wdt_config0.edge_int_en = 0; } +/** + * @brief Set the WDT tick time. + * + * @param hw Beginning address of the peripheral registers. + * @param tick_time_us Tick time. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_tick(timg_dev_t* hw, int tick_time_us) { hw->wdt_config1.clk_prescale=80*tick_time_us; } +/** + * @brief Feed the WDT. + * + * @param hw Beginning address of the peripheral registers. + */ FORCE_INLINE_ATTR void timer_ll_wdt_feed(timg_dev_t* hw) { hw->wdt_feed = 1; } +/** + * @brief Set the WDT timeout. + * + * @param hw Beginning address of the peripheral registers. + * @param stage Stage number of WDT. + * @param timeout_Tick tick threshold of timeout. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout(timg_dev_t* hw, int stage, uint32_t timeout_tick) { switch (stage) { @@ -249,6 +476,13 @@ _Static_assert(TIMER_WDT_INT == TIMG_WDT_STG_SEL_INT, "Add mapping to LL watchdo _Static_assert(TIMER_WDT_RESET_CPU == TIMG_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t"); _Static_assert(TIMER_WDT_RESET_SYSTEM == TIMG_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t"); +/** + * @brief Set the WDT timeout behavior. + * + * @param hw Beginning address of the peripheral registers. + * @param stage Stage number of WDT. + * @param behavior Behavior of WDT, please see enum timer_wdt_behavior_t. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout_behavior(timg_dev_t* hw, int stage, timer_wdt_behavior_t behavior) { switch (stage) { @@ -269,16 +503,47 @@ FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout_behavior(timg_dev_t* hw, int sta } } +/** + * @brief Enable/Disable the WDT enable. + * + * @param hw Beginning address of the peripheral registers. + * @param enable True to enable WDT, false to disable WDT. + */ FORCE_INLINE_ATTR void timer_ll_wdt_set_enable(timg_dev_t* hw, bool enable) { hw->wdt_config0.en = enable; } +/** + * @brief Enable/Disable the WDT flashboot mode. + * + * @param hw Beginning address of the peripheral registers. + * @param enable True to enable WDT flashboot mode, false to disable WDT flashboot mode. + */ FORCE_INLINE_ATTR void timer_ll_wdt_flashboot_en(timg_dev_t* hw, bool enable) { hw->wdt_config0.flashboot_mod_en = enable; } +/** + * @brief Clear the WDT interrupt status. + * + * @param hw Beginning address of the peripheral registers. + */ +FORCE_INLINE_ATTR void timer_ll_wdt_clear_intr_status(timg_dev_t* hw) +{ + hw->int_clr.wdt = 1; +} + +/** + * @brief Enable the WDT interrupt. + * + * @param hw Beginning address of the peripheral registers. + */ +FORCE_INLINE_ATTR void timer_ll_wdt_enable_intr(timg_dev_t* hw) +{ + hw->int_ena.wdt = 1; +} #ifdef __cplusplus } diff --git a/components/soc/include/hal/timer_hal.h b/components/soc/include/hal/timer_hal.h new file mode 100644 index 000000000..6a91e4406 --- /dev/null +++ b/components/soc/include/hal/timer_hal.h @@ -0,0 +1,311 @@ +// Copyright 2019 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. + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in soc/include/hal/readme.md + ******************************************************************************/ + +// The HAL layer for Timer Group. +// There is no parameter check in the hal layer, so the caller must ensure the correctness of the parameters. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "hal/timer_ll.h" +#include "hal/timer_types.h" + +/** + * Context that should be maintained by both the driver and the HAL + */ +typedef struct { + timg_dev_t *dev; + timer_idx_t idx; +} timer_hal_context_t; + +/** + * @brief Init the timer hal. This function should be called first before other hal layer function is called + * + * @param hal Context of the HAL layer + * @param group_num The timer group number + * @param timer_num The timer number + * + * @return None + */ +void timer_hal_init(timer_hal_context_t *hal, timer_group_t group_num, timer_idx_t timer_num); + +/** + * @brief Set timer clock prescale value + * + * @param hal Context of the HAL layer + * @param divider Prescale value + * + * @return None + */ +#define timer_hal_set_divider(hal, divider) timer_ll_set_divider((hal)->dev, (hal)->idx, divider) + +/** + * @brief Get timer clock prescale value + * + * @param hal Context of the HAL layer + * @param divider Pointer to accept the prescale value + * + * @return None + */ +#define timer_hal_get_divider(hal, divider) timer_ll_get_divider((hal)->dev, (hal)->idx, divider) + +/** + * @brief Load counter value into time-base counter + * + * @param hal Context of the HAL layer + * @param load_val Counter value + * + * @return None + */ +#define timer_hal_set_counter_value(hal, load_val) timer_ll_set_counter_value((hal)->dev, (hal)->idx, load_val) + +/** + * @brief Get counter value from time-base counter + * + * @param hal Context of the HAL layer + * @param timer_val Pointer to accept the counter value + * + * @return None + */ +#define timer_hal_get_counter_value(hal, timer_val) timer_ll_get_counter_value((hal)->dev, (hal)->idx, timer_val) + +/** + * @brief Set counter mode, include increment mode and decrement mode. + * + * @param hal Context of the HAL layer + * @param increase_en True to increment mode, fasle to decrement mode + * + * @return None + */ +#define timer_hal_set_counter_increase(hal, increase_en) timer_ll_set_counter_increase((hal)->dev, (hal)->idx, increase_en) + +/** + * @brief Get counter mode, include increment mode and decrement mode. + * + * @param hal Context of the HAL layer + * @param counter_dir Pointer to accept the counter mode + * + * @return + * - true Increment mode + * - false Decrement mode + */ +#define timer_hal_get_counter_increase(hal) timer_ll_get_counter_increase((hal)->dev, (hal)->idx) + +/** + * @brief Set counter status, enable or disable counter. + * + * @param hal Context of the HAL layer + * @param counter_en True to enable counter, false to disable counter + * + * @return None + */ +#define timer_hal_set_counter_enable(hal, counter_en) timer_ll_set_counter_enable((hal)->dev, (hal)->idx, counter_en) + +/** + * @brief Get counter status. + * + * @param hal Context of the HAL layer + * + * @return + * - true Enable counter + * - false Disable conuter + */ +#define timer_hal_get_counter_enable(hal) timer_ll_get_counter_enable((hal)->dev, (hal)->idx) + +/** + * @brief Set auto reload mode. + * + * @param hal Context of the HAL layer + * @param auto_reload_en True to enable auto reload mode, flase to disable auto reload mode + * + * @return None + */ +#define timer_hal_set_auto_reload(hal, auto_reload_en) timer_ll_set_auto_reload((hal)->dev, (hal)->idx, auto_reload_en) + +/** + * @brief Get auto reload mode. + * + * @param hal Context of the HAL layer + * + * @return + * - true Enable auto reload mode + * - false Disable auto reload mode + */ +#define timer_hal_get_auto_reload(hal) timer_ll_get_auto_reload((hal)->dev, (hal)->idx) + +/** + * @brief Set the counter value to trigger the alarm. + * + * @param hal Context of the HAL layer + * @param alarm_value Counter value to trigger the alarm + * + * @return None + */ +#define timer_hal_set_alarm_value(hal, alarm_value) timer_ll_set_alarm_value((hal)->dev, (hal)->idx, alarm_value) + +/** + * @brief Get the counter value to trigger the alarm. + * + * @param hal Context of the HAL layer + * @param alarm_value Pointer to accept the counter value to trigger the alarm + * + * @return None + */ +#define timer_hal_get_alarm_value(hal, alarm_value) timer_ll_get_alarm_value((hal)->dev, (hal)->idx, alarm_value) + +/** + * @brief Set the alarm status, enable or disable the alarm. + * + * @param hal Context of the HAL layer + * @param alarm_en True to enable alarm, false to disable alarm + * + * @return None + */ +#define timer_hal_set_alarm_enable(hal, alarm_en) timer_ll_set_alarm_enable((hal)->dev, (hal)->idx, alarm_en) + +/** + * @brief Get the alarm status. + * + * @param hal Context of the HAL layer + * + * @return + * - true Enable alarm + * - false Disable alarm + */ +#define timer_hal_get_alarm_enable(hal) timer_ll_get_alarm_enable((hal)->dev, (hal)->idx) + +/** + * @brief Set the level interrupt status, enable or disable the level interrupt. + * + * @param hal Context of the HAL layer + * @param level_int_en True to enable level interrupt, false to disable level interrupt + * + * @return None + */ +#define timer_hal_set_level_int_enable(hal, level_int_en) timer_ll_set_level_int_enable((hal)->dev, (hal)->idx, level_int_en) + +/** + * @brief Get the level interrupt status. + * + * @param hal Context of the HAL layer + * + * @return + * - true Enable level interrupt + * - false Disable level interrupt + */ +#define timer_hal_get_level_int_enable(hal) timer_ll_get_level_int_enable((hal)->dev, (hal)->idx) + +/** + * @brief Set the edge interrupt status, enable or disable the edge interrupt. + * + * @param hal Context of the HAL layer + * @param edge_int_en True to enable edge interrupt, false to disable edge interrupt + * + * @return None + */ +#define timer_hal_set_edge_int_enable(hal, edge_int_en) timer_ll_set_edge_int_enable((hal)->dev, (hal)->idx, edge_int_en) + +/** + * @brief Get the edge interrupt status. + * + * @param hal Context of the HAL layer + * + * @return + * - true Enable edge interrupt + * - false Disable edge interrupt + */ +#define timer_hal_get_edge_int_enable(hal) timer_ll_get_edge_int_enable((hal)->dev, (hal)->idx) + +/** + * @brief Enable timer interrupt. + * + * @param hal Context of the HAL layer + * + * @return None + */ +#define timer_hal_intr_enable(hal) timer_ll_intr_enable((hal)->dev, (hal)->idx) + +/** + * @brief Disable timer interrupt. + * + * @param hal Context of the HAL layer + * + * @return None + */ +#define timer_hal_intr_disable(hal) timer_ll_intr_disable((hal)->dev, (hal)->idx) + +/** + * @brief Clear interrupt status. + * + * @param hal Context of the HAL layer + * + * @return None + */ +#define timer_hal_clear_intr_status(hal) timer_ll_clear_intr_status((hal)->dev, (hal)->idx) + +/** + * @brief Get interrupt status. + * + * @param hal Context of the HAL layer + * @param intr_status Interrupt status + * + * @return None + */ +#define timer_hal_get_intr_status(hal, intr_status) timer_ll_get_intr_status((hal)->dev, intr_status) + +/** + * @brief Get interrupt status register address. + * + * @param hal Context of the HAL layer + * @param intr_status_reg Interrupt status register address + * + * @return None + */ +#define timer_hal_get_intr_status_reg(hal, intr_status_reg) timer_ll_get_intr_status_reg((hal)->dev, intr_status_reg) + +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA +/** + * @brief Set clock source. + * + * @param hal Context of the HAL layer + * @param use_xtal_en True to use XTAL clock, flase to use APB clock + * + * @return None + */ +#define timer_hal_set_use_xtal(hal, use_xtal_en) timer_ll_set_use_xtal((hal)->dev, (hal)->idx, use_xtal_en) + +/** + * @brief Get clock source. + * + * @param hal Context of the HAL layer + * + * @return + * - true Use XTAL clock + * - false Use APB clock + */ +#define timer_hal_get_use_xtal(hal) timer_ll_get_use_xtal((hal)->dev, (hal)->idx) +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/include/hal/timer_types.h b/components/soc/include/hal/timer_types.h index e9bcc9985..123875565 100644 --- a/components/soc/include/hal/timer_types.h +++ b/components/soc/include/hal/timer_types.h @@ -22,6 +22,14 @@ extern "C" { #include #include +/** + * @brief Selects a Timer-Group out of 2 available groups + */ +typedef enum { + TIMER_GROUP_0 = 0, /*!dev = TIMER_LL_GET_HW(group_num); + hal->idx = timer_num; +} diff --git a/components/spi_flash/test/test_spi_flash.c b/components/spi_flash/test/test_spi_flash.c index f14c5d034..2139d1f5f 100644 --- a/components/spi_flash/test/test_spi_flash.c +++ b/components/spi_flash/test/test_spi_flash.c @@ -126,7 +126,7 @@ typedef struct { static void IRAM_ATTR timer_isr(void* varg) { block_task_arg_t* arg = (block_task_arg_t*) varg; - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0); ets_delay_us(arg->delay_time_us); arg->repeat_count++; diff --git a/docs/Doxyfile b/docs/Doxyfile index 2a7d801fa..d59099866 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -109,6 +109,7 @@ INPUT = \ ../../components/soc/include/hal/i2s_types.h \ ../../components/soc/include/hal/rtc_io_types.h \ ../../components/soc/include/hal/sigmadelta_types.h \ + ../../components/soc/include/hal/timer_types.h \ ../../components/soc/esp32/include/soc/adc_channel.h \ ../../components/soc/esp32/include/soc/dac_channel.h \ ../../components/soc/esp32/include/soc/touch_channel.h \ diff --git a/examples/peripherals/timer_group/main/timer_group_example_main.c b/examples/peripherals/timer_group/main/timer_group_example_main.c index 4f568ac67..30b3a9c00 100644 --- a/examples/peripherals/timer_group/main/timer_group_example_main.c +++ b/examples/peripherals/timer_group/main/timer_group_example_main.c @@ -55,11 +55,12 @@ static void inline print_timer_counter(uint64_t counter_value) */ void IRAM_ATTR timer_group0_isr(void *para) { + timer_spinlock_take(TIMER_GROUP_0); int timer_idx = (int) para; /* Retrieve the interrupt status and the counter value from the timer that reported the interrupt */ - timer_intr_t timer_intr = timer_group_intr_get_in_isr(TIMER_GROUP_0); + uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0); uint64_t timer_counter_value = timer_group_get_counter_value_in_isr(TIMER_GROUP_0, timer_idx); /* Prepare basic event data @@ -73,12 +74,12 @@ void IRAM_ATTR timer_group0_isr(void *para) and update the alarm time for the timer with without reload */ if (timer_intr & TIMER_INTR_T0) { evt.type = TEST_WITHOUT_RELOAD; - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, timer_idx, timer_counter_value); } else if (timer_intr & TIMER_INTR_T1) { evt.type = TEST_WITH_RELOAD; - timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_1); + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1); } else { evt.type = -1; // not supported even type } @@ -89,6 +90,7 @@ void IRAM_ATTR timer_group0_isr(void *para) /* Now just send the event data back to the main program task */ xQueueSendFromISR(timer_queue, &evt, NULL); + timer_spinlock_give(TIMER_GROUP_0); } /* @@ -110,7 +112,7 @@ static void example_tg0_timer_init(int timer_idx, config.intr_type = TIMER_INTR_LEVEL; config.auto_reload = auto_reload; #ifdef CONFIG_IDF_TARGET_ESP32S2BETA - config.clk_sel = TIMER_SRC_CLK_APB; + config.clk_src = TIMER_SRC_CLK_APB; #endif timer_init(TIMER_GROUP_0, timer_idx, &config); diff --git a/examples/system/sysview_tracing/main/sysview_tracing.c b/examples/system/sysview_tracing/main/sysview_tracing.c index 32c4562e1..a561ca2df 100644 --- a/examples/system/sysview_tracing/main/sysview_tracing.c +++ b/examples/system/sysview_tracing/main/sysview_tracing.c @@ -126,7 +126,7 @@ static void example_timer_isr(void *arg) } } // re-start timer - timer_group_intr_clr_in_isr(tim_arg->group, tim_arg->timer); + timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->timer); timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->timer); }