This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c63840b18 arch/risc-v: add support for capture driver on ESP32C6 and 
ESP32H2.
0c63840b18 is described below

commit 0c63840b18932f3201fcd7d92c7febd4a4e37181
Author: Filipe Cavalcanti <[email protected]>
AuthorDate: Wed Jul 3 09:38:49 2024 -0300

    arch/risc-v: add support for capture driver on ESP32C6 and ESP32H2.
---
 .../esp32c6/boards/esp32c6-devkitc/index.rst       |  16 +
 Documentation/platforms/risc-v/esp32c6/index.rst   |   2 +-
 arch/risc-v/src/common/espressif/Kconfig           |  72 +++
 arch/risc-v/src/common/espressif/Make.defs         |   4 +
 arch/risc-v/src/common/espressif/esp_mcpwm.c       | 691 +++++++++++++++++++++
 arch/risc-v/src/common/espressif/esp_mcpwm.h       |  86 +++
 arch/risc-v/src/esp32c6/hal_esp32c6.mk             |   2 +
 arch/risc-v/src/esp32h2/hal_esp32h2.mk             |   2 +
 .../esp32c6/common/include/esp_board_mcpwm.h       |  70 +++
 boards/risc-v/esp32c6/common/src/Make.defs         |   4 +
 boards/risc-v/esp32c6/common/src/esp_board_mcpwm.c | 114 ++++
 .../esp32c6-devkitc/configs/capture/defconfig      |  51 ++
 .../esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c  |  12 +
 .../esp32h2/common/include/esp_board_mcpwm.h       |  70 +++
 boards/risc-v/esp32h2/common/src/Make.defs         |   4 +
 boards/risc-v/esp32h2/common/src/esp_board_mcpwm.c | 114 ++++
 .../esp32h2-devkit/configs/capture/defconfig       |  51 ++
 .../esp32h2/esp32h2-devkit/src/esp32h2_bringup.c   |  12 +
 18 files changed, 1376 insertions(+), 1 deletion(-)

diff --git 
a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst 
b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst
index c886f3e5ed..e9309ce10b 100644
--- a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst
+++ b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst
@@ -99,6 +99,22 @@ You can check that the sensor is working by using the 
``bmp180`` application::
     Pressure value = 91526
     Pressure value = 91525
 
+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 
18 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/risc-v/esp32c6/index.rst 
b/Documentation/platforms/risc-v/esp32c6/index.rst
index 958fb885f3..b4dc9b5ca9 100644
--- a/Documentation/platforms/risc-v/esp32c6/index.rst
+++ b/Documentation/platforms/risc-v/esp32c6/index.rst
@@ -152,7 +152,7 @@ I2S              No
 Int. Temp.       No
 LED              No
 LED_PWM          Yes
-MCPWM            No
+MCPWM            Yes (Capture)
 Pulse Counter    No
 RMT              No
 RNG              No
diff --git a/arch/risc-v/src/common/espressif/Kconfig 
b/arch/risc-v/src/common/espressif/Kconfig
index 9e13007002..233fb43dce 100644
--- a/arch/risc-v/src/common/espressif/Kconfig
+++ b/arch/risc-v/src/common/espressif/Kconfig
@@ -473,6 +473,14 @@ config ESP_COEX_SW_COEXIST_ENABLE
                If only Bluetooth is used, it is recommended to disable this 
option to reduce binary file
                size.
 
+config ESP_MCPWM
+       bool "Motor Control PWM (MCPWM)"
+       default n
+       depends on ESPRESSIF_ESP32C6 || ESPRESSIF_ESP32H2
+       ---help---
+               Enable support for timer capture and motor control using
+               the Motor Control PWM peripheral.
+
 endmenu # Peripheral Support
 
 menu "Wi-Fi Configuration"
@@ -1273,6 +1281,70 @@ config ESPRESSIF_I2CTIMEOMS
        default 500
 
 endmenu # I2C 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 18
+       ---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 19
+       ---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 20
+       ---help---
+               GPIO pin assigned to capture channel 2.
+
+endif # ESP_MCPWM_CAPTURE_CH2
+
+endif # ESP_MCPWM_CAPTURE
+
+endmenu # MCPWM Configuration
 
 menu "High Resolution Timer"
        depends on ESPRESSIF_HR_TIMER
diff --git a/arch/risc-v/src/common/espressif/Make.defs 
b/arch/risc-v/src/common/espressif/Make.defs
index 287db4d9b2..c51ad327bb 100644
--- a/arch/risc-v/src/common/espressif/Make.defs
+++ b/arch/risc-v/src/common/espressif/Make.defs
@@ -114,6 +114,10 @@ ifeq ($(CONFIG_ESP_WIRELESS),y)
        endif
 endif
 
+ifeq ($(CONFIG_ESP_MCPWM),y)
+       CHIP_CSRCS += esp_mcpwm.c
+endif
+
 #############################################################################
 # Espressif HAL for 3rd Party Platforms
 #############################################################################
diff --git a/arch/risc-v/src/common/espressif/esp_mcpwm.c 
b/arch/risc-v/src/common/espressif/esp_mcpwm.c
new file mode 100644
index 0000000000..e4562e4a95
--- /dev/null
+++ b/arch/risc-v/src/common/espressif/esp_mcpwm.c
@@ -0,0 +1,691 @@
+/****************************************************************************
+ * arch/risc-v/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 <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+#include <inttypes.h>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/spinlock.h>
+#include <nuttx/timers/capture.h>
+
+#include "esp_gpio.h"
+#include "esp_irq.h"
+
+#include "esp_attr.h"
+#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"
+#include "esp_clk_tree.h"
+
+#ifdef CONFIG_ESP_MCPWM
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_CHIP_ESP32H2
+#  define MCPWM_DEV_CLK_SOURCE MCPWM_TIMER_CLK_SRC_PLL96M
+#else
+#  define MCPWM_DEV_CLK_SOURCE SOC_MOD_CLK_PLL_F160M
+#endif
+
+#define MCPWM_DEV_CLK_PRESCALE      4
+#define MCPWM_CAPTURE_DEFAULT_GROUP 0
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct mcpwm_dev_common_s
+{
+  mcpwm_hal_init_config_t group;
+  mcpwm_hal_context_t hal;
+  spinlock_t mcpwm_spinlock;
+  bool initialized;          /* MCPWM peripheral and HAL has been initialized 
*/
+  bool capture_initialized;  /* Capture submodule has been initialized */
+  int group_prescale;
+};
+
+#ifdef CONFIG_ESP_MCPWM_CAPTURE
+/* Capture event data. The 'last_' value is used to calculate frequency */
+
+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 */
+};
+
+/* Lowe-half data structure for a capture channel */
+
+struct mcpwm_cap_channel_lowerhalf_s
+{
+  /* The following block is part of the upper-half device struct */
+
+  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_set_gpio(
+  struct mcpwm_cap_channel_lowerhalf_s *lower);
+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);
+
+/* 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);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct mcpwm_dev_common_s mcpwm_common =
+{
+  .group.group_id      = MCPWM_CAPTURE_DEFAULT_GROUP,
+  .initialized         = false,
+  .capture_initialized = false,
+  .group_prescale      = MCPWM_DEV_CLK_PRESCALE,
+};
+
+#ifdef CONFIG_ESP_MCPWM_CAPTURE
+/* Lower half methods required by the 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     = &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     = &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     = &mcpwm_common,
+  .data       = &event_data_ch2,
+  .channel_id = MCPWM_CAP_CHANNEL_2,
+  .ready      = false,
+};
+#endif
+#endif  /* CONFIG_ESP_MCPWM_CAPTURE */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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;
+
+  DEBUGASSERT(priv != NULL);
+
+  mcpwm_hal_context_t *hal = &priv->common->hal;
+
+  /* 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);
+  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;
+
+  DEBUGASSERT(priv != NULL);
+
+  mcpwm_hal_context_t *hal = &priv->common->hal;
+
+  /* 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);
+  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;
+
+  DEBUGASSERT(priv != NULL);
+
+  *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;
+
+  DEBUGASSERT(priv != NULL);
+
+  *freq = priv->freq;
+  cpinfo("Get freq called from channel %d\n", priv->channel_id);
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: esp_mcpwm_group_start
+ *
+ * Description:
+ *   Initializes the MCPWM0 module, MCPWM HAL.
+ *   Should be called only once.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void esp_mcpwm_group_start(void)
+{
+  mcpwm_hal_context_t *hal = &mcpwm_common.hal;
+
+  /* HAL and MCPWM Initialization */
+
+  periph_module_enable(PERIPH_MCPWM0_MODULE);
+  mcpwm_hal_init(hal, &mcpwm_common.group);
+  mcpwm_hal_timer_reset(hal, 0);
+  mcpwm_ll_group_set_clock_source(hal->dev, MCPWM_DEV_CLK_SOURCE);
+  mcpwm_ll_group_set_clock_prescale(hal->dev, 4);
+  mcpwm_ll_group_enable_clock(hal->dev, true);
+
+  mcpwm_common.initialized = true;
+}
+
+/****************************************************************************
+ * 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 | PULLUP);
+  if (ret < 0)
+    {
+      cperr("Failed configuring GPIO pin\n");
+      return ret;
+    }
+
+  esp_gpio_matrix_in(lower->gpio_pin,
+    mcpwm_periph_signals.groups[0].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;
+
+  cpuint = esp_setup_irq(mcpwm_periph_signals.groups[0].irq_id,
+                         ESP_IRQ_PRIORITY_DEFAULT,
+                         ESP_IRQ_TRIGGER_LEVEL);
+  if (cpuint < 0)
+    {
+      cperr("Failed to allocate a CPU interrupt.\n");
+      return -ENOMEM;
+    }
+
+  ret = irq_attach(ESP_IRQ_MCPWM0,
+                   mcpwm_capture_driver_isr_default,
+                   &mcpwm_common);
+  if (ret < 0)
+    {
+      cperr("Couldn't attach IRQ to handler.\n");
+      esp_teardown_irq(mcpwm_periph_signals.groups[0].irq_id, cpuint);
+      return ret;
+    }
+
+  up_enable_irq(ESP_IRQ_MCPWM0);
+
+  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;
+  irqstate_t flags;
+  uint32_t cap_value;
+  uint32_t status;
+  mcpwm_capture_edge_t cap_edge;
+
+  flags = spin_lock_irqsave(common->mcpwm_spinlock);
+  status = mcpwm_ll_intr_get_status(common->hal.dev);
+
+  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;
+  uint32_t group_clock;
+
+  /* Single time initialization for the entire MCPWM Peripheral
+   * and MCPWM Capture group.
+   */
+
+  if (!mcpwm_common.initialized)
+    {
+      esp_mcpwm_group_start();
+    }
+
+  if (!mcpwm_common.capture_initialized)
+    {
+      mcpwm_ll_capture_enable_timer(mcpwm_common.hal.dev, true);
+      esp_mcpwm_capture_isr_register(mcpwm_capture_driver_isr_default,
+                                     &mcpwm_common);
+      mcpwm_common.capture_initialized = 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;
+    }
+
+  esp_clk_tree_src_get_freq_hz(MCPWM_DEV_CLK_SOURCE,
+                               ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED,
+                               &group_clock);
+
+  /* Set the clock to be used when calculating frequency */
+
+  lower->gpio_pin = pin;
+  lower->clock = group_clock / MCPWM_DEV_CLK_PRESCALE;
+
+  /* Configure GPIO pin */
+
+  esp_mcpwm_capture_set_gpio(lower);
+
+  return (struct cap_lowerhalf_s *)lower;
+}
+#endif
+
+#endif /* CONFIG_ESP_MCPWM */
diff --git a/arch/risc-v/src/common/espressif/esp_mcpwm.h 
b/arch/risc-v/src/common/espressif/esp_mcpwm.h
new file mode 100644
index 0000000000..946f7310d7
--- /dev/null
+++ b/arch/risc-v/src/common/espressif/esp_mcpwm.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * arch/risc-v/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_RISCV_SRC_COMMON_ESPRESSIF_ESP_MCPWM_H
+#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_MCPWM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#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 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_RISCV_SRC_COMMON_ESPRESSIF_ESP_MCPWM_CAPTURE_H */
diff --git a/arch/risc-v/src/esp32c6/hal_esp32c6.mk 
b/arch/risc-v/src/esp32c6/hal_esp32c6.mk
index f871db775b..7837d29b42 100644
--- a/arch/risc-v/src/esp32c6/hal_esp32c6.mk
+++ b/arch/risc-v/src/esp32c6/hal_esp32c6.mk
@@ -136,6 +136,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)cache_hal.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mpu_hal.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mmu_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)uart_hal.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)uart_hal_iram.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)wdt_hal_iram.c
@@ -152,6 +153,7 @@ CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$
 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)i2c_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/arch/risc-v/src/esp32h2/hal_esp32h2.mk 
b/arch/risc-v/src/esp32h2/hal_esp32h2.mk
index e94c983bcf..df170588cf 100644
--- a/arch/risc-v/src/esp32h2/hal_esp32h2.mk
+++ b/arch/risc-v/src/esp32h2/hal_esp32h2.mk
@@ -118,6 +118,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)timer_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)mpu_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)mmu_hal.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)uart_hal.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)uart_hal_iram.c
@@ -135,6 +136,7 @@ CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$
 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)i2c_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/risc-v/esp32c6/common/include/esp_board_mcpwm.h 
b/boards/risc-v/esp32c6/common/include/esp_board_mcpwm.h
new file mode 100644
index 0000000000..421fbffd3a
--- /dev/null
+++ b/boards/risc-v/esp32c6/common/include/esp_board_mcpwm.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * boards/risc-v/esp32c6/common/include/esp_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_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_MCPWM_H
+#define __BOARDS_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_MCPWM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * 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_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_MCPWM_H */
diff --git a/boards/risc-v/esp32c6/common/src/Make.defs 
b/boards/risc-v/esp32c6/common/src/Make.defs
index 0a56520102..764c8920ba 100644
--- a/boards/risc-v/esp32c6/common/src/Make.defs
+++ b/boards/risc-v/esp32c6/common/src/Make.defs
@@ -60,6 +60,10 @@ ifeq ($(CONFIG_SENSORS_BMP180),y)
   CSRCS += esp_board_bmp180.c
 endif
 
+ifeq ($(CONFIG_ESP_MCPWM),y)
+  CSRCS += esp_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/risc-v/esp32c6/common/src/esp_board_mcpwm.c 
b/boards/risc-v/esp32c6/common/src/esp_board_mcpwm.c
new file mode 100644
index 0000000000..5229de617c
--- /dev/null
+++ b/boards/risc-v/esp32c6/common/src/esp_board_mcpwm.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * boards/risc-v/esp32c6/common/src/esp_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 <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/board.h>
+#include <nuttx/timers/capture.h>
+
+#include <arch/board/board.h>
+
+#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 == NULL)
+    {
+      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 == NULL)
+    {
+      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 == NULL)
+    {
+      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/risc-v/esp32c6/esp32c6-devkitc/configs/capture/defconfig 
b/boards/risc-v/esp32c6/esp32c6-devkitc/configs/capture/defconfig
new file mode 100644
index 0000000000..b005c879c0
--- /dev/null
+++ b/boards/risc-v/esp32c6/esp32c6-devkitc/configs/capture/defconfig
@@ -0,0 +1,51 @@
+#
+# 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_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32c6-devkitc"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32C6_DEVKITC=y
+CONFIG_ARCH_CHIP="esp32c6"
+CONFIG_ARCH_CHIP_ESP32C6=y
+CONFIG_ARCH_CHIP_ESP32C6WROOM1=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BUILTIN=y
+CONFIG_DEV_ZERO=y
+CONFIG_ESPRESSIF_ESP32C6=y
+CONFIG_ESP_MCPWM=y
+CONFIG_ESP_MCPWM_CAPTURE=y
+CONFIG_ESP_MCPWM_CAPTURE_CH0=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_DUMPSTACK=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c 
b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c
index 86f8816702..5a1b11ef34 100644
--- a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c
+++ b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c
@@ -85,6 +85,10 @@
 #  include "esp_board_spislavedev.h"
 #endif
 
+#ifdef CONFIG_ESP_MCPWM
+#  include "esp_board_mcpwm.h"
+#endif
+
 #include "esp32c6-devkitc.h"
 
 /****************************************************************************
@@ -322,6 +326,14 @@ int esp_bringup(void)
     }
 #endif /* CONFIG_ESPRESSIF_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
+
   /* If we got here then perhaps not all initialization was successful, but
    * at least enough succeeded to bring-up NSH with perhaps reduced
    * capabilities.
diff --git a/boards/risc-v/esp32h2/common/include/esp_board_mcpwm.h 
b/boards/risc-v/esp32h2/common/include/esp_board_mcpwm.h
new file mode 100644
index 0000000000..3572dfe2ce
--- /dev/null
+++ b/boards/risc-v/esp32h2/common/include/esp_board_mcpwm.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * boards/risc-v/esp32h2/common/include/esp_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_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_MCPWM_H
+#define __BOARDS_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_MCPWM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * 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_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_MCPWM_H */
diff --git a/boards/risc-v/esp32h2/common/src/Make.defs 
b/boards/risc-v/esp32h2/common/src/Make.defs
index 4ac1b9b459..7d8708f4dd 100644
--- a/boards/risc-v/esp32h2/common/src/Make.defs
+++ b/boards/risc-v/esp32h2/common/src/Make.defs
@@ -56,6 +56,10 @@ ifeq ($(CONFIG_SENSORS_BMP180),y)
   CSRCS += esp_board_bmp180.c
 endif
 
+ifeq ($(CONFIG_ESP_MCPWM),y)
+  CSRCS += esp_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/risc-v/esp32h2/common/src/esp_board_mcpwm.c 
b/boards/risc-v/esp32h2/common/src/esp_board_mcpwm.c
new file mode 100644
index 0000000000..e5a080af07
--- /dev/null
+++ b/boards/risc-v/esp32h2/common/src/esp_board_mcpwm.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * boards/risc-v/esp32h2/common/src/esp_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 <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/board.h>
+#include <nuttx/timers/capture.h>
+
+#include <arch/board/board.h>
+
+#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 == NULL)
+    {
+      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 == NULL)
+    {
+      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 == NULL)
+    {
+      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/risc-v/esp32h2/esp32h2-devkit/configs/capture/defconfig 
b/boards/risc-v/esp32h2/esp32h2-devkit/configs/capture/defconfig
new file mode 100644
index 0000000000..ff3be99da5
--- /dev/null
+++ b/boards/risc-v/esp32h2/esp32h2-devkit/configs/capture/defconfig
@@ -0,0 +1,51 @@
+#
+# 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_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32h2-devkit"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32H2_DEVKIT=y
+CONFIG_ARCH_CHIP="esp32h2"
+CONFIG_ARCH_CHIP_ESP32H2=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BUILTIN=y
+CONFIG_DEV_ZERO=y
+CONFIG_ESPRESSIF_ESP32H2=y
+CONFIG_ESP_MCPWM=y
+CONFIG_ESP_MCPWM_CAPTURE=y
+CONFIG_ESP_MCPWM_CAPTURE_CH0=y
+CONFIG_ESP_MCPWM_CAPTURE_CH0_GPIO=12
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_DUMPSTACK=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c 
b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c
index 265ceccc86..c97f0d02f8 100644
--- a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c
+++ b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c
@@ -77,6 +77,10 @@
 #  include "esp_board_spislavedev.h"
 #endif
 
+#ifdef CONFIG_ESP_MCPWM
+#  include "esp_board_mcpwm.h"
+#endif
+
 #include "esp32h2-devkit.h"
 
 /****************************************************************************
@@ -289,6 +293,14 @@ int esp_bringup(void)
     }
 #endif /* CONFIG_ESPRESSIF_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
+
   /* If we got here then perhaps not all initialization was successful, but
    * at least enough succeeded to bring-up NSH with perhaps reduced
    * capabilities.

Reply via email to