Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/esp32: use ESP-IDF timer HAL for system timer and watchdog #18267

Merged
merged 4 commits into from
Jul 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpu/esp32/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ INCLUDES += -I$(ESP32_SDK_DIR)/components/driver/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_common/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/include/soc
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_rom/$(CPU)
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_rom/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_rom/include/$(CPU)
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_system/include
Expand Down
20 changes: 15 additions & 5 deletions cpu/esp32/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,18 +504,28 @@ typedef struct {
* configured here.
* @{
*/

#ifdef MODULE_ESP_HW_COUNTER
/** hardware ccount/ccompare registers are used for timer implementation */
/** Hardware ccount/ccompare registers are used for timer implementation */
#define TIMER_NUMOF (2)
#define TIMER_CHANNEL_NUMOF (1)
#else
/** hardware timer modules are used for timer implementation (default) */
#define TIMER_NUMOF (3)
/**
* @brief Hardware timer modules are used for timer implementation (default)
*
* Since one timer is used for the system time, there is one timer less than
* the total number of timers.
*/
#define TIMER_NUMOF (SOC_TIMER_GROUP_TOTAL_TIMERS - 1)
#define TIMER_CHANNEL_NUMOF (1)
#endif

/** Timer used for system time */
#define TIMER_SYSTEM TIMERG0.hw_timer[0]
/** Timer group used for system time */
#define TIMER_SYSTEM_GROUP TIMER_GROUP_0
/** Index of the timer in the timer timer group used for system time */
#define TIMER_SYSTEM_INDEX TIMER_0
/** System time interrupt source */
#define TIMER_SYSTEM_INT_SRC ETS_TG0_T0_LEVEL_INTR_SOURCE

/** @} */

Expand Down
37 changes: 28 additions & 9 deletions cpu/esp32/periph/rtt_hw_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@
/* ESP-IDF headers */
#include "esp_attr.h"
#include "esp_sleep.h"
#include "hal/interrupt_controller_types.h"
#include "hal/interrupt_controller_ll.h"
#include "rom/ets_sys.h"
#include "soc/dport_reg.h"
#include "soc/periph_defs.h"
#include "soc/rtc_cntl_struct.h"

#if __xtensa__
#include "soc/dport_reg.h"
#include "xtensa/xtensa_api.h"
#endif

#define ENABLE_DEBUG 0
#include "debug.h"
Expand Down Expand Up @@ -77,27 +83,34 @@ static void _rtc_poweron(void)
intr_matrix_set(PRO_CPU_NUM, ETS_RTC_CORE_INTR_SOURCE, CPU_INUM_RTT);

/* set interrupt handler and enable the CPU interrupt */
xt_set_interrupt_handler(CPU_INUM_RTT, _rtc_isr, NULL);
xt_ints_on(BIT(CPU_INUM_RTT));
intr_cntrl_ll_set_int_handler(CPU_INUM_RTT, _rtc_isr, NULL);
intr_cntrl_ll_enable_interrupts(BIT(CPU_INUM_RTT));
}

static void _rtc_poweroff(void)
{
/* reset interrupt handler and disable the CPU interrupt */
xt_ints_off(BIT(CPU_INUM_RTT));
xt_set_interrupt_handler(CPU_INUM_RTT, NULL, NULL);
intr_cntrl_ll_disable_interrupts(BIT(CPU_INUM_RTT));
intr_cntrl_ll_set_int_handler(CPU_INUM_RTT, NULL, NULL);
}

uint64_t _rtc_get_counter(void)
{
/* trigger timer register update */
RTCCNTL.time_update.update = 1;
#if defined(MCU_ESP32)
benpicco marked this conversation as resolved.
Show resolved Hide resolved
/* wait until values in registers are valid */
while (!RTCCNTL.time_update.valid) {
ets_delay_us(1);
}
/* read the time from 48-bit counter and return */
return (((uint64_t)RTCCNTL.time1.val) << 32) + RTCCNTL.time0;
#elif defined(MCU_ESP32C3)
/* read the time from 48-bit counter and return */
return (((uint64_t)RTCCNTL.time_high0.val) << 32) + RTCCNTL.time_low0;
#else
#error "MCU implementation is missing"
#endif
}

static void _rtc_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
Expand All @@ -109,8 +122,9 @@ static void _rtc_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
/* use computed time difference directly to set the RTC counter alarm */
uint64_t rtc_alarm = (rtc_counter + rtt_diff) & RTT_HW_COUNTER_MAX;

DEBUG("%s alarm=%u rtt_diff=%u rtc_alarm=%llu @rtc=%llu\n",
__func__, alarm, rtt_diff, rtc_alarm, rtc_counter);
DEBUG("%s alarm=%" PRIu32 " rtt_diff=%" PRIu32
" rtc_alarm=%" PRIu64 " @rtc=%" PRIu64 "\n",
__func__, alarm, rtt_diff, rtc_alarm, rtc_counter);

/* save the alarm configuration for interrupt handling */
_rtc_alarm.alarm_set = alarm;
Expand All @@ -121,8 +135,13 @@ static void _rtc_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
RTCCNTL.slp_timer0 = rtc_alarm & 0xffffffff;
RTCCNTL.slp_timer1.slp_val_hi = rtc_alarm >> 32;

#if __xtensa__
DEBUG("%s %08x%08x \n", __func__,
RTCCNTL.slp_timer1.slp_val_hi, RTCCNTL.slp_timer0);
#else
DEBUG("%s %08x%08x \n", __func__,
(unsigned)RTCCNTL.slp_timer1.slp_val_hi, (unsigned)RTCCNTL.slp_timer0);
#endif

/* enable RTC timer alarm */
RTCCNTL.slp_timer1.main_timer_alarm_en = 1;
Expand Down Expand Up @@ -168,10 +187,10 @@ static void IRAM _rtc_isr(void *arg)
/* save the lower 32 bit of the current counter value */
uint32_t counter = _rtc_get_counter();

DEBUG("%s %u\n", __func__, counter);
DEBUG("%s %" PRIu32 "\n", __func__, counter);

if (_rtc_alarm.alarm_cb) {
DEBUG("%s alarm %u\n", __func__, counter);
DEBUG("%s alarm %" PRIu32 "\n", __func__, counter);

rtt_cb_t alarm_cb = _rtc_alarm.alarm_cb;
void *alarm_arg = _rtc_alarm.alarm_arg;
Expand Down
71 changes: 39 additions & 32 deletions cpu/esp32/periph/rtt_hw_sys.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Gunar Schorcht
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand Down Expand Up @@ -32,20 +32,28 @@
/* ESP-IDF headers */
#include "esp_attr.h"
#include "esp_sleep.h"
#include "hal/interrupt_controller_types.h"
#include "hal/interrupt_controller_ll.h"
#include "hal/timer_hal.h"
#include "rom/ets_sys.h"
#include "soc/periph_defs.h"
#include "soc/timer_group_struct.h"

#if __xtensa__
#include "xtensa/xtensa_api.h"
#endif

#define ENABLE_DEBUG 0
#include "debug.h"

#define TIMER_SYSTEM_GROUP TIMERG0
#define TIMER_SYSTEM_INT_MASK BIT(0)
#define TIMER_SYSTEM_INT_SRC ETS_TG0_T0_LEVEL_INTR_SOURCE
#define TIMER_SYSTEM_INT_MASK BIT(TIMER_SYSTEM_INDEX)

#define SYS_US_TO_TICKS(us) ((((uint64_t)us) << 15) / US_PER_SEC)
#define SYS_TICKS_TO_US(cnt) (((uint64_t)cnt * US_PER_SEC) >> 15)

/* system timer is defined and initialized in syscalls.c */
extern timer_hal_context_t sys_timer;

typedef struct {
uint32_t alarm_set; /**< alarm set at interface */
rtt_cb_t alarm_cb; /**< alarm callback */
Expand Down Expand Up @@ -77,15 +85,15 @@ static void _sys_poweron(void)
intr_matrix_set(PRO_CPU_NUM, TIMER_SYSTEM_INT_SRC, CPU_INUM_RTT);

/* set interrupt handler and enable the CPU interrupt */
xt_set_interrupt_handler(CPU_INUM_RTT, _sys_isr, NULL);
xt_ints_on(BIT(CPU_INUM_RTT));
intr_cntrl_ll_set_int_handler(CPU_INUM_RTT, _sys_isr, NULL);
intr_cntrl_ll_enable_interrupts(BIT(CPU_INUM_RTT));
}

static void _sys_poweroff(void)
{
/* reset interrupt handler and disable the CPU interrupt */
xt_ints_off(BIT(CPU_INUM_RTT));
xt_set_interrupt_handler(CPU_INUM_RTT, NULL, NULL);
intr_cntrl_ll_disable_interrupts(BIT(CPU_INUM_RTT));
intr_cntrl_ll_set_int_handler(CPU_INUM_RTT, NULL, NULL);
}

static uint64_t _sys_get_counter(void)
Expand All @@ -108,8 +116,8 @@ static void _sys_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
uint64_t _sys_time = system_get_time_64();
uint64_t _sys_alarm_time = _sys_time + _sys_diff;

DEBUG("%s alarm=%u rtt_diff=%u "
"sys_diff=%llu sys_alarm=%llu @sys_time=%llu\n", __func__,
DEBUG("%s alarm=%" PRIu32 " rtt_diff=%" PRIu32 " "
"sys_diff=%" PRIu64 " sys_alarm=%" PRIu64 " @sys_time=%" PRIu64 "\n", __func__,
alarm, rtt_diff, _sys_diff, _sys_alarm_time, _sys_time);

/* save the alarm configuration for interrupt handling */
Expand All @@ -118,27 +126,24 @@ static void _sys_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
_sys_alarm.alarm_arg = arg;

/* set the timer value */
TIMER_SYSTEM.alarm_high = (uint32_t)(_sys_alarm_time >> 32);
TIMER_SYSTEM.alarm_low = (uint32_t)(_sys_alarm_time & 0xffffffff);
timer_hal_set_alarm_value(&sys_timer, _sys_alarm_time);

/* clear the bit in status and set the bit in interrupt enable */
TIMER_SYSTEM_GROUP.int_clr_timers.val |= TIMER_SYSTEM_INT_MASK;
TIMER_SYSTEM_GROUP.int_ena.val |= TIMER_SYSTEM_INT_MASK;
timer_hal_clear_intr_status(&sys_timer);
timer_hal_intr_enable(&sys_timer);

/* enable the timer alarm */
TIMER_SYSTEM.config.level_int_en = 1;
TIMER_SYSTEM.config.alarm_en = 1;
timer_hal_set_alarm_enable(&sys_timer, true);
}

static void _sys_clear_alarm(void)
{
/* disable alarms first */
TIMER_SYSTEM.config.level_int_en = 0;
TIMER_SYSTEM.config.alarm_en = 0;
timer_hal_intr_disable(&sys_timer);
timer_hal_set_alarm_enable(&sys_timer, false);

/* clear the bit in interrupt enable and status register */
TIMER_SYSTEM_GROUP.int_ena.val &= ~TIMER_SYSTEM_INT_MASK;
TIMER_SYSTEM_GROUP.int_clr_timers.val |= TIMER_SYSTEM_INT_MASK;
/* clear the bit in interrupt status register */
timer_hal_clear_intr_status(&sys_timer);

/* reset the alarm configuration for interrupt handling */
_sys_alarm.alarm_set = 0;
Expand All @@ -156,7 +161,7 @@ static void _sys_save_counter(void)

critical_exit();

DEBUG("%s rtc_time_saved=%llu sys_time_saved=%llu\n", __func__,
DEBUG("%s rtc_time_saved=%" PRIu64 " sys_time_saved=%" PRIu64 "\n", __func__,
_rtc_counter_saved, _sys_counter_saved);
}

Expand All @@ -171,34 +176,36 @@ static void _sys_restore_counter(bool in_init)

critical_exit();

DEBUG("%s rtc_time_saved=%llu rtc_time_diff=%llu "
"sys_time_saved=%llu sys_time_offset=%llu\n", __func__,
DEBUG("%s rtc_time_saved=%" PRIu64 " rtc_time_diff=%" PRIu64 " "
"sys_time_saved=%" PRIu64 " sys_time_offset=%" PRIu64 "\n", __func__,
_rtc_counter_saved, _rtc_time_diff,
_sys_counter_saved, _sys_counter_offset);
}

static void IRAM _sys_isr(void *arg)
{
if (!(TIMER_SYSTEM_GROUP.int_st_timers.val & TIMER_SYSTEM_INT_MASK)) {
uint32_t int_status;

timer_hal_get_intr_status(&sys_timer, &int_status);
if (!(int_status & TIMER_SYSTEM_INT_MASK)) {
/* return in case of another timer interrupt */
return;
}

/* disable alarms first */
TIMER_SYSTEM.config.level_int_en = 0;
TIMER_SYSTEM.config.alarm_en = 0;
timer_hal_intr_disable(&sys_timer);
timer_hal_set_alarm_enable(&sys_timer, false);

/* clear the bit in interrupt enable and status register */
TIMER_SYSTEM_GROUP.int_ena.val &= ~TIMER_SYSTEM_INT_MASK;
TIMER_SYSTEM_GROUP.int_clr_timers.val |= TIMER_SYSTEM_INT_MASK;
/* clear the bit in interrupt status register */
timer_hal_clear_intr_status(&sys_timer);

/* save the lower 32 bit of the current counter value */
uint32_t counter = _sys_get_counter();

DEBUG("%s %u\n", __func__, counter);
DEBUG("%s %" PRIu32 "\n", __func__, counter);

if (_sys_alarm.alarm_cb) {
DEBUG("%s alarm %u\n", __func__, counter);
DEBUG("%s alarm %" PRIu32 "\n", __func__, counter);

rtt_cb_t alarm_cb = _sys_alarm.alarm_cb;
void *alarm_arg = _sys_alarm.alarm_arg;
Expand Down
Loading