From 0c63840b18932f3201fcd7d92c7febd4a4e37181 Mon Sep 17 00:00:00 2001 From: Filipe Cavalcanti Date: Wed, 3 Jul 2024 09:38:49 -0300 Subject: [PATCH] arch/risc-v: add support for capture driver on ESP32C6 and ESP32H2. --- .../esp32c6/boards/esp32c6-devkitc/index.rst | 16 + .../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 + .../esp32c6/common/src/esp_board_mcpwm.c | 114 +++ .../esp32c6-devkitc/configs/capture/defconfig | 51 ++ .../esp32c6-devkitc/src/esp32c6_bringup.c | 12 + .../esp32h2/common/include/esp_board_mcpwm.h | 70 ++ boards/risc-v/esp32h2/common/src/Make.defs | 4 + .../esp32h2/common/src/esp_board_mcpwm.c | 114 +++ .../esp32h2-devkit/configs/capture/defconfig | 51 ++ .../esp32h2-devkit/src/esp32h2_bringup.c | 12 + 18 files changed, 1376 insertions(+), 1 deletion(-) create mode 100644 arch/risc-v/src/common/espressif/esp_mcpwm.c create mode 100644 arch/risc-v/src/common/espressif/esp_mcpwm.h create mode 100644 boards/risc-v/esp32c6/common/include/esp_board_mcpwm.h create mode 100644 boards/risc-v/esp32c6/common/src/esp_board_mcpwm.c create mode 100644 boards/risc-v/esp32c6/esp32c6-devkitc/configs/capture/defconfig create mode 100644 boards/risc-v/esp32h2/common/include/esp_board_mcpwm.h create mode 100644 boards/risc-v/esp32h2/common/src/esp_board_mcpwm.c create mode 100644 boards/risc-v/esp32h2/esp32h2-devkit/configs/capture/defconfig 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +#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 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 + +/**************************************************************************** + * 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 + +#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 == 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 + +/**************************************************************************** + * 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 + +#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 == 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.