diff --git a/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst b/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst index 60fa4f7a4f..733be697d8 100644 --- a/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst +++ b/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst @@ -294,6 +294,22 @@ the ``buttons`` application and pressing on any of the available board buttons:: nsh> Sample = 1 Sample = 0 +capture +-------- + +The capture configuration enables the capture driver and the capture example, allowing +the user to measure duty cycle and frequency of a signal. Default pin is GPIO 14 with +an internal pull-up resistor enabled. When connecting a 50 Hz pulse with 50% duty cycle, +the following output is expected: + +nsh> cap +cap_main: Hardware initialized. Opening the capture device: /dev/capture0 +cap_main: Number of samples: 0 +pwm duty cycle: 50 % +pwm frequence: 50 Hz +pwm duty cycle: 50 % +pwm frequence: 50 Hz + coremark -------- diff --git a/Documentation/platforms/xtensa/esp32/index.rst b/Documentation/platforms/xtensa/esp32/index.rst index c21d54513b..8d9b979582 100644 --- a/Documentation/platforms/xtensa/esp32/index.rst +++ b/Documentation/platforms/xtensa/esp32/index.rst @@ -173,7 +173,7 @@ GPIO Yes I2C Yes I2S Yes LED_PWM Yes -MCPWM No +MCPWM Yes Capture Pulse_CNT No RMT Yes RNG Yes diff --git a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst index ad5d4dd1de..44d5c2d6c9 100644 --- a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst @@ -146,6 +146,22 @@ the ``buttons`` application and pressing on any of the available board buttons:: nsh> Sample = 1 Sample = 0 +capture +-------- + +The capture configuration enables the capture driver and the capture example, allowing +the user to measure duty cycle and frequency of a signal. Default pin is GPIO 12 with +an internal pull-up resistor enabled. When connecting a 50 Hz pulse with 50% duty cycle, +the following output is expected: + +nsh> cap +cap_main: Hardware initialized. Opening the capture device: /dev/capture0 +cap_main: Number of samples: 0 +pwm duty cycle: 50 % +pwm frequence: 50 Hz +pwm duty cycle: 50 % +pwm frequence: 50 Hz + coremark -------- diff --git a/Documentation/platforms/xtensa/esp32s3/index.rst b/Documentation/platforms/xtensa/esp32s3/index.rst index 4956759903..9aada315f5 100644 --- a/Documentation/platforms/xtensa/esp32s3/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/index.rst @@ -178,7 +178,7 @@ I2C No I2S Yes LCD No LED_PWM No -MCPWM No +MCPWM Yes Capture Pulse_CNT No RMT No RNG No diff --git a/arch/xtensa/src/common/espressif/Kconfig b/arch/xtensa/src/common/espressif/Kconfig index c6cfce8c7f..d0f473b46c 100644 --- a/arch/xtensa/src/common/espressif/Kconfig +++ b/arch/xtensa/src/common/espressif/Kconfig @@ -7,3 +7,11 @@ config ESP_RMT an infrared transceiver. However, due to the flexibility of its data format, RMT can be extended to a versatile and general-purpose transceiver, transmitting or receiving many other types of signals. + +config ESP_MCPWM + bool "Motor Control PWM (MCPWM)" + default n + depends on ARCH_CHIP_ESP32 || ARCH_CHIP_ESP32S3 + ---help--- + Enable support for timer capture and motor control using + the Motor Control PWM peripheral. diff --git a/arch/xtensa/src/common/espressif/Make.defs b/arch/xtensa/src/common/espressif/Make.defs index 2034dbeebf..7c7db854db 100644 --- a/arch/xtensa/src/common/espressif/Make.defs +++ b/arch/xtensa/src/common/espressif/Make.defs @@ -25,4 +25,8 @@ CHIP_CSRCS += esp_ws2812.c endif endif +ifeq ($(CONFIG_ESP_MCPWM),y) +CHIP_CSRCS += esp_mcpwm.c +endif + INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)common$(DELIM)espressif$(DELIM)platform_include diff --git a/arch/xtensa/src/common/espressif/esp_mcpwm.c b/arch/xtensa/src/common/espressif/esp_mcpwm.c new file mode 100644 index 0000000000..935bf28f84 --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_mcpwm.c @@ -0,0 +1,678 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_mcpwm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xtensa.h" +#ifdef CONFIG_ARCH_CHIP_ESP32 +#include "hardware/esp32_soc.h" +#include "esp32_gpio.h" +#include "esp32_irq.h" +#elif CONFIG_ARCH_CHIP_ESP32S3 +#include "hardware/esp32s3_soc.h" +#include "esp32s3_gpio.h" +#include "esp32s3_irq.h" +#endif + +#include "hal/mcpwm_hal.h" +#include "hal/mcpwm_ll.h" +#include "soc/mcpwm_periph.h" +#include "periph_ctrl.h" +#include "hal/clk_tree_hal.h" + +#ifdef CONFIG_ESP_MCPWM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MCPWM_CAPTURE_DEFAULT_GROUP 0 +#ifdef CONFIG_ARCH_CHIP_ESP32 +# define esp_configgpio esp32_configgpio +# define esp_gpio_matrix_in esp32_gpio_matrix_in +# define esp_setup_irq esp32_setup_irq +# define esp_teardown_irq esp32_teardown_irq +# define ESP_CPUINT_LEVEL ESP32_CPUINT_LEVEL +#elif CONFIG_ARCH_CHIP_ESP32S3 +# define esp_configgpio esp32s3_configgpio +# define esp_gpio_matrix_in esp32s3_gpio_matrix_in +# define esp_setup_irq esp32s3_setup_irq +# define esp_teardown_irq esp32s3_teardown_irq +# define ESP_CPUINT_LEVEL ESP32S3_CPUINT_LEVEL +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Capture event data. The 'last_' value is used to calculate frequency */ + +struct mcpwm_dev_common_s +{ + mcpwm_hal_init_config_t group; + mcpwm_hal_context_t hal; + spinlock_t mcpwm_spinlock; + bool initialized; /* MCPWM periph. and HAL has been initialized */ +#ifdef CONFIG_ESP_MCPWM_CAPTURE + bool capture_initialized; /* Capture submodule has been initialized */ +#endif +}; + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +struct mcpwm_capture_event_data_s +{ + uint32_t pos_edge_count; + uint32_t neg_edge_count; + uint32_t last_pos_edge_count; +}; + +enum mcpwm_capture_channel_e +{ + MCPWM_CAP_CHANNEL_0, /* MCPWM capture channel number 0 */ + MCPWM_CAP_CHANNEL_1, /* MCPWM capture channel number 1 */ + MCPWM_CAP_CHANNEL_2, /* MCPWM capture channel number 2 */ + MCPWM_CAP_CHANNEL_MAX /* Number of MCPWM capture channels */ +}; + +struct mcpwm_cap_channel_lowerhalf_s +{ + /* The following block is part of the upper-half device struct */ + + FAR const struct cap_ops_s *ops; + + /* The following is private to the ESP MCPWM driver */ + + struct mcpwm_dev_common_s *common; + struct mcpwm_capture_event_data_s *data; + int channel_id; + int gpio_pin; + uint32_t clock; + uint32_t freq; + uint8_t duty; + uint8_t isr_count; + bool ready; + bool enabled; +}; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void esp_mcpwm_group_start(void); +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int esp_mcpwm_capture_isr_register(int (*fn)(int, void *, void *), + void *arg); +static int IRAM_ATTR mcpwm_capture_driver_isr_default(int irq, void *context, + void *arg); +static int esp_mcpwm_capture_set_gpio( + struct mcpwm_cap_channel_lowerhalf_s *lower); +#endif + +/* Lower half methods required by capture driver */ + +static int esp_capture_start(struct cap_lowerhalf_s *lower); +static int esp_capture_stop(struct cap_lowerhalf_s *lower); +static int esp_capture_getduty(struct cap_lowerhalf_s *lower, + uint8_t *duty); +static int esp_capture_getfreq(struct cap_lowerhalf_s *lower, + uint32_t *freq); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct mcpwm_dev_common_s g_mcpwm_common = +{ + .group.group_id = 0, + .initialized = false, + .capture_initialized = false, +}; + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +/* Lower half methods required by capture driver */ + +static const struct cap_ops_s mcpwm_cap_ops = +{ + .start = esp_capture_start, + .stop = esp_capture_stop, + .getduty = esp_capture_getduty, + .getfreq = esp_capture_getfreq, +}; + +/* Data structures for the available capture channels */ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH0 +static struct mcpwm_capture_event_data_s event_data_ch0; +static struct mcpwm_cap_channel_lowerhalf_s mcpwm_cap_ch0_lowerhalf = +{ + .ops = &mcpwm_cap_ops, + .common = &g_mcpwm_common, + .data = &event_data_ch0, + .channel_id = MCPWM_CAP_CHANNEL_0, + .ready = false, +}; +#endif + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH1 +static struct mcpwm_capture_event_data_s event_data_ch1; +static struct mcpwm_cap_channel_lowerhalf_s mcpwm_cap_ch1_lowerhalf = +{ + .ops = &mcpwm_cap_ops, + .common = &g_mcpwm_common, + .data = &event_data_ch1, + .channel_id = MCPWM_CAP_CHANNEL_1, + .ready = false, +}; +#endif + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH2 +static struct mcpwm_capture_event_data_s event_data_ch2; +static struct mcpwm_cap_channel_lowerhalf_s mcpwm_cap_ch2_lowerhalf = +{ + .ops = &mcpwm_cap_ops, + .common = &g_mcpwm_common, + .data = &event_data_ch2, + .channel_id = MCPWM_CAP_CHANNEL_2, + .ready = false, +}; +#endif +#endif /* CONFIG_ESP_MCPWM_CAPTURE */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_mcpwm_group_start + * + * Description: + * Initializes the PWM0 module and the MCPWM HAL. + * Should be called only once for the MCPWM peripheral. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void esp_mcpwm_group_start(void) +{ + periph_module_enable(PERIPH_PWM0_MODULE); + mcpwm_hal_init(&g_mcpwm_common.hal, &g_mcpwm_common.group); + mcpwm_hal_timer_reset(&g_mcpwm_common.hal, 0); + + g_mcpwm_common.initialized = true; +} + +/**************************************************************************** + * Name: esp_capture_start + * + * Description: + * This function is a requirement of the upper-half driver. When called, + * enables the capture channel, interruption routine, sets the positive + * edge to trigger this interrupt and resets the frequency and duty + * values. The positive edge is always the first expected. + * + * Input Parameters: + * lower - Pointer to the capture channel lower-half data structure. + * + * Returned Value: + * Returns OK on success. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int esp_capture_start(struct cap_lowerhalf_s *lower) +{ + struct mcpwm_cap_channel_lowerhalf_s *priv = ( + struct mcpwm_cap_channel_lowerhalf_s *)lower; + mcpwm_hal_context_t *hal = &priv->common->hal; + irqstate_t flags; + flags = spin_lock_irqsave(priv->common->mcpwm_spinlock); + + DEBUGASSERT(priv->common->initialized); + + /* Enable channel and interruption for rising edge */ + + mcpwm_ll_capture_enable_channel(hal->dev, priv->channel_id, true); + mcpwm_ll_intr_enable(hal->dev, + MCPWM_LL_EVENT_CAPTURE(priv->channel_id), + true); + mcpwm_ll_intr_clear_status(hal->dev, + MCPWM_LL_EVENT_CAPTURE(priv->channel_id)); + mcpwm_ll_capture_enable_posedge(hal->dev, priv->channel_id, true); + mcpwm_ll_capture_enable_negedge(hal->dev, priv->channel_id, false); + + /* Reset values of interest */ + + priv->freq = 0; + priv->duty = 0; + priv->isr_count = 0; + priv->enabled = true; + priv->ready = false; + + cpinfo("Channel enabled: %d\n", priv->channel_id); + spin_unlock_irqrestore(priv->common->mcpwm_spinlock, flags); + + return OK; +} +#endif + +/**************************************************************************** + * Name: esp_capture_stop + * + * Description: + * This function is a requirement of the upper-half driver. When called, + * disables the capture channel and the interrupt routine associated. + * + * Input Parameters: + * lower - Pointer to the capture channel lower-half data structure. + * + * Returned Value: + * Returns OK on success. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int esp_capture_stop(struct cap_lowerhalf_s *lower) +{ + struct mcpwm_cap_channel_lowerhalf_s *priv = ( + struct mcpwm_cap_channel_lowerhalf_s *)lower; + mcpwm_hal_context_t *hal = &priv->common->hal; + irqstate_t flags; + flags = spin_lock_irqsave(priv->common->mcpwm_spinlock); + + /* Disable channel and interrupts */ + + mcpwm_ll_capture_enable_channel(hal->dev, priv->channel_id, false); + mcpwm_ll_intr_enable(hal->dev, + MCPWM_LL_EVENT_CAPTURE(priv->channel_id), + false); + priv->enabled = false; + + cpinfo("Channel disabled: %d\n", priv->channel_id); + spin_unlock_irqrestore(priv->common->mcpwm_spinlock, flags); + + return OK; +} +#endif + +/**************************************************************************** + * Name: esp_capture_getduty + * + * Description: + * This function is a requirement of the upper-half driver. Returns + * the last calculated duty cycle value. + * + * Input Parameters: + * lower - Pointer to the capture channel lower-half data structure. + * duty - uint8_t pointer where the duty cycle value is written. + * + * Returned Value: + * Returns OK on success. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int esp_capture_getduty(struct cap_lowerhalf_s *lower, + uint8_t *duty) +{ + struct mcpwm_cap_channel_lowerhalf_s *priv = ( + struct mcpwm_cap_channel_lowerhalf_s *)lower; + *duty = priv->duty; + cpinfo("Get duty called from channel %d\n", priv->channel_id); + return OK; +} +#endif + +/**************************************************************************** + * Name: esp_capture_getfreq + * + * Description: + * This function is a requirement of the upper-half driver. Returns + * the last calculated frequency value. + * + * Input Parameters: + * lower - Pointer to the capture channel lower-half data structure. + * duty - uint8_t pointer where the frequency value is written. + * + * Returned Value: + * Returns OK on success. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int esp_capture_getfreq(struct cap_lowerhalf_s *lower, + uint32_t *freq) +{ + struct mcpwm_cap_channel_lowerhalf_s *priv = ( + struct mcpwm_cap_channel_lowerhalf_s *)lower; + *freq = priv->freq; + cpinfo("Get freq called from channel %d\n", priv->channel_id); + return OK; +} +#endif + +/**************************************************************************** + * Name: esp_mcpwm_capture_set_gpio + * + * Description: + * Configures the lower-half GPIO pin to be used as a capture input. + * + * Input Parameters: + * lower - Pointer to the capture channel lower-half data structure. + * + * Returned Value: + * OK on success, otherwise a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int esp_mcpwm_capture_set_gpio( + struct mcpwm_cap_channel_lowerhalf_s *lower) +{ + mcpwm_hal_context_t *hal = &lower->common->hal; + int ret; + + ret = esp_configgpio(lower->gpio_pin, INPUT_FUNCTION | INPUT_PULLUP); + if (ret < 0) + { + cperr("Failed configuring GPIO pin\n"); + return ret; + } + + esp_gpio_matrix_in( + lower->gpio_pin, + mcpwm_periph_signals.groups[MCPWM_CAPTURE_DEFAULT_GROUP].\ + captures[lower->channel_id].cap_sig, + false); + + cpinfo("GPIO: %d configured for channel %d\n", lower->gpio_pin, + lower->channel_id); + return ret; +} +#endif + +/**************************************************************************** + * Name: esp_mcpwm_capture_isr_register + * + * Description: + * Registers a callback function for a channel interrupt request. + * + * Input Parameters: + * fn - Pointer to ISR function that is to be called. + * arg - Pointer to arguments passed to said function. + * + * Returned Value: + * OK on success, otherwise a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int esp_mcpwm_capture_isr_register(int (*fn)(int, void *, void *), + void *arg) +{ + int cpuint; + int ret; + int cpu = up_cpu_index(); + + DEBUGASSERT(fn); + + cpuint = esp_setup_irq(cpu, mcpwm_periph_signals.groups[0].irq_id, + 1, ESP_CPUINT_LEVEL); + if (cpuint < 0) + { + cperr("Failed to allocate a CPU interrupt.\n"); + return -ENOMEM; + } + + ret = irq_attach(mcpwm_periph_signals.groups[0].irq_id + + XTENSA_IRQ_FIRSTPERIPH, fn, arg); + if (ret < 0) + { + cperr("Couldn't attach IRQ to handler.\n"); + esp_teardown_irq(cpu, mcpwm_periph_signals.groups[0].irq_id, cpuint); + return ret; + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: mcpwm_capture_driver_isr_default + * + * Description: + * Default function called when a capture interrupt occurs. + * It reads the capture timer value and the interrupt edge. When positive + * edge triggered the interrupt, the current capture value is stored and + * the interrupt edge is modified to falling edge. + * When the negative edge triggers the interrupt, the timer count + * difference is calculated and the high time period is obtained. + * + * Two pulses are required to properly calculate the frequency. + * + * Input Parameters: + * irq - The interrupt request number. + * context - Pointer to the interrupt context. + * arg - Pointer to the argument to be passed to the ISR. + * + * Returned Value: + * OK on success, otherwise a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +static int IRAM_ATTR mcpwm_capture_driver_isr_default(int irq, void *context, + void *arg) +{ + struct mcpwm_dev_common_s *common = (struct mcpwm_dev_common_s *)arg; + struct mcpwm_cap_channel_lowerhalf_s *lower = NULL; + struct mcpwm_capture_event_data_s *data = NULL; + uint32_t status; + uint32_t cap_value; + mcpwm_capture_edge_t cap_edge; + irqstate_t flags; + + flags = spin_lock_irqsave(common->mcpwm_spinlock); + status = mcpwm_ll_intr_get_status(common->hal.dev); + + /* Evaluate which channel triggered the capture interrupt */ + + if (status & MCPWM_LL_EVENT_CAPTURE(MCPWM_CAP_CHANNEL_0)) + { +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH0 + lower = &mcpwm_cap_ch0_lowerhalf; +#endif + } +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH1 + else if (status & MCPWM_LL_EVENT_CAPTURE(MCPWM_CAP_CHANNEL_1)) + { + lower = &mcpwm_cap_ch1_lowerhalf; + } +#endif +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH2 + else if (status & MCPWM_LL_EVENT_CAPTURE(MCPWM_CAP_CHANNEL_2)) + { + lower = &mcpwm_cap_ch2_lowerhalf; + } +#endif + else + { + return -ERANGE; + } + + mcpwm_ll_intr_clear_status(common->hal.dev, + status & + MCPWM_LL_EVENT_CAPTURE(lower->channel_id)); + + /* At least 4 interrupts are required on a channel before a + * frequency measurement can be executed, otherwise you can + * obtain negative values. + */ + + if (lower->isr_count < 4) + { + lower->isr_count++; + } + + if (!lower->ready && (lower->isr_count >= 4)) + { + cpinfo("Channel %d ready\n", lower->channel_id); + lower->ready = true; + } + + data = lower->data; + cap_value = mcpwm_ll_capture_get_value(common->hal.dev, lower->channel_id); + cap_edge = mcpwm_ll_capture_get_edge(common->hal.dev, lower->channel_id); + + if (cap_edge == MCPWM_CAP_EDGE_POS) + { + data->last_pos_edge_count = data->pos_edge_count; + data->pos_edge_count = cap_value; + data->neg_edge_count = data->pos_edge_count; + mcpwm_ll_capture_enable_negedge(common->hal.dev, + lower->channel_id, + true); + mcpwm_ll_capture_enable_posedge(common->hal.dev, + lower->channel_id, + false); + } + else + { + data->neg_edge_count = cap_value; + + if (lower->ready) + { + uint32_t high_time = data->neg_edge_count - data->pos_edge_count; + uint32_t period = data->pos_edge_count - data->last_pos_edge_count; + + if (period != 0) + { + lower->freq = lower->clock / period; + lower->duty = 100 * high_time / period; + } + } + + mcpwm_ll_capture_enable_negedge(common->hal.dev, + lower->channel_id, + false); + mcpwm_ll_capture_enable_posedge(common->hal.dev, + lower->channel_id, + true); + } + + spin_unlock_irqrestore(common->mcpwm_spinlock, flags); + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_mcpwm_capture_initialize + * + * Description: + * This function initializes the specified MCPWM peripheral and the capture + * submodule with the provided configuration. + * + * Input Parameters: + * channel - Channel to be initialized [0-3]. + * pin - GPIO pin assigned to this channel. + * + * Returned Value: + * On success, this function returns a valid pointer to the Capture device + * structure. If the initialization fails, it returns NULL. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +struct cap_lowerhalf_s *esp_mcpwm_capture_initialize(int channel, int pin) +{ + struct mcpwm_cap_channel_lowerhalf_s *lower = NULL; + + if (!g_mcpwm_common.initialized) + { + esp_mcpwm_group_start(); + } + + if (!g_mcpwm_common.capture_initialized) + { + esp_mcpwm_capture_isr_register(mcpwm_capture_driver_isr_default, + &g_mcpwm_common); + mcpwm_ll_capture_enable_timer(g_mcpwm_common.hal.dev, true); + } + + switch (channel) + { +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH0 + case MCPWM_CAP_CHANNEL_0: + lower = &mcpwm_cap_ch0_lowerhalf; + break; +#endif +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH1 + case MCPWM_CAP_CHANNEL_1: + lower = &mcpwm_cap_ch1_lowerhalf; + break; +#endif +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH2 + case MCPWM_CAP_CHANNEL_2: + lower = &mcpwm_cap_ch2_lowerhalf; + break; +#endif + default: + cperr("Invalid channel selection: %d\n", channel); + return NULL; + } + + lower->clock = clk_hal_apb_get_freq_hz(); + lower->gpio_pin = pin; + esp_mcpwm_capture_set_gpio(lower); + + return (struct cap_lowerhalf_s *) lower; +} +#endif + +#endif /* CONFIG_ESP_MCPWM */ diff --git a/arch/xtensa/src/common/espressif/esp_mcpwm.h b/arch/xtensa/src/common/espressif/esp_mcpwm.h new file mode 100644 index 0000000000..4bcdfbdf36 --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_mcpwm.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_mcpwm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_MCPWM_H +#define __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_MCPWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifdef CONFIG_ESP_MCPWM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_mcpwm_capture_initialize + * + * Description: + * This function initializes the specified MCPWM peripheral and the capture + * submodule with the provided configuration. + * + * Input Parameters: + * channel - Channel to be initialized [0-3]. + * pin - GPIO pin assigned to this channel. + * + * Returned Value: + * On success, this function returns a valid pointer to the Capture device + * structure. If the initialization fails, it returns NULL. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +struct cap_lowerhalf_s *esp_mcpwm_capture_initialize(int channel, int pin); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_ESP_MCPWM */ +#endif /* __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_MCPWM_H */ diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 6f603ebf1e..587a27bbd0 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -2496,6 +2496,71 @@ config ESP32_LEDC_CHANNEL7_PIN endmenu # LEDC configuration +menu "MCPWM Configuration" + depends on ESP_MCPWM + +config ESP_MCPWM_CAPTURE + bool "MCPWM Capture Submodule" + depends on ESP_MCPWM + select CAPTURE + default n + ---help--- + Enables the use of the MCPWM capture submodule. + +if ESP_MCPWM_CAPTURE + +config ESP_MCPWM_CAPTURE_CH0 + bool "Capture Channel 0" + default n + ---help--- + Enables capture on channel 0. + +if ESP_MCPWM_CAPTURE_CH0 + +config ESP_MCPWM_CAPTURE_CH0_GPIO + int "GPIO Pin" + default 14 + ---help--- + GPIO pin assigned to capture channel 0. + +endif # ESP_MCPWM_CAPTURE_CH0 + +config ESP_MCPWM_CAPTURE_CH1 + bool "Capture Channel 1" + default n + ---help--- + Enables capture on channel 1. + +if ESP_MCPWM_CAPTURE_CH1 + +config ESP_MCPWM_CAPTURE_CH1_GPIO + int "GPIO Pin" + default 15 + ---help--- + GPIO pin assigned to capture channel 1. + +endif # ESP_MCPWM_CAPTURE_CH1 + +config ESP_MCPWM_CAPTURE_CH2 + bool "Capture Channel 2" + default n + ---help--- + Enables capture on channel 2. + +if ESP_MCPWM_CAPTURE_CH2 + +config ESP_MCPWM_CAPTURE_CH2_GPIO + int "GPIO Pin" + default 16 + ---help--- + GPIO pin assigned to capture channel 2. + +endif # ESP_MCPWM_CAPTURE_CH2 + +endif # ESP_MCPWM_CAPTURE + +endmenu # MCPWM Configuration + config ESP32_HAVE_OTA_PARTITION bool default n diff --git a/arch/xtensa/src/esp32/hal.mk b/arch/xtensa/src/esp32/hal.mk index 3257f81a46..b9009a1be7 100644 --- a/arch/xtensa/src/esp32/hal.mk +++ b/arch/xtensa/src/esp32/hal.mk @@ -97,6 +97,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)ledc_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)ledc_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)rmt_hal.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mcpwm_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)timer_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)timer_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)uart_hal_iram.c @@ -106,5 +107,6 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)gpio_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)ledc_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)rmt_periph.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)mcpwm_periph.c CFLAGS += ${DEFINE_PREFIX}ESP_PLATFORM=1 diff --git a/arch/xtensa/src/esp32s3/Kconfig b/arch/xtensa/src/esp32s3/Kconfig index 48521315df..4a980f4540 100644 --- a/arch/xtensa/src/esp32s3/Kconfig +++ b/arch/xtensa/src/esp32s3/Kconfig @@ -2117,6 +2117,71 @@ config ESP32S3_LEDC_CHANNEL7_PIN endmenu # LEDC configuration +menu "MCPWM Configuration" + depends on ESP_MCPWM + +config ESP_MCPWM_CAPTURE + bool "MCPWM Capture Submodule" + depends on ESP_MCPWM + select CAPTURE + default n + ---help--- + Enables the use of the MCPWM capture submodule. + +if ESP_MCPWM_CAPTURE + +config ESP_MCPWM_CAPTURE_CH0 + bool "Capture Channel 0" + default n + ---help--- + Enables capture on channel 0. + +if ESP_MCPWM_CAPTURE_CH0 + +config ESP_MCPWM_CAPTURE_CH0_GPIO + int "GPIO Pin" + default 12 + ---help--- + GPIO pin assigned to capture channel 0. + +endif # ESP_MCPWM_CAPTURE_CH0 + +config ESP_MCPWM_CAPTURE_CH1 + bool "Capture Channel 1" + default n + ---help--- + Enables capture on channel 1. + +if ESP_MCPWM_CAPTURE_CH1 + +config ESP_MCPWM_CAPTURE_CH1_GPIO + int "GPIO Pin" + default 15 + ---help--- + GPIO pin assigned to capture channel 1. + +endif # ESP_MCPWM_CAPTURE_CH1 + +config ESP_MCPWM_CAPTURE_CH2 + bool "Capture Channel 2" + default n + ---help--- + Enables capture on channel 2. + +if ESP_MCPWM_CAPTURE_CH2 + +config ESP_MCPWM_CAPTURE_CH2_GPIO + int "GPIO Pin" + default 16 + ---help--- + GPIO pin assigned to capture channel 2. + +endif # ESP_MCPWM_CAPTURE_CH2 + +endif # ESP_MCPWM_CAPTURE + +endmenu # MCPWM Configuration + menu "USB OTG Configuration" depends on ESP32S3_OTG diff --git a/arch/xtensa/src/esp32s3/hal.mk b/arch/xtensa/src/esp32s3/hal.mk index 73f79c0b6a..d88c6e9cd0 100644 --- a/arch/xtensa/src/esp32s3/hal.mk +++ b/arch/xtensa/src/esp32s3/hal.mk @@ -103,6 +103,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)ledc_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)ledc_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)rmt_hal.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mcpwm_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)timer_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)timer_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)cache_hal.c @@ -115,6 +116,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)gpio_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)ledc_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)rmt_periph.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)mcpwm_periph.c ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)bootloader_banner_wrap.c diff --git a/boards/xtensa/esp32/common/include/esp32_board_mcpwm.h b/boards/xtensa/esp32/common/include/esp32_board_mcpwm.h new file mode 100644 index 0000000000..fa8ec257e1 --- /dev/null +++ b/boards/xtensa/esp32/common/include/esp32_board_mcpwm.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * boards/xtensa/esp32/common/include/esp32_board_mcpwm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_BOARD_MCPWM_H +#define __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_BOARD_MCPWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE + +/**************************************************************************** + * Name: esp32_capture_initialize + * + * Description: + * Initialize and register the capture driver using the MCPWM peripheral. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_capture_initialize(void); + +#endif /* CONFIG_ESP_MCPWM_CAPTURE */ +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_BOARD_MCPWM_H */ diff --git a/boards/xtensa/esp32/common/src/Make.defs b/boards/xtensa/esp32/common/src/Make.defs index 6ff049752f..d4e10c7b03 100644 --- a/boards/xtensa/esp32/common/src/Make.defs +++ b/boards/xtensa/esp32/common/src/Make.defs @@ -152,6 +152,10 @@ ifeq ($(CONFIG_SENSORS_ZEROCROSS),y) CSRCS += esp32_zerocross.c endif +ifeq ($(CONFIG_ESP_MCPWM),y) + CSRCS += esp32_board_mcpwm.c +endif + DEPPATH += --dep-path src VPATH += :src CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src diff --git a/boards/xtensa/esp32/common/src/esp32_board_mcpwm.c b/boards/xtensa/esp32/common/src/esp32_board_mcpwm.c new file mode 100644 index 0000000000..0b6992bf5f --- /dev/null +++ b/boards/xtensa/esp32/common/src/esp32_board_mcpwm.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * boards/xtensa/esp32/common/src/esp32_board_mcpwm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include "espressif/esp_mcpwm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_capture_initialize + * + * Description: + * Initialize MCPWM Capture submodule and register the capture device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE +int board_capture_initialize(void) +{ + int ret; + struct cap_lowerhalf_s *cap; + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH0 + cap = esp_mcpwm_capture_initialize(0, + CONFIG_ESP_MCPWM_CAPTURE_CH0_GPIO); + + if (!cap) + { + syslog(LOG_ERR, "ERROR: Failed to start MCPWM Capture: CH0\n"); + return -ENODEV; + } + + ret = cap_register("/dev/capture0", cap); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cap_register failed: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH1 + cap = esp_mcpwm_capture_initialize(1, + CONFIG_ESP_MCPWM_CAPTURE_CH1_GPIO); + if (!cap) + { + syslog(LOG_ERR, "ERROR: Failed to start MCPWM Capture: CH1\n"); + return -ENODEV; + } + + ret = cap_register("/dev/capture1", cap); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cap_register failed: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH2 + cap = esp_mcpwm_capture_initialize(2, + CONFIG_ESP_MCPWM_CAPTURE_CH2_GPIO); + if (!cap) + { + syslog(LOG_ERR, "ERROR: Failed to start MCPWM Capture: CH2\n"); + return -ENODEV; + } + + ret = cap_register("/dev/capture2", cap); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cap_register failed: %d\n", ret); + return ret; + } +#endif + + return OK; +} +#endif diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/capture/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/capture/defconfig new file mode 100644 index 0000000000..b277878e61 --- /dev/null +++ b/boards/xtensa/esp32/esp32-devkitc/configs/capture/defconfig @@ -0,0 +1,50 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32-devkitc" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32_DEVKITC=y +CONFIG_ARCH_CHIP="esp32" +CONFIG_ARCH_CHIP_ESP32=y +CONFIG_ARCH_CHIP_ESP32WROVER=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_ESP32_UART0=y +CONFIG_ESP_MCPWM=y +CONFIG_ESP_MCPWM_CAPTURE=y +CONFIG_ESP_MCPWM_CAPTURE_CH0=y +CONFIG_EXAMPLES_CAPTURE=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=3 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSLOG_BUFFER=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c index a4f0bb69b7..0d4ed6cda7 100644 --- a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c @@ -169,6 +169,10 @@ # include "esp32_board_rmt.h" #endif +#ifdef CONFIG_ESP_MCPWM +# include "esp32_board_mcpwm.h" +#endif + #include "esp32-devkitc.h" /**************************************************************************** @@ -283,6 +287,14 @@ int esp32_bringup(void) } #endif /* CONFIG_ESP32_LEDC */ +#ifdef CONFIG_ESP_MCPWM_CAPTURE + ret = board_capture_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: board_capture_initialize failed: %d\n", ret); + } +#endif + #ifdef CONFIG_SENSORS_MAX6675 ret = board_max6675_initialize(0, 2); if (ret < 0) diff --git a/boards/xtensa/esp32s3/common/include/esp32s3_board_mcpwm.h b/boards/xtensa/esp32s3/common/include/esp32s3_board_mcpwm.h new file mode 100644 index 0000000000..75cf53e426 --- /dev/null +++ b/boards/xtensa/esp32s3/common/include/esp32s3_board_mcpwm.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * boards/xtensa/esp32s3/common/include/esp32s3_board_mcpwm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32S3_BOARD_MCPWM_H +#define __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32S3_BOARD_MCPWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESP_MCPWM_CAPTURE + +/**************************************************************************** + * Name: board_capture_initialize + * + * Description: + * Initialize and register the capture driver using the MCPWM peripheral. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_capture_initialize(void); + +#endif /* CONFIG_ESP_MCPWM_CAPTURE */ +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32S3_BOARD_MCPWM_H */ diff --git a/boards/xtensa/esp32s3/common/src/Make.defs b/boards/xtensa/esp32s3/common/src/Make.defs index 67841238c3..91c075f817 100644 --- a/boards/xtensa/esp32s3/common/src/Make.defs +++ b/boards/xtensa/esp32s3/common/src/Make.defs @@ -72,6 +72,10 @@ ifeq ($(CONFIG_ESP_RMT),y) CSRCS += esp32s3_board_rmt.c endif +ifeq ($(CONFIG_ESP_MCPWM),y) + CSRCS += esp32s3_board_mcpwm.c +endif + DEPPATH += --dep-path src VPATH += :src CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src diff --git a/boards/xtensa/esp32s3/common/src/esp32s3_board_mcpwm.c b/boards/xtensa/esp32s3/common/src/esp32s3_board_mcpwm.c new file mode 100644 index 0000000000..84be2be059 --- /dev/null +++ b/boards/xtensa/esp32s3/common/src/esp32s3_board_mcpwm.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * boards/xtensa/esp32s3/common/src/esp32s3_board_mcpwm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include "espressif/esp_mcpwm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_capture_initialize + * + * Description: + * Initialize MCPWM Capture submodule and register the capture device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_capture_initialize(void) +{ + int ret; + struct cap_lowerhalf_s *cap; + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH0 + cap = esp_mcpwm_capture_initialize(0, + CONFIG_ESP_MCPWM_CAPTURE_CH0_GPIO); + + if (!cap) + { + syslog(LOG_ERR, "ERROR: Failed to start MCPWM Capture: CH0\n"); + return -ENODEV; + } + + ret = cap_register("/dev/capture0", cap); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cap_register failed: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH1 + cap = esp_mcpwm_capture_initialize(1, + CONFIG_ESP_MCPWM_CAPTURE_CH1_GPIO); + if (!cap) + { + syslog(LOG_ERR, "ERROR: Failed to start MCPWM Capture: CH1\n"); + return -ENODEV; + } + + ret = cap_register("/dev/capture1", cap); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cap_register failed: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP_MCPWM_CAPTURE_CH2 + cap = esp_mcpwm_capture_initialize(2, + CONFIG_ESP_MCPWM_CAPTURE_CH2_GPIO); + if (!cap) + { + syslog(LOG_ERR, "ERROR: Failed to start MCPWM Capture: CH2\n"); + return -ENODEV; + } + + ret = cap_register("/dev/capture2", cap); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cap_register failed: %d\n", ret); + return ret; + } +#endif + + return OK; +} diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/capture/defconfig b/boards/xtensa/esp32s3/esp32s3-devkit/configs/capture/defconfig new file mode 100644 index 0000000000..2391bdab72 --- /dev/null +++ b/boards/xtensa/esp32s3/esp32s3-devkit/configs/capture/defconfig @@ -0,0 +1,49 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32s3-devkit" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32S3_DEVKIT=y +CONFIG_ARCH_CHIP="esp32s3" +CONFIG_ARCH_CHIP_ESP32S3=y +CONFIG_ARCH_CHIP_ESP32S3WROOM1N4=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_ESP32S3_UART0=y +CONFIG_ESP_MCPWM=y +CONFIG_ESP_MCPWM_CAPTURE=y +CONFIG_ESP_MCPWM_CAPTURE_CH0=y +CONFIG_EXAMPLES_CAPTURE=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSLOG_BUFFER=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c index 408cd913d6..eb210bcc6b 100644 --- a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c +++ b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c @@ -100,6 +100,10 @@ # include "esp32s3_board_rmt.h" #endif +#ifdef CONFIG_ESP_MCPWM +# include "esp32s3_board_mcpwm.h" +#endif + #ifdef CONFIG_ESP32S3_SPI #include "esp32s3_spi.h" #include "esp32s3_board_spidev.h" @@ -470,6 +474,14 @@ int esp32s3_bringup(void) } #endif +#ifdef CONFIG_ESP_MCPWM_CAPTURE + ret = board_capture_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: board_capture_initialize failed: %d\n", ret); + } +#endif + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities.