mirror of
https://github.com/esphome/esphome.git
synced 2024-11-24 16:08:10 +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
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||||
|
#include "esp_idf_version.h"
|
||||||
#include "hw_timer_esp_idf.h"
|
#include "hw_timer_esp_idf.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -195,7 +196,8 @@ void AcDimmer::setup() {
|
||||||
// PWM and AcDimmer can even run at the same time this way
|
// PWM and AcDimmer can even run at the same time this way
|
||||||
setTimer1Callback(&timer_interrupt);
|
setTimer1Callback(&timer_interrupt);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ESP32
|
|
||||||
|
#if USE_ESP32 && (ESP_IDF_VERSION_MAJOR == 4)
|
||||||
// 80 Divider -> 1 count=1µs
|
// 80 Divider -> 1 count=1µs
|
||||||
dimmer_timer = timerBegin(0, 80, true);
|
dimmer_timer = timerBegin(0, 80, true);
|
||||||
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
||||||
|
@ -205,6 +207,16 @@ void AcDimmer::setup() {
|
||||||
timerAlarmWrite(dimmer_timer, 50, true);
|
timerAlarmWrite(dimmer_timer, 50, true);
|
||||||
timerAlarmEnable(dimmer_timer);
|
timerAlarmEnable(dimmer_timer);
|
||||||
#endif
|
#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) {
|
void AcDimmer::write_state(float state) {
|
||||||
|
|
|
@ -4,7 +4,18 @@
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||||
#include "esp32/clk.h"
|
#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"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
@ -13,6 +24,8 @@ static const char *const TAG = "hw_timer_esp_idf";
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ac_dimmer {
|
namespace ac_dimmer {
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||||
|
|
||||||
#define NUM_OF_TIMERS SOC_TIMER_GROUP_TOTAL_TIMERS
|
#define NUM_OF_TIMERS SOC_TIMER_GROUP_TOTAL_TIMERS
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
@ -195,6 +208,123 @@ uint32_t timerGetConfig(hw_timer_t *timer) {
|
||||||
|
|
||||||
return cfg.val;
|
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 ac_dimmer
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||||
|
|
||||||
|
#include "esp_idf_version.h"
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||||
#include "driver/timer.h"
|
#include "driver/timer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION_MAJOR == 5)
|
||||||
|
#include "driver/gptimer_types.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ac_dimmer {
|
namespace ac_dimmer {
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION_MAJOR == 4)
|
||||||
typedef struct hw_timer_s {
|
typedef struct hw_timer_s {
|
||||||
timer_group_t group;
|
timer_group_t group;
|
||||||
timer_idx_t num;
|
timer_idx_t num;
|
||||||
|
@ -21,7 +32,31 @@ void timerStop(hw_timer_t *timer);
|
||||||
uint32_t timerGetConfig(hw_timer_t *timer);
|
uint32_t timerGetConfig(hw_timer_t *timer);
|
||||||
uint16_t timerGetDivider(hw_timer_t *timer);
|
uint16_t timerGetDivider(hw_timer_t *timer);
|
||||||
void timerSetDivider(hw_timer_t *timer, uint16_t divider);
|
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 ac_dimmer
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue