Merge branch 'bugfix/gpio_standardization_fix' into 'master'

fix(gpio): minor improvement to output/input configuration step

Closes IDF-12240

See merge request espressif/esp-idf!36973
This commit is contained in:
Song Ruo Jing 2025-02-24 15:56:59 +08:00
commit c9dff55c9f
33 changed files with 92 additions and 47 deletions

View File

@ -20,7 +20,7 @@ When a peripheral driver does de-initialization, to de-configure the pin as the
If the signal is routed through IO MUX to the pin, then only needs to call `gpio_iomux_input` to select the IO MUX function index and direct the signal to IO MUX. Input will be enabled for the IO internally.
If the signal is routed through GPIO Matrix to the pin, then first call `gpio_func_sel` to let the pin use `PIN_FUNC_GPIO` function, follow by calling `gpio_input_enable` and `esp_rom_gpio_connect_in_signal` to enable the input and connect the signal to the pin.
If the signal is routed through GPIO Matrix to the pin, then call `gpio_input_enable` and `esp_rom_gpio_connect_in_signal` to enable the input and connect the signal to the pin.
When a peripheral driver does de-initialization, to de-configure the pin as the peripheral signal input, use `esp_rom_gpio_connect_in_signal` to connect the signal to CONST_ONE or CONST_ZERO, so that it is disconnected from the pin. It is not desired to call `gpio_input_disable`, because there might be other drivers still using this pin as an input.

View File

@ -53,7 +53,7 @@ esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num);
esp_err_t gpio_func_sel(gpio_num_t gpio_num, uint32_t func);
/**
* @brief Enable output for an IO
* @brief Enable output for an IO (as a simple GPIO output)
*
* @param gpio_num GPIO number
*
@ -126,13 +126,12 @@ esp_err_t gpio_iomux_input(gpio_num_t gpio_num, int func, uint32_t signal_idx);
* @param gpio_num GPIO number of the pad.
* @param func The index number of the IOMUX function to be selected for the pin.
* One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
* @param out_en_inv Whether the output enable control is inverted or not.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO number error
*/
esp_err_t gpio_iomux_output(gpio_num_t gpio_num, int func, bool out_en_inv);
esp_err_t gpio_iomux_output(gpio_num_t gpio_num, int func);
#ifdef __cplusplus
}

View File

@ -207,7 +207,7 @@ esp_err_t gpio_output_disable(gpio_num_t gpio_num)
{
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
gpio_hal_output_disable(gpio_context.gpio_hal, gpio_num);
gpio_hal_matrix_out_default(gpio_context.gpio_hal, gpio_num); // Ensure no other output signal is routed via GPIO matrix to this pin
gpio_hal_set_output_enable_ctrl(gpio_context.gpio_hal, gpio_num, false, false); // so that output disable could take effect
return ESP_OK;
}
@ -836,15 +836,16 @@ esp_err_t gpio_iomux_input(gpio_num_t gpio_num, int func, uint32_t signal_idx)
// Deprecated function
void gpio_iomux_out(uint8_t gpio_num, int func, bool out_en_inv)
{
gpio_hal_iomux_out(gpio_context.gpio_hal, gpio_num, func, out_en_inv);
(void)out_en_inv; // out_en_inv only takes effect when signal goes through gpio matrix to the IO
gpio_hal_iomux_out(gpio_context.gpio_hal, gpio_num, func);
}
esp_err_t gpio_iomux_output(gpio_num_t gpio_num, int func, bool out_en_inv)
esp_err_t gpio_iomux_output(gpio_num_t gpio_num, int func)
{
GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_iomux_out(gpio_context.gpio_hal, gpio_num, func, out_en_inv);
gpio_hal_iomux_out(gpio_context.gpio_hal, gpio_num, func);
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
return ESP_OK;
@ -1094,11 +1095,18 @@ esp_err_t gpio_dump_io_configuration(FILE *out_stream, uint64_t io_bit_mask)
gpio_io_config_t io_config = {};
gpio_get_io_config(gpio_num, &io_config);
// When the IO is used as a simple GPIO output, oe signal can only be controlled by the oe register
// When the IO is not used as a simple GPIO output, oe signal could be controlled by the peripheral
const char *oe_str = io_config.oe ? "1" : "0";
if (io_config.sig_out != SIG_GPIO_OUT_IDX && io_config.oe_ctrl_by_periph) {
oe_str = "[periph_sig_ctrl]";
}
fprintf(out_stream, "IO[%"PRIu32"]%s -\n", gpio_num, esp_gpio_is_reserved(BIT64(gpio_num)) ? " **RESERVED**" : "");
fprintf(out_stream, " Pullup: %d, Pulldown: %d, DriveCap: %"PRIu32"\n", io_config.pu, io_config.pd, (uint32_t)io_config.drv);
fprintf(out_stream, " InputEn: %d, OutputEn: %d, OpenDrain: %d\n", io_config.ie, io_config.oe, io_config.od);
fprintf(out_stream, " InputEn: %d, OutputEn: %s%s, OpenDrain: %d\n", io_config.ie, oe_str, ((io_config.fun_sel == PIN_FUNC_GPIO) && (io_config.oe_inv)) ? " (inversed)" : "", io_config.od);
fprintf(out_stream, " FuncSel: %"PRIu32" (%s)\n", io_config.fun_sel, (io_config.fun_sel == PIN_FUNC_GPIO) ? "GPIO" : "IOMUX");
if (io_config.oe && io_config.fun_sel == PIN_FUNC_GPIO) {
if (io_config.fun_sel == PIN_FUNC_GPIO) {
fprintf(out_stream, " GPIO Matrix SigOut ID: %"PRIu32"%s\n", io_config.sig_out, (io_config.sig_out == SIG_GPIO_OUT_IDX) ? " (simple GPIO output)" : "");
}
if (io_config.ie && io_config.fun_sel == PIN_FUNC_GPIO) {

View File

@ -258,7 +258,6 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons
if (config->clk_src == PARLIO_CLK_SRC_EXTERNAL) {
ESP_RETURN_ON_FALSE(config->clk_in_gpio_num >= 0, ESP_ERR_INVALID_ARG, TAG, "clk_in_gpio_num must be set while the clock input from external");
/* Connect the clock in signal to the GPIO matrix if it is set */
gpio_func_sel(config->clk_in_gpio_num, PIN_FUNC_GPIO);
gpio_input_enable(config->clk_in_gpio_num);
// deprecated, to be removed in in esp-idf v6.0
@ -290,7 +289,6 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons
/* Initialize the valid GPIO as input */
if (config->valid_gpio_num >= 0) {
gpio_func_sel(config->valid_gpio_num, PIN_FUNC_GPIO);
gpio_input_enable(config->valid_gpio_num);
// deprecated, to be removed in in esp-idf v6.0
@ -305,7 +303,6 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons
for (int i = 0; i < config->data_width; i++) {
/* Loop the data_gpio_nums to connect data and valid signals via GPIO matrix */
if (config->data_gpio_nums[i] >= 0) {
gpio_func_sel(config->data_gpio_nums[i], PIN_FUNC_GPIO);
gpio_input_enable(config->data_gpio_nums[i]);
// deprecated, to be removed in in esp-idf v6.0

View File

@ -183,7 +183,6 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const
parlio_periph_signals.groups[group_id].tx_units[unit_id].clk_out_sig, false, false);
}
if (config->clk_in_gpio_num >= 0) {
gpio_func_sel(config->clk_in_gpio_num, PIN_FUNC_GPIO);
gpio_input_enable(config->clk_in_gpio_num);
// deprecated, to be removed in in esp-idf v6.0

View File

@ -562,7 +562,7 @@ static void configure_pin_iomux(uint8_t gpio_num)
gpio_pulldown_dis(gpio_num);
gpio_input_enable(gpio_num);
gpio_iomux_output(gpio_num, SDMMC_LL_IOMUX_FUNC, false);
gpio_iomux_output(gpio_num, SDMMC_LL_IOMUX_FUNC);
gpio_set_drive_capability(gpio_num, 3);
}

View File

@ -445,7 +445,7 @@ static void bus_iomux_pins_set_oct(spi_host_device_t host, const spi_bus_config_
if (io_nums[i] > 0) {
// In Octal mode use function channel 2
gpio_iomux_input(io_nums[i], SPI2_FUNC_NUM_OCT, io_signals[i]);
gpio_iomux_output(io_nums[i], SPI2_FUNC_NUM_OCT, false);
gpio_iomux_output(io_nums[i], SPI2_FUNC_NUM_OCT);
}
}
}
@ -455,23 +455,23 @@ static void bus_iomux_pins_set_quad(spi_host_device_t host, const spi_bus_config
{
if (bus_config->mosi_io_num >= 0) {
gpio_iomux_input(bus_config->mosi_io_num, spi_periph_signal[host].func, spi_periph_signal[host].spid_in);
gpio_iomux_output(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
gpio_iomux_output(bus_config->mosi_io_num, spi_periph_signal[host].func);
}
if (bus_config->miso_io_num >= 0) {
gpio_iomux_input(bus_config->miso_io_num, spi_periph_signal[host].func, spi_periph_signal[host].spiq_in);
gpio_iomux_output(bus_config->miso_io_num, spi_periph_signal[host].func, false);
gpio_iomux_output(bus_config->miso_io_num, spi_periph_signal[host].func);
}
if (bus_config->quadwp_io_num >= 0) {
gpio_iomux_input(bus_config->quadwp_io_num, spi_periph_signal[host].func, spi_periph_signal[host].spiwp_in);
gpio_iomux_output(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
gpio_iomux_output(bus_config->quadwp_io_num, spi_periph_signal[host].func);
}
if (bus_config->quadhd_io_num >= 0) {
gpio_iomux_input(bus_config->quadhd_io_num, spi_periph_signal[host].func, spi_periph_signal[host].spihd_in);
gpio_iomux_output(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
gpio_iomux_output(bus_config->quadhd_io_num, spi_periph_signal[host].func);
}
if (bus_config->sclk_io_num >= 0) {
gpio_iomux_input(bus_config->sclk_io_num, spi_periph_signal[host].func, spi_periph_signal[host].spiclk_in);
gpio_iomux_output(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
gpio_iomux_output(bus_config->sclk_io_num, spi_periph_signal[host].func);
}
}
@ -733,7 +733,7 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
if (!force_gpio_matrix && cs_io_num == spi_periph_signal[host].spics0_iomux_pin && cs_num == 0) {
//The cs0s for all SPI peripherals map to pin mux source 1, so we use that instead of a define.
gpio_iomux_input(cs_io_num, spi_periph_signal[host].func, spi_periph_signal[host].spics_in);
gpio_iomux_output(cs_io_num, spi_periph_signal[host].func, false);
gpio_iomux_output(cs_io_num, spi_periph_signal[host].func);
} else {
//Use GPIO matrix
if (GPIO_IS_VALID_OUTPUT_GPIO(cs_io_num)) {

View File

@ -686,7 +686,7 @@ static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t id
if (upin->input) {
gpio_iomux_input(io_num, upin->iomux_func, upin->signal);
} else {
gpio_iomux_output(io_num, upin->iomux_func, false);
gpio_iomux_output(io_num, upin->iomux_func);
}
}
#if (SOC_UART_LP_NUM >= 1) && (SOC_RTCIO_PIN_COUNT >= 1)
@ -768,7 +768,6 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
if (rx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX))) {
io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved
if (uart_num < SOC_UART_HP_NUM) {
gpio_func_sel(rx_io_num, PIN_FUNC_GPIO);
gpio_input_enable(rx_io_num);
esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
}
@ -803,7 +802,6 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) {
io_reserve_mask &= ~BIT64(cts_io_num); // input IO via GPIO matrix does not need to be reserved
if (uart_num < SOC_UART_HP_NUM) {
gpio_func_sel(cts_io_num, PIN_FUNC_GPIO);
gpio_pullup_en(cts_io_num);
gpio_input_enable(cts_io_num);
esp_rom_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0);

View File

@ -10,6 +10,7 @@
#include "driver/uart.h"
#include "esp_log.h"
#include "esp_rom_gpio.h"
#include "esp_private/gpio.h"
#if SOC_LP_GPIO_MATRIX_SUPPORTED
#include "driver/lp_io.h"
#include "driver/rtc_io.h"
@ -463,6 +464,7 @@ TEST_CASE("uart int state restored after flush", "[uart]")
/* Make sure UART's TX signal is connected to RX pin
* This creates a loop that lets us receive anything we send on the UART */
if (uart_num < SOC_UART_HP_NUM) {
gpio_func_sel(uart_rx, PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(uart_rx, uart_tx_signal, false, false);
#if SOC_UART_LP_NUM > 0
} else {

View File

@ -90,7 +90,7 @@ static esp_err_t emac_esp_iomux_init(gpio_num_t gpio_num, const emac_iomux_info_
if (is_input) {
ESP_RETURN_ON_ERROR(gpio_iomux_input(iomux_info->gpio_num, iomux_info->func, signal_idx), TAG, "failed to set perip. input via IOMUX");
} else {
ESP_RETURN_ON_ERROR(gpio_iomux_output(iomux_info->gpio_num, iomux_info->func, false), TAG, "failed to set perip. output via IOMUX");
ESP_RETURN_ON_ERROR(gpio_iomux_output(iomux_info->gpio_num, iomux_info->func), TAG, "failed to set perip. output via IOMUX");
}
ESP_RETURN_ON_ERROR(gpio_set_pull_mode(iomux_info->gpio_num, GPIO_FLOATING),
TAG, "failed to set pull mode at GPIO %i", iomux_info->gpio_num);

View File

@ -141,7 +141,7 @@ static esp_clock_output_mapping_t* clkout_mapping_alloc(clkout_channel_handle_t*
allocated_mapping->ref_cnt++;
if (allocated_mapping->ref_cnt == 1) {
#if SOC_GPIO_CLOCKOUT_BY_IO_MUX
gpio_iomux_output(gpio_num, CLKOUT_CHANNEL_TO_IOMUX_FUNC(allocated_mapping->clkout_channel_hdl->channel_id), false);
gpio_iomux_output(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_func_sel(gpio_num, PIN_FUNC_GPIO);

View File

@ -99,8 +99,8 @@ TEST_CASE("GPIO output internal clock", "[gpio_output_clock][ignore]")
#if CONFIG_IDF_TARGET_ESP32
/* ESP32 clock out channel pin reuses UART TX/RX pin, restore its default
configuration at the end of the test */
gpio_iomux_output(U0RXD_GPIO_NUM, FUNC_U0RXD_U0RXD, false);
gpio_iomux_output(U0TXD_GPIO_NUM, FUNC_U0TXD_U0TXD, false);
gpio_iomux_output(U0RXD_GPIO_NUM, FUNC_U0RXD_U0RXD);
gpio_iomux_output(U0TXD_GPIO_NUM, FUNC_U0TXD_U0TXD);
#endif
}

View File

@ -58,6 +58,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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;
io_config->drv = (gpio_drive_cap_t)((iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S);
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
@ -693,7 +695,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}

View File

@ -48,6 +48,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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 = (hw->enable.val & bit_mask) >> gpio_num;
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;
io_config->drv = (gpio_drive_cap_t)((iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S);
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
@ -495,7 +497,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}

View File

@ -495,7 +495,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}
@ -735,6 +735,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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 = (hw->enable.val & bit_mask) >> gpio_num;
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;

View File

@ -50,6 +50,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
io_config->pd = IO_MUX.gpio[gpio_num].fun_wpd;
io_config->ie = IO_MUX.gpio[gpio_num].fun_ie;
io_config->oe = (hw->enable.val & (1 << gpio_num)) >> gpio_num;
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;
io_config->drv = (gpio_drive_cap_t)IO_MUX.gpio[gpio_num].fun_drv;
io_config->fun_sel = IO_MUX.gpio[gpio_num].mcu_sel;
@ -483,7 +485,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}

View File

@ -15,6 +15,7 @@
#include "soc/ledc_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -369,6 +370,7 @@ static inline void ledc_ll_get_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc
*/
static inline void ledc_ll_set_fade_param_range(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint8_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step)
{
HAL_ASSERT(range < SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX);
ledc_channel_gamma_fade_param_t range_param = {
.duty_inc = dir,
.duty_cycle = cycle,

View File

@ -53,6 +53,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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 = (hw->enable.val & bit_mask) >> gpio_num;
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;
io_config->drv = (gpio_drive_cap_t)((iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S);
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
@ -454,7 +456,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}

View File

@ -16,6 +16,7 @@
#include "soc/clk_tree_defs.h"
#include "hal/assert.h"
#include "esp_rom_sys.h" //for sync issue workaround
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -452,6 +453,7 @@ static inline void ledc_ll_set_duty_range_wr_addr(ledc_dev_t *hw, ledc_mode_t sp
*/
static inline void ledc_ll_set_fade_param_range(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint8_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step)
{
HAL_ASSERT(range < SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX);
// To workaround sync issue
// This is to ensure the fade param write to the gamma_wr register would not mess up the last wr_addr
ledc_ll_set_duty_range_wr_addr(hw, speed_mode, channel_num, range);

View File

@ -51,6 +51,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
io_config->pd = IO_MUX.gpion[gpio_num].gpion_fun_wpd;
io_config->ie = IO_MUX.gpion[gpio_num].gpion_fun_ie;
io_config->oe = (hw->enable.val & (1 << gpio_num)) >> gpio_num;
io_config->oe_ctrl_by_periph = !(hw->funcn_out_sel_cfg[gpio_num].funcn_oe_sel);
io_config->oe_inv = hw->funcn_out_sel_cfg[gpio_num].funcn_oe_inv_sel;
io_config->od = hw->pinn[gpio_num].pinn_pad_driver;
io_config->drv = (gpio_drive_cap_t)IO_MUX.gpion[gpio_num].gpion_fun_drv;
io_config->fun_sel = IO_MUX.gpion[gpio_num].gpion_mcu_sel;
@ -483,7 +485,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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->funcn_out_sel_cfg[gpio_num].funcn_oe_inv_sel = oen_inv;
hw->funcn_out_sel_cfg[gpio_num].funcn_oe_inv_sel = oen_inv; // control valid only when using gpio matrix to route signal to the IO
hw->funcn_out_sel_cfg[gpio_num].funcn_oe_sel = !ctrl_by_periph;
}

View File

@ -15,6 +15,7 @@
#include "soc/ledc_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -369,6 +370,7 @@ static inline void ledc_ll_get_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc
*/
static inline void ledc_ll_set_fade_param_range(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint8_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step)
{
HAL_ASSERT(range < SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX);
ledc_channel_gamma_fade_param_t range_param = {
.duty_inc = dir,
.duty_cycle = cycle,

View File

@ -53,6 +53,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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 = (hw->enable.val & bit_mask) >> gpio_num;
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;
io_config->drv = (gpio_drive_cap_t)((iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S);
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
@ -500,7 +502,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}

View File

@ -16,6 +16,7 @@
#include "soc/clk_tree_defs.h"
#include "hal/assert.h"
#include "esp_rom_sys.h" //for sync issue workaround
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -450,6 +451,7 @@ static inline void ledc_ll_set_duty_range_wr_addr(ledc_dev_t *hw, ledc_mode_t sp
*/
static inline void ledc_ll_set_fade_param_range(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint8_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step)
{
HAL_ASSERT(range < SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX);
// To workaround sync issue
// This is to ensure the fade param write to the gamma_wr register would not mess up the last wr_addr
ledc_ll_set_duty_range_wr_addr(hw, speed_mode, channel_num, range);

View File

@ -55,6 +55,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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 = (hw->enable.val & bit_mask) >> gpio_num;
io_config->oe_ctrl_by_periph = !(hw->funcn_out_sel_cfg[gpio_num].funcn_oe_sel);
io_config->oe_inv = hw->funcn_out_sel_cfg[gpio_num].funcn_oe_inv_sel;
io_config->od = hw->pinn[gpio_num].pinn_pad_driver;
io_config->drv = (gpio_drive_cap_t)((iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S);
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
@ -507,7 +509,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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->funcn_out_sel_cfg[gpio_num].funcn_oe_inv_sel = oen_inv;
hw->funcn_out_sel_cfg[gpio_num].funcn_oe_inv_sel = oen_inv; // control valid only when using gpio matrix to route signal to the IO
hw->funcn_out_sel_cfg[gpio_num].funcn_oe_sel = !ctrl_by_periph;
}

View File

@ -59,6 +59,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
io_config->pd = IO_MUX.gpio[gpio_num].fun_wpd;
io_config->ie = IO_MUX.gpio[gpio_num].fun_ie;
io_config->oe = (((gpio_num < 32) ? hw->enable.val : 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;
io_config->drv = (gpio_drive_cap_t)IO_MUX.gpio[gpio_num].fun_drv;
io_config->fun_sel = IO_MUX.gpio[gpio_num].mcu_sel;
@ -586,7 +588,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}

View File

@ -15,6 +15,7 @@
#include "soc/ledc_reg.h"
#include "soc/clk_tree_defs.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -383,6 +384,7 @@ static inline void ledc_ll_get_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc
*/
static inline void ledc_ll_set_fade_param_range(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint8_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step)
{
HAL_ASSERT(range < SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX);
ledc_channel_gamma_fade_param_t range_param = {
.duty_inc = dir,
.duty_cycle = cycle,

View File

@ -48,6 +48,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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;
io_config->drv = (gpio_drive_cap_t)((iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S);
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
@ -507,7 +509,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}

View File

@ -510,7 +510,7 @@ static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal
*/
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;
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;
}
@ -701,6 +701,8 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
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;

View File

@ -38,9 +38,9 @@ void gpio_hal_iomux_in(gpio_hal_context_t *hal, uint32_t gpio_num, int func, uin
gpio_ll_func_sel(hal->dev, gpio_num, func);
}
void gpio_hal_iomux_out(gpio_hal_context_t *hal, uint32_t gpio_num, int func, bool oen_inv)
void gpio_hal_iomux_out(gpio_hal_context_t *hal, uint32_t gpio_num, int func)
{
gpio_ll_set_output_enable_ctrl(hal->dev, gpio_num, true, oen_inv);
gpio_ll_set_output_enable_ctrl(hal->dev, gpio_num, true, false);
gpio_ll_func_sel(hal->dev, gpio_num, func);
}

View File

@ -160,6 +160,16 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num);
*/
#define gpio_hal_output_enable(hal, gpio_num) gpio_ll_output_enable((hal)->dev, gpio_num)
/**
* @brief Configure the source of output enable signal for the GPIO pin.
*
* @param hal Context of the HAL layer
* @param gpio_num GPIO number
* @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
*/
#define gpio_hal_set_output_enable_ctrl(hal, gpio_num, ctrl_by_periph, oen_inv) gpio_ll_set_output_enable_ctrl((hal)->dev, gpio_num, ctrl_by_periph, oen_inv)
/**
* @brief Disable open-drain mode on GPIO.
*
@ -364,9 +374,8 @@ void gpio_hal_iomux_in(gpio_hal_context_t *hal, uint32_t gpio_num, int func, uin
* @param gpio_num GPIO number of the pad.
* @param func The index number of the IOMUX function to be selected for the pin.
* One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
* @param oen_inv True if the output enable needs to be inverted, otherwise False.
*/
void gpio_hal_iomux_out(gpio_hal_context_t *hal, uint32_t gpio_num, int func, bool oen_inv);
void gpio_hal_iomux_out(gpio_hal_context_t *hal, uint32_t gpio_num, int func);
#if SOC_GPIO_SUPPORT_FORCE_HOLD
/**

View File

@ -153,6 +153,8 @@ typedef struct {
bool pd; /*!< Status of pull-down enabled or not */
bool ie; /*!< Status of input enabled or not */
bool oe; /*!< Status of output enabled or not */
bool oe_ctrl_by_periph; /*!< True if use output enable signal from peripheral, otherwise False */
bool oe_inv; /*!< Whether the output enable signal is inversed or not */
bool od; /*!< Status of open-drain enabled or not */
bool slp_sel; /*!< Status of pin sleep mode enabled or not */
} gpio_io_config_t;

View File

@ -39,7 +39,6 @@ void ledc_hal_get_duty(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint
void ledc_hal_set_fade_param(const ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step)
{
#if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
HAL_ASSERT(range < SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX);
ledc_ll_set_fade_param_range(hal->dev, hal->speed_mode, channel_num, range, dir, cycle, scale, step);
#else // !SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
HAL_ASSERT(range == 0);

View File

@ -101,9 +101,9 @@ static void setup_bus(spi_host_device_t host_id)
int wp_pin = spi_periph_signal[host_id].spiwp_iomux_pin;
int hd_pin = spi_periph_signal[host_id].spihd_iomux_pin;
gpio_iomux_input(wp_pin, spi_periph_signal[host_id].func, spi_periph_signal[host_id].spiwp_in);
gpio_iomux_output(wp_pin, spi_periph_signal[host_id].func, false);
gpio_iomux_output(wp_pin, spi_periph_signal[host_id].func);
gpio_iomux_input(hd_pin, spi_periph_signal[host_id].func, spi_periph_signal[host_id].spihd_in);
gpio_iomux_output(hd_pin, spi_periph_signal[host_id].func, false);
gpio_iomux_output(hd_pin, spi_periph_signal[host_id].func);
#endif //CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
//currently the SPI bus for main flash chip is initialized through GPIO matrix
} else if (host_id == SPI2_HOST) {