Merge branch 'bugfix/timer_group_intr_enable_v4.1' into 'release/v4.1'

fix timer group intr enable (backport v4.1)

See merge request espressif/esp-idf!8529
This commit is contained in:
Michael (XIAO Xufeng) 2020-05-08 14:57:20 +08:00
commit f14cdd5d3a
11 changed files with 89 additions and 61 deletions

View file

@ -19,7 +19,7 @@
#include "driver/gpio.h" #include "driver/gpio.h"
#include "hal/sigmadelta_types.h" #include "hal/sigmadelta_types.h"
#ifdef _cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -81,6 +81,6 @@ esp_err_t sigmadelta_set_prescale(sigmadelta_channel_t channel, uint8_t prescale
*/ */
esp_err_t sigmadelta_set_pin(sigmadelta_channel_t channel, gpio_num_t gpio_num); esp_err_t sigmadelta_set_pin(sigmadelta_channel_t channel, gpio_num_t gpio_num);
#ifdef _cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -80,7 +80,7 @@ esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_
uint64_t timer_val; uint64_t timer_val;
esp_err_t err = timer_get_counter_value(group_num, timer_num, &timer_val); esp_err_t err = timer_get_counter_value(group_num, timer_num, &timer_val);
if (err == ESP_OK) { if (err == ESP_OK) {
uint16_t div; uint32_t div;
timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div); timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div);
*time = (double)timer_val * div / rtc_clk_apb_freq_get(); *time = (double)timer_val * div / rtc_clk_apb_freq_get();
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK #ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK
@ -262,7 +262,7 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
int intr_source = 0; int intr_source = 0;
uint32_t status_reg = 0; uint32_t status_reg = 0;
int mask = 0; uint32_t mask = 0;
switch (group_num) { switch (group_num) {
case TIMER_GROUP_0: case TIMER_GROUP_0:
default: default:
@ -271,8 +271,7 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
} else { } else {
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num; intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
} }
timer_hal_get_intr_status_reg(&(p_timer_obj[TIMER_GROUP_0][timer_num]->hal), &status_reg); timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_0][timer_num]->hal), &status_reg, &mask);
mask = 1 << timer_num;
break; break;
case TIMER_GROUP_1: case TIMER_GROUP_1:
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) { if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
@ -280,8 +279,7 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
} else { } else {
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num; 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); timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_1][timer_num]->hal), &status_reg, &mask);
mask = 1 << timer_num;
break; break;
} }
return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle); return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle);
@ -363,13 +361,9 @@ esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer
config->counter_dir = timer_hal_get_counter_increase(&(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)); config->counter_en = timer_hal_get_counter_enable(&(p_timer_obj[group_num][timer_num]->hal));
uint16_t div; uint32_t div;
timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div); timer_hal_get_divider(&(p_timer_obj[group_num][timer_num]->hal), &div);
if (div == 0) { config->divider = div;
config->divider = 65536;
} else {
config->divider = div;
}
if (timer_hal_get_level_int_enable(&(p_timer_obj[group_num][timer_num]->hal))) { if (timer_hal_get_level_int_enable(&(p_timer_obj[group_num][timer_num]->hal))) {
config->intr_type = TIMER_INTR_LEVEL; config->intr_type = TIMER_INTR_LEVEL;

View file

@ -24,7 +24,7 @@
#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS #ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS
#include "soc/gpio_reg.h" #include "soc/gpio_reg.h"
#include "soc/gpio_pins.h" #include "soc/gpio_caps.h"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -113,6 +113,7 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
// When we resume scheduler, we expect the counter task // When we resume scheduler, we expect the counter task
// will preempt and count at least one more item // will preempt and count at least one more item
esp_intr_noniram_enable(); esp_intr_noniram_enable();
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
xTaskResumeAll(); xTaskResumeAll();
TEST_ASSERT_NOT_EQUAL(count_config.counter, no_sched_task); TEST_ASSERT_NOT_EQUAL(count_config.counter, no_sched_task);

View file

@ -29,11 +29,6 @@ _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt ha
_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_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"); _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 // Get timer group instance with giving group number
#define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1)) #define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1))
@ -42,12 +37,18 @@ typedef struct {
* *
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param timer_num The timer number * @param timer_num The timer number
* @param divider Prescale value * @param divider Prescale value (0 and 1 are not valid)
* *
* @return None * @return None
*/ */
static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t divider) static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t divider)
{ {
// refer to TRM 18.2.1
if (divider == 65536) {
divider = 0;
} else if (divider == 1) {
divider = 2;
}
int timer_en = hw->hw_timer[timer_num].config.enable; int timer_en = hw->hw_timer[timer_num].config.enable;
hw->hw_timer[timer_num].config.enable = 0; hw->hw_timer[timer_num].config.enable = 0;
hw->hw_timer[timer_num].config.divider = divider; hw->hw_timer[timer_num].config.divider = divider;
@ -63,9 +64,15 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u
* *
* @return None * @return None
*/ */
static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t *divider) static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider)
{ {
*divider = hw->hw_timer[timer_num].config.divider; uint32_t d = hw->hw_timer[timer_num].config.divider;
if (d == 0) {
d = 65536;
} else if (d == 1) {
d = 2;
}
*divider = d;
} }
/** /**
@ -255,6 +262,7 @@ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_n
FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num) FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num)
{ {
hw->int_ena.val |= BIT(timer_num); hw->int_ena.val |= BIT(timer_num);
hw->hw_timer[timer_num].config.level_int_en = 1;
} }
/** /**
@ -268,6 +276,7 @@ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_nu
FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num) FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num)
{ {
hw->int_ena.val &= (~BIT(timer_num)); hw->int_ena.val &= (~BIT(timer_num));
hw->hw_timer[timer_num].config.level_int_en = 0;
} }
/** /**
@ -372,13 +381,17 @@ static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t time
* @brief Get interrupt status register address. * @brief Get interrupt status register address.
* *
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param intr_status_reg Interrupt status register address
* *
* @return None * @return Interrupt status register address
*/ */
static inline void timer_ll_get_intr_status_reg(timg_dev_t *hw, uint32_t *intr_status_reg) static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw)
{ {
*intr_status_reg = (uint32_t)&(hw->int_st_timers.val); return (uint32_t) & (hw->int_st_timers.val);
}
static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num)
{
return (1U << timer_num);
} }
/* WDT operations */ /* WDT operations */

View file

@ -29,11 +29,6 @@ _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt ha
_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_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"); _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 // Get timer group instance with giving group number
#define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1)) #define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1))
@ -42,12 +37,16 @@ typedef struct {
* *
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param timer_num The timer number * @param timer_num The timer number
* @param divider Prescale value * @param divider Prescale value (0 is not valid)
* *
* @return None * @return None
*/ */
static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t divider) static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t divider)
{ {
// refer to TRM 12.2.1
if (divider == 65536) {
divider = 0;
}
int timer_en = hw->hw_timer[timer_num].config.enable; int timer_en = hw->hw_timer[timer_num].config.enable;
hw->hw_timer[timer_num].config.enable = 0; hw->hw_timer[timer_num].config.enable = 0;
hw->hw_timer[timer_num].config.divider = divider; hw->hw_timer[timer_num].config.divider = divider;
@ -63,9 +62,13 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u
* *
* @return None * @return None
*/ */
static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t *divider) static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider)
{ {
*divider = hw->hw_timer[timer_num].config.divider; uint32_t d = hw->hw_timer[timer_num].config.divider;
if (d == 0) {
d = 65536;
}
*divider = d;
} }
/** /**
@ -255,6 +258,7 @@ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_n
FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num) FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num)
{ {
hw->int_ena.val |= BIT(timer_num); hw->int_ena.val |= BIT(timer_num);
hw->hw_timer[timer_num].config.level_int_en = 1;
} }
/** /**
@ -268,6 +272,7 @@ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_nu
FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num) FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num)
{ {
hw->int_ena.val &= (~BIT(timer_num)); hw->int_ena.val &= (~BIT(timer_num));
hw->hw_timer[timer_num].config.level_int_en = 0;
} }
/** /**
@ -372,13 +377,17 @@ static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t time
* @brief Get interrupt status register address. * @brief Get interrupt status register address.
* *
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param intr_status_reg Interrupt status register address
* *
* @return None * @return uint32_t Interrupt status register address
*/ */
static inline void timer_ll_get_intr_status_reg(timg_dev_t *hw, uint32_t *intr_status_reg) static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw)
{ {
*intr_status_reg = (uint32_t)&(hw->int_st.val); return (uint32_t) & (hw->int_st.val);
}
static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num)
{
return (1U << timer_num);
} }
/** /**

View file

@ -14,4 +14,4 @@
#pragma once #pragma once
#define TIMER_GROUP_SUPPORTS_XTAL_CLOCK #define SOC_TIMER_GROUP_SUPPORT_XTAL

View file

@ -50,6 +50,15 @@ typedef struct {
*/ */
void timer_hal_init(timer_hal_context_t *hal, timer_group_t group_num, timer_idx_t timer_num); void timer_hal_init(timer_hal_context_t *hal, timer_group_t group_num, timer_idx_t timer_num);
/**
* @brief Get interrupt status register address and corresponding control bits mask
*
* @param hal Context of the HAL layer
* @param status_reg[out] interrupt status register address
* @param mask_bit[out] control bits mask
*/
void timer_hal_get_status_reg_mask_bit(timer_hal_context_t *hal, uint32_t *status_reg, uint32_t *mask_bit);
/** /**
* @brief Set timer clock prescale value * @brief Set timer clock prescale value
* *
@ -288,13 +297,12 @@ void timer_hal_init(timer_hal_context_t *hal, timer_group_t group_num, timer_idx
* @brief Get interrupt status register address. * @brief Get interrupt status register address.
* *
* @param hal Context of the HAL layer * @param hal Context of the HAL layer
* @param intr_status_reg Interrupt status register address
* *
* @return None * @return Interrupt status register address
*/ */
#define timer_hal_get_intr_status_reg(hal, intr_status_reg) timer_ll_get_intr_status_reg((hal)->dev, intr_status_reg) #define timer_hal_get_intr_status_reg(hal) timer_ll_get_intr_status_reg((hal)->dev)
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK #ifdef SOC_TIMER_GROUP_SUPPORT_XTAL
/** /**
* @brief Set clock source. * @brief Set clock source.
* *

View file

@ -108,7 +108,7 @@ typedef enum {
TIMER_AUTORELOAD_MAX, TIMER_AUTORELOAD_MAX,
} timer_autoreload_t; } timer_autoreload_t;
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK #ifdef SOC_TIMER_GROUP_SUPPORT_XTAL
/** /**
* @brief Select timer source clock. * @brief Select timer source clock.
*/ */
@ -128,7 +128,7 @@ typedef struct {
timer_count_dir_t counter_dir; /*!< Counter direction */ timer_count_dir_t counter_dir; /*!< Counter direction */
timer_autoreload_t auto_reload; /*!< Timer auto-reload */ timer_autoreload_t auto_reload; /*!< Timer auto-reload */
uint32_t divider; /*!< Counter clock divider. The divider's range is from from 2 to 65536. */ uint32_t divider; /*!< Counter clock divider. The divider's range is from from 2 to 65536. */
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK #ifdef SOC_TIMER_GROUP_SUPPORT_XTAL
timer_src_clk_t clk_src; /*!< Use XTAL as source clock. */ timer_src_clk_t clk_src; /*!< Use XTAL as source clock. */
#endif #endif
} timer_config_t; } timer_config_t;

View file

@ -20,3 +20,9 @@ void timer_hal_init(timer_hal_context_t *hal, timer_group_t group_num, timer_idx
hal->dev = TIMER_LL_GET_HW(group_num); hal->dev = TIMER_LL_GET_HW(group_num);
hal->idx = timer_num; hal->idx = timer_num;
} }
void timer_hal_get_status_reg_mask_bit(timer_hal_context_t *hal, uint32_t *status_reg, uint32_t *mask_bit)
{
*status_reg = timer_ll_get_intr_status_reg(hal->dev);
*mask_bit = timer_ll_get_intr_mask_bit(hal->dev, hal->idx);
}

View file

@ -41,7 +41,7 @@ xQueueHandle timer_queue;
static void inline print_timer_counter(uint64_t counter_value) static void inline print_timer_counter(uint64_t counter_value)
{ {
printf("Counter: 0x%08x%08x\n", (uint32_t) (counter_value >> 32), printf("Counter: 0x%08x%08x\n", (uint32_t) (counter_value >> 32),
(uint32_t) (counter_value)); (uint32_t) (counter_value));
printf("Time : %.8f s\n", (double) counter_value / TIMER_SCALE); printf("Time : %.8f s\n", (double) counter_value / TIMER_SCALE);
} }
@ -101,19 +101,16 @@ void IRAM_ATTR timer_group0_isr(void *para)
* timer_interval_sec - the interval of alarm to set * 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) bool auto_reload, double timer_interval_sec)
{ {
/* Select and initialize basic parameters of the timer */ /* Select and initialize basic parameters of the timer */
timer_config_t config; timer_config_t config = {
config.divider = TIMER_DIVIDER; .divider = TIMER_DIVIDER,
config.counter_dir = TIMER_COUNT_UP; .counter_dir = TIMER_COUNT_UP,
config.counter_en = TIMER_PAUSE; .counter_en = TIMER_PAUSE,
config.alarm_en = TIMER_ALARM_EN; .alarm_en = TIMER_ALARM_EN,
config.intr_type = TIMER_INTR_LEVEL; .auto_reload = auto_reload,
config.auto_reload = auto_reload; }; // default clock source is APB
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK
config.clk_src = TIMER_SRC_CLK_APB;
#endif
timer_init(TIMER_GROUP_0, timer_idx, &config); timer_init(TIMER_GROUP_0, timer_idx, &config);
/* Timer's counter will initially start from value below. /* Timer's counter will initially start from value below.
@ -124,7 +121,7 @@ static void example_tg0_timer_init(int timer_idx,
timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE); timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE);
timer_enable_intr(TIMER_GROUP_0, timer_idx); 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); (void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
timer_start(TIMER_GROUP_0, timer_idx); timer_start(TIMER_GROUP_0, timer_idx);
} }