mirror of
https://github.com/esphome/esphome.git
synced 2024-11-28 01:34:18 +01:00
support esp-idf 5.x
This commit is contained in:
parent
8a077fbe40
commit
65f61f29e0
3 changed files with 180 additions and 3 deletions
|
@ -13,6 +13,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||
#include "esp_idf_version.h"
|
||||
#include "hw_timer_esp_idf.h"
|
||||
#endif
|
||||
|
||||
|
@ -195,7 +196,8 @@ void AcDimmer::setup() {
|
|||
// PWM and AcDimmer can even run at the same time this way
|
||||
setTimer1Callback(&timer_interrupt);
|
||||
#endif
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#if USE_ESP32 && (ESP_IDF_VERSION_MAJOR == 4)
|
||||
// 80 Divider -> 1 count=1µs
|
||||
dimmer_timer = timerBegin(0, 80, true);
|
||||
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
||||
|
@ -205,6 +207,16 @@ void AcDimmer::setup() {
|
|||
timerAlarmWrite(dimmer_timer, 50, true);
|
||||
timerAlarmEnable(dimmer_timer);
|
||||
#endif
|
||||
#if USE_ESP32 && (ESP_IDF_VERSION_MAJOR == 5)
|
||||
// 1 MHz -> 1 count=1µs
|
||||
dimmer_timer = timerBegin(1000000);
|
||||
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr);
|
||||
// For ESP32, we can't use dynamic interval calculation because the timerX functions
|
||||
// are not callable from ISR (placed in flash storage).
|
||||
// Here we just use an interrupt firing every 50 µs.
|
||||
timerAlarm(dimmer_timer, 50, true, 0);
|
||||
timerStart(dimmer_timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AcDimmer::write_state(float state) {
|
||||
|
|
|
@ -4,7 +4,18 @@
|
|||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||
#include "esp32/clk.h"
|
||||
#endif
|
||||
#if (ESP_IDF_VERSION_MAJOR == 5)
|
||||
#include "driver/gptimer.h"
|
||||
#if defined __has_include && __has_include("clk_tree.h")
|
||||
#include "clk_tree.h"
|
||||
#else
|
||||
#include "esp_clk_tree.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
|
@ -13,6 +24,8 @@ static const char *const TAG = "hw_timer_esp_idf";
|
|||
namespace esphome {
|
||||
namespace ac_dimmer {
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||
|
||||
#define NUM_OF_TIMERS SOC_TIMER_GROUP_TOTAL_TIMERS
|
||||
|
||||
typedef union {
|
||||
|
@ -195,6 +208,123 @@ uint32_t timerGetConfig(hw_timer_t *timer) {
|
|||
|
||||
return cfg.val;
|
||||
}
|
||||
#endif // (ESP_IDF_VERSION_MAJOR == 4)
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 5)
|
||||
|
||||
interrupt_config_t *timer_intr_config = NULL;
|
||||
|
||||
hw_timer_t *timerBegin(uint32_t frequency) {
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t counter_src_hz = 0;
|
||||
uint32_t divider = 0;
|
||||
|
||||
// soc_periph_gptimer_clk_src_t clk;
|
||||
int clk;
|
||||
|
||||
// soc_periph_gptimer_clk_src_t gptimer_clks[] = SOC_GPTIMER_CLKS;
|
||||
int gptimer_clks[] = SOC_GPTIMER_CLKS;
|
||||
for (size_t i = 0; i < sizeof(gptimer_clks) / sizeof(gptimer_clks[0]); i++) {
|
||||
clk = gptimer_clks[i];
|
||||
#if defined __has_include && __has_include("clk_tree.h")
|
||||
clk_tree_src_get_freq_hz((soc_module_clk_t) clk, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz);
|
||||
#else
|
||||
esp_clk_tree_src_get_freq_hz((soc_module_clk_t) clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz);
|
||||
#endif
|
||||
divider = counter_src_hz / frequency;
|
||||
if ((divider >= 2) && (divider <= 65536)) {
|
||||
break;
|
||||
} else {
|
||||
divider = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (divider == 0) {
|
||||
ESP_LOGE(TAG, "Resolution cannot be reached with any clock source, aborting!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gptimer_config_t config = {
|
||||
.clk_src = (gptimer_clock_source_t) clk,
|
||||
.direction = GPTIMER_COUNT_UP,
|
||||
.resolution_hz = frequency,
|
||||
.intr_priority = 0,
|
||||
.flags = {.intr_shared = true},
|
||||
};
|
||||
|
||||
hw_timer_t *timer = (hw_timer_t *) malloc(sizeof(hw_timer_t));
|
||||
|
||||
err = gptimer_new_timer(&config, &timer->timer_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to create a new GPTimer, error num=%d", err);
|
||||
free(timer);
|
||||
return NULL;
|
||||
}
|
||||
gptimer_enable(timer->timer_handle);
|
||||
gptimer_start(timer->timer_handle);
|
||||
timer->timer_started = true;
|
||||
return timer;
|
||||
}
|
||||
|
||||
bool IRAM_ATTR timerFnWrapper(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *args) {
|
||||
interrupt_config_t *isr = (interrupt_config_t *) args;
|
||||
if (isr->fn) {
|
||||
if (isr->arg) {
|
||||
((voidFuncPtrArg) isr->fn)(isr->arg);
|
||||
} else {
|
||||
isr->fn();
|
||||
}
|
||||
}
|
||||
// some additional logic or handling may be required here to appropriately yield or not
|
||||
return false;
|
||||
}
|
||||
|
||||
void timerAttachInterruptFunctionalArg(hw_timer_t *timer, void (*userFunc)(void *), void *arg) {
|
||||
esp_err_t err = ESP_OK;
|
||||
gptimer_event_callbacks_t cbs = {
|
||||
.on_alarm = timerFnWrapper,
|
||||
};
|
||||
|
||||
timer->interrupt_handle.fn = (voidFuncPtr) userFunc;
|
||||
timer->interrupt_handle.arg = arg;
|
||||
|
||||
if (timer->timer_started == true) {
|
||||
gptimer_stop(timer->timer_handle);
|
||||
}
|
||||
gptimer_disable(timer->timer_handle);
|
||||
err = gptimer_register_event_callbacks(timer->timer_handle, &cbs, &timer->interrupt_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Timer Attach Interrupt failed, error num=%d", err);
|
||||
}
|
||||
gptimer_enable(timer->timer_handle);
|
||||
if (timer->timer_started == true) {
|
||||
gptimer_start(timer->timer_handle);
|
||||
}
|
||||
}
|
||||
|
||||
void timerAttachInterrupt(hw_timer_t *timer, voidFuncPtr userFunc) {
|
||||
timerAttachInterruptFunctionalArg(timer, (voidFuncPtrArg) userFunc, NULL);
|
||||
}
|
||||
|
||||
void timerAlarm(hw_timer_t *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count) {
|
||||
esp_err_t err = ESP_OK;
|
||||
gptimer_alarm_config_t alarm_cfg = {
|
||||
.alarm_count = alarm_value,
|
||||
.reload_count = reload_count,
|
||||
.flags = {.auto_reload_on_alarm = autoreload},
|
||||
};
|
||||
err = gptimer_set_alarm_action(timer->timer_handle, &alarm_cfg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Timer Alarm Write failed, error num=%d", err);
|
||||
}
|
||||
}
|
||||
|
||||
void timerStart(hw_timer_t *timer) {
|
||||
gptimer_start(timer->timer_handle);
|
||||
timer->timer_started = true;
|
||||
}
|
||||
|
||||
#endif // (ESP_IDF_VERSION_MAJOR == 5)
|
||||
|
||||
} // namespace ac_dimmer
|
||||
} // namespace esphome
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
#pragma once
|
||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||
#include "driver/timer.h"
|
||||
#endif
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 5)
|
||||
#include "driver/gptimer_types.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace ac_dimmer {
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||
typedef struct hw_timer_s {
|
||||
timer_group_t group;
|
||||
timer_idx_t num;
|
||||
|
@ -21,7 +32,31 @@ void timerStop(hw_timer_t *timer);
|
|||
uint32_t timerGetConfig(hw_timer_t *timer);
|
||||
uint16_t timerGetDivider(hw_timer_t *timer);
|
||||
void timerSetDivider(hw_timer_t *timer, uint16_t divider);
|
||||
#endif
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 5)
|
||||
|
||||
typedef void (*voidFuncPtr)(void);
|
||||
typedef void (*voidFuncPtrArg)(void *);
|
||||
|
||||
struct interrupt_config_t {
|
||||
voidFuncPtr fn;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct hw_timer_t {
|
||||
gptimer_handle_t timer_handle;
|
||||
interrupt_config_t interrupt_handle;
|
||||
bool timer_started;
|
||||
};
|
||||
|
||||
hw_timer_t *timerBegin(uint32_t frequency);
|
||||
|
||||
void timerAttachInterrupt(hw_timer_t *timer, void (*userFunc)(void));
|
||||
void timerAlarm(hw_timer_t *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count);
|
||||
void timerStart(hw_timer_t *timer);
|
||||
|
||||
#endif
|
||||
} // namespace ac_dimmer
|
||||
} // namespace esphome
|
||||
|
||||
|
|
Loading…
Reference in a new issue