Merge branch 'refactor/timerg_in_test' into 'master'

timer_group: refactoring to avoid direct register access in the ISR

See merge request espressif/esp-idf!5656
This commit is contained in:
Angus Gratton 2019-08-14 15:32:16 +08:00
commit 367ecc2d60
28 changed files with 729 additions and 372 deletions

View file

@ -21,6 +21,7 @@
#include "soc/timer_periph.h"
#include "esp_app_trace.h"
#include "esp_private/dbg_stubs.h"
#include "hal/timer_ll.h"
#if CONFIG_ESP32_GCOV_ENABLE
@ -124,13 +125,13 @@ void esp_gcov_dump(void)
#endif
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
// to avoid complains that task watchdog got triggered for other tasks
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0;
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_feed(&TIMERG0);
timer_ll_wdt_set_protect(&TIMERG0, true);
// to avoid reboot on INT_WDT
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_feed=1;
TIMERG1.wdt_wprotect=0;
timer_ll_wdt_set_protect(&TIMERG1, false);
timer_ll_wdt_feed(&TIMERG1);
timer_ll_wdt_set_protect(&TIMERG1, true);
}
esp_dbg_stub_gcov_dump_do();

View file

@ -145,56 +145,16 @@ static void esp_apptrace_test_timer_isr(void *arg)
}
tim_arg->data.wr_cnt++;
if (tim_arg->group == 0) {
if (tim_arg->id == 0) {
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].update = 1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG0.int_clr_timers.t1 = 1;
TIMERG0.hw_timer[1].update = 1;
TIMERG0.hw_timer[1].config.alarm_en = 1;
}
}
if (tim_arg->group == 1) {
if (tim_arg->id == 0) {
TIMERG1.int_clr_timers.t0 = 1;
TIMERG1.hw_timer[0].update = 1;
TIMERG1.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG1.int_clr_timers.t1 = 1;
TIMERG1.hw_timer[1].update = 1;
TIMERG1.hw_timer[1].config.alarm_en = 1;
}
}
timer_group_intr_clr_in_isr(tim_arg->group, tim_arg->id);
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
}
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;
if (tim_arg->group == 0) {
if (tim_arg->id == 0) {
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].update = 1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG0.int_clr_timers.t1 = 1;
TIMERG0.hw_timer[1].update = 1;
TIMERG0.hw_timer[1].config.alarm_en = 1;
}
}
if (tim_arg->group == 1) {
if (tim_arg->id == 0) {
TIMERG1.int_clr_timers.t0 = 1;
TIMERG1.hw_timer[0].update = 1;
TIMERG1.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG1.int_clr_timers.t1 = 1;
TIMERG1.hw_timer[1].update = 1;
TIMERG1.hw_timer[1].config.alarm_en = 1;
}
}
timer_group_intr_clr_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));
*ts = (uint32_t)esp_apptrace_test_ts_get();//xthal_get_ccount();//xTaskGetTickCount();
@ -850,28 +810,8 @@ 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);
if (tim_arg->group == 0) {
if (tim_arg->timer == 0) {
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].update = 1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG0.int_clr_timers.t1 = 1;
TIMERG0.hw_timer[1].update = 1;
TIMERG0.hw_timer[1].config.alarm_en = 1;
}
}
if (tim_arg->group == 1) {
if (tim_arg->timer == 0) {
TIMERG1.int_clr_timers.t0 = 1;
TIMERG1.hw_timer[0].update = 1;
TIMERG1.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG1.int_clr_timers.t1 = 1;
TIMERG1.hw_timer[1].update = 1;
TIMERG1.hw_timer[1].config.alarm_en = 1;
}
}
timer_group_intr_clr_in_isr(tim_arg->group, tim_arg->id);
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
}
static void esp_sysviewtrace_test_task(void *p)

View file

@ -53,6 +53,7 @@
#include "bootloader_flash_config.h"
#include "flash_qio_mode.h"
#include "hal/timer_ll.h"
extern int _bss_start;
extern int _bss_end;
@ -158,8 +159,8 @@ static esp_err_t bootloader_main(void)
/* disable watch dog here */
rtc_wdt_disable();
#endif
REG_SET_FIELD(TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY, TIMG_WDT_WKEY_VALUE);
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_flashboot_en(&TIMERG0, false);
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = ets_efuse_get_spiconfig();

View file

@ -319,3 +319,31 @@ TEST_CASE("can call std::function and bind", "[cxx]")
#endif
/* Tests below are done in the compile time, don't actually get run. */
/* Check whether a enumerator flag can be used in C++ */
template<typename T> __attribute__((unused)) static void test_binary_operators()
{
T flag1 = (T)0;
T flag2 = (T)0;
flag1 = ~flag1;
flag1 = flag1 | flag2;
flag1 = flag1 & flag2;
flag1 = flag1 ^ flag2;
flag1 = flag1 >> 2;
flag1 = flag1 << 2;
flag1 |= flag2;
flag1 &= flag2;
flag1 ^= flag2;
flag1 >>= 2;
flag1 <<= 2;
}
//Add more types here. If any flags cannot pass the build, use FLAG_ATTR in esp_attr.h
#include "hal/timer_types.h"
template void test_binary_operators<timer_intr_t>();

View file

@ -19,6 +19,7 @@
#include "soc/soc.h"
#include "soc/timer_periph.h"
#include "esp_intr_alloc.h"
#include "hal/timer_types.h"
#ifdef __cplusplus
extern "C" {
@ -36,15 +37,6 @@ typedef enum {
TIMER_GROUP_MAX,
} timer_group_t;
/**
* @brief Select a hardware timer from timer groups
*/
typedef enum {
TIMER_0 = 0, /*!<Select timer0 of GROUPx*/
TIMER_1 = 1, /*!<Select timer1 of GROUPx*/
TIMER_MAX,
} timer_idx_t;
/**
* @brief Decides the direction of counter
*/
@ -54,14 +46,6 @@ typedef enum {
TIMER_COUNT_MAX
} timer_count_dir_t;
/**
* @brief Decides whether timer is on or paused
*/
typedef enum {
TIMER_PAUSE = 0, /*!<Pause timer counter*/
TIMER_START = 1, /*!<Start timer counter*/
} timer_start_t;
/**
* @brief Decides whether to enable alarm mode
*/
@ -262,9 +246,9 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
*
* @note If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set,
* the handler function must be declared with IRAM_ATTR attribute
* and can only call functions in IRAM or ROM. It cannot call other timer APIs.
* @note If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set,
* the handler function must be declared with IRAM_ATTR attribute
* and can only call functions in IRAM or ROM. It cannot call other timer APIs.
* Use direct register access to configure timers from inside the ISR in this case.
*
* @return
@ -274,7 +258,7 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
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);
/** @brief Initializes and configure the timer.
*
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param config Pointer to timer initialization parameters.
@ -300,28 +284,30 @@ esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer
/** @brief Enable timer group interrupt, by enable mask
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param en_mask Timer interrupt enable mask.
* Use TIMG_T0_INT_ENA_M to enable t0 interrupt
* Use TIMG_T1_INT_ENA_M to enable t1 interrupt
* @param intr_mask Timer interrupt enable mask.
* - TIMER_INTR_T0: t0 interrupt
* - TIMER_INTR_T1: t1 interrupt
* - TIMER_INTR_WDT: watchdog interrupt
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_group_intr_enable(timer_group_t group_num, uint32_t en_mask);
esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t intr_mask);
/** @brief Disable timer group interrupt, by disable mask
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param disable_mask Timer interrupt disable mask.
* Use TIMG_T0_INT_ENA_M to disable t0 interrupt
* Use TIMG_T1_INT_ENA_M to disable t1 interrupt
* @param intr_mask Timer interrupt disable mask.
* - TIMER_INTR_T0: t0 interrupt
* - TIMER_INTR_T1: t1 interrupt
* - TIMER_INTR_WDT: watchdog interrupt
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_group_intr_disable(timer_group_t group_num, uint32_t disable_mask);
esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t intr_mask);
/** @brief Enable timer interrupt
*
@ -345,6 +331,52 @@ esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num);
*/
esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num);
/** @cond */
/* Utilities functions that can be used in the ISR */
/* Preview, don't treat them as stable API. */
/**
* Clear interrupt status bit.
*/
void timer_group_intr_clr_in_isr(timer_group_t group_num, timer_idx_t timer_num);
/**
* Enable alarm.
*/
void timer_group_enable_alarm_in_isr(timer_group_t group_num, timer_idx_t timer_num);
/**
* Get the current counter value.
*/
uint64_t timer_group_get_counter_value_in_isr(timer_group_t group_num, timer_idx_t timer_num);
/**
* Set the alarm threshold for the timer.
*/
void timer_group_set_alarm_value_in_isr(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_val);
/**
* Enable/disable a counter.
*/
void timer_group_set_counter_enable_in_isr(timer_group_t group_num, timer_idx_t timer_num, timer_start_t counter_en);
/**
* Get the masked interrupt status.
*/
timer_intr_t timer_group_intr_get_in_isr(timer_group_t group_num);
/**
* Clear interrupt.
*/
void timer_group_clr_intr_sta_in_isr(timer_group_t group_num, timer_intr_t intr_mask);
/**
* Get auto reload enable status.
*/
bool timer_group_get_auto_reload_in_isr(timer_group_t group_num, timer_idx_t timer_num);
/** @endcond */
#ifdef __cplusplus
}
#endif

View file

@ -11,68 +11,44 @@
#define TIMER_DELTA 0.001
static bool alarm_flag;
// group0 interruption
static void test_timer_group0_isr(void *para)
{
int timer_idx = (int) para;
uint64_t timer_val;
double time;
uint64_t alarm_value;
alarm_flag = true;
if (TIMERG0.hw_timer[timer_idx].config.autoreload == 1) {
if (timer_idx == 0) {
TIMERG0.int_clr_timers.t0 = 1;
} else {
TIMERG0.int_clr_timers.t1 = 1;
}
ets_printf("This is TG0 timer[%d] reload-timer alarm!\n", timer_idx);
timer_get_counter_value(TIMER_GROUP_0, timer_idx, &timer_val);
timer_get_counter_time_sec(TIMER_GROUP_0, timer_idx, &time);
ets_printf("time: %.8f S\n", time);
} else {
if (timer_idx == 0) {
TIMERG0.int_clr_timers.t0 = 1;
} else {
TIMERG0.int_clr_timers.t1 = 1;
}
ets_printf("This is TG0 timer[%d] count-up-timer alarm!\n", timer_idx);
timer_get_counter_value(TIMER_GROUP_0, timer_idx, &timer_val);
timer_get_counter_time_sec(TIMER_GROUP_0, timer_idx, &time);
timer_get_alarm_value(TIMER_GROUP_0, timer_idx, &alarm_value);
ets_printf("time: %.8f S\n", time);
double alarm_time = (double) alarm_value / TIMER_SCALE;
ets_printf("alarm_time: %.8f S\n", alarm_time);
}
}
typedef struct {
timer_group_t timer_group;
timer_idx_t timer_idx;
} timer_info_t;
// group1 interruption
static void test_timer_group1_isr(void *para)
#define TIMER_INFO_INIT(TG, TID) {.timer_group = (TG), .timer_idx = (TID),}
static timer_info_t timer_info[4] = {
TIMER_INFO_INIT(TIMER_GROUP_0, TIMER_0),
TIMER_INFO_INIT(TIMER_GROUP_0, TIMER_1),
TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_0),
TIMER_INFO_INIT(TIMER_GROUP_1, TIMER_1),
};
#define GET_TIMER_INFO(TG, TID) (&timer_info[(TG)*2+(TID)])
// timer group interruption
static void test_timer_group_isr(void *para)
{
int timer_idx = (int) para;
timer_info_t* info = (timer_info_t*) para;
const timer_group_t timer_group = info->timer_group;
const timer_idx_t timer_idx = info->timer_idx;
uint64_t timer_val;
double time;
uint64_t alarm_value;
alarm_flag = true;
if (TIMERG1.hw_timer[timer_idx].config.autoreload == 1) {
if (timer_idx == 0) {
TIMERG1.int_clr_timers.t0 = 1;
} else {
TIMERG1.int_clr_timers.t1 = 1;
}
ets_printf("This is TG1 timer[%d] reload-timer alarm!\n", timer_idx);
timer_get_counter_value(TIMER_GROUP_1, timer_idx, &timer_val);
timer_get_counter_time_sec(TIMER_GROUP_1, timer_idx, &time);
if (timer_group_get_auto_reload_in_isr(timer_group, timer_idx)) {
timer_group_intr_clr_in_isr(timer_group, timer_idx);
ets_printf("This is TG%d timer[%d] reload-timer alarm!\n", timer_group, timer_idx);
timer_get_counter_value(timer_group, timer_idx, &timer_val);
timer_get_counter_time_sec(timer_group, timer_idx, &time);
ets_printf("time: %.8f S\n", time);
} else {
if (timer_idx == 0) {
TIMERG1.int_clr_timers.t0 = 1;
} else {
TIMERG1.int_clr_timers.t1 = 1;
}
ets_printf("This is TG1 timer[%d] count-up-timer alarm!\n", timer_idx);
timer_get_counter_value(TIMER_GROUP_1, timer_idx, &timer_val);
timer_get_counter_time_sec(TIMER_GROUP_1, timer_idx, &time);
timer_get_alarm_value(TIMER_GROUP_1, timer_idx, &alarm_value);
timer_group_intr_clr_in_isr(timer_group, timer_idx);
ets_printf("This is TG%d timer[%d] count-up-timer alarm!\n", timer_group, timer_idx);
timer_get_counter_value(timer_group, timer_idx, &timer_val);
timer_get_counter_time_sec(timer_group, timer_idx, &time);
timer_get_alarm_value(timer_group, timer_idx, &alarm_value);
ets_printf("time: %.8f S\n", time);
double alarm_time = (double) alarm_value / TIMER_SCALE;
ets_printf("alarm_time: %.8f S\n", alarm_time);
@ -86,13 +62,7 @@ static void tg_timer_init(int timer_group, int timer_idx, double alarm_time)
timer_set_counter_value(timer_group, timer_idx, 0x0);
timer_set_alarm_value(timer_group, timer_idx, alarm_time * TIMER_SCALE);
timer_enable_intr(timer_group, timer_idx);
if (timer_group == 0) {
timer_isr_register(timer_group, timer_idx, test_timer_group0_isr,
(void *) timer_idx, ESP_INTR_FLAG_LOWMED, NULL);
} else {
timer_isr_register(timer_group, timer_idx, test_timer_group1_isr,
(void *) timer_idx, ESP_INTR_FLAG_LOWMED, NULL);
}
timer_isr_register(timer_group, timer_idx, test_timer_group_isr, GET_TIMER_INFO(timer_group, timer_idx), ESP_INTR_FLAG_LOWMED, NULL);
timer_start(timer_group, timer_idx);
}
@ -747,8 +717,8 @@ TEST_CASE("Timer enable timer interrupt", "[hw_timer]")
// enable timer_intr0
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val);
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1.2 * TIMER_SCALE);
timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr,
(void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL);
timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group_isr,
GET_TIMER_INFO(TIMER_GROUP_0, TIMER_0), ESP_INTR_FLAG_LOWMED, NULL);
timer_start(TIMER_GROUP_0, TIMER_0);
vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT(alarm_flag == true)
@ -765,8 +735,8 @@ TEST_CASE("Timer enable timer interrupt", "[hw_timer]")
// enable timer_intr1
timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val);
timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE);
timer_isr_register(TIMER_GROUP_1, TIMER_1, test_timer_group1_isr,
(void *) TIMER_1, ESP_INTR_FLAG_LOWMED, NULL);
timer_isr_register(TIMER_GROUP_1, TIMER_1, test_timer_group_isr,
GET_TIMER_INFO(TIMER_GROUP_1, TIMER_1), ESP_INTR_FLAG_LOWMED, NULL);
timer_start(TIMER_GROUP_1, TIMER_1);
vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT(alarm_flag == true)
@ -813,23 +783,21 @@ TEST_CASE("Timer enable timer group interrupt", "[hw_timer][ignore]")
all_timer_set_alarm_value(1.2);
// enable timer group
timer_group_intr_enable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M);
timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr,
(void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL);
timer_group_intr_enable(TIMER_GROUP_0, TIMER_INTR_T0);
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);
timer_start(TIMER_GROUP_0, TIMER_0);
vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT(alarm_flag == true);
//test enable auto_reload
alarm_flag = false;
timer_group_intr_disable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M);
timer_group_intr_disable(TIMER_GROUP_0, TIMER_INTR_T0);
timer_start(TIMER_GROUP_0, TIMER_0);
vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT(alarm_flag == false);
timer_group_intr_enable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M);
timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr,
(void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL);
timer_group_intr_enable(TIMER_GROUP_0, TIMER_INTR_T0);
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);
timer_start(TIMER_GROUP_0, TIMER_0);
vTaskDelay(2000 / portTICK_PERIOD_MS);
TEST_ASSERT(alarm_flag == true);

View file

@ -19,6 +19,7 @@
#include "freertos/xtensa_api.h"
#include "driver/timer.h"
#include "driver/periph_ctrl.h"
#include "hal/timer_ll.h"
static const char* TIMER_TAG = "timer_group";
#define TIMER_CHECK(a, str, ret_val) \
@ -35,7 +36,7 @@ static const char* TIMER_TAG = "timer_group";
#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"
static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
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);
@ -171,7 +172,7 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
return ESP_OK;
}
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
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)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
@ -253,7 +254,7 @@ esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer
return ESP_OK;
}
esp_err_t timer_group_intr_enable(timer_group_t group_num, uint32_t en_mask)
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]);
@ -262,7 +263,7 @@ esp_err_t timer_group_intr_enable(timer_group_t group_num, uint32_t en_mask)
return ESP_OK;
}
esp_err_t timer_group_intr_disable(timer_group_t group_num, uint32_t disable_mask)
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]);
@ -275,14 +276,54 @@ 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, BIT(timer_num));
return timer_group_intr_enable(group_num, TIMER_LL_GET_INTR(timer_num));
}
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, BIT(timer_num));
return timer_group_intr_disable(group_num, TIMER_LL_GET_INTR(timer_num));
}
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]);
}
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));
}
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);
}
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);
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);
}
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);
}
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);
}
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);
}

View file

@ -34,6 +34,9 @@
// Forces data to be placed to DMA-capable places
#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR
// Forces a function to be inlined
#define FORCE_INLINE_ATTR static inline __attribute__((always_inline))
// Forces a string into DRAM instead of flash
// Use as ets_printf(DRAM_STR("Hello world!\n"));
#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;}))
@ -45,7 +48,7 @@
// Forces bss variable into external memory. "
#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__)
#else
#define EXT_RAM_ATTR
#define EXT_RAM_ATTR
#endif
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
@ -73,6 +76,30 @@
// Forces to not inline function
#define NOINLINE_ATTR __attribute__((noinline))
// This allows using enum as flags in C++
// Format: FLAG_ATTR(flag_enum_t)
#ifdef __cplusplus
#define FLAG_ATTR_IMPL(TYPE, INT_TYPE) \
constexpr TYPE operator~ (TYPE a) { return (TYPE)~(INT_TYPE)a; } \
constexpr TYPE operator| (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a | (INT_TYPE)b); } \
constexpr TYPE operator& (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a & (INT_TYPE)b); } \
constexpr TYPE operator^ (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a ^ (INT_TYPE)b); } \
constexpr TYPE operator>> (TYPE a, int b) { return (TYPE)((INT_TYPE)a >> b); } \
constexpr TYPE operator<< (TYPE a, int b) { return (TYPE)((INT_TYPE)a << b); } \
TYPE& operator|=(TYPE& a, TYPE b) { a = a | b; return a; } \
TYPE& operator&=(TYPE& a, TYPE b) { a = a & b; return a; } \
TYPE& operator^=(TYPE& a, TYPE b) { a = a ^ b; return a; } \
TYPE& operator>>=(TYPE& a, int b) { a >>= b; return a; } \
TYPE& operator<<=(TYPE& a, int b) { a <<= b; return a; }
#define FLAG_ATTR_U32(TYPE) FLAG_ATTR_IMPL(TYPE, uint32_t)
#define FLAG_ATTR FLAG_ATTR_U32
#else
#define FLAG_ATTR(TYPE)
#endif
// Implementation for a unique custom section
//
// This prevents gcc producing "x causes a section type conflict with y"

View file

@ -30,10 +30,11 @@
#include "driver/timer.h"
#include "driver/periph_ctrl.h"
#include "esp_int_wdt.h"
#include "hal/timer_ll.h"
#if CONFIG_ESP_INT_WDT
#define TG1_WDT_TICK_US 500
#define WDT_INT_NUM 24
@ -48,11 +49,15 @@ static void IRAM_ATTR tick_hook(void) {
} else {
//Only feed wdt if app cpu also ticked.
if (int_wdt_app_cpu_ticked) {
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_config2=CONFIG_ESP_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt
TIMERG1.wdt_config3=CONFIG_ESP_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset
TIMERG1.wdt_feed=1;
TIMERG1.wdt_wprotect=0;
timer_ll_wdt_set_protect(&TIMERG1, false);
//Set timeout before interrupt
timer_ll_wdt_set_timeout(&TIMERG1, 0,
CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/TG1_WDT_TICK_US);
//Set timeout before reset
timer_ll_wdt_set_timeout(&TIMERG1, 1,
2*CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/TG1_WDT_TICK_US);
timer_ll_wdt_feed(&TIMERG1);
timer_ll_wdt_set_protect(&TIMERG1, true);
int_wdt_app_cpu_ticked=false;
}
}
@ -60,33 +65,36 @@ static void IRAM_ATTR tick_hook(void) {
#else
static void IRAM_ATTR tick_hook(void) {
if (xPortGetCoreID()!=0) return;
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_config2=CONFIG_ESP_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt
TIMERG1.wdt_config3=CONFIG_ESP_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset
TIMERG1.wdt_feed=1;
TIMERG1.wdt_wprotect=0;
timer_ll_wdt_set_protect(&TIMERG1, false);
//Set timeout before interrupt
timer_ll_wdt_set_timeout(&TIMERG1, 0, CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/TG1_WDT_TICK_US);
//Set timeout before reset
timer_ll_wdt_set_timeout(&TIMERG1, 1, 2*CONFIG_ESP_INT_WDT_TIMEOUT_MS*1000/TG1_WDT_TICK_US);
timer_ll_wdt_feed(&TIMERG1);
timer_ll_wdt_set_protect(&TIMERG1, true);
}
#endif
void esp_int_wdt_init(void) {
periph_module_enable(PERIPH_TIMG1_MODULE);
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_config0.sys_reset_length=7; //3.2uS
TIMERG1.wdt_config0.cpu_reset_length=7; //3.2uS
TIMERG1.wdt_config0.level_int_en=1;
TIMERG1.wdt_config0.stg0=TIMG_WDT_STG_SEL_INT; //1st stage timeout: interrupt
TIMERG1.wdt_config0.stg1=TIMG_WDT_STG_SEL_RESET_SYSTEM; //2nd stage timeout: reset system
TIMERG1.wdt_config1.clk_prescale=80*500; //Prescaler: wdt counts in ticks of 0.5mS
//The timer configs initially are set to 5 seconds, to make sure the CPU can start up. The tick hook sets
//it to their actual value.
TIMERG1.wdt_config2=10000;
TIMERG1.wdt_config3=10000;
TIMERG1.wdt_config0.en=1;
TIMERG1.wdt_feed=1;
TIMERG1.wdt_wprotect=0;
TIMERG1.int_clr_timers.wdt=1;
timer_group_intr_enable(TIMER_GROUP_1, TIMG_WDT_INT_ENA_M);
timer_ll_wdt_set_protect(&TIMERG1, false);
timer_ll_wdt_init(&TIMERG1);
timer_ll_wdt_set_tick(&TIMERG1, TG1_WDT_TICK_US); //Prescaler: wdt counts in ticks of TG1_WDT_TICK_US
//1st stage timeout: interrupt
timer_ll_wdt_set_timeout_behavior(&TIMERG1, 0, TIMER_WDT_INT);
timer_ll_wdt_set_timeout(&TIMERG1, 0, 5*1000*1000/TG1_WDT_TICK_US);
//2nd stage timeout: reset system
timer_ll_wdt_set_timeout_behavior(&TIMERG1, 1, TIMER_WDT_RESET_SYSTEM);
timer_ll_wdt_set_timeout(&TIMERG1, 1, 5*1000*1000/TG1_WDT_TICK_US);
timer_ll_wdt_set_enable(&TIMERG1, true);
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);
}
void esp_int_wdt_cpu_init(void)

View file

@ -44,6 +44,8 @@
#include "esp_private/system_internal.h"
#include "sdkconfig.h"
#include "esp_ota_ops.h"
#include "driver/timer.h"
#include "hal/timer_ll.h"
#if CONFIG_SYSVIEW_ENABLE
#include "SEGGER_RTT.h"
#endif
@ -311,7 +313,7 @@ void panicHandler(XtExcFrame *frame)
disableAllWdts();
if (frame->exccause == PANIC_RSN_INTWDT_CPU0 ||
frame->exccause == PANIC_RSN_INTWDT_CPU1) {
TIMERG1.int_clr_timers.wdt = 1;
timer_group_clr_intr_sta_in_isr(TIMER_GROUP_1, TIMER_INTR_WDT);
}
#if CONFIG_ESP32_APPTRACE_ENABLE
#if CONFIG_SYSVIEW_ENABLE
@ -401,19 +403,21 @@ static void illegal_instruction_helper(XtExcFrame *frame)
*/
static void reconfigureAllWdts(void)
{
TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed = 1;
TIMERG0.wdt_config0.sys_reset_length = 7; //3.2uS
TIMERG0.wdt_config0.cpu_reset_length = 7; //3.2uS
TIMERG0.wdt_config0.stg0 = TIMG_WDT_STG_SEL_RESET_SYSTEM; //1st stage timeout: reset system
TIMERG0.wdt_config1.clk_prescale = 80 * 500; //Prescaler: wdt counts in ticks of 0.5mS
TIMERG0.wdt_config2 = 2000; //1 second before reset
TIMERG0.wdt_config0.en = 1;
TIMERG0.wdt_wprotect = 0;
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_feed(&TIMERG0);
timer_ll_wdt_init(&TIMERG0);
timer_ll_wdt_set_tick(&TIMERG0, TG0_WDT_TICK_US); //Prescaler: wdt counts in ticks of TG0_WDT_TICK_US
//1st stage timeout: reset system
timer_ll_wdt_set_timeout_behavior(&TIMERG0, 0, TIMER_WDT_RESET_SYSTEM);
//1 second before reset
timer_ll_wdt_set_timeout(&TIMERG0, 0, 1000*1000/TG0_WDT_TICK_US);
timer_ll_wdt_set_enable(&TIMERG0, true);
timer_ll_wdt_set_protect(&TIMERG0, true);
//Disable wdt 1
TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_config0.en = 0;
TIMERG1.wdt_wprotect = 0;
timer_ll_wdt_set_protect(&TIMERG1, false);
timer_ll_wdt_set_enable(&TIMERG1, false);
timer_ll_wdt_set_protect(&TIMERG1, true);
}
/*
@ -421,12 +425,13 @@ static void reconfigureAllWdts(void)
*/
static inline void disableAllWdts(void)
{
TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_config0.en = 0;
TIMERG0.wdt_wprotect = 0;
TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_config0.en = 0;
TIMERG1.wdt_wprotect = 0;
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_set_enable(&TIMERG0, false);
timer_ll_wdt_set_protect(&TIMERG0, true);
timer_ll_wdt_set_protect(&TIMERG1, false);
timer_ll_wdt_set_enable(&TIMERG1, false);
timer_ll_wdt_set_protect(&TIMERG1, true);
}
#if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT

View file

@ -38,6 +38,7 @@
#include "esp_private/system_internal.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "hal/timer_ll.h"
static const char* TAG = "system_api";
@ -281,12 +282,13 @@ void IRAM_ATTR esp_restart_noos(void)
esp_dport_access_int_abort();
// Disable TG0/TG1 watchdogs
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_config0.en = 0;
TIMERG0.wdt_wprotect=0;
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_config0.en = 0;
TIMERG1.wdt_wprotect=0;
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_set_enable(&TIMERG0, false);
timer_ll_wdt_set_protect(&TIMERG0, true);
timer_ll_wdt_set_protect(&TIMERG1, false);
timer_ll_wdt_set_enable(&TIMERG1, false);
timer_ll_wdt_set_protect(&TIMERG1, true);
// Flush any data left in UART FIFOs
uart_tx_wait_idle(0);

View file

@ -34,6 +34,8 @@
#include "driver/periph_ctrl.h"
#include "esp_task_wdt.h"
#include "esp_private/system_internal.h"
#include "hal/timer_ll.h"
static const char *TAG = "task_wdt";
@ -107,9 +109,9 @@ static twdt_task_t *find_task_in_twdt_list(TaskHandle_t handle, bool *all_reset)
static void reset_hw_timer(void)
{
//All tasks have reset; time to reset the hardware timer.
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0;
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_feed(&TIMERG0);
timer_ll_wdt_set_protect(&TIMERG0, true);
//Clear all has_reset flags in list
for (twdt_task_t *task = twdt_config->list; task != NULL; task = task->next){
task->has_reset=false;
@ -137,11 +139,11 @@ static void task_wdt_isr(void *arg)
twdt_task_t *twdttask;
const char *cpu;
//Reset hardware timer so that 2nd stage timeout is not reached (will trigger system reset)
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0;
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_feed(&TIMERG0);
timer_ll_wdt_set_protect(&TIMERG0, true);
//Acknowledge interrupt
TIMERG0.int_clr_timers.wdt=1;
timer_group_clr_intr_sta_in_isr(TIMER_GROUP_0, TIMER_INTR_WDT);
//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
@ -198,32 +200,33 @@ esp_err_t esp_task_wdt_init(uint32_t timeout, bool panic)
//Configure hardware timer
periph_module_enable(PERIPH_TIMG0_MODULE);
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; //Disable write protection
TIMERG0.wdt_config0.sys_reset_length=7; //3.2uS
TIMERG0.wdt_config0.cpu_reset_length=7; //3.2uS
TIMERG0.wdt_config0.level_int_en=1;
TIMERG0.wdt_config0.stg0=TIMG_WDT_STG_SEL_INT; //1st stage timeout: interrupt
TIMERG0.wdt_config0.stg1=TIMG_WDT_STG_SEL_RESET_SYSTEM; //2nd stage timeout: reset system
TIMERG0.wdt_config1.clk_prescale=80*500; //Prescaler: wdt counts in ticks of 0.5mS
TIMERG0.wdt_config2=twdt_config->timeout*2000; //Set timeout before interrupt
TIMERG0.wdt_config3=twdt_config->timeout*4000; //Set timeout before reset
TIMERG0.wdt_config0.en=1;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0; //Enable write protection
}else{ //twdt_config previously initialized
timer_ll_wdt_set_protect(&TIMERG0, false); //Disable write protection
timer_ll_wdt_init(&TIMERG0);
timer_ll_wdt_set_tick(&TIMERG0, TG0_WDT_TICK_US); //Prescaler: wdt counts in ticks of TG0_WDT_TICK_US
//1st stage timeout: interrupt
timer_ll_wdt_set_timeout_behavior(&TIMERG0, 0, TIMER_WDT_INT);
timer_ll_wdt_set_timeout(&TIMERG0, 0, twdt_config->timeout*1000*1000/TG0_WDT_TICK_US);
//2nd stage timeout: reset system
timer_ll_wdt_set_timeout_behavior(&TIMERG0, 1, TIMER_WDT_RESET_SYSTEM);
timer_ll_wdt_set_timeout(&TIMERG0, 1, 2*twdt_config->timeout*1000*1000/TG0_WDT_TICK_US);
timer_ll_wdt_set_enable(&TIMERG0, true);
timer_ll_wdt_feed(&TIMERG0);
timer_ll_wdt_set_protect(&TIMERG0, true); //Enable write protection
} else { //twdt_config previously initialized
//Reconfigure task wdt
twdt_config->panic = panic;
twdt_config->timeout = timeout;
//Reconfigure hardware timer
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; //Disable write protection
TIMERG0.wdt_config0.en=0; //Disable timer
TIMERG0.wdt_config2=twdt_config->timeout*2000; //Set timeout before interrupt
TIMERG0.wdt_config3=twdt_config->timeout*4000; //Set timeout before reset
TIMERG0.wdt_config0.en=1; //Renable timer
TIMERG0.wdt_feed=1; //Reset timer
TIMERG0.wdt_wprotect=0; //Enable write protection
timer_ll_wdt_set_protect(&TIMERG0, false); //Disable write protection
timer_ll_wdt_set_enable(&TIMERG0, false); //Disable timer
//Set timeout before interrupt
timer_ll_wdt_set_timeout(&TIMERG0, 0, twdt_config->timeout*1000*1000/TG0_WDT_TICK_US);
//Set timeout before reset
timer_ll_wdt_set_timeout(&TIMERG0, 1, 2*twdt_config->timeout*1000*1000/TG0_WDT_TICK_US);
timer_ll_wdt_set_enable(&TIMERG0, true); //Renable timer
timer_ll_wdt_feed(&TIMERG0); //Reset timer
timer_ll_wdt_set_protect(&TIMERG0, true); //Enable write protection
}
portEXIT_CRITICAL(&twdt_spinlock);
return ESP_OK;
@ -238,9 +241,9 @@ esp_err_t esp_task_wdt_deinit(void)
ASSERT_EXIT_CRIT_RETURN((twdt_config->list == NULL), ESP_ERR_INVALID_STATE);
//Disable hardware timer
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; //Disable write protection
TIMERG0.wdt_config0.en=0; //Disable timer
TIMERG0.wdt_wprotect=0; //Enable write protection
timer_ll_wdt_set_protect(&TIMERG0, false); //Disable write protection
timer_ll_wdt_set_enable(&TIMERG0, false); //Disable timer
timer_ll_wdt_set_protect(&TIMERG0, true); //Enable write protection
ESP_ERROR_CHECK(esp_intr_free(twdt_config->intr_handle)); //Unregister interrupt
free(twdt_config); //Free twdt_config

View file

@ -55,24 +55,20 @@ static void timer_isr(void *arg)
int timer_idx = (int)arg;
count[timer_idx]++;
if (timer_idx==0) {
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].update=1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
}
if (timer_idx==1) {
TIMERG0.int_clr_timers.t1 = 1;
TIMERG0.hw_timer[1].update=1;
TIMERG0.hw_timer[1].config.alarm_en = 1;
timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_1);
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_1);
}
if (timer_idx==2) {
TIMERG1.int_clr_timers.t0 = 1;
TIMERG1.hw_timer[0].update=1;
TIMERG1.hw_timer[0].config.alarm_en = 1;
timer_group_intr_clr_in_isr(TIMER_GROUP_1, TIMER_0);
timer_group_enable_alarm_in_isr(TIMER_GROUP_1, TIMER_0);
}
if (timer_idx==3) {
TIMERG1.int_clr_timers.t1 = 1;
TIMERG1.hw_timer[1].update=1;
TIMERG1.hw_timer[1].config.alarm_en = 1;
timer_group_intr_clr_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);
}
@ -280,7 +276,7 @@ TEST_CASE("allocate 2 handlers for a same source and remove the later one","[esp
r=esp_intr_alloc(ETS_SPI2_INTR_SOURCE, ESP_INTR_FLAG_SHARED, int_handler2, &ctx, &handle2);
TEST_ESP_OK(r);
SPI2.slave.trans_inten = 1;
printf("trigger first time.\n");
SPI2.slave.trans_done = 1;

View file

@ -280,11 +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( !TIMERG0.int_raw.t0 && loop_cnt++ < 100) {
while( !(timer_group_intr_get_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_EQUAL(1, TIMERG0.int_raw.t0);
TEST_ASSERT(timer_group_intr_get_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0);
esp_restart();
}

View file

@ -20,6 +20,8 @@ extern "C" {
#include "esp_system.h"
#define TG0_WDT_TICK_US 500
/**
* @brief Internal function to restart PRO and APP CPUs.
*

View file

@ -30,14 +30,14 @@ static const char* TAG = "test_event";
#define TEST_CONFIG_WAIT_MULTIPLIER 5
// The initial logging "initializing test" is to ensure mutex allocation is not counted against memory not being freed
// during teardown.
// The initial logging "initializing test" is to ensure mutex allocation is not counted against memory not being freed
// during teardown.
#define TEST_SETUP() \
ESP_LOGI(TAG, "initializing test"); \
size_t free_mem_before = heap_caps_get_free_size(MALLOC_CAP_DEFAULT); \
test_setup(); \
s_test_core_id = xPortGetCoreID(); \
s_test_priority = uxTaskPriorityGet(NULL);
s_test_priority = uxTaskPriorityGet(NULL);
#define TEST_TEARDOWN() \
test_teardown(); \
@ -294,15 +294,11 @@ void IRAM_ATTR test_event_on_timer_alarm(void* para)
{
/* Retrieve the interrupt status and the counter value
from the timer that reported the interrupt */
TIMERG0.hw_timer[TIMER_0].update = 1;
uint64_t timer_counter_value =
((uint64_t) TIMERG0.hw_timer[TIMER_0].cnt_high) << 32
| TIMERG0.hw_timer[TIMER_0].cnt_low;
TIMERG0.int_clr_timers.t0 = 1;
timer_group_get_counter_value_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0);
timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
TIMERG0.hw_timer[TIMER_0].alarm_high = (uint32_t) (timer_counter_value >> 32);
TIMERG0.hw_timer[TIMER_0].alarm_low = (uint32_t) timer_counter_value;
timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, TIMER_0, timer_counter_value);
int data = (int) para;
// Posting events with data more than 4 bytes should fail.

View file

@ -356,8 +356,8 @@ static int iterations;
static void ringbuffer_isr(void *arg)
{
//Clear timer interrupt
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[xPortGetCoreID()].config.alarm_en = 1;
timer_group_intr_clr_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
if (buf_type < NO_OF_RB_TYPES) {

View file

@ -64,19 +64,15 @@
static const USHORT usTimerIndex = CONFIG_FMB_TIMER_INDEX; // Modbus Timer index used by stack
static const USHORT usTimerGroupIndex = CONFIG_FMB_TIMER_GROUP; // Modbus Timer group index used by stack
static timg_dev_t *MB_TG[2] = {&TIMERG0, &TIMERG1};
/* ----------------------- Start implementation -----------------------------*/
static void IRAM_ATTR vTimerGroupIsr(void *param)
{
// Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st_timers.val;
if (intr_status & BIT(usTimerIndex)) {
MB_TG[usTimerGroupIndex]->int_clr_timers.val |= BIT(usTimerIndex);
(void)pxMBPortCBTimerExpired(); // Timer callback function
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].config.alarm_en = TIMER_ALARM_EN;
}
assert((int)param == usTimerIndex);
// Retrieve the counter value from the timer that reported the interrupt
timer_group_intr_clr_in_isr(usTimerGroupIndex, usTimerIndex);
(void)pxMBPortCBTimerExpired(); // Timer callback function
// Enable alarm
timer_group_enable_alarm_in_isr(usTimerGroupIndex, usTimerIndex);
}
#endif
@ -113,7 +109,7 @@ BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
"failure to set alarm failure, timer_set_alarm_value() returned (0x%x).",
(uint32_t)xErr);
// Register ISR for timer
xErr = timer_isr_register(usTimerGroupIndex, usTimerIndex, vTimerGroupIsr, NULL, ESP_INTR_FLAG_IRAM, NULL);
xErr = timer_isr_register(usTimerGroupIndex, usTimerIndex, vTimerGroupIsr, (void*)(uint32_t)usTimerIndex, ESP_INTR_FLAG_IRAM, NULL);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"timer set value failure, timer_isr_register() returned (0x%x).",
(uint32_t)xErr);

View file

@ -61,22 +61,16 @@ static USHORT usT35TimeOut50us;
static const USHORT usTimerIndex = MB_TIMER_INDEX; // Initialize Modbus Timer index used by stack,
static const USHORT usTimerGroupIndex = MB_TIMER_GROUP; // Timer group index used by stack
static timg_dev_t *MB_TG[2] = { &TIMERG0, &TIMERG1 };
/* ----------------------- static functions ---------------------------------*/
static void IRAM_ATTR vTimerGroupIsr(void *param)
{
// Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st_timers.val;
if (intr_status & BIT(usTimerIndex)) {
MB_TG[usTimerGroupIndex]->int_clr_timers.val |= BIT(usTimerIndex);
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].update = 1;
(void)pxMBMasterPortCBTimerExpired(); // Timer expired callback function
// Enable alarm
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].config.alarm_en = TIMER_ALARM_EN;
}
assert((int)param == usTimerIndex);
// Retrieve the the counter value from the timer that reported the interrupt
timer_group_intr_clr_in_isr(usTimerGroupIndex, usTimerIndex);
(void)pxMBMasterPortCBTimerExpired(); // Timer expired callback function
// Enable alarm
timer_group_enable_alarm_in_isr(usTimerGroupIndex, usTimerIndex);
}
/* ----------------------- Start implementation -----------------------------*/
@ -115,7 +109,7 @@ BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
(uint32_t)xErr);
// Register ISR for timer
xErr = timer_isr_register(usTimerGroupIndex, usTimerIndex,
vTimerGroupIsr, NULL, ESP_INTR_FLAG_IRAM, NULL);
vTimerGroupIsr, (void*)(uint32_t)usTimerIndex, ESP_INTR_FLAG_IRAM, NULL);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"timer set value failure, timer_isr_register() returned (0x%x).",
(uint32_t)xErr);

View file

@ -138,8 +138,8 @@ static bool test_clear_bits;
static void IRAM_ATTR event_group_isr(void *arg)
{
portBASE_TYPE task_woken = pdFALSE;
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[xPortGetCoreID()].config.alarm_en = 1;
timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, xPortGetCoreID());
if(test_set_bits){
xEventGroupSetBitsFromISR(eg, BITS, &task_woken);

View file

@ -97,16 +97,10 @@ static void receiver_task (void* arg){
static void IRAM_ATTR sender_ISR (void *arg)
{
int curcore = xPortGetCoreID();
if(curcore == 0){ //Clear timer interrupt
//Clear intr and pause via direct reg access as IRAM ISR cannot access timer APIs
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].config.enable = 0;
}else{
TIMERG0.int_clr_timers.t1 = 1;
TIMERG0.hw_timer[1].config.enable = 0;
}
timer_group_intr_clr_in_isr(TIMER_GROUP_0, curcore);
timer_group_set_counter_enable_in_isr(TIMER_GROUP_0, curcore, TIMER_PAUSE);
//Re-enable alarm
TIMERG0.hw_timer[curcore].config.alarm_en = 1;
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, curcore);
if(isr_give){ //Test vTaskNotifyGiveFromISR() on same core
notifs_sent++;

View file

@ -20,9 +20,8 @@ static volatile unsigned isr_count;
mutex semaphore to wake up another counter task */
static void timer_group0_isr(void *vp_arg)
{
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[TIMER_0].update = 1;
TIMERG0.hw_timer[TIMER_0].config.alarm_en = 1;
timer_group_intr_clr_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++;
xSemaphoreGiveFromISR(isr_semaphore, &higher_awoken);

View file

@ -118,7 +118,7 @@ volatile bool timer_isr_fired;
void IRAM_ATTR timer_group0_isr(void *vp_arg)
{
// Clear interrupt
TIMERG0.int_clr_timers.val = TIMERG0.int_st_timers.val;
timer_group_clr_intr_sta_in_isr(TIMER_GROUP_0, TIMER_0|TIMER_1);
timer_isr_fired = true;
TaskHandle_t handle = vp_arg;

View file

@ -0,0 +1,285 @@
// Copyright 2015-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.
// The LL layer for Timer Group register operations.
// Note that most of the register operations in this layer are non-atomic operations.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#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");
/**
* @brief Enable timer interrupt.
*
* @param hw Beginning address of the peripheral registers.
* @param intr_mask Interrupt enable mask
*
* @return None
*/
static inline void timer_ll_intr_enable(timg_dev_t *hw, timer_intr_t intr_mask)
{
hw->int_ena.val |= intr_mask;
}
/**
* @brief Disable timer interrupt.
*
* @param hw Beginning address of the peripheral registers.
* @param intr_mask Interrupt disable mask
*
* @return None
*/
static inline void timer_ll_intr_disable(timg_dev_t *hw, timer_intr_t intr_mask)
{
hw->int_ena.val &= (~intr_mask);
}
/**
* @brief Get timer interrupt status.
*
* @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
*
* @return None
*/
static inline void timer_ll_intr_status_clear(timg_dev_t *hw, timer_intr_t intr_mask)
{
hw->int_clr_timers.val = intr_mask;
}
/**
* @brief Get counter vaule from time-base counter
*
* @param hw Beginning address of the peripheral registers.
* @param timer_num The timer number
* @param timer_val Pointer to accept the counter value
*
* @return None
*/
static inline 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 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
*
* @return None
*/
static inline void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, timer_start_t counter_en)
{
hw->hw_timer[timer_num].config.enable = counter_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
*/
static inline bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num)
{
return hw->hw_timer[timer_num].config.autoreload;
}
/**
* @brief Set the counter value to trigger the alarm.
*
* @param hw Beginning address of the peripheral registers.
* @param timer_num The timer number
* @param alarm_value Counter value to trigger the alarm
*
* @return None
*/
static inline 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;
}
/**
* @brief Get the counter value to trigger the alarm.
*
* @param hw Beginning address of the peripheral registers.
* @param timer_num The timer number
* @param alarm_value Pointer to accept the counter value to trigger the alarm
*
* @return None
*/
static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value)
{
*alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarm_high << 32) | (hw->hw_timer[timer_num].alarm_low);
}
/**
* @brief Set the alarm status, enable or disable the alarm.
*
* @param hw Beginning address of the peripheral registers.
* @param timer_num The timer number
* @param alarm_en true to enable, false to disable
*
* @return None
*/
static inline 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;
}
/**
* @brief Get the alarm status.
*
* @param hw Beginning address of the peripheral registers.
* @param timer_num The timer number
* @param alarm_en Pointer to accept the alarm status
*
* @return None
*/
static inline void timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool *alarm_en)
{
*alarm_en = hw->hw_timer[timer_num].config.alarm_en;
}
/* WDT operations */
/**
* 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.
*
* @param hw Beginning address of the peripheral registers.
*
* @note Call ``timer_ll_wdt_set_protect first``
*/
FORCE_INLINE_ATTR void timer_ll_wdt_init(timg_dev_t* hw)
{
hw->wdt_config0.sys_reset_length=7; //3.2uS
hw->wdt_config0.cpu_reset_length=7; //3.2uS
//currently only level interrupt is supported
hw->wdt_config0.level_int_en = 1;
hw->wdt_config0.edge_int_en = 0;
}
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;
}
FORCE_INLINE_ATTR void timer_ll_wdt_feed(timg_dev_t* hw)
{
hw->wdt_feed = 1;
}
FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout(timg_dev_t* hw, int stage, uint32_t timeout_tick)
{
switch (stage) {
case 0:
hw->wdt_config2=timeout_tick;
break;
case 1:
hw->wdt_config3=timeout_tick;
break;
case 2:
hw->wdt_config4=timeout_tick;
break;
case 3:
hw->wdt_config5=timeout_tick;
break;
default:
abort();
}
}
_Static_assert(TIMER_WDT_OFF == TIMG_WDT_STG_SEL_OFF, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with the timer_wdt_behavior_t");
_Static_assert(TIMER_WDT_INT == TIMG_WDT_STG_SEL_INT, "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_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");
FORCE_INLINE_ATTR void timer_ll_wdt_set_timeout_behavior(timg_dev_t* hw, int stage, timer_wdt_behavior_t behavior)
{
switch (stage) {
case 0:
hw->wdt_config0.stg0 = behavior;
break;
case 1:
hw->wdt_config0.stg1 = behavior;
break;
case 2:
hw->wdt_config0.stg2 = behavior;
break;
case 3:
hw->wdt_config0.stg3 = behavior;
break;
default:
abort();
}
}
FORCE_INLINE_ATTR void timer_ll_wdt_set_enable(timg_dev_t* hw, bool enable)
{
hw->wdt_config0.en = enable;
}
FORCE_INLINE_ATTR void timer_ll_wdt_flashboot_en(timg_dev_t* hw, bool enable)
{
hw->wdt_config0.flashboot_mod_en = enable;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,67 @@
// Copyright 2015-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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <esp_bit_defs.h>
/**
* @brief Select a hardware timer from timer groups
*/
typedef enum {
TIMER_0 = 0, /*!<Select timer0 of GROUPx*/
TIMER_1 = 1, /*!<Select timer1 of GROUPx*/
TIMER_MAX,
} timer_idx_t;
/**
* @brief Decides whether timer is on or paused
*/
typedef enum {
TIMER_PAUSE = 0, /*!<Pause timer counter*/
TIMER_START = 1, /*!<Start timer counter*/
} timer_start_t;
/**
* @brief Interrupt types of the timer.
*/
//this is compatible with the value of esp32.
typedef enum {
TIMER_INTR_T0 = BIT(0), /*!< interrupt of timer 0 */
TIMER_INTR_T1 = BIT(1), /*!< interrupt of timer 1 */
TIMER_INTR_WDT = BIT(2), /*!< interrupt of watchdog */
} timer_intr_t;
FLAG_ATTR(timer_intr_t)
/**
* @brief Behavior of the watchdog if a stage times out.
*/
//this is compatible with the value of esp32.
typedef enum {
TIMER_WDT_OFF = 0, ///< The stage is turned off
TIMER_WDT_INT = 1, ///< The stage will trigger an interrupt
TIMER_WDT_RESET_CPU = 2, ///< The stage will reset the CPU
TIMER_WDT_RESET_SYSTEM = 3, ///< The stage will reset the whole system
} timer_wdt_behavior_t;
#ifdef __cplusplus
}
#endif

View file

@ -108,8 +108,8 @@ typedef struct {
static void IRAM_ATTR timer_isr(void* varg) {
block_task_arg_t* arg = (block_task_arg_t*) varg;
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
timer_group_intr_clr_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++;
}

View file

@ -60,11 +60,8 @@ void IRAM_ATTR timer_group0_isr(void *para)
/* Retrieve the interrupt status and the counter value
from the timer that reported the interrupt */
uint32_t intr_status = TIMERG0.int_st_timers.val;
TIMERG0.hw_timer[timer_idx].update = 1;
uint64_t timer_counter_value =
((uint64_t) TIMERG0.hw_timer[timer_idx].cnt_high) << 32
| TIMERG0.hw_timer[timer_idx].cnt_low;
timer_intr_t timer_intr = timer_group_intr_get_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
that will be then sent back to the main program task */
@ -75,22 +72,21 @@ void IRAM_ATTR timer_group0_isr(void *para)
/* Clear the interrupt
and update the alarm time for the timer with without reload */
if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_0) {
if (timer_intr & TIMER_INTR_T0) {
evt.type = TEST_WITHOUT_RELOAD;
TIMERG0.int_clr_timers.t0 = 1;
timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0);
timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
TIMERG0.hw_timer[timer_idx].alarm_high = (uint32_t) (timer_counter_value >> 32);
TIMERG0.hw_timer[timer_idx].alarm_low = (uint32_t) timer_counter_value;
} else if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_1) {
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;
TIMERG0.int_clr_timers.t1 = 1;
timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_1);
} else {
evt.type = -1; // not supported even type
}
/* After the alarm has been triggered
we need enable it again, so it is triggered the next time */
TIMERG0.hw_timer[timer_idx].config.alarm_en = TIMER_ALARM_EN;
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, timer_idx);
/* Now just send the event data back to the main program task */
xQueueSendFromISR(timer_queue, &evt, NULL);
@ -103,7 +99,7 @@ void IRAM_ATTR timer_group0_isr(void *para)
* auto_reload - should the timer auto reload on alarm?
* timer_interval_sec - the interval of alarm to set
*/
static void example_tg0_timer_init(int timer_idx,
static void example_tg0_timer_init(int timer_idx,
bool auto_reload, double timer_interval_sec)
{
/* Select and initialize basic parameters of the timer */
@ -123,7 +119,7 @@ static void example_tg0_timer_init(int timer_idx,
/* Configure the alarm value and the interrupt on alarm. */
timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE);
timer_enable_intr(TIMER_GROUP_0, timer_idx);
timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr,
timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr,
(void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
timer_start(TIMER_GROUP_0, timer_idx);

View file

@ -107,32 +107,6 @@ static void example_timer_init(int timer_group, int timer_idx, uint32_t period)
timer_enable_intr(timer_group, timer_idx);
}
static void example_timer_rearm(int timer_group, int timer_idx)
{
if (timer_group == 0) {
if (timer_idx == 0) {
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].update = 1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG0.int_clr_timers.t1 = 1;
TIMERG0.hw_timer[1].update = 1;
TIMERG0.hw_timer[1].config.alarm_en = 1;
}
}
if (timer_group == 1) {
if (timer_idx == 0) {
TIMERG1.int_clr_timers.t0 = 1;
TIMERG1.hw_timer[0].update = 1;
TIMERG1.hw_timer[0].config.alarm_en = 1;
} else {
TIMERG1.int_clr_timers.t1 = 1;
TIMERG1.hw_timer[1].update = 1;
TIMERG1.hw_timer[1].config.alarm_en = 1;
}
}
}
static void example_timer_isr(void *arg)
{
example_event_data_t *tim_arg = (example_event_data_t *)arg;
@ -152,7 +126,8 @@ static void example_timer_isr(void *arg)
}
}
// re-start timer
example_timer_rearm(tim_arg->group, tim_arg->timer);
timer_group_intr_clr_in_isr(tim_arg->group, tim_arg->timer);
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->timer);
}
static void example_task(void *p)