mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-30 12:30:59 +02:00
Timer based od ESP-IDF (#5931)
This commit is contained in:
@ -13,335 +13,227 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "esp32-hal-timer.h"
|
#include "esp32-hal-timer.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "driver/timer.h"
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
#include "soc/soc_caps.h"
|
||||||
#include "freertos/xtensa_api.h"
|
|
||||||
#include "soc/dport_reg.h"
|
|
||||||
#endif
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "soc/timer_group_struct.h"
|
|
||||||
#include "esp_attr.h"
|
|
||||||
#include "driver/periph_ctrl.h"
|
|
||||||
|
|
||||||
#include "esp_system.h"
|
typedef union {
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
struct {
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
uint32_t reserved0: 10;
|
||||||
#include "esp32/rom/ets_sys.h"
|
uint32_t alarm_en: 1; /*When set alarm is enabled*/
|
||||||
#include "esp_intr_alloc.h"
|
uint32_t level_int_en: 1; /*When set level type interrupt will be generated during alarm*/
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
uint32_t edge_int_en: 1; /*When set edge type interrupt will be generated during alarm*/
|
||||||
#include "esp32s2/rom/ets_sys.h"
|
uint32_t divider: 16; /*Timer clock (T0/1_clk) pre-scale value.*/
|
||||||
#include "esp_intr_alloc.h"
|
uint32_t autoreload: 1; /*When set timer 0/1 auto-reload at alarming is enabled*/
|
||||||
#include "soc/periph_defs.h"
|
uint32_t increase: 1; /*When set timer 0/1 time-base counter increment. When cleared timer 0 time-base counter decrement.*/
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
uint32_t enable: 1; /*When set timer 0/1 time-base counter is enabled*/
|
||||||
#include "esp32c3/rom/ets_sys.h"
|
};
|
||||||
#include "esp_intr_alloc.h"
|
uint32_t val;
|
||||||
#include "soc/periph_defs.h"
|
} timer_cfg_t;
|
||||||
#else
|
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
|
||||||
#endif
|
|
||||||
#else // ESP32 Before IDF 4.0
|
|
||||||
#include "rom/ets_sys.h"
|
|
||||||
#include "esp_intr.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define HWTIMER_LOCK() portENTER_CRITICAL(timer->lock)
|
#define NUM_OF_TIMERS SOC_TIMER_GROUP_TOTAL_TIMERS
|
||||||
#define HWTIMER_UNLOCK() portEXIT_CRITICAL(timer->lock)
|
|
||||||
|
|
||||||
typedef volatile struct {
|
typedef struct {
|
||||||
union {
|
int timer_group;
|
||||||
struct {
|
int timer_idx;
|
||||||
uint32_t reserved0: 10;
|
int alarm_interval;
|
||||||
uint32_t alarm_en: 1; /*When set alarm is enabled*/
|
bool auto_reload;
|
||||||
uint32_t level_int_en: 1; /*When set level type interrupt will be generated during alarm*/
|
} timer_info_t;
|
||||||
uint32_t edge_int_en: 1; /*When set edge type interrupt will be generated during alarm*/
|
|
||||||
uint32_t divider: 16; /*Timer clock (T0/1_clk) pre-scale value.*/
|
|
||||||
uint32_t autoreload: 1; /*When set timer 0/1 auto-reload at alarming is enabled*/
|
|
||||||
uint32_t increase: 1; /*When set timer 0/1 time-base counter increment. When cleared timer 0 time-base counter decrement.*/
|
|
||||||
uint32_t enable: 1; /*When set timer 0/1 time-base counter is enabled*/
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} config;
|
|
||||||
uint32_t cnt_low; /*Register to store timer 0/1 time-base counter current value lower 32 bits.*/
|
|
||||||
uint32_t cnt_high; /*Register to store timer 0 time-base counter current value higher 32 bits.*/
|
|
||||||
uint32_t update; /*Write any value will trigger a timer 0 time-base counter value update (timer 0 current value will be stored in registers above)*/
|
|
||||||
uint32_t alarm_low; /*Timer 0 time-base counter value lower 32 bits that will trigger the alarm*/
|
|
||||||
uint32_t alarm_high; /*Timer 0 time-base counter value higher 32 bits that will trigger the alarm*/
|
|
||||||
uint32_t load_low; /*Lower 32 bits of the value that will load into timer 0 time-base counter*/
|
|
||||||
uint32_t load_high; /*higher 32 bits of the value that will load into timer 0 time-base counter*/
|
|
||||||
uint32_t reload; /*Write any value will trigger timer 0 time-base counter reload*/
|
|
||||||
} hw_timer_reg_t;
|
|
||||||
|
|
||||||
typedef struct hw_timer_s {
|
typedef struct hw_timer_s
|
||||||
hw_timer_reg_t * dev;
|
{
|
||||||
uint8_t num;
|
uint8_t group;
|
||||||
uint8_t group;
|
uint8_t num;
|
||||||
uint8_t timer;
|
|
||||||
portMUX_TYPE lock;
|
|
||||||
} hw_timer_t;
|
} hw_timer_t;
|
||||||
|
|
||||||
static hw_timer_t hw_timer[4] = {
|
// Works for all chips
|
||||||
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE),0,0,0,portMUX_INITIALIZER_UNLOCKED},
|
static hw_timer_t timer_dev[4] = {
|
||||||
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE + 0x0024),1,0,1,portMUX_INITIALIZER_UNLOCKED},
|
{0,0}, {1,0}, {1,0}, {1,1}
|
||||||
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE + 0x1000),2,1,0,portMUX_INITIALIZER_UNLOCKED},
|
|
||||||
{(hw_timer_reg_t *)(DR_REG_TIMERGROUP0_BASE + 0x1024),3,1,1,portMUX_INITIALIZER_UNLOCKED}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*voidFuncPtr)(void);
|
// NOTE: (in IDF 5.0 there wont be need to know groups/numbers
|
||||||
static voidFuncPtr __timerInterruptHandlers[4] = {0,0,0,0};
|
// timer_init() will list thru all timers and return free timer handle)
|
||||||
|
|
||||||
void ARDUINO_ISR_ATTR __timerISR(void * arg){
|
|
||||||
uint32_t s0 = TIMERG0.int_st_timers.val;
|
|
||||||
uint32_t s1 = TIMERG1.int_st_timers.val;
|
|
||||||
TIMERG0.int_clr_timers.val = s0;
|
|
||||||
TIMERG1.int_clr_timers.val = s1;
|
|
||||||
uint8_t status = (s1 & 3) << 2 | (s0 & 3);
|
|
||||||
uint8_t i = 4;
|
|
||||||
//restart the timers that should autoreload
|
|
||||||
while(i--){
|
|
||||||
hw_timer_reg_t * dev = hw_timer[i].dev;
|
|
||||||
if((status & (1 << i)) && dev->config.autoreload){
|
|
||||||
dev->config.alarm_en = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = 4;
|
|
||||||
//call callbacks
|
|
||||||
while(i--){
|
|
||||||
if(__timerInterruptHandlers[i] && (status & (1 << i))){
|
|
||||||
__timerInterruptHandlers[i]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t inline timerRead(hw_timer_t *timer){
|
uint64_t inline timerRead(hw_timer_t *timer){
|
||||||
timer->dev->update = 1;
|
|
||||||
while (timer->dev->update) {};
|
uint64_t value;
|
||||||
uint64_t h = timer->dev->cnt_high;
|
timer_get_counter_value(timer->group, timer->num,&value);
|
||||||
uint64_t l = timer->dev->cnt_low;
|
return value;
|
||||||
return (h << 32) | l;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t timerAlarmRead(hw_timer_t *timer){
|
uint64_t timerAlarmRead(hw_timer_t *timer){
|
||||||
uint64_t h = timer->dev->alarm_high;
|
uint64_t value;
|
||||||
uint64_t l = timer->dev->alarm_low;
|
timer_get_alarm_value(timer->group, timer->num, &value);
|
||||||
return (h << 32) | l;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerWrite(hw_timer_t *timer, uint64_t val){
|
void timerWrite(hw_timer_t *timer, uint64_t val){
|
||||||
timer->dev->load_high = (uint32_t) (val >> 32);
|
timer_set_counter_value(timer->group, timer->num, val);
|
||||||
timer->dev->load_low = (uint32_t) (val);
|
|
||||||
timer->dev->reload = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload){
|
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload){
|
||||||
timer->dev->alarm_high = (uint32_t) (alarm_value >> 32);
|
timer_set_alarm_value(timer->group, timer->num, alarm_value);
|
||||||
timer->dev->alarm_low = (uint32_t) alarm_value;
|
timerSetAutoReload(timer,autoreload);
|
||||||
timer->dev->config.autoreload = autoreload;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerSetConfig(hw_timer_t *timer, uint32_t config){
|
void timerSetConfig(hw_timer_t *timer, uint32_t config){
|
||||||
timer->dev->config.val = config;
|
timer_cfg_t cfg;
|
||||||
|
cfg.val = config;
|
||||||
|
timer_set_alarm(timer->group, timer->num, cfg.alarm_en);
|
||||||
|
timerSetDivider(timer,cfg.divider);
|
||||||
|
timerSetAutoReload(timer,cfg.autoreload);
|
||||||
|
timerSetCountUp(timer, cfg.increase);
|
||||||
|
|
||||||
|
if (cfg.enable) {
|
||||||
|
timerStart(timer);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
timerStop(timer);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t timerGetConfig(hw_timer_t *timer){
|
uint32_t timerGetConfig(hw_timer_t *timer){
|
||||||
return timer->dev->config.val;
|
timer_config_t timer_cfg;
|
||||||
|
timer_get_config(timer->group, timer->num,&timer_cfg);
|
||||||
|
|
||||||
|
//Translate to default uint32_t
|
||||||
|
timer_cfg_t cfg;
|
||||||
|
cfg.alarm_en = timer_cfg.alarm_en;
|
||||||
|
cfg.autoreload = timer_cfg.auto_reload;
|
||||||
|
cfg.divider = timer_cfg.divider;
|
||||||
|
cfg.edge_int_en = timer_cfg.intr_type;
|
||||||
|
cfg.level_int_en = !timer_cfg.intr_type;
|
||||||
|
cfg.enable = timer_cfg.counter_en;
|
||||||
|
cfg.increase = timer_cfg.counter_dir;
|
||||||
|
|
||||||
|
return cfg.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerSetCountUp(hw_timer_t *timer, bool countUp){
|
void timerSetCountUp(hw_timer_t *timer, bool countUp){
|
||||||
timer->dev->config.increase = countUp;
|
timer_set_counter_mode(timer->group, timer->num,countUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool timerGetCountUp(hw_timer_t *timer){
|
bool timerGetCountUp(hw_timer_t *timer){
|
||||||
return timer->dev->config.increase;
|
timer_cfg_t config;
|
||||||
|
config.val = timerGetConfig(timer);
|
||||||
|
return config.increase;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerSetAutoReload(hw_timer_t *timer, bool autoreload){
|
void timerSetAutoReload(hw_timer_t *timer, bool autoreload){
|
||||||
timer->dev->config.autoreload = autoreload;
|
timer_set_auto_reload(timer->group, timer->num,autoreload);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool timerGetAutoReload(hw_timer_t *timer){
|
bool timerGetAutoReload(hw_timer_t *timer){
|
||||||
return timer->dev->config.autoreload;
|
timer_cfg_t config;
|
||||||
|
config.val= timerGetConfig(timer);
|
||||||
|
return config.autoreload;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerSetDivider(hw_timer_t *timer, uint16_t divider){//2 to 65536
|
// Set divider from 2 to 65535
|
||||||
if(!divider){
|
void timerSetDivider(hw_timer_t *timer, uint16_t divider){
|
||||||
divider = 0xFFFF;
|
if(divider < 2)
|
||||||
} else if(divider == 1){
|
{
|
||||||
divider = 2;
|
log_e("Timer divider must be set in range of 2 to 65535");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
int timer_en = timer->dev->config.enable;
|
timer_set_divider(timer->group, timer->num,divider);
|
||||||
timer->dev->config.enable = 0;
|
|
||||||
timer->dev->config.divider = divider;
|
|
||||||
timer->dev->config.enable = timer_en;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t timerGetDivider(hw_timer_t *timer){
|
uint16_t timerGetDivider(hw_timer_t *timer){
|
||||||
return timer->dev->config.divider;
|
timer_cfg_t config;
|
||||||
|
config.val = timerGetConfig(timer);
|
||||||
|
return config.divider;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerStart(hw_timer_t *timer){
|
void timerStart(hw_timer_t *timer){
|
||||||
timer->dev->config.enable = 1;
|
timer_start(timer->group, timer->num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerStop(hw_timer_t *timer){
|
void timerStop(hw_timer_t *timer){
|
||||||
timer->dev->config.enable = 0;
|
timer_pause(timer->group, timer->num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerRestart(hw_timer_t *timer){
|
void timerRestart(hw_timer_t *timer){
|
||||||
timer->dev->config.enable = 0;
|
timerWrite(timer,0);
|
||||||
timer->dev->reload = 1;
|
|
||||||
timer->dev->config.enable = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool timerStarted(hw_timer_t *timer){
|
bool timerStarted(hw_timer_t *timer){
|
||||||
return timer->dev->config.enable;
|
timer_cfg_t config;
|
||||||
|
config.val = timerGetConfig(timer);
|
||||||
|
return config.enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerAlarmEnable(hw_timer_t *timer){
|
void timerAlarmEnable(hw_timer_t *timer){
|
||||||
timer->dev->config.alarm_en = 1;
|
timer_set_alarm(timer->group, timer->num,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerAlarmDisable(hw_timer_t *timer){
|
void timerAlarmDisable(hw_timer_t *timer){
|
||||||
timer->dev->config.alarm_en = 0;
|
timer_set_alarm(timer->group, timer->num,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool timerAlarmEnabled(hw_timer_t *timer){
|
bool timerAlarmEnabled(hw_timer_t *timer){
|
||||||
return timer->dev->config.alarm_en;
|
timer_cfg_t config;
|
||||||
|
config.val = timerGetConfig(timer);
|
||||||
|
return config.alarm_en;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||||
hw_timer_t * timer = (hw_timer_t *)arg;
|
hw_timer_t * timer = (hw_timer_t *)arg;
|
||||||
if(ev_type == APB_BEFORE_CHANGE){
|
if(ev_type == APB_BEFORE_CHANGE){
|
||||||
timer->dev->config.enable = 0;
|
timerStop(timer);
|
||||||
} else {
|
} else {
|
||||||
old_apb /= 1000000;
|
old_apb /= 1000000;
|
||||||
new_apb /= 1000000;
|
new_apb /= 1000000;
|
||||||
timer->dev->config.divider = (new_apb * timer->dev->config.divider) / old_apb;
|
uint16_t divider = (new_apb * timerGetDivider(timer)) / old_apb;
|
||||||
timer->dev->config.enable = 1;
|
timerSetDivider(timer,divider);
|
||||||
|
timerStart(timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
|
hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
|
||||||
if(num > 3){
|
if(num >= NUM_OF_TIMERS)
|
||||||
|
{
|
||||||
|
log_e("Timer dont have that timer number.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
hw_timer_t * timer = &hw_timer[num];
|
|
||||||
if(timer->group) {
|
hw_timer_t * timer = &timer_dev[num]; //Get Timer group/num from 0-3 number
|
||||||
periph_module_enable(PERIPH_TIMG1_MODULE);
|
|
||||||
} else {
|
timer_config_t config = {
|
||||||
periph_module_enable(PERIPH_TIMG0_MODULE);
|
.divider = divider,
|
||||||
}
|
.counter_dir = countUp,
|
||||||
timer->dev->config.enable = 0;
|
.counter_en = TIMER_PAUSE,
|
||||||
if(timer->group) {
|
.alarm_en = TIMER_ALARM_DIS,
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
.auto_reload = false,
|
||||||
TIMERG1.int_ena.val &= ~BIT(timer->timer);
|
};
|
||||||
#else
|
|
||||||
TIMERG1.int_ena_timers.val &= ~BIT(timer->timer);
|
timer_init(timer->group, timer->num, &config);
|
||||||
#endif
|
timer_set_counter_value(timer->group, timer->num, 0);
|
||||||
TIMERG1.int_clr_timers.val |= BIT(timer->timer);
|
timerStart(timer);
|
||||||
} else {
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
TIMERG0.int_ena.val &= ~BIT(timer->timer);
|
|
||||||
#else
|
|
||||||
TIMERG0.int_ena_timers.val &= ~BIT(timer->timer);
|
|
||||||
#endif
|
|
||||||
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
|
|
||||||
}
|
|
||||||
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK
|
|
||||||
timer->dev->config.use_xtal = 0;
|
|
||||||
#endif
|
|
||||||
timerSetDivider(timer, divider);
|
|
||||||
timerSetCountUp(timer, countUp);
|
|
||||||
timerSetAutoReload(timer, false);
|
|
||||||
timerAttachInterrupt(timer, NULL, false);
|
|
||||||
timerWrite(timer, 0);
|
|
||||||
timer->dev->config.enable = 1;
|
|
||||||
addApbChangeCallback(timer, _on_apb_change);
|
addApbChangeCallback(timer, _on_apb_change);
|
||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerEnd(hw_timer_t *timer){
|
void timerEnd(hw_timer_t *timer){
|
||||||
timer->dev->config.enable = 0;
|
|
||||||
timerAttachInterrupt(timer, NULL, false);
|
|
||||||
removeApbChangeCallback(timer, _on_apb_change);
|
removeApbChangeCallback(timer, _on_apb_change);
|
||||||
|
timer_deinit(timer->group, timer->num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
if(edge){
|
if(edge){
|
||||||
log_w("EDGE timer interrupt does not work properly on ESP32! Setting to LEVEL...");
|
log_w("EDGE timer interrupt is not supported! Setting to LEVEL...");
|
||||||
edge = false;
|
edge = false;
|
||||||
}
|
}
|
||||||
#endif
|
timer_enable_intr(timer->group, timer->num);
|
||||||
static bool initialized = false;
|
|
||||||
static intr_handle_t intr_handle = NULL;
|
timer_info_t *timer_info = calloc(1, sizeof(timer_info_t));
|
||||||
if(intr_handle){
|
timer_info->timer_group = timer->group;
|
||||||
esp_intr_disable(intr_handle);
|
timer_info->timer_idx = timer->num;
|
||||||
}
|
timer_info->auto_reload = timerGetAutoReload(timer);
|
||||||
if(fn == NULL){
|
timer_info->alarm_interval = timerAlarmRead(timer);
|
||||||
timer->dev->config.level_int_en = 0;
|
|
||||||
timer->dev->config.edge_int_en = 0;
|
timer_isr_callback_add(timer->group, timer->num, (timer_isr_t)fn, timer_info, 0);
|
||||||
timer->dev->config.alarm_en = 0;
|
|
||||||
if(timer->num & 2){
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
TIMERG1.int_ena.val &= ~BIT(timer->timer);
|
|
||||||
#else
|
|
||||||
TIMERG1.int_ena_timers.val &= ~BIT(timer->timer);
|
|
||||||
#endif
|
|
||||||
TIMERG1.int_clr_timers.val |= BIT(timer->timer);
|
|
||||||
} else {
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
TIMERG0.int_ena.val &= ~BIT(timer->timer);
|
|
||||||
#else
|
|
||||||
TIMERG0.int_ena_timers.val &= ~BIT(timer->timer);
|
|
||||||
#endif
|
|
||||||
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
|
|
||||||
}
|
|
||||||
__timerInterruptHandlers[timer->num] = NULL;
|
|
||||||
} else {
|
|
||||||
__timerInterruptHandlers[timer->num] = fn;
|
|
||||||
timer->dev->config.level_int_en = edge?0:1;//When set, an alarm will generate a level type interrupt.
|
|
||||||
timer->dev->config.edge_int_en = edge?1:0;//When set, an alarm will generate an edge type interrupt.
|
|
||||||
int intr_source = 0;
|
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
|
||||||
if(!edge){
|
|
||||||
#endif
|
|
||||||
if(timer->group){
|
|
||||||
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer->timer;
|
|
||||||
} else {
|
|
||||||
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer->timer;
|
|
||||||
}
|
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
|
||||||
} else {
|
|
||||||
if(timer->group){
|
|
||||||
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer->timer;
|
|
||||||
} else {
|
|
||||||
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer->timer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(!initialized){
|
|
||||||
initialized = true;
|
|
||||||
esp_intr_alloc(intr_source, (int)(ARDUINO_ISR_FLAG|ESP_INTR_FLAG_LOWMED), __timerISR, NULL, &intr_handle);
|
|
||||||
} else {
|
|
||||||
intr_matrix_set(esp_intr_get_cpu(intr_handle), intr_source, esp_intr_get_intno(intr_handle));
|
|
||||||
}
|
|
||||||
if(timer->group){
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
TIMERG1.int_ena.val |= BIT(timer->timer);
|
|
||||||
#else
|
|
||||||
TIMERG1.int_ena_timers.val |= BIT(timer->timer);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
TIMERG0.int_ena.val |= BIT(timer->timer);
|
|
||||||
#else
|
|
||||||
TIMERG0.int_ena_timers.val |= BIT(timer->timer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(intr_handle){
|
|
||||||
esp_intr_enable(intr_handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerDetachInterrupt(hw_timer_t *timer){
|
void timerDetachInterrupt(hw_timer_t *timer){
|
||||||
@ -354,6 +246,12 @@ uint64_t timerReadMicros(hw_timer_t *timer){
|
|||||||
return timer_val * div / (getApbFrequency() / 1000000);
|
return timer_val * div / (getApbFrequency() / 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t timerReadMilis(hw_timer_t *timer){
|
||||||
|
uint64_t timer_val = timerRead(timer);
|
||||||
|
uint16_t div = timerGetDivider(timer);
|
||||||
|
return timer_val * div / (getApbFrequency() / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
double timerReadSeconds(hw_timer_t *timer){
|
double timerReadSeconds(hw_timer_t *timer){
|
||||||
uint64_t timer_val = timerRead(timer);
|
uint64_t timer_val = timerRead(timer);
|
||||||
uint16_t div = timerGetDivider(timer);
|
uint16_t div = timerGetDivider(timer);
|
||||||
@ -366,6 +264,12 @@ uint64_t timerAlarmReadMicros(hw_timer_t *timer){
|
|||||||
return timer_val * div / (getApbFrequency() / 1000000);
|
return timer_val * div / (getApbFrequency() / 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t timerAlarmReadMilis(hw_timer_t *timer){
|
||||||
|
uint64_t timer_val = timerAlarmRead(timer);
|
||||||
|
uint16_t div = timerGetDivider(timer);
|
||||||
|
return timer_val * div / (getApbFrequency() / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
double timerAlarmReadSeconds(hw_timer_t *timer){
|
double timerAlarmReadSeconds(hw_timer_t *timer){
|
||||||
uint64_t timer_val = timerAlarmRead(timer);
|
uint64_t timer_val = timerAlarmRead(timer);
|
||||||
uint16_t div = timerGetDivider(timer);
|
uint16_t div = timerGetDivider(timer);
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
#ifndef MAIN_ESP32_HAL_TIMER_H_
|
#ifndef MAIN_ESP32_HAL_TIMER_H_
|
||||||
#define MAIN_ESP32_HAL_TIMER_H_
|
#define MAIN_ESP32_HAL_TIMER_H_
|
||||||
|
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
|
|
||||||
struct hw_timer_s;
|
struct hw_timer_s;
|
||||||
typedef struct hw_timer_s hw_timer_t;
|
typedef struct hw_timer_s hw_timer_t;
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ void timerSetAutoReload(hw_timer_t *timer, bool autoreload);
|
|||||||
bool timerStarted(hw_timer_t *timer);
|
bool timerStarted(hw_timer_t *timer);
|
||||||
uint64_t timerRead(hw_timer_t *timer);
|
uint64_t timerRead(hw_timer_t *timer);
|
||||||
uint64_t timerReadMicros(hw_timer_t *timer);
|
uint64_t timerReadMicros(hw_timer_t *timer);
|
||||||
|
uint64_t timerReadMilis(hw_timer_t *timer);
|
||||||
double timerReadSeconds(hw_timer_t *timer);
|
double timerReadSeconds(hw_timer_t *timer);
|
||||||
uint16_t timerGetDivider(hw_timer_t *timer);
|
uint16_t timerGetDivider(hw_timer_t *timer);
|
||||||
bool timerGetCountUp(hw_timer_t *timer);
|
bool timerGetCountUp(hw_timer_t *timer);
|
||||||
|
Reference in New Issue
Block a user