mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
refactor(hal): graduate systimer hal driver into esp_hal_systimer
This commit is contained in:
7
components/esp_hal_systimer/.build-test-rules.yml
Normal file
7
components/esp_hal_systimer/.build-test-rules.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
components/esp_hal_systimer/test_apps/systimer_rom_impl:
|
||||
disable:
|
||||
- if: SOC_SYSTIMER_SUPPORTED != 1
|
||||
depends_components:
|
||||
- esp_hal_systimer
|
||||
29
components/esp_hal_systimer/CMakeLists.txt
Normal file
29
components/esp_hal_systimer/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs)
|
||||
set(public_include "include")
|
||||
if(CONFIG_SOC_SYSTIMER_SUPPORTED)
|
||||
list(APPEND public_include "${target}/include")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_SYSTIMER_SUPPORTED)
|
||||
if(CONFIG_HAL_SYSTIMER_USE_ROM_IMPL)
|
||||
list(APPEND srcs "rom_patch.c")
|
||||
# ESP32C2 revision < 2.0 needs additional ROM patches
|
||||
if(CONFIG_IDF_TARGET_ESP32C2 AND (CONFIG_ESP32C2_REV_MIN_FULL LESS 200))
|
||||
list(APPEND srcs "esp32c2/rom_patch_rev1.c")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND srcs "systimer_hal.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${public_include}
|
||||
REQUIRES soc hal esp_rom
|
||||
LDFRAGMENTS linker.lf)
|
||||
|
||||
# Link the ROM SYSTIMER HAL implementation linker script if selected
|
||||
if(CONFIG_HAL_SYSTIMER_USE_ROM_IMPL)
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${target}/rom.systimer.ld")
|
||||
endif()
|
||||
12
components/esp_hal_systimer/Kconfig.hal_systimer
Normal file
12
components/esp_hal_systimer/Kconfig.hal_systimer
Normal file
@@ -0,0 +1,12 @@
|
||||
config HAL_SYSTIMER_USE_ROM_IMPL
|
||||
bool "Use ROM implementation of SysTimer HAL driver"
|
||||
depends on ESP_ROM_HAS_HAL_SYSTIMER
|
||||
default y
|
||||
help
|
||||
Enable this flag to use HAL functions from ROM instead of ESP-IDF.
|
||||
|
||||
If keeping this as "n" in your project, you will have less free IRAM.
|
||||
If making this as "y" in your project, you will increase free IRAM,
|
||||
but you will lose the possibility to debug this module, and some new
|
||||
features will be added and bugs will be fixed in the IDF source
|
||||
but cannot be synced to ROM.
|
||||
62
components/esp_hal_systimer/README.md
Normal file
62
components/esp_hal_systimer/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# ESP Hardware Abstraction Layer for System Timer Peripheral
|
||||
|
||||
> [!NOTE]
|
||||
> This component is currently in beta. Its API, behavior, and compatibility may change at any time and without notice; backward compatibility is not guaranteed. Use caution when integrating into production systems.
|
||||
|
||||
## Overview
|
||||
|
||||
The ESP Hardware Abstraction Layer for System Timer Peripheral (`esp_hal_systimer`) provides a unified interface to interact with the system timer (SYSTIMER) peripheral across all ESP chip families. This component abstracts the hardware-specific details of different SYSTIMER implementations, enabling consistent usage patterns regardless of the underlying hardware.
|
||||
|
||||
The SYSTIMER is a high-resolution timer used for:
|
||||
- System time tracking
|
||||
- FreeRTOS tick generation
|
||||
- High-precision timing operations
|
||||
- Event timer (ETM) trigger generation
|
||||
|
||||
## Architecture
|
||||
|
||||
The HAL architecture consists of two primary layers:
|
||||
|
||||
1. **HAL Layer (Upper)**: Defines the operational sequences and data structures required to interact with the SYSTIMER peripheral, including:
|
||||
- Initialization and de-initialization functions
|
||||
- Counter value operations
|
||||
- Alarm configuration and management
|
||||
- Time conversion utilities
|
||||
- Clock source configuration
|
||||
|
||||
2. **Low-Level Layer (Bottom)**: Acts as a translation layer between the HAL and the register definitions in the `soc` component, handling:
|
||||
- Register access abstractions
|
||||
- Chip-specific register configurations
|
||||
- Hardware feature compatibility
|
||||
- Clock and prescaler settings
|
||||
|
||||
## Features
|
||||
|
||||
- Unified SYSTIMER interface across all ESP chip families
|
||||
- Support for multiple counters and alarms
|
||||
- High-resolution timing (typically 16MHz resolution)
|
||||
- Flexible clock source configuration
|
||||
- ETM (Event Timer Module) support where available
|
||||
- Platform-specific optimizations
|
||||
- IRAM-safe implementation for critical sections
|
||||
- ROM implementation support for certain chips
|
||||
- Chip-specific implementations contained in separate directories
|
||||
|
||||
## Usage
|
||||
|
||||
This component is primarily used by ESP-IDF system services such as:
|
||||
- **esp_timer**: High-resolution timer implementation
|
||||
- **FreeRTOS**: System tick generation
|
||||
- **esp_hw_support**: System time and clock management
|
||||
|
||||
For advanced developers implementing custom timing solutions, the HAL functions can be used directly. However, please note that the interfaces provided by this component are internal to ESP-IDF and are subject to change.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `soc`: Provides chip-specific register definitions
|
||||
- `hal`: Core hardware abstraction utilities and macros
|
||||
- `esp_rom`: ROM function interfaces (when using ROM implementation)
|
||||
|
||||
## ROM Implementation
|
||||
|
||||
Some chips support using ROM-based SYSTIMER HAL implementations for reduced code size. This is controlled by the `CONFIG_HAL_SYSTIMER_USE_ROM_IMPL` configuration option. When enabled, the component uses ROM linker scripts to link against ROM functions instead of compiling the HAL implementation.
|
||||
210
components/esp_hal_systimer/esp32c2/include/hal/systimer_ll.h
Normal file
210
components/esp_hal_systimer/esp32c2/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/system_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
(void)clk_src;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
SYSTEM.perip_clk_en0.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
SYSTEM.perip_rst_en0.systimer_rst = 1;
|
||||
SYSTEM.perip_rst_en0.systimer_rst = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
19
components/esp_hal_systimer/esp32c2/rom.systimer.ld
Normal file
19
components/esp_hal_systimer/esp32c2/rom.systimer.ld
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
PROVIDE( systimer_hal_get_counter_value = 0x400002ac );
|
||||
PROVIDE( systimer_hal_get_alarm_value = 0x400002bc );
|
||||
PROVIDE( systimer_hal_enable_alarm_int = 0x400002c0 );
|
||||
PROVIDE( systimer_hal_enable_counter = 0x400002cc );
|
||||
PROVIDE( systimer_hal_select_alarm_mode = 0x400002d0 );
|
||||
PROVIDE( systimer_hal_connect_alarm_counter = 0x400002d4 );
|
||||
PROVIDE( systimer_hal_counter_can_stall_by_cpu = 0x400002d8 );
|
||||
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* PROVIDE( systimer_hal_init = 0x400002a8 ); */
|
||||
/* PROVIDE( systimer_hal_get_time = 0x400002b0 ); */
|
||||
/* PROVIDE( systimer_hal_set_alarm_target = 0x400002b4 ); */
|
||||
/* PROVIDE( systimer_hal_set_alarm_period = 0x400002b8 ); */
|
||||
/* PROVIDE( systimer_hal_counter_value_advance = 0x400002c8 ); */
|
||||
75
components/esp_hal_systimer/esp32c2/rom_patch_rev1.c
Normal file
75
components/esp_hal_systimer/esp32c2/rom_patch_rev1.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief ROM patch for ESP32C2 revision < 2.0
|
||||
*
|
||||
* ESP32C2 early revisions (< 2.0) have incomplete systimer HAL implementations in ROM.
|
||||
* The ROM provides only basic functions (get_counter_value, get_alarm_value, etc.),
|
||||
* while the following functions need to be patched in flash:
|
||||
* - systimer_hal_init
|
||||
* - systimer_hal_deinit
|
||||
* - systimer_hal_set_tick_rate_ops
|
||||
* - systimer_hal_get_time
|
||||
* - systimer_hal_set_alarm_target
|
||||
* - systimer_hal_set_alarm_period
|
||||
* - systimer_hal_counter_value_advance
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "hal/systimer_hal.h"
|
||||
#include "hal/systimer_ll.h"
|
||||
|
||||
void systimer_hal_init(systimer_hal_context_t *hal)
|
||||
{
|
||||
hal->dev = &SYSTIMER;
|
||||
systimer_ll_enable_clock(hal->dev, true);
|
||||
}
|
||||
|
||||
void systimer_hal_deinit(systimer_hal_context_t *hal)
|
||||
{
|
||||
systimer_ll_enable_clock(hal->dev, false);
|
||||
hal->dev = NULL;
|
||||
}
|
||||
|
||||
void systimer_hal_set_tick_rate_ops(systimer_hal_context_t *hal, systimer_hal_tick_rate_ops_t *ops)
|
||||
{
|
||||
hal->ticks_to_us = ops->ticks_to_us;
|
||||
hal->us_to_ticks = ops->us_to_ticks;
|
||||
}
|
||||
|
||||
uint64_t systimer_hal_get_time(systimer_hal_context_t *hal, uint32_t counter_id)
|
||||
{
|
||||
return hal->ticks_to_us(systimer_hal_get_counter_value(hal, counter_id));
|
||||
}
|
||||
|
||||
void systimer_hal_set_alarm_target(systimer_hal_context_t *hal, uint32_t alarm_id, uint64_t target)
|
||||
{
|
||||
systimer_counter_value_t alarm = {
|
||||
.val = hal->us_to_ticks(target),
|
||||
};
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, false);
|
||||
systimer_ll_set_alarm_target(hal->dev, alarm_id, alarm.val);
|
||||
systimer_ll_apply_alarm_value(hal->dev, alarm_id);
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, true);
|
||||
}
|
||||
|
||||
void systimer_hal_set_alarm_period(systimer_hal_context_t *hal, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, false);
|
||||
systimer_ll_set_alarm_period(hal->dev, alarm_id, hal->us_to_ticks(period));
|
||||
systimer_ll_apply_alarm_value(hal->dev, alarm_id);
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, true);
|
||||
}
|
||||
|
||||
void systimer_hal_counter_value_advance(systimer_hal_context_t *hal, uint32_t counter_id, int64_t time_us)
|
||||
{
|
||||
systimer_counter_value_t new_count = {
|
||||
.val = systimer_hal_get_counter_value(hal, counter_id) + hal->us_to_ticks(time_us),
|
||||
};
|
||||
systimer_ll_set_counter_value(hal->dev, counter_id, new_count.val);
|
||||
systimer_ll_apply_counter_value(hal->dev, counter_id);
|
||||
}
|
||||
210
components/esp_hal_systimer/esp32c3/include/hal/systimer_ll.h
Normal file
210
components/esp_hal_systimer/esp32c3/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/system_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
(void)clk_src;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
SYSTEM.perip_clk_en0.reg_systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
SYSTEM.perip_rst_en0.reg_systimer_rst = 1;
|
||||
SYSTEM.perip_rst_en0.reg_systimer_rst = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
218
components/esp_hal_systimer/esp32c5/include/hal/systimer_ll.h
Normal file
218
components/esp_hal_systimer/esp32c5/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
PCR.systimer_func_clk_conf.systimer_func_clk_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (PCR.systimer_func_clk_conf.systimer_func_clk_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.systimer_conf.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
PCR.systimer_conf.systimer_rst_en = 1;
|
||||
PCR.systimer_conf.systimer_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
27
components/esp_hal_systimer/esp32c5/rom.systimer.ld
Normal file
27
components/esp_hal_systimer/esp32c5/rom.systimer.ld
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* systimer_hal_init = 0x400003d0; */
|
||||
/* systimer_hal_deinit = 0x400003d4; */
|
||||
systimer_hal_set_tick_rate_ops = 0x400003d8;
|
||||
systimer_hal_get_counter_value = 0x400003dc;
|
||||
systimer_hal_get_time = 0x400003e0;
|
||||
systimer_hal_set_alarm_target = 0x400003e4;
|
||||
systimer_hal_set_alarm_period = 0x400003e8;
|
||||
systimer_hal_get_alarm_value = 0x400003ec;
|
||||
systimer_hal_enable_alarm_int = 0x400003f0;
|
||||
systimer_hal_on_apb_freq_update = 0x400003f4;
|
||||
systimer_hal_counter_value_advance = 0x400003f8;
|
||||
systimer_hal_enable_counter = 0x400003fc;
|
||||
systimer_hal_select_alarm_mode = 0x40000400;
|
||||
systimer_hal_connect_alarm_counter = 0x40000404;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x40000408;
|
||||
218
components/esp_hal_systimer/esp32c6/include/hal/systimer_ll.h
Normal file
218
components/esp_hal_systimer/esp32c6/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
PCR.systimer_func_clk_conf.systimer_func_clk_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (PCR.systimer_func_clk_conf.systimer_func_clk_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.systimer_conf.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
PCR.systimer_conf.systimer_rst_en = 1;
|
||||
PCR.systimer_conf.systimer_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
28
components/esp_hal_systimer/esp32c6/rom.systimer.ld
Normal file
28
components/esp_hal_systimer/esp32c6/rom.systimer.ld
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* systimer_hal_init = 0x400003c0; */
|
||||
/* systimer_hal_deinit = 0x400003c4; */
|
||||
|
||||
systimer_hal_set_tick_rate_ops = 0x400003c8;
|
||||
systimer_hal_get_counter_value = 0x400003cc;
|
||||
systimer_hal_get_time = 0x400003d0;
|
||||
systimer_hal_set_alarm_target = 0x400003d4;
|
||||
systimer_hal_set_alarm_period = 0x400003d8;
|
||||
systimer_hal_get_alarm_value = 0x400003dc;
|
||||
systimer_hal_enable_alarm_int = 0x400003e0;
|
||||
systimer_hal_on_apb_freq_update = 0x400003e4;
|
||||
systimer_hal_counter_value_advance = 0x400003e8;
|
||||
systimer_hal_enable_counter = 0x400003ec;
|
||||
systimer_hal_select_alarm_mode = 0x400003f0;
|
||||
systimer_hal_connect_alarm_counter = 0x400003f4;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x400003f8;
|
||||
218
components/esp_hal_systimer/esp32c61/include/hal/systimer_ll.h
Normal file
218
components/esp_hal_systimer/esp32c61/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
PCR.systimer_func_clk_conf.systimer_func_clk_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (PCR.systimer_func_clk_conf.systimer_func_clk_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.systimer_conf.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
PCR.systimer_conf.systimer_rst_en = 1;
|
||||
PCR.systimer_conf.systimer_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
29
components/esp_hal_systimer/esp32c61/rom.systimer.ld
Normal file
29
components/esp_hal_systimer/esp32c61/rom.systimer.ld
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* systimer_hal_init = 0x400003d0; */
|
||||
/* systimer_hal_deinit = 0x400003d4; */
|
||||
|
||||
systimer_hal_set_tick_rate_ops = 0x400003d8;
|
||||
systimer_hal_get_counter_value = 0x400003dc;
|
||||
systimer_hal_get_time = 0x400003e0;
|
||||
systimer_hal_set_alarm_target = 0x400003e4;
|
||||
systimer_hal_set_alarm_period = 0x400003e8;
|
||||
systimer_hal_get_alarm_value = 0x400003ec;
|
||||
systimer_hal_enable_alarm_int = 0x400003f0;
|
||||
systimer_hal_on_apb_freq_update = 0x400003f4;
|
||||
systimer_hal_counter_value_advance = 0x400003f8;
|
||||
systimer_hal_enable_counter = 0x400003fc;
|
||||
systimer_hal_select_alarm_mode = 0x40000400;
|
||||
systimer_hal_connect_alarm_counter = 0x40000404;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x40000408;
|
||||
218
components/esp_hal_systimer/esp32h2/include/hal/systimer_ll.h
Normal file
218
components/esp_hal_systimer/esp32h2/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed to 2 when clock source is XTAL
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
PCR.systimer_func_clk_conf.systimer_func_clk_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (PCR.systimer_func_clk_conf.systimer_func_clk_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.systimer_conf.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
PCR.systimer_conf.systimer_rst_en = 1;
|
||||
PCR.systimer_conf.systimer_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
28
components/esp_hal_systimer/esp32h2/rom.systimer.ld
Normal file
28
components/esp_hal_systimer/esp32h2/rom.systimer.ld
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* systimer_hal_init = 0x400003b8; */
|
||||
/* systimer_hal_deinit = 0x400003bc; */
|
||||
|
||||
systimer_hal_set_tick_rate_ops = 0x400003c0;
|
||||
systimer_hal_get_counter_value = 0x400003c4;
|
||||
systimer_hal_get_time = 0x400003c8;
|
||||
systimer_hal_set_alarm_target = 0x400003cc;
|
||||
systimer_hal_set_alarm_period = 0x400003d0;
|
||||
systimer_hal_get_alarm_value = 0x400003d4;
|
||||
systimer_hal_enable_alarm_int = 0x400003d8;
|
||||
systimer_hal_on_apb_freq_update = 0x400003dc;
|
||||
systimer_hal_counter_value_advance = 0x400003e0;
|
||||
systimer_hal_enable_counter = 0x400003e4;
|
||||
systimer_hal_select_alarm_mode = 0x400003e8;
|
||||
systimer_hal_connect_alarm_counter = 0x400003ec;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x400003f0;
|
||||
218
components/esp_hal_systimer/esp32h21/include/hal/systimer_ll.h
Normal file
218
components/esp_hal_systimer/esp32h21/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed to 2 when clock source is XTAL
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
PCR.systimer_func_clk_conf.systimer_func_clk_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (PCR.systimer_func_clk_conf.systimer_func_clk_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.systimer_conf.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
PCR.systimer_conf.systimer_rst_en = 1;
|
||||
PCR.systimer_conf.systimer_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
27
components/esp_hal_systimer/esp32h21/rom.systimer.ld
Normal file
27
components/esp_hal_systimer/esp32h21/rom.systimer.ld
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* systimer_hal_init = 0x400003b8; */
|
||||
/* systimer_hal_deinit = 0x400003bc; */
|
||||
systimer_hal_set_tick_rate_ops = 0x400003c0;
|
||||
systimer_hal_get_counter_value = 0x400003c4;
|
||||
systimer_hal_get_time = 0x400003c8;
|
||||
systimer_hal_set_alarm_target = 0x400003cc;
|
||||
systimer_hal_set_alarm_period = 0x400003d0;
|
||||
systimer_hal_get_alarm_value = 0x400003d4;
|
||||
systimer_hal_enable_alarm_int = 0x400003d8;
|
||||
systimer_hal_on_apb_freq_update = 0x400003dc;
|
||||
systimer_hal_counter_value_advance = 0x400003e0;
|
||||
systimer_hal_enable_counter = 0x400003e4;
|
||||
systimer_hal_select_alarm_mode = 0x400003e8;
|
||||
systimer_hal_connect_alarm_counter = 0x400003ec;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x400003f0;
|
||||
218
components/esp_hal_systimer/esp32h4/include/hal/systimer_ll.h
Normal file
218
components/esp_hal_systimer/esp32h4/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
PCR.systimer_func_clk_conf.systimer_func_clk_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (PCR.systimer_func_clk_conf.systimer_func_clk_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.systimer_conf.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
PCR.systimer_conf.systimer_rst_en = 1;
|
||||
PCR.systimer_conf.systimer_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
37
components/esp_hal_systimer/esp32h4/rom.systimer.ld
Normal file
37
components/esp_hal_systimer/esp32h4/rom.systimer.ld
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ROM function interface esp32h4.rom.systimer.ld for esp32h4
|
||||
*
|
||||
*
|
||||
* Generated from ../../rom/target/esp32h4/interface-esp32h4.yml md5sum bb9ee317148d3c5b10610936a3675a65
|
||||
*
|
||||
* Compatible with ROM where ECO version equal or greater to 0.
|
||||
*
|
||||
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
*/
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* systimer_hal_init = 0x4000036c; */
|
||||
/* systimer_hal_deinit = 0x40000370; */
|
||||
|
||||
systimer_hal_set_tick_rate_ops = 0x40000374;
|
||||
systimer_hal_get_counter_value = 0x40000378;
|
||||
systimer_hal_get_time = 0x4000037c;
|
||||
systimer_hal_set_alarm_target = 0x40000380;
|
||||
systimer_hal_set_alarm_period = 0x40000384;
|
||||
systimer_hal_get_alarm_value = 0x40000388;
|
||||
systimer_hal_enable_alarm_int = 0x4000038c;
|
||||
systimer_hal_on_apb_freq_update = 0x40000390;
|
||||
systimer_hal_counter_value_advance = 0x40000394;
|
||||
systimer_hal_enable_counter = 0x40000398;
|
||||
systimer_hal_select_alarm_mode = 0x4000039c;
|
||||
systimer_hal_connect_alarm_counter = 0x400003a0;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x400003a4;
|
||||
225
components/esp_hal_systimer/esp32p4/include/hal/systimer_ll.h
Normal file
225
components/esp_hal_systimer/esp32p4/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/hp_sys_clkrst_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
HP_SYS_CLKRST.peri_clk_ctrl21.reg_systimer_clk_src_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_set_clock_source(...) do { \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||
systimer_ll_set_clock_source(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (HP_SYS_CLKRST.peri_clk_ctrl21.reg_systimer_clk_src_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
HP_SYS_CLKRST.soc_clk_ctrl2.reg_systimer_apb_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_stimer = 1;
|
||||
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_stimer = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
28
components/esp_hal_systimer/esp32p4/rom.systimer.ld
Normal file
28
components/esp_hal_systimer/esp32p4/rom.systimer.ld
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
/* The following ROM functions are commented out because they're patched in the rom_patch.c */
|
||||
/* systimer_hal_init = 0x4fc00228; */
|
||||
/* systimer_hal_deinit = 0x4fc0022c; */
|
||||
systimer_hal_set_tick_rate_ops = 0x4fc00230;
|
||||
systimer_hal_get_counter_value = 0x4fc00234;
|
||||
systimer_hal_get_time = 0x4fc00238;
|
||||
systimer_hal_set_alarm_target = 0x4fc0023c;
|
||||
systimer_hal_set_alarm_period = 0x4fc00240;
|
||||
systimer_hal_get_alarm_value = 0x4fc00244;
|
||||
systimer_hal_enable_alarm_int = 0x4fc00248;
|
||||
systimer_hal_on_apb_freq_update = 0x4fc0024c;
|
||||
systimer_hal_counter_value_advance = 0x4fc00250;
|
||||
systimer_hal_enable_counter = 0x4fc00254;
|
||||
systimer_hal_select_alarm_mode = 0x4fc00258;
|
||||
systimer_hal_connect_alarm_counter = 0x4fc0025c;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x4fc00260;
|
||||
220
components/esp_hal_systimer/esp32s2/include/hal/systimer_ll.h
Normal file
220
components/esp_hal_systimer/esp32s2/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 1 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 32 // Bit width of systimer high part
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
(void)clk_src;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
uint32_t reg_val = READ_PERI_REG(DPORT_PERIP_CLK_EN0_REG);
|
||||
reg_val &= ~DPORT_SYSTIMER_CLK_EN_M;
|
||||
reg_val |= enable << DPORT_SYSTIMER_CLK_EN_S;
|
||||
WRITE_PERI_REG(DPORT_PERIP_CLK_EN0_REG, reg_val);
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, DPORT_SYSTIMER_RST_M);
|
||||
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, 0);
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
// ESP32-S2 only has one counter in systimer group
|
||||
(void)dev;
|
||||
(void)counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
(void)dev;
|
||||
(void)counter_id;
|
||||
(void)cpu_id;
|
||||
(void)can;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
(void)counter_id;
|
||||
dev->update.timer_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
(void)counter_id;
|
||||
return dev->update.timer_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
(void)counter_id;
|
||||
dev->load_hi.timer_load_hi = value >> 32;
|
||||
dev->load_lo.timer_load_lo = value;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->value_lo.timer_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->value_hi.timer_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->load.timer_load = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_step_for_pll(systimer_dev_t *dev, uint32_t step)
|
||||
{
|
||||
dev->step.timer_pll_step = step;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_step_for_xtal(systimer_dev_t *dev, uint32_t step)
|
||||
{
|
||||
dev->step.timer_xtal_step = step;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
// On esp32-s2, counter int the systimer is fixed connectred to other three alarm comparators
|
||||
(void)dev;
|
||||
(void)alarm_id;
|
||||
(void)counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 30));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
(void)dev;
|
||||
(void)alarm_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_work_en = en;
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_raw.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
210
components/esp_hal_systimer/esp32s3/include/hal/systimer_ll.h
Normal file
210
components/esp_hal_systimer/esp32s3/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/system_struct.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
(void)clk_src;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
SYSTEM.perip_clk_en0.systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
SYSTEM.perip_rst_en0.systimer_rst = 1;
|
||||
SYSTEM.perip_rst_en0.systimer_rst = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||
systimer_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
17
components/esp_hal_systimer/esp32s3/rom.systimer.ld
Normal file
17
components/esp_hal_systimer/esp32s3/rom.systimer.ld
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
PROVIDE( systimer_hal_get_counter_value = 0x40000e40 );
|
||||
PROVIDE( systimer_hal_get_time = 0x40000e4c );
|
||||
PROVIDE( systimer_hal_set_alarm_target = 0x40000e58 );
|
||||
PROVIDE( systimer_hal_set_alarm_period = 0x40000e64 );
|
||||
PROVIDE( systimer_hal_get_alarm_value = 0x40000e70 );
|
||||
PROVIDE( systimer_hal_enable_alarm_int = 0x40000e7c );
|
||||
PROVIDE( systimer_hal_on_apb_freq_update = 0x40000e88 );
|
||||
PROVIDE( systimer_hal_counter_value_advance = 0x40000e94 );
|
||||
PROVIDE( systimer_hal_enable_counter = 0x40000ea0 );
|
||||
PROVIDE( systimer_hal_init = 0x40000eac );
|
||||
PROVIDE( systimer_hal_select_alarm_mode = 0x40000eb8 );
|
||||
PROVIDE( systimer_hal_connect_alarm_counter = 0x40000ec4 );
|
||||
232
components/esp_hal_systimer/esp32s31/include/hal/systimer_ll.h
Normal file
232
components/esp_hal_systimer/esp32s31/include/hal/systimer_ll.h
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/systimer_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/hp_sys_clkrst_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
// TODO: [ESP32S31] IDF-14693
|
||||
|
||||
/******************* SYSTIMER LL CAPS *************************/
|
||||
#define SYSTIMER_LL_COUNTER_NUM 2 // Number of counter units
|
||||
#define SYSTIMER_LL_ALARM_NUM 3 // Number of alarm units
|
||||
#define SYSTIMER_LL_BIT_WIDTH_LO 32 // Bit width of systimer low part
|
||||
#define SYSTIMER_LL_BIT_WIDTH_HI 20 // Bit width of systimer high part
|
||||
#define SYSTIMER_LL_INT_LEVEL 1 // Systimer peripheral uses level interrupt
|
||||
#define SYSTIMER_LL_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SYSTIMER_LL_FIXED_DIVIDER 1 // Clock source divider is fixed: 2.5
|
||||
|
||||
/******************* Clock *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.clk_en = en;
|
||||
}
|
||||
|
||||
// Set clock source: XTAL(default) or RC_FAST
|
||||
static inline void systimer_ll_set_clock_source(soc_periph_systimer_clk_src_t clk_src)
|
||||
{
|
||||
HP_SYS_CLKRST.systimer_ctrl0.reg_systimer_clk_src_sel = (clk_src == SYSTIMER_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline soc_periph_systimer_clk_src_t systimer_ll_get_clock_source(void)
|
||||
{
|
||||
return (HP_SYS_CLKRST.systimer_ctrl0.reg_systimer_clk_src_sel == 1) ? SYSTIMER_CLK_SRC_RC_FAST : SYSTIMER_CLK_SRC_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the sys clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_sys_clock(bool enable)
|
||||
{
|
||||
HP_SYS_CLKRST.systimer_ctrl0.reg_systimer_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_sys_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; systimer_ll_enable_sys_clock(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for systimer module
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void systimer_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
HP_SYS_CLKRST.systimer_ctrl0.reg_systimer_apb_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; systimer_ll_enable_bus_clock(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Reset the systimer module
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void systimer_ll_reset_register(void)
|
||||
{
|
||||
HP_SYS_CLKRST.systimer_ctrl0.reg_systimer_rst_en = 1;
|
||||
HP_SYS_CLKRST.systimer_ctrl0.reg_systimer_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define systimer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; systimer_ll_reset_register(__VA_ARGS__)
|
||||
|
||||
/********************** ETM *****************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_etm(systimer_dev_t *dev, bool en)
|
||||
{
|
||||
dev->conf.etm_en = en;
|
||||
}
|
||||
|
||||
/******************* Counter *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(systimer_dev_t *dev, uint32_t counter_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (30 - counter_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (30 - counter_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(systimer_dev_t *dev, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
dev->conf.val |= 1 << ((28 - counter_id * 2) - cpu_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_op[counter_id].timer_unit_update = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
return dev->unit_op[counter_id].timer_unit_value_valid;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(systimer_dev_t *dev, uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
dev->unit_load_val[counter_id].hi.timer_unit_load_hi = value >> 32;
|
||||
dev->unit_load_val[counter_id].lo.timer_unit_load_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
(void)counter_id;
|
||||
return dev->unit_val[counter_id].lo.timer_unit_value_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
(void)counter_id;
|
||||
return dev->unit_val[counter_id].hi.timer_unit_value_hi;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(systimer_dev_t *dev, uint32_t counter_id)
|
||||
{
|
||||
dev->unit_load[counter_id].val = 0x01;
|
||||
}
|
||||
|
||||
/******************* Alarm *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(systimer_dev_t *dev, uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
dev->target_val[alarm_id].hi.timer_target_hi = value >> 32;
|
||||
dev->target_val[alarm_id].lo.timer_target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t)(dev->target_val[alarm_id].hi.timer_target_hi) << 32) | dev->target_val[alarm_id].lo.timer_target_lo;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(systimer_dev_t *dev, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_timer_unit_sel = counter_id;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->target_conf[alarm_id].target_period_mode = 1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(systimer_dev_t *dev, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
HAL_ASSERT(period < (1 << 26));
|
||||
dev->target_conf[alarm_id].target_period = period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
return dev->target_conf[alarm_id].target_period;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
dev->comp_load[alarm_id].val = 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->conf.val |= 1 << (24 - alarm_id);
|
||||
} else {
|
||||
dev->conf.val &= ~(1 << (24 - alarm_id));
|
||||
}
|
||||
}
|
||||
|
||||
/******************* Interrupt *************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(systimer_dev_t *dev, uint32_t alarm_id, bool en)
|
||||
{
|
||||
if (en) {
|
||||
dev->int_ena.val |= 1 << alarm_id;
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << alarm_id);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
(void)alarm_id;
|
||||
return dev->int_st.val & (1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(systimer_dev_t *dev, uint32_t alarm_id)
|
||||
{
|
||||
(void)alarm_id;
|
||||
dev->int_clr.val |= 1 << alarm_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
35
components/esp_hal_systimer/esp32s31/rom.systimer.ld
Normal file
35
components/esp_hal_systimer/esp32s31/rom.systimer.ld
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ROM function interface esp32s31.rom.systimer.ld for esp32s31
|
||||
*
|
||||
*
|
||||
* Generated from ../../rom/target/esp32s31/interface-esp32s31.yml md5sum 0cb775308c66eebf0757e406021ad5be
|
||||
*
|
||||
* Compatible with ROM where ECO version equal or greater to 0.
|
||||
*
|
||||
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
*/
|
||||
|
||||
/***************************************
|
||||
Group hal_systimer
|
||||
***************************************/
|
||||
|
||||
/* Functions */
|
||||
systimer_hal_init = 0x2f800394;
|
||||
systimer_hal_deinit = 0x2f800398;
|
||||
systimer_hal_set_tick_rate_ops = 0x2f80039c;
|
||||
systimer_hal_get_counter_value = 0x2f8003a0;
|
||||
systimer_hal_get_time = 0x2f8003a4;
|
||||
systimer_hal_set_alarm_target = 0x2f8003a8;
|
||||
systimer_hal_set_alarm_period = 0x2f8003ac;
|
||||
systimer_hal_get_alarm_value = 0x2f8003b0;
|
||||
systimer_hal_enable_alarm_int = 0x2f8003b4;
|
||||
systimer_hal_on_apb_freq_update = 0x2f8003b8;
|
||||
systimer_hal_counter_value_advance = 0x2f8003bc;
|
||||
systimer_hal_enable_counter = 0x2f8003c0;
|
||||
systimer_hal_select_alarm_mode = 0x2f8003c4;
|
||||
systimer_hal_connect_alarm_counter = 0x2f8003c8;
|
||||
systimer_hal_counter_can_stall_by_cpu = 0x2f8003cc;
|
||||
139
components/esp_hal_systimer/include/hal/systimer_hal.h
Normal file
139
components/esp_hal_systimer/include/hal/systimer_hal.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hal/systimer_types.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#if SOC_SYSTIMER_SUPPORTED
|
||||
#include "hal/systimer_ll.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct systimer_dev_t *systimer_soc_handle_t; // systimer SOC layer handle
|
||||
|
||||
// the definitions of the following functions are provided by esp_hw_support component, see esp_hw_support/port/${TARGET}/systimer.c
|
||||
typedef uint64_t (*ticks_to_us_func_t)(uint64_t ticks); // prototype of function to convert ticks to microseconds
|
||||
typedef uint64_t (*us_to_ticks_func_t)(uint64_t us); // prototype of function to convert microseconds to ticks
|
||||
|
||||
/**
|
||||
* @brief systimer HAL context structure
|
||||
*/
|
||||
typedef struct {
|
||||
systimer_soc_handle_t dev; /*!< systimer peripheral base address */
|
||||
ticks_to_us_func_t ticks_to_us; /*!< function to convert ticks to microseconds */
|
||||
us_to_ticks_func_t us_to_ticks; /*!< function to convert microseconds to ticks */
|
||||
} systimer_hal_context_t;
|
||||
|
||||
/**
|
||||
* @brief systimer HAL configuration structure
|
||||
*/
|
||||
typedef struct {
|
||||
ticks_to_us_func_t ticks_to_us; /*!< function to convert ticks to microseconds */
|
||||
us_to_ticks_func_t us_to_ticks; /*!< function to convert microseconds to ticks */
|
||||
} systimer_hal_tick_rate_ops_t;
|
||||
|
||||
/**
|
||||
* @brief Systimer clock source
|
||||
*/
|
||||
typedef soc_periph_systimer_clk_src_t systimer_clock_source_t;
|
||||
|
||||
/**
|
||||
* @brief initialize systimer in HAL layer
|
||||
*/
|
||||
void systimer_hal_init(systimer_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize systimer HAL layer
|
||||
*/
|
||||
void systimer_hal_deinit(systimer_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Set tick rate operation functions
|
||||
*/
|
||||
void systimer_hal_set_tick_rate_ops(systimer_hal_context_t *hal, systimer_hal_tick_rate_ops_t *ops);
|
||||
|
||||
/**
|
||||
* @brief enable systimer counter
|
||||
*/
|
||||
void systimer_hal_enable_counter(systimer_hal_context_t *hal, uint32_t counter_id);
|
||||
|
||||
/**
|
||||
* @brief get current counter value
|
||||
*/
|
||||
uint64_t systimer_hal_get_counter_value(systimer_hal_context_t *hal, uint32_t counter_id);
|
||||
|
||||
/**
|
||||
* @brief get current time (in microseconds)
|
||||
*/
|
||||
uint64_t systimer_hal_get_time(systimer_hal_context_t *hal, uint32_t counter_id);
|
||||
|
||||
/*
|
||||
* @brief set alarm target value (used in one-shot mode)
|
||||
*/
|
||||
void systimer_hal_set_alarm_target(systimer_hal_context_t *hal, uint32_t alarm_id, uint64_t target);
|
||||
|
||||
/**
|
||||
* @brief set alarm period value (used in period mode)
|
||||
*/
|
||||
void systimer_hal_set_alarm_period(systimer_hal_context_t *hal, uint32_t alarm_id, uint32_t period);
|
||||
|
||||
/**
|
||||
* @brief get alarm time
|
||||
*/
|
||||
uint64_t systimer_hal_get_alarm_value(systimer_hal_context_t *hal, uint32_t alarm_id);
|
||||
|
||||
/**
|
||||
* @brief enable alarm interrupt
|
||||
*/
|
||||
void systimer_hal_enable_alarm_int(systimer_hal_context_t *hal, uint32_t alarm_id);
|
||||
|
||||
/**
|
||||
* @brief select alarm mode
|
||||
*/
|
||||
void systimer_hal_select_alarm_mode(systimer_hal_context_t *hal, uint32_t alarm_id, systimer_alarm_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief update systimer step when apb clock gets changed
|
||||
*/
|
||||
void systimer_hal_on_apb_freq_update(systimer_hal_context_t *hal, uint32_t apb_ticks_per_us);
|
||||
|
||||
/**
|
||||
* @brief move systimer counter value forward or backward
|
||||
*/
|
||||
void systimer_hal_counter_value_advance(systimer_hal_context_t *hal, uint32_t counter_id, int64_t time_us);
|
||||
|
||||
/**
|
||||
* @brief connect alarm unit to selected counter
|
||||
*/
|
||||
void systimer_hal_connect_alarm_counter(systimer_hal_context_t *hal, uint32_t alarm_id, uint32_t counter_id);
|
||||
|
||||
/**
|
||||
* @brief set if a counter should be stalled when CPU is halted by the debugger
|
||||
*/
|
||||
void systimer_hal_counter_can_stall_by_cpu(systimer_hal_context_t *hal, uint32_t counter_id, uint32_t cpu_id, bool can);
|
||||
|
||||
#if !SYSTIMER_LL_FIXED_DIVIDER
|
||||
/**
|
||||
* @brief set increase steps for systimer counter on different clock source
|
||||
*/
|
||||
void systimer_hal_set_steps_per_tick(systimer_hal_context_t *hal, int clock_source, uint32_t steps);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get Systimer clock source
|
||||
*/
|
||||
systimer_clock_source_t systimer_hal_get_clock_source(systimer_hal_context_t *hal);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
53
components/esp_hal_systimer/include/hal/systimer_types.h
Normal file
53
components/esp_hal_systimer/include/hal/systimer_types.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @brief The structure of the counter value in systimer
|
||||
*
|
||||
*/
|
||||
#if SOC_SYSTIMER_SUPPORTED
|
||||
#include "hal/systimer_ll.h"
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint64_t lo : SYSTIMER_LL_BIT_WIDTH_LO; /*!< Low part of counter value */
|
||||
uint64_t hi : SYSTIMER_LL_BIT_WIDTH_HI; /*!< High part of counter value */
|
||||
#if (SYSTIMER_LL_BIT_WIDTH_LO + SYSTIMER_LL_BIT_WIDTH_HI) < 64
|
||||
uint64_t reserved: (64 - (SYSTIMER_LL_BIT_WIDTH_LO + SYSTIMER_LL_BIT_WIDTH_HI));
|
||||
#endif
|
||||
};
|
||||
uint64_t val; /*!< counter value */
|
||||
};
|
||||
} systimer_counter_value_t;
|
||||
|
||||
/** @cond */
|
||||
ESP_STATIC_ASSERT(sizeof(systimer_counter_value_t) == 8, "systimer_counter_value_t should occupy 8 bytes in memory");
|
||||
/** @endcond */
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief systimer alarm mode
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SYSTIMER_ALARM_MODE_ONESHOT, /*!< systimer alarm oneshot mode */
|
||||
SYSTIMER_ALARM_MODE_PERIOD, /*!< systimer alarm period mode */
|
||||
} systimer_alarm_mode_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
6
components/esp_hal_systimer/linker.lf
Normal file
6
components/esp_hal_systimer/linker.lf
Normal file
@@ -0,0 +1,6 @@
|
||||
[mapping:esp_hal_systimer]
|
||||
archive: libesp_hal_systimer.a
|
||||
entries:
|
||||
if SOC_SYSTIMER_SUPPORTED = y:
|
||||
# All systimer HAL code must be in IRAM for ISR safety and cache-disabled operation
|
||||
* (noflash)
|
||||
37
components/esp_hal_systimer/rom_patch.c
Normal file
37
components/esp_hal_systimer/rom_patch.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief ROM patch for systimer HAL
|
||||
*
|
||||
* Some chips have systimer HAL implementations in ROM that require patches.
|
||||
* This file provides the necessary patches when ROM implementation is used.
|
||||
*
|
||||
* For chips with ESP_ROM_SYSTIMER_INIT_PATCH defined (e.g., ESP32-C5, ESP32-C6,
|
||||
* ESP32-H2, ESP32-P4), the ROM systimer_hal_init/deinit functions do not
|
||||
* enable ETM, so we need to patch them here.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "esp_rom_caps.h"
|
||||
#include "hal/systimer_hal.h"
|
||||
#include "hal/systimer_ll.h"
|
||||
|
||||
#if ESP_ROM_SYSTIMER_INIT_PATCH
|
||||
void systimer_hal_init(systimer_hal_context_t *hal)
|
||||
{
|
||||
hal->dev = &SYSTIMER;
|
||||
systimer_ll_enable_clock(hal->dev, true);
|
||||
systimer_ll_enable_etm(&SYSTIMER, true);
|
||||
}
|
||||
|
||||
void systimer_hal_deinit(systimer_hal_context_t *hal)
|
||||
{
|
||||
systimer_ll_enable_etm(&SYSTIMER, false);
|
||||
systimer_ll_enable_clock(hal->dev, false);
|
||||
hal->dev = NULL;
|
||||
}
|
||||
#endif // ESP_ROM_SYSTIMER_INIT_PATCH
|
||||
204
components/esp_hal_systimer/systimer_hal.c
Normal file
204
components/esp_hal_systimer/systimer_hal.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/param.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/systimer_hal.h"
|
||||
#include "hal/systimer_types.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
void systimer_hal_init(systimer_hal_context_t *hal)
|
||||
{
|
||||
hal->dev = &SYSTIMER;
|
||||
systimer_ll_enable_clock(hal->dev, true);
|
||||
#if SOC_SYSTIMER_SUPPORT_ETM
|
||||
systimer_ll_enable_etm(&SYSTIMER, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void systimer_hal_deinit(systimer_hal_context_t *hal)
|
||||
{
|
||||
#if SOC_SYSTIMER_SUPPORT_ETM
|
||||
systimer_ll_enable_etm(&SYSTIMER, false);
|
||||
#endif
|
||||
systimer_ll_enable_clock(hal->dev, false);
|
||||
hal->dev = NULL;
|
||||
}
|
||||
|
||||
systimer_clock_source_t systimer_hal_get_clock_source(systimer_hal_context_t *hal)
|
||||
{
|
||||
(void)hal;
|
||||
return systimer_ll_get_clock_source();
|
||||
}
|
||||
|
||||
void systimer_hal_set_tick_rate_ops(systimer_hal_context_t *hal, systimer_hal_tick_rate_ops_t *ops)
|
||||
{
|
||||
hal->ticks_to_us = ops->ticks_to_us;
|
||||
hal->us_to_ticks = ops->us_to_ticks;
|
||||
}
|
||||
|
||||
uint64_t systimer_hal_get_counter_value(systimer_hal_context_t *hal, uint32_t counter_id)
|
||||
{
|
||||
uint32_t lo, lo_start, hi;
|
||||
/* Set the "update" bit and wait for acknowledgment */
|
||||
systimer_ll_counter_snapshot(hal->dev, counter_id);
|
||||
while (!systimer_ll_is_counter_value_valid(hal->dev, counter_id));
|
||||
/* Read LO, HI, then LO again, check that LO returns the same value.
|
||||
* This accounts for the case when an interrupt may happen between reading
|
||||
* HI and LO values, and this function may get called from the ISR.
|
||||
* In this case, the repeated read will return consistent values.
|
||||
*/
|
||||
lo_start = systimer_ll_get_counter_value_low(hal->dev, counter_id);
|
||||
do {
|
||||
lo = lo_start;
|
||||
hi = systimer_ll_get_counter_value_high(hal->dev, counter_id);
|
||||
lo_start = systimer_ll_get_counter_value_low(hal->dev, counter_id);
|
||||
} while (lo_start != lo);
|
||||
|
||||
systimer_counter_value_t result = {
|
||||
.lo = lo,
|
||||
.hi = hi
|
||||
};
|
||||
|
||||
return result.val;
|
||||
}
|
||||
|
||||
uint64_t systimer_hal_get_time(systimer_hal_context_t *hal, uint32_t counter_id)
|
||||
{
|
||||
return hal->ticks_to_us(systimer_hal_get_counter_value(hal, counter_id));
|
||||
}
|
||||
|
||||
#if SYSTIMER_LL_ALARM_MISS_COMPENSATE
|
||||
void systimer_hal_set_alarm_target(systimer_hal_context_t *hal, uint32_t alarm_id, uint64_t target)
|
||||
{
|
||||
systimer_counter_value_t alarm = {
|
||||
.val = hal->us_to_ticks(target),
|
||||
};
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, false);
|
||||
systimer_ll_set_alarm_target(hal->dev, alarm_id, alarm.val);
|
||||
systimer_ll_apply_alarm_value(hal->dev, alarm_id);
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, true);
|
||||
}
|
||||
|
||||
#else // SYSTIMER_LL_ALARM_MISS_COMPENSATE
|
||||
|
||||
void systimer_hal_set_alarm_target(systimer_hal_context_t *hal, uint32_t alarm_id, uint64_t timestamp)
|
||||
{
|
||||
int64_t offset = hal->us_to_ticks(1) * 2;
|
||||
uint64_t now_time = systimer_hal_get_counter_value(hal, 0);
|
||||
uint64_t timestamp_ticks = hal->us_to_ticks(timestamp);
|
||||
systimer_counter_value_t alarm = { .val = MAX(timestamp_ticks, now_time + offset) };
|
||||
do {
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, false);
|
||||
systimer_ll_set_alarm_target(hal->dev, alarm_id, alarm.val);
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, true);
|
||||
now_time = systimer_hal_get_counter_value(hal, 0);
|
||||
int64_t delta = (int64_t)alarm.val - (int64_t)now_time;
|
||||
if (delta <= 0 && !systimer_ll_is_alarm_int_fired(hal->dev, alarm_id)) {
|
||||
// new alarm is less than the counter and the interrupt flag is not set
|
||||
offset += -1 * delta + hal->us_to_ticks(1) * 2;
|
||||
alarm.val = now_time + offset;
|
||||
} else {
|
||||
// finish if either (alarm > counter) or the interrupt flag is already set.
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
#endif // SYSTIMER_LL_ALARM_MISS_COMPENSATE
|
||||
|
||||
void systimer_hal_set_alarm_period(systimer_hal_context_t *hal, uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, false);
|
||||
systimer_ll_set_alarm_period(hal->dev, alarm_id, hal->us_to_ticks(period));
|
||||
systimer_ll_apply_alarm_value(hal->dev, alarm_id);
|
||||
systimer_ll_enable_alarm(hal->dev, alarm_id, true);
|
||||
}
|
||||
|
||||
uint64_t systimer_hal_get_alarm_value(systimer_hal_context_t *hal, uint32_t alarm_id)
|
||||
{
|
||||
return systimer_ll_get_alarm_target(hal->dev, alarm_id);
|
||||
}
|
||||
|
||||
void systimer_hal_enable_alarm_int(systimer_hal_context_t *hal, uint32_t alarm_id)
|
||||
{
|
||||
systimer_ll_enable_alarm_int(hal->dev, alarm_id, true);
|
||||
}
|
||||
|
||||
void systimer_hal_counter_value_advance(systimer_hal_context_t *hal, uint32_t counter_id, int64_t time_us)
|
||||
{
|
||||
systimer_counter_value_t new_count = {
|
||||
.val = systimer_hal_get_counter_value(hal, counter_id) + hal->us_to_ticks(time_us),
|
||||
};
|
||||
systimer_ll_set_counter_value(hal->dev, counter_id, new_count.val);
|
||||
systimer_ll_apply_counter_value(hal->dev, counter_id);
|
||||
}
|
||||
|
||||
void systimer_hal_enable_counter(systimer_hal_context_t *hal, uint32_t counter_id)
|
||||
{
|
||||
systimer_ll_enable_counter(hal->dev, counter_id, true);
|
||||
}
|
||||
|
||||
void systimer_hal_select_alarm_mode(systimer_hal_context_t *hal, uint32_t alarm_id, systimer_alarm_mode_t mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case SYSTIMER_ALARM_MODE_ONESHOT:
|
||||
systimer_ll_enable_alarm_oneshot(hal->dev, alarm_id);
|
||||
break;
|
||||
case SYSTIMER_ALARM_MODE_PERIOD:
|
||||
systimer_ll_enable_alarm_period(hal->dev, alarm_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void systimer_hal_connect_alarm_counter(systimer_hal_context_t *hal, uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
systimer_ll_connect_alarm_counter(hal->dev, alarm_id, counter_id);
|
||||
}
|
||||
|
||||
void systimer_hal_counter_can_stall_by_cpu(systimer_hal_context_t *hal, uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
systimer_ll_counter_can_stall_by_cpu(hal->dev, counter_id, cpu_id, can);
|
||||
}
|
||||
|
||||
#if !SYSTIMER_LL_FIXED_DIVIDER
|
||||
|
||||
void systimer_hal_set_steps_per_tick(systimer_hal_context_t *hal, int clock_source, uint32_t steps)
|
||||
{
|
||||
/* Configure the counter:
|
||||
* - increment by 1 when running from PLL (80 ticks per microsecond),
|
||||
* - increment by 2 when running from XTAL (40 ticks per microsecond).
|
||||
* Note that if the APB frequency is derived from XTAL with divider != 1,
|
||||
* XTAL_STEP needs to be adjusted accordingly. For example, if
|
||||
* the APB frequency is XTAL/4 = 10 MHz, then XTAL_STEP should be set to 8.
|
||||
* This is handled in systimer_hal_on_apb_freq_update function.
|
||||
*/
|
||||
switch (clock_source) {
|
||||
case 0:
|
||||
systimer_ll_set_step_for_xtal(hal->dev, steps);
|
||||
break;
|
||||
case 1:
|
||||
systimer_ll_set_step_for_pll(hal->dev, steps);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void systimer_hal_on_apb_freq_update(systimer_hal_context_t *hal, uint32_t apb_ticks_per_us)
|
||||
{
|
||||
/* If this function was called when switching APB clock to PLL, don't need
|
||||
* do anything: the SYSTIMER_TIMER_PLL_STEP is already correct.
|
||||
* If this was called when switching APB clock to XTAL, need to adjust
|
||||
* XTAL_STEP value accordingly.
|
||||
*/
|
||||
if (apb_ticks_per_us != hal->us_to_ticks(1)) {
|
||||
HAL_ASSERT((hal->us_to_ticks(1) % apb_ticks_per_us) == 0 && "TICK_PER_US should be divisible by APB frequency (in MHz)");
|
||||
systimer_ll_set_step_for_xtal(hal->dev, hal->us_to_ticks(1) / apb_ticks_per_us);
|
||||
}
|
||||
}
|
||||
#endif // !SYSTIMER_LL_FIXED_DIVIDER
|
||||
@@ -0,0 +1,9 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
set(COMPONENTS main)
|
||||
|
||||
project(systimer_rom_impl)
|
||||
@@ -0,0 +1,26 @@
|
||||
| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
# esp_hal_systimer ROM implementation test app
|
||||
|
||||
This test app verifies that the systimer HAL is correctly linked from either ROM or the component implementation, depending on `CONFIG_HAL_SYSTIMER_USE_ROM_IMPL`.
|
||||
|
||||
## Configurations
|
||||
|
||||
- **rom_impl**: Builds with `CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=y`, tests that `systimer_hal_get_counter_value` is in ROM.
|
||||
- **no_rom_impl**: Builds with `CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=n`, tests that the function is not in ROM.
|
||||
|
||||
## Building and running
|
||||
|
||||
```bash
|
||||
idf.py set-target <target>
|
||||
idf.py build flash monitor
|
||||
```
|
||||
|
||||
To run with pytest:
|
||||
|
||||
```bash
|
||||
idf.py set-target <target>
|
||||
idf.py build
|
||||
pytest --target=<target>
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
set(srcs "test_app_main.c")
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES unity esp_hal_systimer
|
||||
WHOLE_ARCHIVE)
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/systimer_hal.h"
|
||||
|
||||
static bool fn_in_rom(void *fn)
|
||||
{
|
||||
const int fnaddr = (int)fn;
|
||||
return (fnaddr >= SOC_IROM_MASK_LOW && fnaddr < SOC_IROM_MASK_HIGH);
|
||||
}
|
||||
|
||||
#if CONFIG_HAL_SYSTIMER_USE_ROM_IMPL
|
||||
TEST_CASE("Test that systimer implementation from ROM is used", "[systimer-rom-impl]")
|
||||
{
|
||||
TEST_ASSERT_TRUE(fn_in_rom(systimer_hal_get_counter_value));
|
||||
}
|
||||
|
||||
#else
|
||||
TEST_CASE("Test that systimer implementation from ROM is NOT used", "[systimer-rom-impl]")
|
||||
{
|
||||
TEST_ASSERT_FALSE(fn_in_rom(systimer_hal_get_counter_value));
|
||||
}
|
||||
#endif // CONFIG_HAL_SYSTIMER_USE_ROM_IMPL
|
||||
|
||||
#define TEST_MEMORY_LEAK_THRESHOLD (-100)
|
||||
|
||||
static size_t before_free_8bit;
|
||||
static size_t before_free_32bit;
|
||||
|
||||
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
||||
{
|
||||
ssize_t delta = after_free - before_free;
|
||||
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
|
||||
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
|
||||
}
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
check_leak(before_free_8bit, after_free_8bit, "8BIT");
|
||||
check_leak(before_free_32bit, after_free_32bit, "32BIT");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
unity_run_menu();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
from pytest_embedded_idf.utils import soc_filtered_targets
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'no_rom_impl',
|
||||
'rom_impl',
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', soc_filtered_targets('SOC_SYSTIMER_SUPPORTED == 1'), indirect=['target'])
|
||||
def test_esp_hal_systimer_rom_impl(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=n
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_HAL_SYSTIMER_USE_ROM_IMPL=y
|
||||
Reference in New Issue
Block a user