Merge branch 'feature/support_output_internal_clock' into 'master'

feature(gpio): Add api to support output internal clock

Closes IDF-8016 and IDF-4935

See merge request espressif/esp-idf!25753
This commit is contained in:
Jiang Jiang Jian 2023-10-22 22:06:13 +08:00
commit 0049cc663a
46 changed files with 747 additions and 140 deletions

View File

@ -39,6 +39,10 @@
#include "driver/adc_types_legacy.h"
#endif // SOC_I2S_SUPPORTS_ADC
#if CONFIG_IDF_TARGET_ESP32
#include "esp_clock_output.h"
#endif
#if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h"
#endif
@ -135,7 +139,9 @@ typedef struct {
bool use_apll; /*!< I2S use APLL clock */
int fixed_mclk; /*!< I2S fixed MLCK clock */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of I2S master clock(MCLK) to sample rate */
#if CONFIG_IDF_TARGET_ESP32
esp_clock_output_mapping_handle_t mclk_out_hdl;
#endif
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock;
#endif
@ -1500,6 +1506,12 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
i2s_obj_t *obj = p_i2s[i2s_num];
i2s_stop(i2s_num);
#if CONFIG_IDF_TARGET_ESP32
if (obj->mclk_out_hdl) {
esp_clock_output_stop(obj->mclk_out_hdl);
}
#endif
#if SOC_I2S_SUPPORTS_ADC_DAC
if ((int)(obj->mode) == I2S_COMM_MODE_ADC_DAC) {
if (obj->dir & I2S_DIR_TX) {
@ -1800,20 +1812,8 @@ static esp_err_t i2s_check_set_mclk(i2s_port_t i2s_num, gpio_num_t gpio_num)
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32
ESP_RETURN_ON_FALSE((gpio_num == GPIO_NUM_0 || gpio_num == GPIO_NUM_1 || gpio_num == GPIO_NUM_3),
ESP_ERR_INVALID_ARG, TAG,
"ESP32 only support to set GPIO0/GPIO1/GPIO3 as mclk signal, error GPIO number:%d", gpio_num);
bool is_i2s0 = i2s_num == I2S_NUM_0;
if (gpio_num == GPIO_NUM_0) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
WRITE_PERI_REG(PIN_CTRL, is_i2s0 ? 0xFFF0 : 0xFFFF);
} else if (gpio_num == GPIO_NUM_1) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
WRITE_PERI_REG(PIN_CTRL, is_i2s0 ? 0xF0F0 : 0xF0FF);
} else {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_CLK_OUT2);
WRITE_PERI_REG(PIN_CTRL, is_i2s0 ? 0xFF00 : 0xFF0F);
}
soc_clkout_sig_id_t clkout_sig = (i2s_num == I2S_NUM_0) ? CLKOUT_SIG_I2S0 : CLKOUT_SIG_I2S1;
ESP_RETURN_ON_ERROR(esp_clock_output_start(clkout_sig, gpio_num, &p_i2s[i2s_num]->mclk_out_hdl), TAG, "mclk configure failed");
#else
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "mck_io_num invalid");
gpio_matrix_out_check_and_set(gpio_num, i2s_periph_signal[i2s_num].mck_out_sig, 0, 0);

View File

@ -46,6 +46,10 @@
#include "driver/i2s_common.h"
#include "i2s_private.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp_clock_output.h"
#endif
#include "clk_ctrl_os.h"
#include "esp_clk_tree.h"
#include "esp_intr_alloc.h"
@ -152,6 +156,11 @@ static esp_err_t i2s_destroy_controller_obj(i2s_controller_t **i2s_obj)
ESP_ERR_INVALID_STATE, TAG,
"there still have channels under this i2s controller");
int id = (*i2s_obj)->id;
#if CONFIG_IDF_TARGET_ESP32
if ((*i2s_obj)->mclk_out_hdl) {
esp_clock_output_stop((*i2s_obj)->mclk_out_hdl);
}
#endif
#if SOC_I2S_HW_VERSION_1
i2s_ll_enable_dma((*i2s_obj)->hal.dev, false);
#endif
@ -739,20 +748,11 @@ esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_sr
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32
ESP_RETURN_ON_FALSE((gpio_num == GPIO_NUM_0 || gpio_num == GPIO_NUM_1 || gpio_num == GPIO_NUM_3),
ESP_ERR_INVALID_ARG, TAG,
"ESP32 only support to set GPIO0/GPIO1/GPIO3 as mclk signal, error GPIO number:%d", gpio_num);
bool is_i2s0 = id == I2S_NUM_0;
bool is_apll = clk_src == I2S_CLK_SRC_APLL;
if (gpio_num == GPIO_NUM_0) {
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
gpio_ll_iomux_pin_ctrl(is_apll ? 0xFFF6 : (is_i2s0 ? 0xFFF0 : 0xFFFF));
} else if (gpio_num == GPIO_NUM_1) {
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
gpio_ll_iomux_pin_ctrl(is_apll ? 0xF6F6 : (is_i2s0 ? 0xF0F0 : 0xF0FF));
} else {
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_CLK_OUT2);
gpio_ll_iomux_pin_ctrl(is_apll ? 0xFF66 : (is_i2s0 ? 0xFF00 : 0xFF0F));
if (g_i2s.controller[id]->mclk_out_hdl == NULL) {
soc_clkout_sig_id_t clkout_sig = is_apll ? CLKOUT_SIG_APLL : (is_i2s0 ? CLKOUT_SIG_I2S0 : CLKOUT_SIG_I2S1);
ESP_RETURN_ON_ERROR(esp_clock_output_start(clkout_sig, gpio_num, &(g_i2s.controller[id]->mclk_out_hdl)), TAG, "mclk configure failed");
}
#else
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "mck_io_num invalid");

View File

@ -7,12 +7,15 @@
#pragma once
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "soc/lldesc.h"
#include "soc/soc_caps.h"
#include "hal/i2s_hal.h"
#include "driver/i2s_types.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp_clock_output.h"
#endif
#if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h"
#endif
@ -114,6 +117,9 @@ typedef struct {
i2s_chan_handle_t tx_chan; /*!< tx channel handler */
i2s_chan_handle_t rx_chan; /*!< rx channel handler */
int mclk; /*!< MCK out pin, shared by tx/rx*/
#if CONFIG_IDF_TARGET_ESP32
esp_clock_output_mapping_handle_t mclk_out_hdl; /*!< The handle of MCLK output signal */
#endif
} i2s_controller_t;
struct i2s_channel_obj_t {

View File

@ -125,6 +125,10 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "sleep_wake_stub.c")
endif()
if(CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX OR CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX)
list(APPEND srcs "esp_clock_output.c")
endif()
if(CONFIG_IDF_TARGET_ESP32P4)
list(REMOVE_ITEM srcs
"sleep_cpu.c" # TODO: IDF-7528, IDF-7529

View File

@ -0,0 +1,220 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/queue.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "esp_clock_output.h"
#include "esp_check.h"
#include "esp_rom_gpio.h"
#include "esp_private/clkout_channel.h"
#include "esp_private/startup_internal.h"
#include "hal/gpio_hal.h"
#include "soc/soc_caps.h"
#include "soc/io_mux_reg.h"
typedef struct clkout_channel_handle {
bool is_mapped;
soc_clkout_sig_id_t mapped_clock;
uint8_t channel_id;
uint8_t ref_cnt;
uint64_t mapped_io_bmap;
portMUX_TYPE clkout_channel_lock;
} clkout_channel_handle_t;
typedef struct esp_clock_output_mapping {
gpio_num_t mapped_io;
clkout_channel_handle_t* clkout_channel_hdl;
uint8_t ref_cnt;
portMUX_TYPE clkout_mapping_lock;
SLIST_ENTRY(esp_clock_output_mapping) next;
} esp_clock_output_mapping_t;
static const char *TAG = "esp_clock_output";
static SLIST_HEAD(esp_clock_output_mapping_head, esp_clock_output_mapping) s_mapping_list = SLIST_HEAD_INITIALIZER(s_mapping_list_head);
static portMUX_TYPE s_mapping_list_lock = portMUX_INITIALIZER_UNLOCKED;
static portMUX_TYPE s_clkout_lock = portMUX_INITIALIZER_UNLOCKED;
static clkout_channel_handle_t s_clkout_handle[CLKOUT_CHANNEL_MAX] = {
[0 ... CLKOUT_CHANNEL_MAX - 1] = {
.is_mapped = false,
.ref_cnt = 0,
.mapped_io_bmap = 0,
.clkout_channel_lock = portMUX_INITIALIZER_UNLOCKED,
}
};
static clkout_channel_handle_t* clkout_channel_alloc(soc_clkout_sig_id_t clk_sig, gpio_num_t gpio_num)
{
clkout_channel_handle_t *allocated_channel = NULL;
#if SOC_GPIO_CLOCKOUT_BY_IO_MUX
portENTER_CRITICAL(&s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)].clkout_channel_lock);
if (!s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)].is_mapped) {
s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)].is_mapped = true;
allocated_channel = &s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)];
} else if ((s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)].mapped_io_bmap & BIT(gpio_num)) &&
(s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)].mapped_clock == clk_sig)) {
allocated_channel = &s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)];
}
allocated_channel->channel_id = (clock_out_channel_t)IONUM_TO_CLKOUT_CHANNEL(gpio_num);
portEXIT_CRITICAL(&s_clkout_handle[IONUM_TO_CLKOUT_CHANNEL(gpio_num)].clkout_channel_lock);
#elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
for(uint32_t channel = 0; channel < CLKOUT_CHANNEL_MAX; channel++) {
portENTER_CRITICAL(&s_clkout_handle[channel].clkout_channel_lock);
if (!s_clkout_handle[channel].is_mapped) {
s_clkout_handle[channel].is_mapped = true;
allocated_channel = &s_clkout_handle[channel];
allocated_channel->channel_id = (clock_out_channel_t)channel;
portEXIT_CRITICAL(&s_clkout_handle[channel].clkout_channel_lock);
break;
} else if (s_clkout_handle[channel].mapped_clock == clk_sig) {
allocated_channel = &s_clkout_handle[channel];
portEXIT_CRITICAL(&s_clkout_handle[channel].clkout_channel_lock);
break;
}
portEXIT_CRITICAL(&s_clkout_handle[channel].clkout_channel_lock);
}
#endif
if (allocated_channel != NULL) {
portENTER_CRITICAL(&allocated_channel->clkout_channel_lock);
allocated_channel->mapped_io_bmap |= BIT(gpio_num);
allocated_channel->mapped_clock = clk_sig;
allocated_channel->ref_cnt++;
if (allocated_channel->ref_cnt == 1) {
portENTER_CRITICAL(&s_clkout_lock);
gpio_ll_set_pin_ctrl(clk_sig, CLKOUT_CHANNEL_MASK(allocated_channel->channel_id), CLKOUT_CHANNEL_SHIFT(allocated_channel->channel_id));
portEXIT_CRITICAL(&s_clkout_lock);
}
portEXIT_CRITICAL(&allocated_channel->clkout_channel_lock);
}
return allocated_channel;
}
static esp_clock_output_mapping_t* clkout_mapping_alloc(clkout_channel_handle_t* channel_hdl, gpio_num_t gpio_num)
{
esp_clock_output_mapping_t *allocated_mapping = NULL;
portENTER_CRITICAL(&s_mapping_list_lock);
esp_clock_output_mapping_t *hdl;
SLIST_FOREACH(hdl, &s_mapping_list, next) {
if ((hdl->clkout_channel_hdl == channel_hdl) && (hdl->mapped_io == gpio_num)) {
allocated_mapping = hdl;
}
}
portEXIT_CRITICAL(&s_mapping_list_lock);
if (allocated_mapping == NULL) {
allocated_mapping = (esp_clock_output_mapping_t *)malloc(sizeof(esp_clock_output_mapping_t));
allocated_mapping->mapped_io = gpio_num;
allocated_mapping->clkout_channel_hdl = channel_hdl;
allocated_mapping->ref_cnt = 0;
portMUX_INITIALIZE(&allocated_mapping->clkout_mapping_lock);
portENTER_CRITICAL(&s_mapping_list_lock);
SLIST_INSERT_HEAD(&s_mapping_list, allocated_mapping, next);
portEXIT_CRITICAL(&s_mapping_list_lock);
}
portENTER_CRITICAL(&allocated_mapping->clkout_mapping_lock);
allocated_mapping->ref_cnt++;
if (allocated_mapping->ref_cnt == 1) {
#if SOC_GPIO_CLOCKOUT_BY_IO_MUX
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], CLKOUT_CHANNEL_TO_IOMUX_FUNC(allocated_mapping->clkout_channel_hdl->channel_id));
#elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
gpio_set_pull_mode(gpio_num, GPIO_FLOATING);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio_num, CLKOUT_CHANNEL_TO_GPIO_SIG_ID(allocated_mapping->clkout_channel_hdl->channel_id), false, false);
#endif
}
portEXIT_CRITICAL(&allocated_mapping->clkout_mapping_lock);
return allocated_mapping;
}
static void clkout_channel_free(clkout_channel_handle_t *channel_hdl)
{
portENTER_CRITICAL(&channel_hdl->clkout_channel_lock);
if (--channel_hdl->ref_cnt == 0) {
channel_hdl->mapped_clock = CLKOUT_SIG_INVALID;
portENTER_CRITICAL(&s_clkout_lock);
gpio_ll_set_pin_ctrl(0, CLKOUT_CHANNEL_MASK(channel_hdl->channel_id), CLKOUT_CHANNEL_SHIFT(channel_hdl->channel_id));
portEXIT_CRITICAL(&s_clkout_lock);
channel_hdl->is_mapped = false;
}
portEXIT_CRITICAL(&channel_hdl->clkout_channel_lock);
}
static void clkout_mapping_free(esp_clock_output_mapping_t *mapping_hdl)
{
portENTER_CRITICAL(&mapping_hdl->clkout_mapping_lock);
clkout_channel_free(mapping_hdl->clkout_channel_hdl);
bool do_free_mapping_hdl = false;
if (--mapping_hdl->ref_cnt == 0) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[mapping_hdl->mapped_io], PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(mapping_hdl->mapped_io, SIG_GPIO_OUT_IDX, false, false);
gpio_set_direction(mapping_hdl->mapped_io, GPIO_MODE_DISABLE);
portENTER_CRITICAL(&mapping_hdl->clkout_channel_hdl->clkout_channel_lock);
mapping_hdl->clkout_channel_hdl->mapped_io_bmap &= ~BIT(mapping_hdl->mapped_io);
portEXIT_CRITICAL(&mapping_hdl->clkout_channel_hdl->clkout_channel_lock);
portENTER_CRITICAL(&s_mapping_list_lock);
SLIST_REMOVE(&s_mapping_list, mapping_hdl, esp_clock_output_mapping, next);
portEXIT_CRITICAL(&s_mapping_list_lock);
do_free_mapping_hdl = true;
}
portEXIT_CRITICAL(&mapping_hdl->clkout_mapping_lock);
if (do_free_mapping_hdl) {
free(mapping_hdl);
}
}
esp_err_t esp_clock_output_start(soc_clkout_sig_id_t clk_sig, gpio_num_t gpio_num, esp_clock_output_mapping_handle_t *clkout_mapping_ret_hdl)
{
ESP_RETURN_ON_FALSE((clkout_mapping_ret_hdl != NULL), ESP_ERR_INVALID_ARG, TAG, "Clock out mapping handle passed in is invalid");
ESP_RETURN_ON_FALSE(IS_VALID_CLKOUT_IO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "%s", "Output GPIO number error");
esp_clock_output_mapping_t *hdl;
SLIST_FOREACH(hdl, &s_mapping_list, next) {
ESP_RETURN_ON_FALSE(!((hdl->mapped_io == gpio_num) && (hdl->clkout_channel_hdl->mapped_clock != clk_sig)), ESP_ERR_INVALID_ARG, TAG, "Selected io is already mapped by another signal");
}
clkout_channel_handle_t *channel_hdl = clkout_channel_alloc(clk_sig, gpio_num);
#if SOC_GPIO_CLOCKOUT_BY_IO_MUX
ESP_RETURN_ON_FALSE((channel_hdl != NULL), ESP_ERR_INVALID_ARG, TAG, "Selected clock out IO is already mapped to other internal clock source");
#elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
ESP_RETURN_ON_FALSE((channel_hdl != NULL), ESP_FAIL, TAG, "Maximum support for %d output clock signals, no available clock_out channel for assignment", CLKOUT_CHANNEL_MAX);
#endif
*clkout_mapping_ret_hdl = clkout_mapping_alloc(channel_hdl, gpio_num);
return ESP_OK;
}
esp_err_t esp_clock_output_stop(esp_clock_output_mapping_handle_t clkout_mapping_hdl)
{
ESP_RETURN_ON_FALSE((clkout_mapping_hdl != NULL), ESP_ERR_INVALID_ARG, TAG, "Clock out mapping handle passed in is invalid");
ESP_RETURN_ON_FALSE(clkout_mapping_hdl->ref_cnt > 0, ESP_ERR_INVALID_STATE, TAG, "%s", "Clock outputting is already disabled");
clkout_mapping_free(clkout_mapping_hdl);
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32
// Due to a hardware bug, PIN_CTRL cannot select 0xf output, whereas 0xf is the default value.
__attribute__((constructor))
static void esp_clock_output_pin_ctrl_init(void)
{
gpio_ll_set_pin_ctrl(0, CLK_OUT1, CLK_OUT1_S);
gpio_ll_set_pin_ctrl(0, CLK_OUT2, CLK_OUT2_S);
gpio_ll_set_pin_ctrl(0, CLK_OUT3, CLK_OUT3_S);
}
#endif

View File

@ -0,0 +1,53 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
#include "esp_err.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX || SOC_GPIO_CLOCKOUT_BY_IO_MUX
typedef struct esp_clock_output_mapping *esp_clock_output_mapping_handle_t;
/**
* @brief Start output specified clock signal to specified GPIO, will also
* initialize the clkout_mapping_ret_hdl.
*
* @param[in] clk_src The clock signal source to be mapped to GPIOs
* @param[in] gpio_num GPIO number to be mapped soc_root_clk signal source
* @param[out] clkout_mapping_ret_hdl Clock output controll handler
* @return
* - ESP_OK: Output specified clock signal to specified GPIO successfully
* - ESP_ERR_INVALID_ARG: Specified GPIO not supported to output internal clock
* or specified GPIO is already mapped to other internal clock source.
* - ESP_FAIL: There are no clock out signals that can be allocated.
*/
esp_err_t esp_clock_output_start(soc_clkout_sig_id_t clk_sig, gpio_num_t gpio_num, esp_clock_output_mapping_handle_t *clkout_mapping_ret_hdl);
/**
* @brief Stop clock signal to GPIO outputting
* @param[in] clkout_mapping_hdl Clock output mapping controll handle
* @return
* - ESP_OK: Disable the clock output on GPIO successfully
* - ESP_ERR_INVALID_STATE The clock in handle is already in the disabled state
*/
esp_err_t esp_clock_output_stop(esp_clock_output_mapping_handle_t clkout_mapping_hdl);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum clock_out_channel {
CLKOUT_CHANNEL_1,
CLKOUT_CHANNEL_2,
CLKOUT_CHANNEL_3,
CLKOUT_CHANNEL_MAX,
} clock_out_channel_t;
#if SOC_GPIO_CLOCKOUT_BY_IO_MUX
#if CONFIG_IDF_TARGET_ESP32
#define CLKOUT_CHANNEL1_GPIO GPIO_NUM_0
#define CLKOUT_CHANNEL2_GPIO GPIO_NUM_3
#define CLKOUT_CHANNEL3_GPIO GPIO_NUM_1
#define FUNC_CLK_OUT1 FUNC_GPIO0_CLK_OUT1
#define FUNC_CLK_OUT2 FUNC_U0RXD_CLK_OUT2
#define FUNC_CLK_OUT3 FUNC_U0TXD_CLK_OUT3
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define CLKOUT_CHANNEL1_GPIO GPIO_NUM_20
#define CLKOUT_CHANNEL2_GPIO GPIO_NUM_19
#define CLKOUT_CHANNEL3_GPIO GPIO_NUM_18
#define FUNC_CLK_OUT1 FUNC_GPIO20_CLK_OUT1
#define FUNC_CLK_OUT2 FUNC_GPIO19_CLK_OUT2
#define FUNC_CLK_OUT3 FUNC_DAC_2_CLK_OUT3
#endif
#define IONUM_TO_CLKOUT_CHANNEL(gpio_num) ((gpio_num == CLKOUT_CHANNEL1_GPIO) ? CLKOUT_CHANNEL_1 : \
(gpio_num == CLKOUT_CHANNEL2_GPIO) ? CLKOUT_CHANNEL_2 : \
(gpio_num == CLKOUT_CHANNEL3_GPIO) ? CLKOUT_CHANNEL_3 : 0)
#define CLKOUT_CHANNEL_TO_IOMUX_FUNC(channel) ((channel == CLKOUT_CHANNEL_1) ? FUNC_CLK_OUT1 : \
(channel == CLKOUT_CHANNEL_2) ? FUNC_CLK_OUT2 : \
(channel == CLKOUT_CHANNEL_3) ? FUNC_CLK_OUT3 : 0)
#define IS_VALID_CLKOUT_IO(gpio_num) ((gpio_num == CLKOUT_CHANNEL1_GPIO) || (gpio_num == CLKOUT_CHANNEL2_GPIO) || (gpio_num == CLKOUT_CHANNEL3_GPIO))
#elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
#define CLKOUT_CHANNEL_TO_GPIO_SIG_ID(channel) ((channel == CLKOUT_CHANNEL_1) ? CLK_OUT_OUT1_IDX : \
(channel == CLKOUT_CHANNEL_2) ? CLK_OUT_OUT2_IDX : \
(channel == CLKOUT_CHANNEL_3) ? CLK_OUT_OUT3_IDX : SIG_GPIO_OUT_IDX)
#define IS_VALID_CLKOUT_IO(gpio_num) GPIO_IS_VALID_GPIO(gpio_num)
#endif
#define CLKOUT_CHANNEL_MASK(channel) ((channel == CLKOUT_CHANNEL_1) ? CLK_OUT1 : \
(channel == CLKOUT_CHANNEL_2) ? CLK_OUT2 : \
(channel == CLKOUT_CHANNEL_3) ? CLK_OUT3 : 0)
#define CLKOUT_CHANNEL_SHIFT(channel) ((channel == CLKOUT_CHANNEL_1) ? CLK_OUT1_S : \
(channel == CLKOUT_CHANNEL_2) ? CLK_OUT2_S : \
(channel == CLKOUT_CHANNEL_3) ? CLK_OUT3_S : 0)
#ifdef __cplusplus
}
#endif

View File

@ -8,6 +8,10 @@ set(srcs "test_app_main.c"
"test_random.c"
)
if(CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX OR CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX)
list(APPEND srcs "test_esp_clock_output.c")
endif()
# 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}

View File

@ -0,0 +1,148 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "esp_clock_output.h"
#include "hal/gpio_hal.h"
#include "soc/rtc.h"
#define TEST_LOOPS 100
#if CONFIG_IDF_TARGET_ESP32
static const int test_clk_out_io[] = {0, 1, 3};
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
static const int test_clk_out_io[] = {18, 19, 20};
#else
static const int test_clk_out_io[] = {3, 4, 5, 6};
#endif
static soc_clkout_sig_id_t test_clk_out_sig[] = {CLKOUT_SIG_XTAL, CLKOUT_SIG_RC_SLOW, CLKOUT_SIG_RC_FAST, CLKOUT_SIG_INVALID};
static SemaphoreHandle_t test_done_semphr;
void output_clock_1(void *pvParameter)
{
esp_clock_output_mapping_handle_t clkout_mapping_hdl;
for (int i = 0; i < TEST_LOOPS; ++i) {
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], &clkout_mapping_hdl));
vTaskDelay(3);
TEST_ESP_OK(esp_clock_output_stop(clkout_mapping_hdl));
vTaskDelay(7);
}
xSemaphoreGive(test_done_semphr);
vTaskDelete(NULL);
}
void output_clock_2(void *pvParameter)
{
esp_clock_output_mapping_handle_t clkout_mapping_hdl;
for (int i = 0; i < TEST_LOOPS; ++i) {
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[1], &clkout_mapping_hdl));
vTaskDelay(4);
TEST_ESP_OK(esp_clock_output_stop(clkout_mapping_hdl));
vTaskDelay(6);
}
xSemaphoreGive(test_done_semphr);
vTaskDelete(NULL);
}
void output_clock_3(void *pvParameter)
{
rtc_dig_clk8m_enable();
esp_clock_output_mapping_handle_t clkout_mapping_hdl;
for (int i = 0; i < TEST_LOOPS; ++i) {
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[2], test_clk_out_io[2], &clkout_mapping_hdl));
vTaskDelay(5);
TEST_ESP_OK(esp_clock_output_stop(clkout_mapping_hdl));
vTaskDelay(5);
}
xSemaphoreGive(test_done_semphr);
vTaskDelete(NULL);
}
// This case is now tested only manually
TEST_CASE("GPIO output internal clock", "[gpio_output_clock][ignore]")
{
test_done_semphr = xSemaphoreCreateCounting(3, 0);
xTaskCreate(&output_clock_1, "output_clock_1", 4096, NULL, 4, NULL);
xTaskCreate(&output_clock_2, "output_clock_2", 4096, NULL, 4, NULL);
xTaskCreate(&output_clock_3, "output_clock_3", 4096, NULL, 4, NULL);
int cnt = 0;
while (cnt < 3) {
if (xSemaphoreTake(test_done_semphr, portMAX_DELAY) == pdTRUE) {
cnt++;
}
}
vTaskDelay(1);
vSemaphoreDelete(test_done_semphr);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
}
#if SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
TEST_CASE("GPIO output internal clock one-to-many", "[gpio_output_clock][ignore]")
{
// Test NULL handle assertion
TEST_ESP_ERR(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], NULL), ESP_ERR_INVALID_ARG);
// Test first mapping
esp_clock_output_mapping_handle_t clkout_mapping_hdl_0;
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], &clkout_mapping_hdl_0)); // [0]:0(1) [1]:x [2]:x
// Test the same mapping allocate the same handle
esp_clock_output_mapping_handle_t clkout_mapping_hdl_1;
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], &clkout_mapping_hdl_1)); // [0]:0(2) [1]:x [2]:x
TEST_ASSERT(clkout_mapping_hdl_0 == clkout_mapping_hdl_1);
// Test map multi signal to one IO assertion
esp_clock_output_mapping_handle_t clkout_mapping_hdl_2;
TEST_ESP_ERR(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[0], &clkout_mapping_hdl_2), ESP_ERR_INVALID_ARG);
// Test the same signal mapping to multi GPIO
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[1], &clkout_mapping_hdl_2)); // [0]:0(2) 1 [1]:x [2]:x
esp_clock_output_mapping_handle_t clkout_mapping_hdl_3;
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[2], &clkout_mapping_hdl_3)); // [0]:0(2) 1 2 [1]:x [2]:x
// Test the clkout mapping ref_cnt validity
esp_clock_output_stop(clkout_mapping_hdl_0); // [0]:0(1) 1 2 [1]:x [2]:x
esp_clock_output_mapping_handle_t clkout_mapping_hdl_4;
TEST_ESP_ERR(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[0], &clkout_mapping_hdl_4), ESP_ERR_INVALID_ARG);
esp_clock_output_stop(clkout_mapping_hdl_1); // [0]:1 2 [1]:x [2]:x
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[0], &clkout_mapping_hdl_4)); // [0]:1 2 [1]:0 [2]:x
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3
test_clk_out_sig[3] = CLKOUT_SIG_PLL_F80M;
#else
test_clk_out_sig[3] = CLKOUT_SIG_RC_32K;
#endif
// Test the excess clock channel request assertion
esp_clock_output_stop(clkout_mapping_hdl_3); // [0]:1 [1]:0 [2]:x
esp_clock_output_mapping_handle_t clkout_mapping_hdl_5;
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[2], test_clk_out_io[2], &clkout_mapping_hdl_5)); // [0]:1 [1]:0 [2]:2
esp_clock_output_mapping_handle_t clkout_mapping_hdl_6;
TEST_ASSERT(ESP_FAIL == esp_clock_output_start(test_clk_out_sig[3], test_clk_out_io[3], &clkout_mapping_hdl_6));
// Test the clock out channel recycle
esp_clock_output_stop(clkout_mapping_hdl_4); // [0]:1 [1]:x [2]:2
esp_clock_output_mapping_handle_t clkout_mapping_hdl_7;
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[3], test_clk_out_io[0], &clkout_mapping_hdl_7)); // [0]:1 [1]:0 [2]:2
// Stop all
esp_clock_output_stop(clkout_mapping_hdl_2);
esp_clock_output_stop(clkout_mapping_hdl_5);
esp_clock_output_stop(clkout_mapping_hdl_6);
esp_clock_output_stop(clkout_mapping_hdl_7);
}
#endif

View File

@ -679,11 +679,13 @@ static inline __attribute__((always_inline)) void gpio_ll_iomux_func_sel(uint32_
/**
* @brief Control the pin in the IOMUX
*
* @param val Control value
* @param bmap write mask of control value
* @param val Control value
* @param shift write mask shift of control value
*/
static inline __attribute__((always_inline)) void gpio_ll_iomux_pin_ctrl(uint32_t val)
static inline __attribute__((always_inline)) void gpio_ll_set_pin_ctrl(uint32_t val, uint32_t bmap, uint32_t shift)
{
WRITE_PERI_REG(PIN_CTRL, val);
SET_PERI_REG_BITS(PIN_CTRL, bmap, val, shift);
}
/**

View File

@ -492,6 +492,18 @@ static inline __attribute__((always_inline)) void gpio_ll_iomux_func_sel(uint32_
PIN_FUNC_SELECT(pin_name, func);
}
/**
* @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
*/
static inline __attribute__((always_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 Set peripheral output to an GPIO pad through the IOMUX.
*

View File

@ -508,6 +508,18 @@ static inline __attribute__((always_inline)) void gpio_ll_iomux_func_sel(uint32_
PIN_FUNC_SELECT(pin_name, func);
}
/**
* @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
*/
static inline __attribute__((always_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 Set peripheral output to an GPIO pad through the IOMUX.
*

View File

@ -458,6 +458,18 @@ static inline void gpio_ll_iomux_func_sel(uint32_t pin_name, uint32_t func)
PIN_FUNC_SELECT(pin_name, func);
}
/**
* @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
*/
static inline __attribute__((always_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 Select a function for the pin in the IOMUX
*

View File

@ -534,6 +534,18 @@ static inline void gpio_ll_iomux_out(gpio_dev_t *hw, uint8_t gpio_num, int func,
gpio_ll_func_sel(hw, gpio_num, func);
}
/**
* @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
*/
static inline __attribute__((always_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 Set clock source of IO MUX module
*

View File

@ -579,6 +579,17 @@ static inline void gpio_ll_iomux_func_sel(uint32_t pin_name, uint32_t func)
PIN_FUNC_SELECT(pin_name, func);
}
/**
* @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
*/
static inline __attribute__((always_inline)) void gpio_ll_set_pin_ctrl(uint32_t val, uint32_t bmap, uint32_t shift)
{
// TODO: IDF-8226
}
/**
* @brief Select a function for the pin in the IOMUX
*

View File

@ -507,6 +507,17 @@ static inline __attribute__((always_inline)) void gpio_ll_iomux_func_sel(uint32_
PIN_FUNC_SELECT(pin_name, func);
}
/**
* @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
*/
static inline __attribute__((always_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 Set peripheral output to an GPIO pad through the IOMUX.
*

View File

@ -526,6 +526,18 @@ static inline __attribute__((always_inline)) void gpio_ll_iomux_func_sel(uint32_
PIN_FUNC_SELECT(pin_name, func);
}
/**
* @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
*/
static inline __attribute__((always_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 Set peripheral output to an GPIO pad through the IOMUX.
*

View File

@ -315,6 +315,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0xEF0FEA
config SOC_GPIO_CLOCKOUT_BY_IO_MUX
bool
default y
config SOC_I2C_NUM
int
default 2

View File

@ -441,6 +441,21 @@ typedef enum {
SDMMC_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_160M as the source clock */
} soc_periph_sdmmc_clk_src_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_I2S0 = 0, /*!< I2S0 clock, depends on the i2s driver configuration */
CLKOUT_SIG_PLL = 1, /*!< PLL_CLK is the output of crystal oscillator frequency multiplier */
CLKOUT_SIG_RC_SLOW = 4, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_APLL = 6, /*!< Divided by PLL, frequency is configurable */
CLKOUT_SIG_REF_TICK = 12, /*!< Divided by APB clock, usually be 1MHz */
CLKOUT_SIG_PLL_F80M = 13, /*!< From PLL, usually be 80MHz */
CLKOUT_SIG_RC_FAST = 14, /*!< RC fast clock, about 8MHz */
CLKOUT_SIG_I2S1 = 15, /*!< I2S1 clock, depends on the i2s driver configuration */
CLKOUT_SIG_INVALID = 0xFF,
} soc_clkout_sig_id_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,20 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SOC_CLKOUT_CHANNEL_H
#define _SOC_CLKOUT_CHANNEL_H
//CLKOUT channels
#define CLKOUT_IOMUX_FUNC_NUM 1
#define CLKOUT_GPIO0_DIRECT_CHANNEL CLKOUT_CHANNEL_1
#define CLKOUT_CHANNEL_1_DIRECT_GPIO_NUM 0
#define CLKOUT_GPIO3_DIRECT_CHANNEL CLKOUT_CHANNEL_2
#define CLKOUT_CHANNEL_2_DIRECT_GPIO_NUM 3
#define CLKOUT_GPIO1_DIRECT_CHANNEL CLKOUT_CHANNEL_3
#define CLKOUT_CHANNEL_3_DIRECT_GPIO_NUM 1
#endif

View File

@ -181,6 +181,9 @@
// digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM: 1, 3, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 21, 22, 23)
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0xEF0FEAULL
// The Clock Out singnal is binding to the pin's IO_MUX function
#define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1)
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32 has 2 I2C
#define SOC_I2C_NUM (2)

View File

@ -279,6 +279,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0x00000000001FFFC0
config SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
bool
default y
config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM
int
default 8

View File

@ -285,6 +285,16 @@ typedef enum {
LEDC_USE_RTC8M_CLK __attribute__((deprecated("please use 'LEDC_USE_RC_FAST_CLK' instead"))) = LEDC_USE_RC_FAST_CLK, /*!< Alias of 'LEDC_USE_RC_FAST_CLK' */
} soc_periph_ledc_clk_src_legacy_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_PLL = 1, /*!< PLL_CLK is the output of crystal oscillator frequency multiplier */
CLKOUT_SIG_RC_SLOW = 4, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_PLL_F80M = 13, /*!< From PLL, usually be 80MHz */
CLKOUT_SIG_RC_FAST = 14, /*!< RC fast clock, about 8MHz */
CLKOUT_SIG_INVALID = 0xFF,
} soc_clkout_sig_id_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,12 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SOC_CLKOUT_CHANNEL_H
#define _SOC_CLKOUT_CHANNEL_H
// ESP32C2 CLKOUT signals has no corresponding iomux pins
#endif

View File

@ -136,6 +136,9 @@
// digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_6~GPIO_NUM_20)
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x00000000001FFFC0ULL
// The Clock Out singnal is route to the pin by GPIO matrix
#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
/*-------------------------- Dedicated GPIO CAPS -----------------------------*/
#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */

View File

@ -371,6 +371,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0x00000000003FFFC0
config SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
bool
default y
config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM
int
default 8

View File

@ -357,6 +357,16 @@ typedef enum {
LEDC_USE_RTC8M_CLK __attribute__((deprecated("please use 'LEDC_USE_RC_FAST_CLK' instead"))) = LEDC_USE_RC_FAST_CLK, /*!< Alias of 'LEDC_USE_RC_FAST_CLK' */
} soc_periph_ledc_clk_src_legacy_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_PLL = 1, /*!< PLL_CLK is the output of crystal oscillator frequency multiplier */
CLKOUT_SIG_RC_SLOW = 4, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_PLL_F80M = 13, /*!< From PLL, usually be 80MHz */
CLKOUT_SIG_RC_FAST = 14, /*!< RC fast clock, about 17.5MHz */
CLKOUT_SIG_INVALID = 0xFF,
} soc_clkout_sig_id_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,12 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SOC_CLKOUT_CHANNEL_H
#define _SOC_CLKOUT_CHANNEL_H
// ESP32C3 CLKOUT signals has no corresponding iomux pins
#endif

View File

@ -174,6 +174,9 @@
// digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_6~GPIO_NUM_21)
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x00000000003FFFC0ULL
// The Clock Out singnal is route to the pin by GPIO matrix
#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
/*-------------------------- Dedicated GPIO CAPS -----------------------------*/
#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */

View File

@ -475,6 +475,10 @@ config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
bool
default y
config SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
bool
default y
config SOC_RTCIO_PIN_COUNT
int
default 8

View File

@ -463,6 +463,22 @@ typedef enum {
PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F240M, /*!< Select PLL_F240M as the default clock choice */
} soc_periph_parlio_clk_src_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_PLL = 1, /*!< PLL_CLK is the output of crystal oscillator frequency multiplier */
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_PLL_F80M = 13, /*!< From PLL, usually be 80MHz */
CLKOUT_SIG_CPU = 16, /*!< CPU clock */
CLKOUT_SIG_AHB = 17, /*!< AHB clock */
CLKOUT_SIG_APB = 18, /*!< APB clock */
CLKOUT_SIG_XTAL32K = 21, /*!< External 32kHz crystal clock */
CLKOUT_SIG_EXT32K = 22, /*!< External slow clock input through XTAL_32K_P */
CLKOUT_SIG_RC_FAST = 23, /*!< RC fast clock, about 17.5MHz */
CLKOUT_SIG_RC_32K = 24, /*!< Internal slow RC oscillator */
CLKOUT_SIG_RC_SLOW = 25, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */
CLKOUT_SIG_INVALID = 0xFF,
} soc_clkout_sig_id_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,8 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
// ESP32C6 CLKOUT signals has no corresponding iomux pins

View File

@ -208,6 +208,9 @@
// Support to hold a single digital I/O when the digital domain is powered off
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
// The Clock Out singnal is route to the pin by GPIO matrix
#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
/*-------------------------- RTCIO CAPS --------------------------------------*/
#define SOC_RTCIO_PIN_COUNT 8
#define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 /* This macro indicates that the target has separate RTC IOMUX hardware feature,

View File

@ -467,6 +467,10 @@ config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
bool
default y
config SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
bool
default y
config SOC_RTCIO_PIN_COUNT
int
default 8

View File

@ -479,6 +479,20 @@ typedef enum {
MSPI_CLK_SRC_ROM_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as ROM default clock source */
} soc_periph_mspi_clk_src_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_CPU = 16, /*!< CPU clock */
CLKOUT_SIG_AHB = 17, /*!< AHB clock */
CLKOUT_SIG_APB = 18, /*!< APB clock */
CLKOUT_SIG_XTAL32K = 21, /*!< External 32kHz crystal clock */
CLKOUT_SIG_EXT32K = 22, /*!< External slow clock input through XTAL_32K_P */
CLKOUT_SIG_RC_FAST = 23, /*!< RC fast clock, about 17.5MHz */
CLKOUT_SIG_RC_32K = 24, /*!< Internal slow RC oscillator */
CLKOUT_SIG_RC_SLOW = 25, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */
CLKOUT_SIG_INVALID = 0xFF,
} soc_clkout_sig_id_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,8 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
// ESP32H2 CLKOUT signals has no corresponding iomux pins

View File

@ -210,6 +210,9 @@
// Support to hold a single digital I/O when the digital domain is powered off
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
// The Clock Out singnal is route to the pin by GPIO matrix
#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
/*-------------------------- RTCIO CAPS --------------------------------------*/
/* No dedicated LP_IOMUX subsystem on ESP32-H2. LP functions are still supported
* for hold, wake & 32kHz crystal functions - via LP_AON registers */

View File

@ -1,8 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
// ESP32P4 CLKOUT signals has no corresponding iomux pins

View File

@ -367,6 +367,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0x00007FFFFC000000
config SOC_GPIO_CLOCKOUT_BY_IO_MUX
bool
default y
config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM
int
default 8

View File

@ -415,6 +415,18 @@ typedef enum {
LEDC_USE_RTC8M_CLK __attribute__((deprecated("please use 'LEDC_USE_RC_FAST_CLK' instead"))) = LEDC_USE_RC_FAST_CLK, /*!< Alias of 'LEDC_USE_RC_FAST_CLK' */
} soc_periph_ledc_clk_src_legacy_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_PLL = 1, /*!< PLL_CLK is the output of crystal oscillator frequency multiplier */
CLKOUT_SIG_RC_SLOW = 4, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_APLL = 6, /*!< Divided by PLL, frequency is configurable */
CLKOUT_SIG_REF_TICK = 12, /*!< Divided by APB clock, usually be 1MHz */
CLKOUT_SIG_PLL_F80M = 13, /*!< From PLL, usually be 80MHz */
CLKOUT_SIG_RC_FAST = 14, /*!< RC fast clock, about 17.5MHz */
CLKOUT_SIG_INVALID = 0xFF,
} soc_clkout_sig_id_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,20 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SOC_CLKOUT_CHANNEL_H
#define _SOC_CLKOUT_CHANNEL_H
//CLKOUT channels
#define CLKOUT_IOMUX_FUNC_NUM 3
#define CLKOUT_GPIO20_DIRECT_CHANNEL CLKOUT_CHANNEL_1
#define CLKOUT_CHANNEL_1_DIRECT_GPIO_NUM 20
#define CLKOUT_GPIO19_DIRECT_CHANNEL CLKOUT_CHANNEL_2
#define CLKOUT_CHANNEL_2_DIRECT_GPIO_NUM 19
#define CLKOUT_GPIO18_DIRECT_CHANNEL CLKOUT_CHANNEL_3
#define CLKOUT_CHANNEL_3_DIRECT_GPIO_NUM 18
#endif

View File

@ -171,6 +171,9 @@
// digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_26~GPIO_NUM_46)
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x00007FFFFC000000ULL
// The Clock Out singnal is binding to the pin's IO_MUX function
#define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1)
/*-------------------------- Dedicated GPIO CAPS ---------------------------------------*/
#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */

View File

@ -435,6 +435,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0x0001FFFFFC000000
config SOC_GPIO_CLOCKOUT_BY_IO_MUX
bool
default y
config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM
int
default 8

View File

@ -444,6 +444,15 @@ typedef enum {
SDMMC_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
} soc_periph_sdmmc_clk_src_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_PLL = 1, /*!< PLL_CLK is the output of crystal oscillator frequency multiplier */
CLKOUT_SIG_RC_SLOW = 4, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_PLL_F80M = 13, /*!< From PLL, usually be 80MHz */
CLKOUT_SIG_RC_FAST = 14, /*!< RC fast clock, about 17.5MHz */
CLKOUT_SIG_INVALID = 0xFF,
} soc_clkout_sig_id_t;
#ifdef __cplusplus
}

View File

@ -1,20 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
//CLKOUT channels
#define CLKOUT_IOMUX_FUNC_NUM 3
#define CLKOUT_GPIO20_DIRECT_CHANNEL CLKOUT_CHANNEL_1
#define CLKOUT_CHANNEL_1_DIRECT_GPIO_NUM 20
#define CLKOUT_GPIO19_DIRECT_CHANNEL CLKOUT_CHANNEL_2
#define CLKOUT_CHANNEL_2_DIRECT_GPIO_NUM 19
#define CLKOUT_GPIO18_DIRECT_CHANNEL CLKOUT_CHANNEL_3
#define CLKOUT_CHANNEL_3_DIRECT_GPIO_NUM 18
// ESP32S3 has two other sets of GPIO pins which could route to CLKOUT_CHANNEL_1/2/3 through IO_MUX
// Please check TRM IO MUX Function List table if needed

View File

@ -177,6 +177,9 @@
// digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_26~GPIO_NUM_48)
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x0001FFFFFC000000ULL
// The Clock Out singnal is binding to the pin's IO_MUX function
#define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1)
/*-------------------------- Dedicated GPIO CAPS -----------------------------*/
#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */