summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2023-07-12 16:39:26 +1000
committerDamien George <damien@micropython.org>2023-07-14 10:02:42 +1000
commit7d66ae603d91157069d7cdee065919a61f678fb9 (patch)
tree872981448f61242e392c40b3b87a3ae86154c732
parent671b35ceae2d2b7b64f755524b3a5a42e29abcfe (diff)
esp32/machine_timer: Switch from legacy driver to timer HAL.
The legacy driver was deprecated in IDF v5, and crashes when the ISR handler is called. Instead of fixing the legacy code, this commit reworks the machine.Timer class to use the low-level HAL driver. Tested on ESP32, ESP32S2, ESP32S3 and ESP32C3. Behaviour is the same as it was before this commit, except the way the Timer object is printed, it now gives more useful information (timer id, mode, period in ms). Fixes issue #11970. Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/esp32/boards/sdkconfig.base1
-rw-r--r--ports/esp32/machine_timer.c97
2 files changed, 52 insertions, 46 deletions
diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base
index c74a19c0c..bf6c3f45c 100644
--- a/ports/esp32/boards/sdkconfig.base
+++ b/ports/esp32/boards/sdkconfig.base
@@ -75,6 +75,5 @@ CONFIG_UART_ISR_IN_IRAM=y
# IDF 5 deprecated
CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y
-CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN=y
CONFIG_RMT_SUPPRESS_DEPRECATE_WARN=y
CONFIG_I2S_SUPPRESS_DEPRECATE_WARN=y
diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c
index 5855cfb3e..aba3db198 100644
--- a/ports/esp32/machine_timer.c
+++ b/ports/esp32/machine_timer.c
@@ -35,10 +35,10 @@
#include "modmachine.h"
#include "mphalport.h"
-#include "driver/timer.h"
+#include "hal/timer_hal.h"
#include "hal/timer_ll.h"
+#include "soc/timer_periph.h"
-#define TIMER_INTR_SEL TIMER_INTR_LEVEL
#define TIMER_DIVIDER 8
// TIMER_BASE_CLK is normally 80MHz. TIMER_DIVIDER ought to divide this exactly
@@ -48,6 +48,8 @@
typedef struct _machine_timer_obj_t {
mp_obj_base_t base;
+
+ timer_hal_context_t hal_context;
mp_uint_t group;
mp_uint_t index;
@@ -80,15 +82,9 @@ void machine_timer_deinit_all(void) {
STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_timer_obj_t *self = self_in;
-
- timer_config_t config;
- mp_printf(print, "Timer(%p; ", self);
-
- timer_get_config(self->group, self->index, &config);
-
- mp_printf(print, "alarm_en=%d, ", config.alarm_en);
- mp_printf(print, "auto_reload=%d, ", config.auto_reload);
- mp_printf(print, "counter_en=%d)", config.counter_en);
+ qstr mode = self->repeat ? MP_QSTR_PERIODIC : MP_QSTR_ONE_SHOT;
+ uint64_t period = self->period / (TIMER_SCALE / 1000); // convert to ms
+ mp_printf(print, "Timer(%u, mode=%q, period=%lu)", (self->group << 1) | self->index, mode, period);
}
STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
@@ -126,8 +122,14 @@ STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args,
}
STATIC void machine_timer_disable(machine_timer_obj_t *self) {
+ if (self->hal_context.dev != NULL) {
+ // Disable the counter and alarm.
+ timer_ll_enable_counter(self->hal_context.dev, self->index, false);
+ timer_ll_enable_alarm(self->hal_context.dev, self->index, false);
+ }
+
if (self->handle) {
- timer_pause(self->group, self->index);
+ // Free the interrupt handler.
esp_intr_free(self->handle);
self->handle = NULL;
}
@@ -138,39 +140,47 @@ STATIC void machine_timer_disable(machine_timer_obj_t *self) {
STATIC void machine_timer_isr(void *self_in) {
machine_timer_obj_t *self = self_in;
- timg_dev_t *device = self->group ? &(TIMERG1) : &(TIMERG0);
- #if CONFIG_IDF_TARGET_ESP32S3
- device->hw_timer[self->index].update.tn_update = 1;
- #else
- device->hw_timer[self->index].update.tx_update = 1;
- #endif
+ uint32_t intr_status = timer_ll_get_intr_status(self->hal_context.dev);
- timer_ll_clear_intr_status(device, self->index);
- timer_ll_set_alarm_value(device, self->index, self->repeat);
-
- mp_sched_schedule(self->callback, self);
- mp_hal_wake_main_task_from_isr();
+ if (intr_status & TIMER_LL_EVENT_ALARM(self->index)) {
+ timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
+ if (self->repeat) {
+ timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
+ }
+ mp_sched_schedule(self->callback, self);
+ mp_hal_wake_main_task_from_isr();
+ }
}
STATIC void machine_timer_enable(machine_timer_obj_t *self) {
- timer_config_t config;
- config.alarm_en = TIMER_ALARM_EN;
- config.auto_reload = self->repeat;
- config.counter_dir = TIMER_COUNT_UP;
- config.divider = TIMER_DIVIDER;
- config.intr_type = TIMER_INTR_LEVEL;
- config.counter_en = TIMER_PAUSE;
- #if SOC_TIMER_GROUP_SUPPORT_XTAL
- config.clk_src = TIMER_SRC_CLK_APB;
- #endif
-
- check_esp_err(timer_init(self->group, self->index, &config));
- check_esp_err(timer_set_counter_value(self->group, self->index, 0x00000000));
- check_esp_err(timer_set_alarm_value(self->group, self->index, self->period));
- check_esp_err(timer_enable_intr(self->group, self->index));
- check_esp_err(timer_isr_register(self->group, self->index, machine_timer_isr, (void *)self, TIMER_FLAGS, &self->handle));
- check_esp_err(timer_start(self->group, self->index));
+ // Initialise the timer.
+ timer_hal_init(&self->hal_context, self->group, self->index);
+ timer_ll_enable_counter(self->hal_context.dev, self->index, false);
+ timer_ll_set_clock_source(self->hal_context.dev, self->index, GPTIMER_CLK_SRC_APB);
+ timer_ll_set_clock_prescale(self->hal_context.dev, self->index, TIMER_DIVIDER);
+ timer_hal_set_counter_value(&self->hal_context, 0);
+ timer_ll_set_count_direction(self->hal_context.dev, self->index, GPTIMER_COUNT_UP);
+
+ // Allocate and enable the alarm interrupt.
+ timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), false);
+ timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
+ ESP_ERROR_CHECK(
+ esp_intr_alloc(timer_group_periph_signals.groups[self->group].timer_irq_id[self->index],
+ TIMER_FLAGS, machine_timer_isr, self, &self->handle)
+ );
+ timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), true);
+
+ // Enable the alarm to trigger at the given period.
+ timer_ll_set_alarm_value(self->hal_context.dev, self->index, self->period);
+ timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
+
+ // Set the counter to reload at 0 if it's in repeat mode.
+ timer_ll_set_reload_value(self->hal_context.dev, self->index, 0);
+ timer_ll_enable_auto_reload(self->hal_context.dev, self->index, self->repeat);
+
+ // Enable the counter.
+ timer_ll_enable_counter(self->hal_context.dev, self->index, true);
}
STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -234,11 +244,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init)
STATIC mp_obj_t machine_timer_value(mp_obj_t self_in) {
machine_timer_obj_t *self = self_in;
- double result;
-
- timer_get_counter_time_sec(self->group, self->index, &result);
-
- return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(result * 1000)); // value in ms
+ uint64_t result = timer_ll_get_counter_value(self->hal_context.dev, self->index);
+ return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(result / (TIMER_SCALE / 1000))); // value in ms
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_value_obj, machine_timer_value);