mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
timer_group: support interrupt LL and some utility functions in ISR
This commit is contained in:
parent
a97fe5615f
commit
c02981a99b
@ -246,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
|
||||
@ -258,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.
|
||||
@ -284,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
|
||||
*
|
||||
@ -329,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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -24,6 +24,65 @@ extern "C" {
|
||||
#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
|
||||
@ -40,8 +99,6 @@ static inline void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_
|
||||
*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.
|
||||
*
|
||||
@ -56,7 +113,6 @@ static inline void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer
|
||||
hw->hw_timer[timer_num].config.enable = counter_en;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get auto reload mode.
|
||||
*
|
||||
|
@ -20,6 +20,8 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <esp_bit_defs.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Select a hardware timer from timer groups
|
||||
@ -39,6 +41,16 @@ typedef enum {
|
||||
} 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;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user