feat(ledc): add esp_gpio_reserve to ledc driver

This commit is contained in:
Song Ruo Jing
2024-07-02 12:27:30 +08:00
parent 4cd74f51db
commit 51a7f7895c
6 changed files with 64 additions and 43 deletions

View File

@@ -11,7 +11,6 @@
#include "freertos/idf_additions.h"
#include "esp_log.h"
#include "esp_check.h"
#include "soc/gpio_periph.h"
#include "soc/ledc_periph.h"
#include "esp_clk_tree.h"
#include "soc/soc_caps.h"
@@ -19,10 +18,10 @@
#include "hal/gpio_hal.h"
#include "driver/ledc.h"
#include "esp_rom_gpio.h"
#include "esp_rom_sys.h"
#include "clk_ctrl_os.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/gpio.h"
#include "esp_private/esp_gpio_reserve.h"
#include "esp_memory_utils.h"
static __attribute__((unused)) const char *LEDC_TAG = "ledc";
@@ -88,7 +87,9 @@ typedef struct {
#endif
} ledc_obj_t;
static ledc_obj_t *p_ledc_obj[LEDC_SPEED_MODE_MAX] = {0};
static ledc_obj_t *p_ledc_obj[LEDC_SPEED_MODE_MAX] = {
[0 ... LEDC_SPEED_MODE_MAX - 1] = NULL,
};
static ledc_fade_t *s_ledc_fade_rec[LEDC_SPEED_MODE_MAX][LEDC_CHANNEL_MAX];
static ledc_isr_handle_t s_ledc_fade_isr_handle = NULL;
static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED;
@@ -641,17 +642,30 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf)
return ret;
}
esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel)
esp_err_t _ledc_set_pin(int gpio_num, bool out_inv, ledc_mode_t speed_mode, ledc_channel_t channel)
{
LEDC_ARG_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel");
LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num");
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
gpio_func_sel(gpio_num, PIN_FUNC_GPIO);
gpio_set_level(gpio_num, out_inv);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio_num, ledc_periph_signal[speed_mode].sig_out0_idx + ledc_channel, 0, 0);
// reserve the GPIO output path, because we don't expect another peripheral to signal to the same GPIO
uint64_t old_gpio_rsv_mask = esp_gpio_reserve(BIT64(gpio_num));
// check if the GPIO is already used by others, LEDC signal only uses the output path of the GPIO
if (old_gpio_rsv_mask & BIT64(gpio_num)) {
ESP_LOGW(LEDC_TAG, "GPIO %d is not usable, maybe conflict with others", gpio_num);
}
esp_rom_gpio_connect_out_signal(gpio_num, ledc_periph_signal[speed_mode].sig_out0_idx + channel, out_inv, 0);
return ESP_OK;
}
// One LEDC channel signal can be directed to multiple IOs as outputs
esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t channel)
{
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num");
return _ledc_set_pin(gpio_num, false, speed_mode, channel);
}
esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
{
LEDC_ARG_CHECK(ledc_conf, "ledc_conf");
@@ -710,10 +724,7 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
ESP_LOGD(LEDC_TAG, "LEDC_PWM CHANNEL %"PRIu32"|GPIO %02u|Duty %04"PRIu32"|Time %"PRIu32,
ledc_channel, gpio_num, duty, timer_select);
/*set LEDC signal in gpio matrix*/
gpio_func_sel(gpio_num, PIN_FUNC_GPIO);
gpio_set_level(gpio_num, output_invert);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio_num, ledc_periph_signal[speed_mode].sig_out0_idx + ledc_channel, output_invert, 0);
_ledc_set_pin(gpio_num, output_invert, speed_mode, ledc_channel);
return ret;
}