refactor(gpio): split GPIO HAL into separate component

cleaned up some includes in GPIO peripheral files
This commit is contained in:
Song Ruo Jing
2025-11-26 15:35:07 +08:00
parent c68237f5fa
commit 1862fdec74
195 changed files with 367 additions and 369 deletions
@@ -1,51 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
__attribute__((always_inline))
static inline void dedic_gpio_cpu_ll_enable_output(uint32_t mask)
{
// Dedicated GPIO output attribution is enabled automatically on the target
}
__attribute__((always_inline))
static inline uint32_t dedic_gpio_cpu_ll_read_in(void)
{
uint32_t value = 0;
asm volatile("ee.get_gpio_in %0" : "=r"(value) : :);
return value;
}
__attribute__((always_inline))
static inline uint32_t dedic_gpio_cpu_ll_read_out(void)
{
uint32_t value = 0;
asm volatile("rur.gpio_out %0" : "=r"(value) : :);
return value;
}
__attribute__((always_inline))
static inline void dedic_gpio_cpu_ll_write_all(uint32_t value)
{
asm volatile("wur.gpio_out %0"::"r"(value):);
}
__attribute__((always_inline))
static inline void dedic_gpio_cpu_ll_write_mask(uint32_t mask, uint32_t value)
{
asm volatile("ee.wr_mask_gpio_out %0, %1" : : "r"(value), "r"(mask):);
}
#ifdef __cplusplus
}
#endif
@@ -1,43 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "soc/system_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void _dedic_gpio_ll_enable_bus_clock(bool enable)
{
SYSTEM.cpu_peri_clk_en.clk_en_dedicated_gpio = 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_ATOMIC_ENV variable in advance
#define dedic_gpio_ll_enable_bus_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_dedic_gpio_ll_enable_bus_clock(__VA_ARGS__); \
} while(0)
static inline void _dedic_gpio_ll_reset_register(void)
{
SYSTEM.cpu_peri_rst_en.rst_en_dedicated_gpio = 1;
SYSTEM.cpu_peri_rst_en.rst_en_dedicated_gpio = 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 dedic_gpio_ll_reset_register(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_dedic_gpio_ll_reset_register(__VA_ARGS__); \
} while(0)
#ifdef __cplusplus
}
#endif
@@ -1,737 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32-S3 GPIO register operations
#pragma once
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/gpio_periph.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/usb_serial_jtag_reg.h"
#include "hal/gpio_types.h"
#include "soc/gpio_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get GPIO hardware instance with giving gpio num
#define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
// On ESP32S3, pro cpu and app cpu shares the same interrupt enable bit
#define GPIO_LL_INTR_ENA (BIT(0))
#define GPIO_LL_NMI_INTR_ENA (BIT(1))
#define GPIO_LL_INTR_SOURCE0 ETS_GPIO_INTR_SOURCE
/**
* @brief Enable pull-up on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
{
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
}
/**
* @brief Disable pull-up on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
// The pull-up value of the USB pins are controlled by the pins’ pull-up value together with USB pull-up value
// USB DP pin is default to PU enabled
// Note that from esp32s3 ECO1, USB_EXCHG_PINS feature has been supported. If this efuse is burnt, the gpio pin
// which should be checked is USB_INT_PHY0_DM_GPIO_NUM instead.
if (gpio_num == USB_INT_PHY0_DP_GPIO_NUM) {
SET_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_PAD_PULL_OVERRIDE);
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_DP_PULLUP);
}
REG_CLR_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PU);
}
/**
* @brief Enable pull-down on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
{
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
}
/**
* @brief Disable pull-down on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
REG_CLR_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PD);
}
/**
* @brief GPIO set interrupt trigger type
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param intr_type Interrupt type, select from gpio_int_type_t
*/
static inline void gpio_ll_set_intr_type(gpio_dev_t *hw, uint32_t gpio_num, gpio_int_type_t intr_type)
{
hw->pin[gpio_num].int_type = intr_type;
}
/**
* @brief Get GPIO interrupt status
*
* @param hw Peripheral GPIO hardware instance address.
* @param core_id interrupt core id
* @param status interrupt status
*/
__attribute__((always_inline))
static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
{
// On ESP32S3, pcpu_int register represents GPIO0-31 interrupt status on both cores
(void)core_id;
*status = hw->pcpu_int;
}
/**
* @brief Get GPIO interrupt status high
*
* @param hw Peripheral GPIO hardware instance address.
* @param core_id interrupt core id
* @param status interrupt status high
*/
__attribute__((always_inline))
static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
{
// On ESP32S3, pcpu_int1 register represents GPIO32-48 interrupt status on both cores
(void)core_id;
*status = hw->pcpu_int1.intr;
}
/**
* @brief Clear GPIO interrupt status
*
* @param hw Peripheral GPIO hardware instance address.
* @param mask interrupt status clear mask
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask)
{
hw->status_w1tc = mask;
}
/**
* @brief Clear GPIO interrupt status high
*
* @param hw Peripheral GPIO hardware instance address.
* @param mask interrupt status high clear mask
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask)
{
hw->status1_w1tc.intr_st = mask;
}
/**
* @brief Enable GPIO module interrupt signal
*
* @param hw Peripheral GPIO hardware instance address.
* @param core_id Interrupt enabled CPU to corresponding ID
* @param gpio_num GPIO number. If you want to enable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
*/
__attribute__((always_inline))
static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, uint32_t gpio_num)
{
(void)core_id;
GPIO.pin[gpio_num].int_ena = GPIO_LL_INTR_ENA; //enable intr
}
/**
* @brief Disable GPIO module interrupt signal
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
*/
__attribute__((always_inline))
static inline void gpio_ll_intr_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].int_ena = 0; //disable GPIO intr
}
/**
* @brief Disable input mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_INPUT_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
}
/**
* @brief Enable input mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
}
/**
* @brief Enable GPIO pin filter
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number of the pad.
*/
static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_FILTER_EN(IO_MUX_GPIO0_REG + (gpio_num * 4));
}
/**
* @brief Disable GPIO pin filter
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number of the pad.
*/
static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_FILTER_DIS(IO_MUX_GPIO0_REG + (gpio_num * 4));
}
/**
* @brief Disable output mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
if (gpio_num < 32) {
hw->enable_w1tc = (0x1 << gpio_num);
} else {
hw->enable1_w1tc.data = (0x1 << (gpio_num - 32));
}
}
/**
* @brief Enable output mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
if (gpio_num < 32) {
hw->enable_w1ts = (0x1 << gpio_num);
} else {
hw->enable1_w1ts.data = (0x1 << (gpio_num - 32));
}
}
/**
* @brief Disable open-drain mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_od_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].pad_driver = 0;
}
/**
* @brief Enable open-drain mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_od_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].pad_driver = 1;
}
/**
* @brief Select a function for the pin in the IOMUX
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @param func Function to assign to the pin
*/
__attribute__((always_inline))
static inline void gpio_ll_func_sel(gpio_dev_t *hw, uint8_t gpio_num, uint32_t func)
{
if (gpio_num == USB_INT_PHY0_DM_GPIO_NUM || gpio_num == USB_INT_PHY0_DP_GPIO_NUM) {
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
}
PIN_FUNC_SELECT(IO_MUX_GPIO0_REG + (gpio_num * 4), func);
}
/**
* @brief GPIO set output level
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param level Output level. 0: low ; 1: high
*/
__attribute__((always_inline))
static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level)
{
if (level) {
if (gpio_num < 32) {
hw->out_w1ts = 1 << gpio_num;
} else {
hw->out1_w1ts.val = 1 << (gpio_num - 32);
}
} else {
if (gpio_num < 32) {
hw->out_w1tc = 1 << gpio_num;
} else {
hw->out1_w1tc.val = 1 << (gpio_num - 32);
}
}
}
/**
* @brief GPIO get input level
*
* @warning If the pad is not configured for input (or input and output) the returned value is always 0.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16);
*
* @return
* - 0 the GPIO input level is 0
* - 1 the GPIO input level is 1
*/
__attribute__((always_inline))
static inline int gpio_ll_get_level(gpio_dev_t *hw, uint32_t gpio_num)
{
if (gpio_num < 32) {
return (hw->in >> gpio_num) & 0x1;
} else {
return (hw->in1.data >> (gpio_num - 32)) & 0x1;
}
}
/**
* @brief Enable GPIO wake-up function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number.
*/
static inline void gpio_ll_wakeup_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].wakeup_enable = 1;
}
/**
* @brief Disable GPIO wake-up function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].wakeup_enable = 0;
}
/**
* @brief Set GPIO pad drive capability
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Drive capability of the pad
*/
static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t strength)
{
uint32_t drv_cap = (uint32_t)strength;
// DRV = 1 and DRV = 2 register bits are flipped for IO17, IO18 on the target
if (gpio_num == 17 || gpio_num == 18) {
drv_cap = ((drv_cap & 0x1) << 1) | ((drv_cap & 0x2) >> 1); // swap bit0 and bit1
}
SET_PERI_REG_BITS(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, drv_cap, FUN_DRV_S);
}
/**
* @brief Get GPIO pad drive capability
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Pointer to accept drive capability of the pad
*/
static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t *strength)
{
uint32_t drv_cap = GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S);
// DRV = 1 and DRV = 2 register bits are flipped for IO17, IO18 on the target
if (gpio_num == 17 || gpio_num == 18) {
drv_cap = ((drv_cap & 0x1) << 1) | ((drv_cap & 0x2) >> 1); // swap bit0 and bit1
}
*strength = (gpio_drive_cap_t)drv_cap;
}
/**
* @brief Enable all digital gpio pad hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
}
/**
* @brief Disable all digital gpio pad hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
}
/**
* @brief Get deep sleep hold status
*
* @param hw Peripheral GPIO hardware instance address.
*
* @return
* - true deep sleep hold is enabled
* - false deep sleep hold is disabled
*/
__attribute__((always_inline))
static inline bool gpio_ll_deep_sleep_hold_is_en(gpio_dev_t *hw)
{
return !GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD) && GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
}
/**
* @brief Enable gpio pad hold function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*/
static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num)
{
SET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
}
/**
* @brief Disable gpio pad hold function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*/
static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
}
/**
* @brief Get gpio pad hold status.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*
* @note caller must ensure that gpio_num is a digital io pad
*
* @return
* - true digital gpio pad is held
* - false digital gpio pad is unheld
*/
__attribute__((always_inline))
static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num)
{
return GET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, BIT(gpio_num - 21));
}
/**
* @brief Configure peripheral signal input whether to bypass GPIO matrix.
*
* @param hw Peripheral GPIO hardware instance address.
* @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
* @param from_gpio_matrix True if not to bypass GPIO matrix, otherwise False.
*/
__attribute__((always_inline))
static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal_idx, bool from_gpio_matrix)
{
hw->func_in_sel_cfg[signal_idx].sig_in_sel = from_gpio_matrix;
}
/**
* @brief Connect a GPIO input with a peripheral signal, which tagged as input attribute.
*
* @note There's no limitation on the number of signals that a GPIO can combine with.
*
* @param signal_idx Peripheral signal index (tagged as input attribute)
* @param gpio_num GPIO number, especially, `GPIO_MATRIX_CONST_ZERO_INPUT` means connect logic 0 to signal
* `GPIO_MATRIX_CONST_ONE_INPUT` means connect logic 1 to signal
* @param in_inv True if the GPIO input needs to be inverted, otherwise False.
*/
static inline void gpio_ll_set_input_signal_matrix_source(gpio_dev_t *hw, uint32_t signal_idx, uint32_t gpio_num, bool in_inv)
{
hw->func_in_sel_cfg[signal_idx].func_sel = gpio_num;
hw->func_in_sel_cfg[signal_idx].sig_in_inv = in_inv;
gpio_ll_set_input_signal_from(hw, signal_idx, true);
}
/**
* @brief Get the GPIO number that is routed to the input peripheral signal through GPIO matrix.
*
* @param hw Peripheral GPIO hardware instance address.
* @param in_sig_idx Peripheral signal index (tagged as input attribute).
*
* @return
* - -1 Signal bypassed GPIO matrix
* - Others GPIO number
*/
static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in_sig_idx)
{
typeof(hw->func_in_sel_cfg[in_sig_idx]) reg;
reg.val = hw->func_in_sel_cfg[in_sig_idx].val;
return (reg.sig_in_sel ? reg.func_sel : -1);
}
/**
* @brief Configure the source of output enable signal for the pad (only takes effect if func sel is selected to be GPIO).
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number of the pad.
* @param ctrl_by_periph True if use output enable signal from peripheral, false if force the output enable signal to be sourced from bit n of GPIO_ENABLE_REG
* @param oen_inv True if the output enable needs to be inverted, otherwise False.
*/
static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_num, bool ctrl_by_periph, bool oen_inv)
{
hw->func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv; // control valid only when using gpio matrix to route signal to the IO
hw->func_out_sel_cfg[gpio_num].oen_sel = !ctrl_by_periph;
}
/**
* @brief Connect a peripheral signal which tagged as output attribute with a GPIO.
*
* @note There's no limitation on the number of signals that a GPIO can combine with.
*
* @param gpio_num GPIO number
* @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level.
* @param out_inv True if the signal output needs to be inverted, otherwise False.
*/
static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv)
{
hw->func_out_sel_cfg[gpio_num].func_sel = signal_idx;
hw->func_out_sel_cfg[gpio_num].inv_sel = out_inv;
}
/**
* @brief Control the pin in the IOMUX
*
* @param bmap write mask of control value
* @param val Control value
* @param shift write mask shift of control value
*/
__attribute__((always_inline))
static inline void gpio_ll_set_pin_ctrl(uint32_t val, uint32_t bmap, uint32_t shift)
{
SET_PERI_REG_BITS(PIN_CTRL, bmap, val, shift);
}
/**
* @brief Force hold digital gpio pad.
* @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
*/
static inline void gpio_ll_force_hold_all(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
}
/**
* @brief Force unhold digital gpio pad.
* @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
*/
static inline void gpio_ll_force_unhold_all(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
}
/**
* @brief Enable GPIO pin used for wakeup from sleep.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_SEL_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pin used for wakeup from sleep.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_SEL_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pull-up in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLUP_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO pull-up in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLUP_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO pull-down in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLDOWN_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pull-down in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLDOWN_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO input in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO input in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO output in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_OUTPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO output in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Get the configuration for an IO
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @param[out] io_config Pointer to the structure that saves the specific IO configuration
*/
static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio_io_config_t *io_config)
{
uint32_t bit_shift = (gpio_num < 32) ? gpio_num : (gpio_num - 32);
uint32_t bit_mask = 1 << bit_shift;
uint32_t iomux_reg_val = REG_READ(GPIO_PIN_MUX_REG[gpio_num]);
io_config->pu = (iomux_reg_val & FUN_PU_M) >> FUN_PU_S;
io_config->pd = (iomux_reg_val & FUN_PD_M) >> FUN_PD_S;
io_config->ie = (iomux_reg_val & FUN_IE_M) >> FUN_IE_S;
io_config->oe = (((gpio_num < 32) ? hw->enable : hw->enable1.val) & bit_mask) >> bit_shift;
io_config->oe_ctrl_by_periph = !(hw->func_out_sel_cfg[gpio_num].oen_sel);
io_config->oe_inv = hw->func_out_sel_cfg[gpio_num].oen_inv_sel;
io_config->od = hw->pin[gpio_num].pad_driver;
gpio_ll_get_drive_capability(hw, gpio_num, &(io_config->drv)); // specific workaround in the LL
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
io_config->sig_out = hw->func_out_sel_cfg[gpio_num].func_sel;
io_config->slp_sel = (iomux_reg_val & SLP_SEL_M) >> SLP_SEL_S;
}
#ifdef __cplusplus
}
#endif
@@ -1,442 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
#pragma once
#include <stdbool.h>
#include <stdlib.h>
#include "hal/gpio_types.h"
#include "hal/assert.h"
#include "soc/rtc_io_struct.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_periph.h"
#include "soc/io_mux_reg.h"
#include "soc/usb_serial_jtag_reg.h"
#include "soc/usb_serial_jtag_struct.h"
#include "soc/sens_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RTCIO_LL_PIN_FUNC 0
typedef enum {
RTCIO_LL_FUNC_RTC = 0x0, /*!< The pin controlled by RTC module. */
RTCIO_LL_FUNC_DIGITAL = 0x1, /*!< The pin controlled by DIGITAL module. */
} rtcio_ll_func_t;
typedef enum {
RTCIO_LL_OUTPUT_NORMAL = 0, /*!< RTCIO output mode is normal. */
RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */
} rtcio_ll_out_mode_t;
/**
* @brief Enable/Disable LP IOMUX clock.
*
* @param enable true to enable the clock / false to disable the clock
*/
static inline void rtcio_ll_enable_io_clock(bool enable)
{
SENS.sar_peri_clk_gate_conf.iomux_clk_en = enable;
}
/**
* @brief Select a RTC IOMUX function for the RTC IO
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param func Function to assign to the pin
*/
static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func)
{
SET_PERI_REG_BITS(rtc_io_desc[rtcio_num].reg, 0x3, func, rtc_io_desc[rtcio_num].func);
}
/**
* @brief Select the rtcio function.
*
* @note The RTC function must be selected before the pad analog function is enabled.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param func Select pin function.
*/
static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func)
{
if (func == RTCIO_LL_FUNC_RTC) {
// Disable USB Serial JTAG if pin 19 or pin 20 needs to select the rtc function
if (rtcio_num == rtc_io_num_map[USB_INT_PHY0_DM_GPIO_NUM] || rtcio_num == rtc_io_num_map[USB_INT_PHY0_DP_GPIO_NUM]) {
USB_SERIAL_JTAG.conf0.usb_pad_enable = 0;
}
// 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module.
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux));
//0:RTC FUNCTION 1,2,3:Reserved
rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC);
} else if (func == RTCIO_LL_FUNC_DIGITAL) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux));
// USB Serial JTAG pad re-enable won't be done here (it requires both DM and DP pins not in rtc function)
// Instead, USB_SERIAL_JTAG_USB_PAD_ENABLE needs to be guaranteed to be set in usb_serial_jtag driver
}
}
/**
* Enable rtcio output.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_output_enable(int rtcio_num)
{
RTCIO.enable_w1ts.val = (1U << (rtcio_num + RTC_GPIO_ENABLE_W1TS_S));
}
/**
* Disable rtcio output.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_output_disable(int rtcio_num)
{
RTCIO.enable_w1tc.val = (1U << (rtcio_num + RTC_GPIO_ENABLE_W1TC_S));
}
/**
* Set RTCIO output level.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param level 0: output low; ~0: output high.
*/
static inline void rtcio_ll_set_level(int rtcio_num, uint32_t level)
{
if (level) {
RTCIO.out_w1ts.val = (1U << (rtcio_num + RTC_GPIO_OUT_DATA_W1TS_S));
} else {
RTCIO.out_w1tc.val = (1U << (rtcio_num + RTC_GPIO_OUT_DATA_W1TC_S));
}
}
/**
* Enable rtcio input.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_input_enable(int rtcio_num)
{
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].ie);
}
/**
* Disable rtcio input.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_input_disable(int rtcio_num)
{
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].ie);
}
/**
* Get RTCIO input level.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return 0: input low; ~0: input high.
*/
static inline uint32_t rtcio_ll_get_level(int rtcio_num)
{
return (uint32_t)(RTCIO.in_val.in >> rtcio_num) & 0x1;
}
/**
* @brief Set RTC GPIO pad drive capability
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param strength Drive capability of the pad. Range: 0 ~ 3.
*/
static inline void rtcio_ll_set_drive_capability(int rtcio_num, uint32_t strength)
{
if (rtc_io_desc[rtcio_num].drv_v) {
uint32_t drv_cap = strength;
// DRV = 1 and DRV = 2 register bits are flipped for IO17, IO18 on the target
if (rtcio_num == RTCIO_GPIO17_CHANNEL || rtcio_num == RTCIO_GPIO18_CHANNEL) {
drv_cap = ((drv_cap & 0x1) << 1) | ((drv_cap & 0x2) >> 1); // swap bit0 and bit1
}
SET_PERI_REG_BITS(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].drv_v, drv_cap, rtc_io_desc[rtcio_num].drv_s);
}
}
/**
* @brief Get RTC GPIO pad drive capability.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return Drive capability of the pad. Range: 0 ~ 3.
*/
static inline uint32_t rtcio_ll_get_drive_capability(int rtcio_num)
{
uint32_t strength = GET_PERI_REG_BITS2(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].drv_v, rtc_io_desc[rtcio_num].drv_s);
// DRV = 1 and DRV = 2 register bits are flipped for IO17, IO18 on the target
if (rtcio_num == RTCIO_GPIO17_CHANNEL || rtcio_num == RTCIO_GPIO18_CHANNEL) {
strength = ((strength & 0x1) << 1) | ((strength & 0x2) >> 1); // swap bit0 and bit1
}
return strength;
}
/**
* @brief Set RTC GPIO pad output mode.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return mode Output mode.
*/
static inline void rtcio_ll_output_mode_set(int rtcio_num, rtcio_ll_out_mode_t mode)
{
RTCIO.pin[rtcio_num].pad_driver = mode;
}
/**
* RTC GPIO pullup enable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_pullup_enable(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pullup) {
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pullup);
}
}
/**
* RTC GPIO pullup disable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_pullup_disable(int rtcio_num)
{
// The pull-up value of the USB pins are controlled by the pins’ pull-up value together with USB pull-up value
// USB DP pin is default to PU enabled
// Note that from esp32s3 ECO1, USB_EXCHG_PINS feature has been supported. If this efuse is burnt, the gpio pin
// which should be checked is USB_INT_PHY0_DM_GPIO_NUM instead.
if (rtcio_num == USB_INT_PHY0_DP_GPIO_NUM) {
SET_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_PAD_PULL_OVERRIDE);
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_DP_PULLUP);
}
if (rtc_io_desc[rtcio_num].pullup) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pullup);
}
}
/**
* @brief Get RTC GPIO pad pullup status.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return Whether the pullup of the pad is enabled or not.
*/
static inline bool rtcio_ll_is_pullup_enabled(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pullup) {
return GET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pullup);
} else {
return false;
}
}
/**
* RTC GPIO pulldown enable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_pulldown_enable(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pulldown) {
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pulldown);
}
}
/**
* RTC GPIO pulldown disable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_pulldown_disable(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pulldown) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pulldown);
}
}
/**
* @brief Get RTC GPIO pad pulldown status.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return Whether the pulldown of the pad is enabled or not.
*/
static inline bool rtcio_ll_is_pulldown_enabled(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pulldown) {
return GET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pulldown);
} else {
return false;
}
}
/**
* Enable force hold function on an RTC IO pad.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
* This function is useful when going into light or deep sleep mode to prevent
* the pin configuration from changing.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_hold_enable(int rtcio_num)
{
SET_PERI_REG_MASK(RTC_CNTL_PAD_HOLD_REG, rtc_io_desc[rtcio_num].hold_force);
}
/**
* Disable hold function on an RTC IO pad.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_hold_disable(int rtcio_num)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_PAD_HOLD_REG, rtc_io_desc[rtcio_num].hold_force);
}
/**
* Enable force hold function on all RTC IO pads.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
* This function is useful when going into light or deep sleep mode to prevent
* the pin configuration from changing.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_hold_all(void)
{
SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M);
}
/**
* Disable hold function on all RTC IO pads.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_unhold_all(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M);
}
/**
* Enable wakeup function and set wakeup type from light sleep status for rtcio.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param type Wakeup on high level or low level.
*/
static inline void rtcio_ll_wakeup_enable(int rtcio_num, gpio_int_type_t type)
{
HAL_ASSERT(type == GPIO_INTR_LOW_LEVEL || type == GPIO_INTR_HIGH_LEVEL);
RTCIO.pin[rtcio_num].wakeup_enable = 1;
RTCIO.pin[rtcio_num].int_type = type;
}
/**
* Disable wakeup function from light sleep status for rtcio.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_wakeup_disable(int rtcio_num)
{
RTCIO.pin[rtcio_num].wakeup_enable = 0;
RTCIO.pin[rtcio_num].int_type = 0;
}
/**
* Enable rtc io output in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_enable_output_in_sleep(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].slpoe) {
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpoe);
}
}
/**
* Disable rtc io output in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_disable_output_in_sleep(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].slpoe) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpoe);
}
}
/**
* Enable rtc io input in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_enable_input_in_sleep(int rtcio_num)
{
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpie);
}
/**
* Disable rtc io input in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_disable_input_in_sleep(int rtcio_num)
{
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpie);
}
/**
* Enable rtc io keep another setting in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_enable_sleep_setting(int rtcio_num)
{
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpsel);
}
/**
* Disable rtc io keep another setting in deep sleep. (Default)
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_disable_sleep_setting(int rtcio_num)
{
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpsel);
}
/**
* Set specific logic level on an RTC IO pin as a wakeup trigger.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param level Logic level (0)
*/
static inline void rtcio_ll_ext0_set_wakeup_pin(int rtcio_num, int level)
{
REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, rtcio_num);
// Set level which will trigger wakeup
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
level , RTC_CNTL_EXT_WAKEUP0_LV_S);
}
#ifdef __cplusplus
}
#endif
@@ -1,67 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/assert.h"
#include "hal/misc.h"
#include "soc/gpio_sd_struct.h"
#include "soc/gpio_sd_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get SDM register base address with giving group number
#define SDM_LL_GET_HW(group_id) ((group_id == 0) ? (&SDM) : NULL)
#define SDM_LL_PRESCALE_MAX (GPIO_SD0_PRESCALE_V + 1)
// Support APB as function clock
#define SDM_LL_FUNC_CLOCK_SUPPORT_APB 1
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param density Sigma-delta quantized density of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
__attribute__((always_inline))
static inline void sdm_ll_set_pulse_density(gpio_sd_dev_t *hw, int channel, int8_t density)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)density);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 1 to 256
*/
static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale)
{
HAL_ASSERT(prescale && prescale <= SDM_LL_PRESCALE_MAX);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale - 1);
}
#ifdef __cplusplus
}
#endif