diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/README.md b/components/esp_driver_mcpwm/test_apps/mcpwm/README.md index fe35f9e4f5..24b8600b2e 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/README.md +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_hal_mcpwm/esp32c5/mcpwm_periph.c b/components/esp_hal_mcpwm/esp32c5/mcpwm_periph.c index 6edcd5869d..50969c5be8 100644 --- a/components/esp_hal_mcpwm/esp32c5/mcpwm_periph.c +++ b/components/esp_hal_mcpwm/esp32c5/mcpwm_periph.c @@ -84,7 +84,6 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[1] = { /** * MCPWM Registers to be saved during sleep retention - * - Clk Configuration registers, e.g.: MCPWM_CLK_CFG_REG * - Timer Configuration registers, e.g.: MCPWM_TIMER_SYNCI_CFG_REG, MCPWM_TIMER0_CFG0_REG, MCPWM_TIMER0_CFG1_REG, MCPWM_TIMER0_CFG1_REG * - Operator Configuration registers, e.g.: MCPWM_OPERATOR_TIMERSEL_REG * |- Generator Configuration registers, e.g.: MCPWM_GEN0_STMP_CFG_REG, MCPWM_GEN0_TSTMP_A_REG, MCPWM_GEN0_TSTMP_B_REG, MCPWM_GEN0_CFG0_REG, MCPWM_GEN0_FORCE_REG, MCPWM_GEN0_A_REG, MCPWM_GEN0_B_REG @@ -96,9 +95,9 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[1] = { * - ETM Configurations, e.g.: MCPWM_EVT_EN_REG, MCPWM_EVT_EN2_REG, MCPWM_TASK_EN_REG, MCPWM_OP0_TSTMP_E1_REG, MCPWM_OP0_TSTMP_E2_REG, MCPWM_OP1_TSTMP_E1_REG, MCPWM_OP1_TSTMP_E2_REG, MCPWM_OP2_TSTMP_E1_REG, MCPWM_OP2_TSTMP_E2_REG * - Misc Configurations, e.g.: MCPWM_UPDATE_CFG_REG */ -#define MCPWM_RETENTION_REGS_CNT 68 -#define MCPWM_RETENTION_REGS_BASE (DR_REG_MCPWM_BASE + 0x0) -static const uint32_t mcpwm_regs_map[4] = {0xefffeeef, 0x7efffbff, 0x1ff18, 0x0}; +#define MCPWM_RETENTION_REGS_CNT 67 +#define MCPWM_RETENTION_REGS_BASE (DR_REG_MCPWM_BASE + 0x4) +static const uint32_t mcpwm_regs_map[4] = {0xf7fff777, 0x3f7ffdff, 0xff8c, 0x0}; static const regdma_entries_config_t mcpwm_regs_retention[] = { // backup stage: save configuration registers // restore stage: restore the configuration registers diff --git a/components/esp_hal_mcpwm/esp32c6/mcpwm_periph.c b/components/esp_hal_mcpwm/esp32c6/mcpwm_periph.c index 319e8474b2..23946365c5 100644 --- a/components/esp_hal_mcpwm/esp32c6/mcpwm_periph.c +++ b/components/esp_hal_mcpwm/esp32c6/mcpwm_periph.c @@ -83,7 +83,6 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[1] = { /** * MCPWM Registers to be saved during sleep retention - * - Clk Configuration registers, e.g.: MCPWM_CLK_CFG_REG * - Timer Configuration registers, e.g.: MCPWM_TIMER_SYNCI_CFG_REG, MCPWM_TIMER0_CFG0_REG, MCPWM_TIMER0_CFG1_REG, MCPWM_TIMER0_CFG1_REG * - Operator Configuration registers, e.g.: MCPWM_OPERATOR_TIMERSEL_REG * |- Generator Configuration registers, e.g.: MCPWM_GEN0_STMP_CFG_REG, MCPWM_GEN0_TSTMP_A_REG, MCPWM_GEN0_TSTMP_B_REG, MCPWM_GEN0_CFG0_REG, MCPWM_GEN0_FORCE_REG, MCPWM_GEN0_A_REG, MCPWM_GEN0_B_REG @@ -95,9 +94,9 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[1] = { * - ETM Configurations, e.g.: MCPWM_EVT_EN_REG, MCPWM_TASK_EN_REG * - Misc Configurations, e.g.: MCPWM_UPDATE_CFG_REG */ -#define MCPWM_RETENTION_REGS_CNT 61 -#define MCPWM_RETENTION_REGS_BASE (DR_REG_MCPWM_BASE + 0x0) -static const uint32_t mcpwm_regs_map[4] = {0xefffeeef, 0x7efffbff, 0x318, 0x0}; +#define MCPWM_RETENTION_REGS_CNT 60 +#define MCPWM_RETENTION_REGS_BASE (DR_REG_MCPWM_BASE + 0x4) +static const uint32_t mcpwm_regs_map[4] = {0xf7fff777, 0x3f7ffdff, 0x18c, 0x0}; static const regdma_entries_config_t mcpwm_regs_retention[] = { // backup stage: save configuration registers // restore stage: restore the configuration registers diff --git a/components/esp_hal_mcpwm/esp32h2/mcpwm_periph.c b/components/esp_hal_mcpwm/esp32h2/mcpwm_periph.c index a9c4ae5a0b..c33ebe2a94 100644 --- a/components/esp_hal_mcpwm/esp32h2/mcpwm_periph.c +++ b/components/esp_hal_mcpwm/esp32h2/mcpwm_periph.c @@ -83,7 +83,6 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[1] = { /** * MCPWM Registers to be saved during sleep retention - * - Clk Configuration registers, e.g.: MCPWM_CLK_CFG_REG * - Timer Configuration registers, e.g.: MCPWM_TIMER_SYNCI_CFG_REG, MCPWM_TIMER0_CFG0_REG, MCPWM_TIMER0_CFG1_REG, MCPWM_TIMER0_CFG1_REG * - Operator Configuration registers, e.g.: MCPWM_OPERATOR_TIMERSEL_REG * |- Generator Configuration registers, e.g.: MCPWM_GEN0_STMP_CFG_REG, MCPWM_GEN0_TSTMP_A_REG, MCPWM_GEN0_TSTMP_B_REG, MCPWM_GEN0_CFG0_REG, MCPWM_GEN0_FORCE_REG, MCPWM_GEN0_A_REG, MCPWM_GEN0_B_REG @@ -95,9 +94,9 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[1] = { * - ETM Configurations, e.g.: MCPWM_EVT_EN_REG, MCPWM_TASK_EN_REG * - Misc Configurations, e.g.: MCPWM_UPDATE_CFG_REG */ -#define MCPWM_RETENTION_REGS_CNT 61 -#define MCPWM_RETENTION_REGS_BASE (DR_REG_MCPWM_BASE + 0x0) -static const uint32_t mcpwm_regs_map[4] = {0xefffeeef, 0x7efffbff, 0x318, 0x0}; +#define MCPWM_RETENTION_REGS_CNT 60 +#define MCPWM_RETENTION_REGS_BASE (DR_REG_MCPWM_BASE + 0x4) +static const uint32_t mcpwm_regs_map[4] = {0xf7fff777, 0x3f7ffdff, 0x18c, 0x0}; static const regdma_entries_config_t mcpwm_regs_retention[] = { // backup stage: save configuration registers // restore stage: restore the configuration registers diff --git a/components/esp_hal_mcpwm/esp32h4/include/hal/mcpwm_ll.h b/components/esp_hal_mcpwm/esp32h4/include/hal/mcpwm_ll.h new file mode 100644 index 0000000000..ec0f1ba5a2 --- /dev/null +++ b/components/esp_hal_mcpwm/esp32h4/include/hal/mcpwm_ll.h @@ -0,0 +1,1722 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/soc_caps.h" +#include "soc/mcpwm_struct.h" +#include "soc/clk_tree_defs.h" +#include "soc/pcr_struct.h" +#include "hal/mcpwm_types.h" +#include "hal/misc.h" +#include "hal/assert.h" +#include "soc/soc_etm_source.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// MCPWM LL get macro +#define MCPWM_LL_GET(attr) (MCPWM_LL_ ## attr) + +// Get MCPWM group register base address +#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1) + +// MCPWM capabilities +#define MCPWM_LL_GROUP_NUM (2U) ///< 2 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals) +#define MCPWM_LL_TIMERS_PER_GROUP (3) ///< The number of timers that each group has +#define MCPWM_LL_OPERATORS_PER_GROUP (3) ///< The number of operators that each group has +#define MCPWM_LL_COMPARATORS_PER_OPERATOR (2) ///< The number of comparators that each operator has +#define MCPWM_LL_GENERATORS_PER_OPERATOR (2) ///< The number of generators that each operator has +#define MCPWM_LL_EVENT_COMPARATORS_PER_OPERATOR (2) ///< The number of event comparators that each operator has +#define MCPWM_LL_TRIGGERS_PER_OPERATOR (2) ///< The number of triggers that each operator has +#define MCPWM_LL_GPIO_FAULTS_PER_GROUP (3) ///< The number of fault signal detectors that each group has +#define MCPWM_LL_CAPTURE_TIMERS_PER_GROUP (1) ///< The number of capture timers that each group has +#define MCPWM_LL_CAPTURE_CHANNELS_PER_TIMER (3) ///< The number of capture channels that each capture timer has +#define MCPWM_LL_GPIO_SYNCHROS_PER_GROUP (3) ///< The number of GPIO synchros that each group has + +// MCPWM interrupt event mask +#define MCPWM_LL_EVENT_TIMER_STOP(timer) (1 << (timer)) +#define MCPWM_LL_EVENT_TIMER_EMPTY(timer) (1 << ((timer) + 3)) +#define MCPWM_LL_EVENT_TIMER_FULL(timer) (1 << ((timer) + 6)) +#define MCPWM_LL_EVENT_TIMER_MASK(timer) (MCPWM_LL_EVENT_TIMER_STOP(timer) | MCPWM_LL_EVENT_TIMER_EMPTY(timer) | MCPWM_LL_EVENT_TIMER_FULL(timer)) +#define MCPWM_LL_EVENT_FAULT_ENTER(fault) (1 << ((fault) + 9)) +#define MCPWM_LL_EVENT_FAULT_EXIT(fault) (1 << ((fault) + 12)) +#define MCPWM_LL_EVENT_FAULT_MASK(fault) (MCPWM_LL_EVENT_FAULT_ENTER(fault) | MCPWM_LL_EVENT_FAULT_EXIT(fault)) +#define MCPWM_LL_EVENT_CMP_EQUAL(oper, cmp) (1 << ((oper) + (cmp) * 3 + 15)) +#define MCPWM_LL_EVENT_OPER_BRAKE_CBC(oper) (1 << ((oper) + 21)) +#define MCPWM_LL_EVENT_OPER_BRAKE_OST(oper) (1 << ((oper) + 24)) +#define MCPWM_LL_EVENT_OPER_MASK(oper) (MCPWM_LL_EVENT_OPER_BRAKE_CBC(oper) | MCPWM_LL_EVENT_OPER_BRAKE_OST(oper)) +#define MCPWM_LL_EVENT_CAPTURE(cap) (1 << ((cap) + 27)) + +// Maximum values due to limited register bit width +#define MCPWM_LL_MAX_GROUP_PRESCALE 256 +#define MCPWM_LL_MAX_TIMER_PRESCALE 256 +#define MCPWM_LL_MAX_CARRIER_PRESCALE 16 +#define MCPWM_LL_MAX_CARRIER_ONESHOT 16 +#define MCPWM_LL_MAX_CAPTURE_PRESCALE 256 +#define MCPWM_LL_MAX_CAPTURE_TIMER_PRESCALE 1 +#define MCPWM_LL_MAX_DEAD_DELAY 65536 +#define MCPWM_LL_MAX_COUNT_VALUE 65536 + +// translate the HAL types into register values +#define MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) ((uint8_t[]) {0, 1}[(event)]) +#define MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) ((uint8_t[]) {0, 1, 2, 3}[(action)]) +#define MCPWM_LL_BRAKE_MODE_TO_REG_VAL(mode) ((uint8_t[]) {0, 1}[(mode)]) + +// MCPWM ETM comparator event table +#define MCPWM_LL_ETM_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \ + (uint32_t[2][MCPWM_CMPR_ETM_EVENT_MAX]){ \ + { \ + [MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM0_EVT_OP0_TEA + oper_id + 3 * cmpr_id, \ + }, \ + }[group][event] + +// MCPWM ETM event comparator event table +#define MCPWM_LL_ETM_EVENT_COMPARATOR_EVENT_TABLE(group, oper_id, cmpr_id, event) \ + (uint32_t[2][MCPWM_CMPR_ETM_EVENT_MAX]){ \ + { \ + [MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM0_EVT_OP0_TEE1 + oper_id + 3 * cmpr_id, \ + }, \ + }[group][event] + +/** + * @brief The dead time module's clock source + */ +typedef enum { + MCPWM_LL_DEADTIME_CLK_SRC_GROUP, + MCPWM_LL_DEADTIME_CLK_SRC_TIMER, +} mcpwm_ll_deadtime_clock_src_t; + +////////////////////////////////////////MCPWM Group Specific//////////////////////////////////////////////////////////// + +/** + * @brief Enable the bus clock for MCPWM module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void mcpwm_ll_enable_bus_clock(int group_id, bool enable) +{ + if (group_id == 0) { + PCR.pwm0_conf.pwm0_clk_en = enable; + } else { + PCR.pwm1_conf.pwm1_clk_en = enable; + } +} + +/** + * @brief Reset the MCPWM module + * + * @param group_id Group ID + */ +static inline void mcpwm_ll_reset_register(int group_id) +{ + if (group_id == 0) { + PCR.pwm0_conf.pwm0_rst_en = 1; + PCR.pwm0_conf.pwm0_rst_en = 0; + } else { + PCR.pwm1_conf.pwm1_rst_en = 1; + PCR.pwm1_conf.pwm1_rst_en = 0; + } +} + +/** + * @brief Enable MCPWM function clock + * + * @param group_id Group ID + * @param en true to enable, false to disable + */ +static inline void mcpwm_ll_group_enable_clock(int group_id, bool en) +{ + if (group_id == 0) { + PCR.pwm0_clk_conf.pwm0_clkm_en = en; + } else { + PCR.pwm1_clk_conf.pwm1_clkm_en = en; + } +} + +/** + * @brief Set the clock source for MCPWM + * + * @param group_id Group ID + * @param clk_src Clock source for the MCPWM peripheral + */ +static inline void mcpwm_ll_group_set_clock_source(int group_id, soc_module_clk_t clk_src) +{ + (void)group_id; // only support MCPWM0 + uint8_t clk_id = 0; + switch (clk_src) { + case SOC_MOD_CLK_XTAL: + clk_id = 0; + break; + case SOC_MOD_CLK_RC_FAST: + clk_id = 1; + break; + case SOC_MOD_CLK_PLL_F96M: + clk_id = 2; + break; + default: + HAL_ASSERT(false); + break; + } + if (group_id == 0) { + PCR.pwm0_clk_conf.pwm0_clkm_sel = clk_id; + } else { + PCR.pwm1_clk_conf.pwm1_clkm_sel = clk_id; + } +} + +/** + * @brief Set the MCPWM group clock prescale + * + * @param group_id Group ID + * @param prescale Prescale value + */ +static inline void mcpwm_ll_group_set_clock_prescale(int group_id, int prescale) +{ + (void)group_id; // only support MCPWM0 + // group clock: PWM_clk = source_clock / (prescale) + HAL_ASSERT(prescale <= 256 && prescale > 0); + if (group_id == 0) { + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.pwm0_clk_conf, pwm0_div_num, prescale - 1); + } else { + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.pwm1_clk_conf, pwm1_div_num, prescale - 1); + } +} + +/** + * @brief Enable update MCPWM active registers from shadow registers + * + * @param mcpwm Peripheral instance address + */ +static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) +{ + mcpwm->update_cfg.global_up_en = 1; + mcpwm->update_cfg.op0_up_en = 1; + mcpwm->update_cfg.op1_up_en = 1; + mcpwm->update_cfg.op2_up_en = 1; +} + +/** + * @brief Flush shadow registers to active registers + * + * @param mcpwm Peripheral instance address + */ +static inline void mcpwm_ll_group_flush_shadow(mcpwm_dev_t *mcpwm) +{ + // a toggle can trigger a forced update of all active registers in MCPWM, i.e. shadow->active + mcpwm->update_cfg.global_force_up = 1; + mcpwm->update_cfg.global_force_up = 0; +} + +//////////////////////////////////////////Interrupt Specific//////////////////////////////////////////////////////////// + +/** + * @brief Get interrupt status register address + * + * @param mcpwm Peripheral instance address + * @return Register address + */ +static inline volatile void *mcpwm_ll_intr_get_status_reg(mcpwm_dev_t *mcpwm) +{ + return &mcpwm->int_st; +} + +/** + * @brief Enable MCPWM interrupt for specific event mask + * + * @param mcpwm Peripheral instance address + * @param mask Event mask + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_intr_enable(mcpwm_dev_t *mcpwm, uint32_t mask, bool enable) +{ + if (enable) { + mcpwm->int_ena.val |= mask; + } else { + mcpwm->int_ena.val &= ~mask; + } +} + +/** + * @brief Get MCPWM interrupt status + * + * @param mcpwm Peripheral instance address + * @return Interrupt status + */ +__attribute__((always_inline)) +static inline uint32_t mcpwm_ll_intr_get_status(mcpwm_dev_t *mcpwm) +{ + return mcpwm->int_st.val; +} + +/** + * @brief Clear MCPWM interrupt status by mask + * + * @param mcpwm Peripheral instance address + * @param mask Interrupt status mask + */ +__attribute__((always_inline)) +static inline void mcpwm_ll_intr_clear_status(mcpwm_dev_t *mcpwm, uint32_t mask) +{ + mcpwm->int_clr.val = mask; +} + +////////////////////////////////////////MCPWM Timer Specific//////////////////////////////////////////////////////////// + +/** + * @brief Set MCPWM timer prescale + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param prescale Prescale value + */ +static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale) +{ + HAL_ASSERT(prescale <= 256 && prescale > 0); + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timern_cfg0, timern_prescale, prescale - 1); +} + +/** + * @brief Set peak value for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param peak Peak value + * @param symmetric True to set symmetric peak value, False to set asymmetric peak value + */ +__attribute__((always_inline)) +static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) +{ + if (!symmetric) { // in asymmetric mode, period = [0,peak-1] + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timern_cfg0, timern_period, peak - 1); + } else { // in symmetric mode, period = [0,peak-1] + [peak,1] + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timern_cfg0, timern_period, peak); + } +} + +/** + * @brief Update MCPWM period immediately + * @note When period value is updated in the shadow register, it will be flushed to active register immediately. + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) +{ + mcpwm->timer[timer_id].timern_cfg0.timern_period_upmethod = 0; +} + +/** + * @brief Enable to update MCPWM period upon TEZ event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_timer_enable_update_period_on_tez(mcpwm_dev_t *mcpwm, int timer_id, bool enable) +{ + if (enable) { + mcpwm->timer[timer_id].timern_cfg0.timern_period_upmethod |= 0x01; + } else { + mcpwm->timer[timer_id].timern_cfg0.timern_period_upmethod &= ~0x01; + } +} + +/** + * @brief Enable to update MCPWM period upon sync event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpwm, int timer_id, bool enable) +{ + if (enable) { + mcpwm->timer[timer_id].timern_cfg0.timern_period_upmethod |= 0x02; + } else { + mcpwm->timer[timer_id].timern_cfg0.timern_period_upmethod &= ~0x02; + } +} + +/** + * @brief Set MCPWM timer count mode + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param mode Timer count mode + */ +static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_count_mode_t mode) +{ + switch (mode) { + case MCPWM_TIMER_COUNT_MODE_PAUSE: + mcpwm->timer[timer_id].timern_cfg1.timern_mod = 0; + break; + case MCPWM_TIMER_COUNT_MODE_UP: + mcpwm->timer[timer_id].timern_cfg1.timern_mod = 1; + break; + case MCPWM_TIMER_COUNT_MODE_DOWN: + mcpwm->timer[timer_id].timern_cfg1.timern_mod = 2; + break; + case MCPWM_TIMER_COUNT_MODE_UP_DOWN: + mcpwm->timer[timer_id].timern_cfg1.timern_mod = 3; + break; + default: + HAL_ASSERT(false); + break; + } +} + +/** + * @brief Execute MCPWM timer start/stop command + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param cmd Timer start/stop command + */ +static inline void mcpwm_ll_timer_set_start_stop_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_start_stop_cmd_t cmd) +{ + switch (cmd) { + case MCPWM_TIMER_STOP_EMPTY: + mcpwm->timer[timer_id].timern_cfg1.timern_start = 0; + break; + case MCPWM_TIMER_STOP_FULL: + mcpwm->timer[timer_id].timern_cfg1.timern_start = 1; + break; + case MCPWM_TIMER_START_NO_STOP: + mcpwm->timer[timer_id].timern_cfg1.timern_start = 2; + break; + case MCPWM_TIMER_START_STOP_EMPTY: + mcpwm->timer[timer_id].timern_cfg1.timern_start = 3; + break; + case MCPWM_TIMER_START_STOP_FULL: + mcpwm->timer[timer_id].timern_cfg1.timern_start = 4; + break; + default: + HAL_ASSERT(false); + break; + } +} + +/** + * @brief Get timer count value + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @return Timer count value + */ +__attribute__((always_inline)) +static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id) +{ + // status.value saves the "next count value", so need an extra round up here to get the current count value according to count mode + // timer is paused + if (mcpwm->timer[timer_id].timern_cfg1.timern_mod == 0) { + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timern_status, timern_value); + } + if (mcpwm->timer[timer_id].timern_status.timern_direction) { // down direction + return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timern_status, timern_value) + 1) % + (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timern_cfg0, timern_period) + 1); + } + // up direction + return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timern_status, timern_value) + + HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timern_cfg0, timern_period)) % + (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timern_cfg0, timern_period) + 1); +} + +/** + * @brief Get timer count direction + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @return Timer count direction + */ +__attribute__((always_inline)) +static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) +{ + return mcpwm->timer[timer_id].timern_status.timern_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; +} + +/** + * @brief Enable sync input for timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) +{ + mcpwm->timer[timer_id].timern_sync.timern_synci_en = enable; +} + +/** + * @brief Use the input sync signal as the output sync signal (i.e. propagate the input sync signal) + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_propagate_input_sync(mcpwm_dev_t *mcpwm, int timer_id) +{ + // sync_out is selected to sync_in + mcpwm->timer[timer_id].timern_sync.timern_synco_sel = 0; +} + +/** + * @brief Set the sync output signal to one of the timer event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param event Timer event + */ +static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) +{ + switch (event) { + case MCPWM_TIMER_EVENT_EMPTY: + mcpwm->timer[timer_id].timern_sync.timern_synco_sel = 1; + break; + case MCPWM_TIMER_EVENT_FULL: + mcpwm->timer[timer_id].timern_sync.timern_synco_sel = 2; + break; + default: + HAL_ASSERT(false); + break; + } +} + +/** + * @brief Disable sync output for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) +{ + // sync_out will always be zero + mcpwm->timer[timer_id].timern_sync.timern_synco_sel = 3; +} + +/** + * @brief Trigger MCPWM timer software sync event + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) +{ + mcpwm->timer[timer_id].timern_sync.timern_sync_sw = ~mcpwm->timer[timer_id].timern_sync.timern_sync_sw; +} + +/** + * @brief Set sync count value for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param phase_value Sync phase value + */ +static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timern_sync, timern_phase, phase_value); +} + +/** + * @brief Set sync phase direction for MCPWM timer + * + * @param mcpwm Peripheral instance address + * @param timer_id Timer ID, index from 0 to 2 + * @param direction Sync phase direction + */ +static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) +{ + mcpwm->timer[timer_id].timern_sync.timern_phase_direction = direction; +} + +/** + * @brief Select which GPIO sync input to use + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + * @param gpio_sync_id GPIO sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_set_gpio_sync_input(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) +{ + mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); + mcpwm->timer_synci_cfg.val |= (gpio_sync_id + 4) << (timer * 3); +} + +/** + * @brief Select which timer sync input to use + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + * @param timer_sync_id Timer sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_set_timer_sync_input(mcpwm_dev_t *mcpwm, int timer, int timer_sync_id) +{ + mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); + mcpwm->timer_synci_cfg.val |= (timer_sync_id + 1) << (timer * 3); +} + +/** + * @brief Clear timer sync input selection + * + * @param mcpwm Peripheral instance address + * @param timer Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_timer_clear_sync_input(mcpwm_dev_t *mcpwm, int timer) +{ + // no sync input is selected, but software sync can still work + mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3)); +} + +/** + * @brief Invert the GPIO sync input signal + * + * @param mcpwm Peripheral instance address + * @param sync_id GPIO sync ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_invert_gpio_sync_input(mcpwm_dev_t *mcpwm, int sync_id, bool invert) +{ + if (invert) { + mcpwm->timer_synci_cfg.val |= 1 << (sync_id + 9); + } else { + mcpwm->timer_synci_cfg.val &= ~(1 << (sync_id + 9)); + } +} + +////////////////////////////////////////MCPWM Operator Specific///////////////////////////////////////////////////////// + +/** + * @brief Flush operator shadow registers to active registers + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->update_cfg.val ^= (1 << (2 * operator_id + 3)); +} + +/** + * @brief Connect operator and timer by ID + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param timer_id Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_operator_connect_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) +{ + mcpwm->operator_timersel.val &= ~(0x03 << (2 * operator_id)); + mcpwm->operator_timersel.val |= (timer_id << (2 * operator_id)); +} + +/** + * @brief Update the compare value immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + */ +static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) +{ + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); +} + +/** + * @brief Enable to update the compare value upon TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 0) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 0) << (4 * compare_id)); + } +} + +/** + * @brief Enable to update the compare value upon TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 1) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 1) << (4 * compare_id)); + } +} + +/** + * @brief Enable to update the compare value upon sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 2) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 2) << (4 * compare_id)); + } +} + +/** + * @brief Stop updating the compare value + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param stop_or_not True to stop, False to not stop + */ +static inline void mcpwm_ll_operator_stop_update_compare(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 3) << (4 * compare_id); + } else { + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 3) << (4 * compare_id)); + } +} + +/** + * @brief Set compare value for comparator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param compare_id Compare ID, index from 0 to 1 + * @param compare_value Compare value + */ +__attribute__((always_inline)) +static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], cmprn, compare_value); +} + +/** + * @brief Set equal value for operator event comparator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param event_cmpr_id Event Comparator ID, index from 0 to 1 + * @param compare_value Compare value + */ +__attribute__((always_inline)) +static inline void mcpwm_ll_operator_set_event_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int event_cmpr_id, uint32_t compare_value) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators_timestamp[operator_id].timestamp[event_cmpr_id], opn_tstmp_e, compare_value); +} + +/** + * @brief Update operator actions immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod = 0; +} + +/** + * @brief Enable update actions on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod |= 1 << 0; + } else { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod &= ~(1 << 0); + } +} + +/** + * @brief Enable update actions on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod |= 1 << 1; + } else { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod &= ~(1 << 1); + } +} + +/** + * @brief Enable update actions on sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod |= 1 << 2; + } else { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod &= ~(1 << 2); + } +} + +/** + * @brief Stop updating actions + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param stop_or_not True to stop, False to not stop + */ +static inline void mcpwm_ll_operator_stop_update_action(mcpwm_dev_t *mcpwm, int operator_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod |= 1 << 3; + } else { + mcpwm->operators[operator_id].gen_cfg0.genn_cfg_upmethod &= ~(1 << 3); + } +} + +/** + * @brief Set trigger from GPIO (reuse the fault GPIO) + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param trig_id Trigger ID, index from 0 to 1 + * @param fault_gpio_id Fault GPIO ID, index from 0 to 3 + */ +static inline void mcpwm_ll_operator_set_trigger_from_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_gpio_id) +{ + mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val |= (fault_gpio_id << (4 + 3 * trig_id)); +} + +/** + * @brief Set trigger from sync event (when the timer/gpio/soft taken the sync signal) + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param trig_id Trigger ID, index from 0 to 1 + */ +static inline void mcpwm_ll_operator_set_trigger_from_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) +{ + // the timer here is not selectable, must be the one connected with the operator + mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); +} + +////////////////////////////////////////MCPWM Generator Specific//////////////////////////////////////////////////////// + +/** + * @brief Reset actions for the generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + mcpwm->operators[operator_id].generator[generator_id].val = 0; +} + +/** + * @brief Set generator action on timer event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param event Timer event + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) +{ + // empty: 0, full: 1 + if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2 + 12)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (MCPWM_LL_TIMER_EVENT_TO_REG_VAL(event) * 2 + 12); + } +} + +/** + * @brief Set generator action on compare event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param comp_id Compare ID, index from 0 to 1 + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, int cmp_id, int action) +{ + if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (cmp_id * 2 + 4); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (cmp_id * 2 + 16); + } +} + +/** + * @brief Set generator action on trigger event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param trig_id Trigger ID, index from 0 to 1 + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, int trig_id, int action) +{ + if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (trig_id * 2 + 8); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); + mcpwm->operators[operator_id].generator[generator_id].val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (trig_id * 2 + 20); + } +} + +/** + * @brief Set generator action on brake event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param direction Timer direction + * @param brake_mode Brake mode + * @param action Action to set + */ +static inline void mcpwm_ll_generator_set_action_on_brake_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, + mcpwm_timer_direction_t direction, mcpwm_operator_brake_mode_t brake_mode, int action) +{ + // the following bit operation is highly depend on the register bit layout. + // the priority comes: generator ID > brake mode > direction + if (direction == MCPWM_TIMER_DIRECTION_UP) { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode) + 2)); + mcpwm->operators[operator_id].fh_cfg0.val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode) + 2); + } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode))); + mcpwm->operators[operator_id].fh_cfg0.val |= MCPWM_LL_GEN_ACTION_TO_REG_CAL(action) << (8 + 8 * generator_id + 4 * MCPWM_LL_BRAKE_MODE_TO_REG_VAL(brake_mode)); + } +} + +/** + * @brief Trigger non-continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.genn_a_nciforce = ~mcpwm->operators[operator_id].gen_force.genn_a_nciforce; + } else { + mcpwm->operators[operator_id].gen_force.genn_b_nciforce = ~mcpwm->operators[operator_id].gen_force.genn_b_nciforce; + } +} + +/** + * @brief Disable continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + mcpwm->operators[operator_id].gen_force.genn_cntuforce_upmethod = 0; // update force method immediately + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.genn_a_cntuforce_mode = 0; + } else { + mcpwm->operators[operator_id].gen_force.genn_b_cntuforce_mode = 0; + } +} + +/** + * @brief Disable non-continue forced action for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) +{ + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.genn_a_nciforce_mode = 0; + } else { + mcpwm->operators[operator_id].gen_force.genn_b_nciforce_mode = 0; + } +} + +/** + * @brief Set continue force level for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param level Force level to set + */ +static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) +{ + mcpwm->operators[operator_id].gen_force.genn_cntuforce_upmethod = 0; // update force method immediately + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.genn_a_cntuforce_mode = level + 1; + } else { + mcpwm->operators[operator_id].gen_force.genn_b_cntuforce_mode = level + 1; + } +} + +/** + * @brief Set non-continue force level for generator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator_id Generator ID, index from 0 to 1 + * @param level Force level to set + */ +static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) +{ + if (generator_id == 0) { + mcpwm->operators[operator_id].gen_force.genn_a_nciforce_mode = level + 1; + } else { + mcpwm->operators[operator_id].gen_force.genn_b_nciforce_mode = level + 1; + } +} + +////////////////////////////////////////MCPWM Dead Time Specific//////////////////////////////////////////////////////// + +/** + * @brief Set clock source for dead time submodule + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param src Clock source for dead time submodule + */ +static inline void mcpwm_ll_operator_set_deadtime_clock_src(mcpwm_dev_t *mcpwm, int operator_id, mcpwm_ll_deadtime_clock_src_t src) +{ + switch (src) { + case MCPWM_LL_DEADTIME_CLK_SRC_GROUP: + mcpwm->operators[operator_id].dt_cfg.dbn_clk_sel = 0; + break; + case MCPWM_LL_DEADTIME_CLK_SRC_TIMER: + mcpwm->operators[operator_id].dt_cfg.dbn_clk_sel = 1; + break; + default: + HAL_ASSERT(false); + } +} + +/** + * @brief Select the generator for RED block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) +{ + mcpwm->operators[operator_id].dt_cfg.dbn_red_insel = generator; +} + +/** + * @brief Select the generator for FED block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param generator Generator ID, index from 0 to 1 + */ +static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) +{ + mcpwm->operators[operator_id].dt_cfg.dbn_fed_insel = generator; +} + +/** + * @brief Set which path to bypass in the deadtime submodule + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to bypass, index from 0 to 1 + * @param bypass True to bypass, False to not bypass + */ +static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) +{ + if (bypass) { + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 15); + } else { + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 15)); + } +} + +/** + * @brief Invert the output path + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to invert, index from 0 to 1 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) +{ + if (invert) { + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 13); + } else { + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 13)); + } +} + +/** + * @brief Swap the output path + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param path Path to swap, index from 0 to 1 + * @param swap True to swap, False to not swap + */ +static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) +{ + if (swap) { + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 9); + } else { + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 9)); + } +} + +/** + * @brief Enable the DEB block + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].dt_cfg.dbn_deb_mode = enable; +} + +/** + * @brief Get the deadtime switch topology + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return Dead time submodule's switch topology, each bit represents one switch on/off status + */ +static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) +{ + return (mcpwm->operators[operator_id].dt_cfg.dbn_deb_mode << 8) | (mcpwm->operators[operator_id].dt_cfg.dbn_b_outswap << 7) | + (mcpwm->operators[operator_id].dt_cfg.dbn_a_outswap << 6) | (mcpwm->operators[operator_id].dt_cfg.dbn_fed_insel << 5) | + (mcpwm->operators[operator_id].dt_cfg.dbn_red_insel << 4) | (mcpwm->operators[operator_id].dt_cfg.dbn_fed_outinvert << 3) | + (mcpwm->operators[operator_id].dt_cfg.dbn_red_outinvert << 2) | (mcpwm->operators[operator_id].dt_cfg.dbn_a_outbypass << 1) | + (mcpwm->operators[operator_id].dt_cfg.dbn_b_outbypass << 0); +} + +/** + * @brief Set falling edge delay duration + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fed Delay duration, in deadtime submodule's clock cycles + */ +static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dbn_fed, fed - 1); +} + +/** + * @brief Set rising edge delay duration + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param red Delay duration, in deadtime submodule's clock cycles + */ +static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dbn_red, red - 1); +} + +/** + * @brief Update deadtime immediately + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod = 0; + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod = 0; +} + +/** + * @brief Enable to update deadtime on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod |= 1 << 0; + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod |= 1 << 0; + } else { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod &= ~(1 << 0); + } +} + +/** + * @brief Enable to update deadtime on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod |= 1 << 1; + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod |= 1 << 1; + } else { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod &= ~(1 << 1); + } +} + +/** + * @brief Enable to update deadtime on sync event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod |= 1 << 2; + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod |= 1 << 2; + } else { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod &= ~(1 << 2); + } +} + +/** + * @brief Stop updating deadtime + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param stop_or_not True to stop, False to continue + */ +static inline void mcpwm_ll_deadtime_stop_update_delay(mcpwm_dev_t *mcpwm, int operator_id, bool stop_or_not) +{ + if (stop_or_not) { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod |= 1 << 3; + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod |= 1 << 3; + } else { + mcpwm->operators[operator_id].dt_cfg.dbn_fed_upmethod &= ~(1 << 3); + mcpwm->operators[operator_id].dt_cfg.dbn_red_upmethod &= ~(1 << 3); + } +} + +////////////////////////////////////////MCPWM Carrier Specific////////////////////////////////////////////////////////// + +/** + * @brief Enable carrier for MCPWM operator + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].carrier_cfg.choppern_en = enable; +} + +/** + * @brief Set prescale for MCPWM carrier source clock + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param prescale Prescale value + */ +static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) +{ + HAL_ASSERT(prescale > 0 && prescale <= 16); + mcpwm->operators[operator_id].carrier_cfg.choppern_prescale = prescale - 1; +} + +/** + * @brief Set duty cycle of MCPWM carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param carrier_duty Duty cycle value + */ +static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) +{ + mcpwm->operators[operator_id].carrier_cfg.choppern_duty = carrier_duty; +} + +/** + * @brief Invert the signal after the carrier is applied + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) +{ + mcpwm->operators[operator_id].carrier_cfg.choppern_out_invert = invert; +} + +/** + * @brief Invert the signal before applying the carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) +{ + mcpwm->operators[operator_id].carrier_cfg.choppern_in_invert = invert; +} + +/** + * @brief Set the first pulse width of the carrier + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param pulse_width Pulse width + */ +static inline void mcpwm_ll_carrier_set_first_pulse_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) +{ + HAL_ASSERT(pulse_width >= 1); + mcpwm->operators[operator_id].carrier_cfg.choppern_oshtwth = pulse_width - 1; +} + +////////////////////////////////////////MCPWM Fault Specific//////////////////////////////////////////////////////////// + +/** + * @brief Enable GPIO fault detection + * + * @param mcpwm Peripheral instance address + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_fault_enable_detection(mcpwm_dev_t *mcpwm, int fault_sig, bool enable) +{ + if (enable) { + mcpwm->fault_detect.val |= 1 << fault_sig; + } else { + mcpwm->fault_detect.val &= ~(1 << fault_sig); + } +} + +/** + * @brief Set fault polarity (i.e. which level is treated as an active fault) + * + * @param mcpwm Peripheral instance address + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param level Active level, 0 for low, 1 for high + */ +static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault_sig, bool level) +{ + if (level) { + mcpwm->fault_detect.val |= 1 << (fault_sig + 3); + } else { + mcpwm->fault_detect.val &= ~(1 << (fault_sig + 3)); + } +} + +/** + * @brief Clear the OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) +{ + // a posedge can clear the ost fault status + mcpwm->operators[operator_id].fh_cfg1.tzn_clr_ost = 0; + mcpwm->operators[operator_id].fh_cfg1.tzn_clr_ost = 1; +} + +/** + * @brief Enable the OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg0.val |= (1 << (7 - fault_sig)); + } else { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); + } +} + +/** + * @brief Enable the CBC brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param fault_sig GPIO fault ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); + } else { + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); + } +} + +/** + * @brief Enable refresh the CBC brake on TEZ event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 1; + } else { + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 1); + } +} + +/** + * @brief Enable refresh the CBC brake on TEP event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + if (enable) { + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 2; + } else { + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 2); + } +} + +/** + * @brief Enable software CBC brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_soft_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].fh_cfg0.tzn_sw_cbc = enable; +} + +/** + * @brief Enable software OST brake + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_brake_enable_soft_ost(mcpwm_dev_t *mcpwm, int operator_id, bool enable) +{ + mcpwm->operators[operator_id].fh_cfg0.tzn_sw_ost = enable; +} + +/** + * @brief Trigger software CBC brake for once + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_trigger_soft_cbc(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].fh_cfg1.tzn_force_cbc = ~mcpwm->operators[operator_id].fh_cfg1.tzn_force_cbc; +} + +/** + * @brief Trigger software OST brake for once + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + */ +static inline void mcpwm_ll_brake_trigger_soft_ost(mcpwm_dev_t *mcpwm, int operator_id) +{ + mcpwm->operators[operator_id].fh_cfg1.tzn_force_ost = ~mcpwm->operators[operator_id].fh_cfg1.tzn_force_ost; +} + +/** + * @brief Whether the OST brake is still active + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return True if active, False if not + */ +static inline bool mcpwm_ll_ost_brake_active(mcpwm_dev_t *mcpwm, int operator_id) +{ + return mcpwm->operators[operator_id].fh_status.tzn_ost_on; +} + +/** + * @brief Whether the CBC brake is still active + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @return True if active, False if not + */ +static inline bool mcpwm_ll_cbc_brake_active(mcpwm_dev_t *mcpwm, int operator_id) +{ + return mcpwm->operators[operator_id].fh_status.tzn_cbc_on; +} + +////////////////////////////////////////MCPWM Capture Specific////////////////////////////////////////////////////////// + +/** + * @brief Enable capture timer + * + * @param mcpwm Peripheral instance address + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) +{ + mcpwm->cap_timer_cfg.cap_timer_en = enable; +} + +/** + * @brief Enable capture channel + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) +{ + mcpwm->cap_chn_cfg[channel].capn_en = enable; +} + +/** + * @brief Set sync phase for capture timer + * + * @param mcpwm Peripheral instance address + * @param phase_value Phase value + */ +static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) +{ + mcpwm->cap_timer_phase.cap_phase = phase_value; +} + +/** + * @brief Enable sync for capture timer + * + * @param mcpwm Peripheral instance address + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) +{ + mcpwm->cap_timer_cfg.cap_synci_en = enable; +} + +/** + * @brief Set the timer sync source for MCPWM capture timer + * + * @param mcpwm Peripheral instance address + * @param sync_out_timer MCPWM Timer ID, index from 0 to 2 + */ +static inline void mcpwm_ll_capture_set_timer_sync(mcpwm_dev_t *mcpwm, int sync_out_timer) +{ + mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; +} + +/** + * @brief Set the GPIO sync source for MCPWM capture timer + * + * @param mcpwm Peripheral instance address + * @param gpio_sync GPIO sync ID, index from 0 to 2 + */ +static inline void mcpwm_ll_capture_set_gpio_sync(mcpwm_dev_t *mcpwm, int gpio_sync) +{ + mcpwm->cap_timer_cfg.cap_synci_sel = gpio_sync + 4; +} + +/** + * @brief Trigger a software sync for capture timer + * + * @param mcpwm Peripheral instance address + */ +static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) +{ + mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear +} + +/** + * @brief Enable capture on positive edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) +{ + if (enable) { + mcpwm->cap_chn_cfg[channel].val |= 1 << 2; + } else { + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 2); + } +} + +/** + * @brief Enable capture on negative edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param enable True to enable, False to disable + */ +static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) +{ + if (enable) { + mcpwm->cap_chn_cfg[channel].val |= 1 << 1; + } else { + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 1); + } +} + +/** + * @brief Invert the capture input signal + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param invert True to invert, False to not invert + */ +static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) +{ + mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; +} + +/** + * @brief Trigger the software capture for once + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + */ +static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) +{ + mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear +} + +/** + * @brief Get the captured value + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @return Captured value + */ +__attribute__((always_inline)) +static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) +{ + return mcpwm->cap_chn[channel].capn_value; +} + +/** + * @brief Get the captured edge + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @return Captured edge + */ +__attribute__((always_inline)) +static inline mcpwm_capture_edge_t mcpwm_ll_capture_get_edge(mcpwm_dev_t *mcpwm, int channel) +{ + return mcpwm->cap_status.val & (1 << channel) ? MCPWM_CAP_EDGE_NEG : MCPWM_CAP_EDGE_POS; +} + +/** + * @brief Set the prescale of the input capture signal + * + * @param mcpwm Peripheral instance address + * @param channel Channel ID, index from 0 to 2 + * @param prescale Prescale value + */ +static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) +{ + HAL_ASSERT(prescale > 0); + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); +} + +//////////////////////////////////////////MCPWM ETM Specific//////////////////////////////////////////////////////////// + +/** + * @brief Enable comparator ETM event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param cmpr_id Comparator ID, index from 0 to 2 + * @param en True: enable ETM module, False: disable ETM module + */ +static inline void mcpwm_ll_etm_enable_comparator_event(mcpwm_dev_t *mcpwm, int operator_id, int cmpr_id, bool en) +{ + if (en) { + mcpwm->evt_en.val |= 1 << (operator_id + 3 * cmpr_id + 9); + } else { + mcpwm->evt_en.val &= ~(1 << (operator_id + 3 * cmpr_id + 9)); + } +} + +/** + * @brief Enable event_comparator ETM event + * + * @param mcpwm Peripheral instance address + * @param operator_id Operator ID, index from 0 to 2 + * @param evt_cmpr_id Event comparator ID, index from 0 to 2 + * @param en True: enable ETM module, False: disable ETM module + */ +static inline void mcpwm_ll_etm_enable_evt_comparator_event(mcpwm_dev_t *mcpwm, int operator_id, int evt_cmpr_id, bool en) +{ + if (en) { + mcpwm->evt_en2.val |= 1 << (operator_id + 3 * evt_cmpr_id); + } else { + mcpwm->evt_en2.val &= ~(1 << (operator_id + 3 * evt_cmpr_id)); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_mcpwm/esp32h4/mcpwm_periph.c b/components/esp_hal_mcpwm/esp32h4/mcpwm_periph.c new file mode 100644 index 0000000000..b5afae1d3d --- /dev/null +++ b/components/esp_hal_mcpwm/esp32h4/mcpwm_periph.c @@ -0,0 +1,202 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/interrupts.h" +#include "hal/mcpwm_periph.h" +#include "soc/mcpwm_reg.h" +#include "soc/gpio_sig_map.h" + +const soc_mcpwm_signal_desc_t soc_mcpwm_signals[2] = { + { + .module_name = "MCPWM0", + .irq_id = ETS_PWM0_INTR_SOURCE, + .operators = { + [0] = { + .generators = { + [0] = { + .pwm_sig = PWM0_OUT0A_IDX + }, + [1] = { + .pwm_sig = PWM0_OUT0B_IDX + } + } + }, + [1] = { + .generators = { + [0] = { + .pwm_sig = PWM0_OUT1A_IDX + }, + [1] = { + .pwm_sig = PWM0_OUT1B_IDX + } + } + }, + [2] = { + .generators = { + [0] = { + .pwm_sig = PWM0_OUT2A_IDX + }, + [1] = { + .pwm_sig = PWM0_OUT2B_IDX + } + } + } + }, + .gpio_faults = { + [0] = { + .fault_sig = PWM0_F0_IN_IDX + }, + [1] = { + .fault_sig = PWM0_F1_IN_IDX + }, + [2] = { + .fault_sig = PWM0_F2_IN_IDX + } + }, + .captures = { + [0] = { + .cap_sig = PWM0_CAP0_IN_IDX + }, + [1] = { + .cap_sig = PWM0_CAP1_IN_IDX + }, + [2] = { + .cap_sig = PWM0_CAP2_IN_IDX + } + }, + .gpio_synchros = { + [0] = { + .sync_sig = PWM0_SYNC0_IN_IDX + }, + [1] = { + .sync_sig = PWM0_SYNC1_IN_IDX + }, + [2] = { + .sync_sig = PWM0_SYNC2_IN_IDX + } + } + }, + { + .module_name = "MCPWM1", + .irq_id = ETS_PWM1_INTR_SOURCE, + .operators = { + [0] = { + .generators = { + [0] = { + .pwm_sig = PWM1_OUT0A_IDX + }, + [1] = { + .pwm_sig = PWM1_OUT0B_IDX + } + } + }, + [1] = { + .generators = { + [0] = { + .pwm_sig = PWM1_OUT1A_IDX + }, + [1] = { + .pwm_sig = PWM1_OUT1B_IDX + } + } + }, + [2] = { + .generators = { + [0] = { + .pwm_sig = PWM1_OUT2A_IDX + }, + [1] = { + .pwm_sig = PWM1_OUT2B_IDX + } + } + } + }, + .gpio_faults = { + [0] = { + .fault_sig = PWM1_F0_IN_IDX + }, + [1] = { + .fault_sig = PWM1_F1_IN_IDX + }, + [2] = { + .fault_sig = PWM1_F2_IN_IDX + } + }, + .captures = { + [0] = { + .cap_sig = PWM1_CAP0_IN_IDX + }, + [1] = { + .cap_sig = PWM1_CAP1_IN_IDX + }, + [2] = { + .cap_sig = PWM1_CAP2_IN_IDX + } + }, + .gpio_synchros = { + [0] = { + .sync_sig = PWM1_SYNC0_IN_IDX + }, + [1] = { + .sync_sig = PWM1_SYNC1_IN_IDX + }, + [2] = { + .sync_sig = PWM1_SYNC2_IN_IDX + } + } + } +}; + +/** + * MCPWM Registers to be saved during sleep retention + * - Timer Configuration registers, e.g.: MCPWM_TIMER_SYNCI_CFG_REG, MCPWM_TIMER0_CFG0_REG, MCPWM_TIMER0_CFG1_REG, MCPWM_TIMER0_CFG1_REG,MCPWM_TIMER0_SYNC_REG + * - Operator Configuration registers, e.g.: MCPWM_OPERATOR_TIMERSEL_REG + * |- Generator Configuration registers, e.g.: MCPWM_GEN0_STMP_CFG_REG, MCPWM_GEN0_TSTMP_A_REG, MCPWM_GEN0_TSTMP_B_REG, MCPWM_GEN0_CFG0_REG, MCPWM_GEN0_FORCE_REG, MCPWM_GEN0_A_REG, MCPWM_GEN0_B_REG + * |- Dead Time Configuration registers, e.g.: MCPWM_DT0_CFG_REG, MCPWM_DT0_FED_CFG_REG, MCPWM_DT0_RED_CFG_REG + * |- Carrier Configuration registers, e.g.: MCPWM_CARRIER0_CFG_REG + * └- Fault Handle Configuration registers, e.g.: MCPWM_FAULT_DETECT_REG, MCPWM_FH0_CFG0_REG, MCPWM_FH0_CFG1_REG + * - Capture Timer Configuration registers, e.g.: MCPWM_CAP_TIMER_CFG_REG, MCPWM_CAP_TIMER_PHASE_REG, MCPWM_CAP_CH0_CFG_REG, MCPWM_CAP_CH1_CFG_REG, MCPWM_CAP_CH2_CFG_REG + * - Interrupt enable registers, e.g.: MCPWM_INT_ENA_REG + * - ETM Configurations, e.g.: MCPWM_EVT_EN_REG, MCPWM_EVT_EN2_REG, MCPWM_TASK_EN_REG, MCPWM_OP0_TSTMP_E1_REG, MCPWM_OP0_TSTMP_E2_REG, MCPWM_OP1_TSTMP_E1_REG, MCPWM_OP1_TSTMP_E2_REG, MCPWM_OP2_TSTMP_E1_REG, MCPWM_OP2_TSTMP_E2_REG + * - Misc Configurations, e.g.: MCPWM_UPDATE_CFG_REG +*/ + +#define MCPWM_RETENTION_REGS_CNT 67 +#define MCPWM_RETENTION_REGS_BASE(i) DR_REG_MCPWM_BASE(i) +static const uint32_t mcpwm_regs_map[4] = {0xf7fff777, 0x3f7ffdff, 0xff8c, 0x0}; +static const regdma_entries_config_t mcpwm0_regdma_entries[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MCPWM_LINK(0x00), + MCPWM_RETENTION_REGS_BASE(0), MCPWM_RETENTION_REGS_BASE(0), + MCPWM_RETENTION_REGS_CNT, 0, 0, + mcpwm_regs_map[0], mcpwm_regs_map[1], + mcpwm_regs_map[2], mcpwm_regs_map[3]), + .owner = ENTRY(0) | ENTRY(2), + }, +}; +static const regdma_entries_config_t mcpwm1_regdma_entries[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MCPWM_LINK(0x00), + MCPWM_RETENTION_REGS_BASE(1), MCPWM_RETENTION_REGS_BASE(1), + MCPWM_RETENTION_REGS_CNT, 0, 0, + mcpwm_regs_map[0], mcpwm_regs_map[1], + mcpwm_regs_map[2], mcpwm_regs_map[3]), + .owner = ENTRY(0) | ENTRY(2), + }, +}; + +const mcpwm_reg_retention_info_t mcpwm_reg_retention_info[2] = { + [0] = { + .regdma_entry_array = mcpwm0_regdma_entries, + .array_size = ARRAY_SIZE(mcpwm0_regdma_entries), + .retention_module = SLEEP_RETENTION_MODULE_MCPWM0 + }, + [1] = { + .regdma_entry_array = mcpwm0_regdma_entries, + .array_size = ARRAY_SIZE(mcpwm1_regdma_entries), + .retention_module = SLEEP_RETENTION_MODULE_MCPWM1 + }, +}; diff --git a/components/esp_hal_mcpwm/esp32p4/mcpwm_periph.c b/components/esp_hal_mcpwm/esp32p4/mcpwm_periph.c index 061aefb68c..edaa2aa7d1 100644 --- a/components/esp_hal_mcpwm/esp32p4/mcpwm_periph.c +++ b/components/esp_hal_mcpwm/esp32p4/mcpwm_periph.c @@ -153,7 +153,6 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[2] = { #if SOC_MCPWM_SUPPORT_SLEEP_RETENTION /** * MCPWM Registers to be saved during sleep retention - * - Clk Configuration registers, e.g.: MCPWM_CLK_CFG_REG * - Timer Configuration registers, e.g.: MCPWM_TIMER_SYNCI_CFG_REG, MCPWM_TIMER0_CFG0_REG, MCPWM_TIMER0_CFG1_REG, MCPWM_TIMER0_CFG1_REG * - Operator Configuration registers, e.g.: MCPWM_OPERATOR_TIMERSEL_REG * |- Generator Configuration registers, e.g.: MCPWM_GEN0_STMP_CFG_REG, MCPWM_GEN0_TSTMP_A_REG, MCPWM_GEN0_TSTMP_B_REG, MCPWM_GEN0_CFG0_REG, MCPWM_GEN0_FORCE_REG, MCPWM_GEN0_A_REG, MCPWM_GEN0_B_REG @@ -165,9 +164,9 @@ const soc_mcpwm_signal_desc_t soc_mcpwm_signals[2] = { * - ETM Configurations, e.g.: MCPWM_EVT_EN_REG, MCPWM_TASK_EN_REG * - Misc Configurations, e.g.: MCPWM_UPDATE_CFG_REG */ -#define MCPWM_RETENTION_REGS_CNT 68 -#define MCPWM_RETENTION_REGS_BASE(i) REG_MCPWM_BASE(i) -static const uint32_t mcpwm_regs_map[4] = {0xefffeeef, 0x7efffbff, 0x1ff18, 0x0}; +#define MCPWM_RETENTION_REGS_CNT 67 +#define MCPWM_RETENTION_REGS_BASE(i) (REG_MCPWM_BASE(i) + 0x4) +static const uint32_t mcpwm_regs_map[4] = {0xf7fff777, 0x3f7ffdff, 0xff8c, 0x0}; #define MCPWM_SLEEP_RETENTION_ENTRIES(mcpwm_port) { \ /* backup stage: save configuration registers \ restore stage: restore the configuration registers */ \ diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index c23b67815d..8b43a903be 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -23,6 +23,10 @@ config SOC_PCNT_SUPPORTED bool default y +config SOC_MCPWM_SUPPORTED + bool + default y + config SOC_TWAI_SUPPORTED bool default y @@ -587,6 +591,26 @@ config SOC_RMT_SUPPORT_SLEEP_RETENTION bool default y +config SOC_MCPWM_SWSYNC_CAN_PROPAGATE + bool + default y + +config SOC_MCPWM_SUPPORT_ETM + bool + default y + +config SOC_MCPWM_SUPPORT_EVENT_COMPARATOR + bool + default y + +config SOC_MCPWM_CAPTURE_CLK_FROM_GROUP + bool + default y + +config SOC_MCPWM_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_SPI_PERIPH_NUM int default 3 @@ -961,7 +985,7 @@ config SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE config SOC_PM_RETENTION_MODULE_NUM int - default 32 + default 64 config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool diff --git a/components/soc/esp32h4/include/soc/clk_tree_defs.h b/components/soc/esp32h4/include/soc/clk_tree_defs.h index c52a4e7567..95f9a1c9d1 100644 --- a/components/soc/esp32h4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h4/include/soc/clk_tree_defs.h @@ -347,6 +347,53 @@ typedef enum { LEDC_USE_XTAL_CLK = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ } soc_periph_ledc_clk_src_legacy_t; +//////////////////////////////////////////////////MCPWM///////////////////////////////////////////////////////////////// + +/** + * @brief Array initializer for all supported clock sources of MCPWM Timer + */ +#define SOC_MCPWM_TIMER_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} + +/** + * @brief Type of MCPWM timer clock source + */ +typedef enum { + MCPWM_TIMER_CLK_SRC_PLL96M = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the source clock */ + MCPWM_TIMER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + MCPWM_TIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + MCPWM_TIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ +} soc_periph_mcpwm_timer_clk_src_t; + +/** + * @brief Array initializer for all supported clock sources of MCPWM Capture Timer + */ +#define SOC_MCPWM_CAPTURE_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} + +/** + * @brief Type of MCPWM capture clock source + */ +typedef enum { + MCPWM_CAPTURE_CLK_SRC_PLL96M = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the source clock */ + MCPWM_CAPTURE_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + MCPWM_CAPTURE_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + MCPWM_CAPTURE_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ +} soc_periph_mcpwm_capture_clk_src_t; + +/** + * @brief Array initializer for all supported clock sources of MCPWM Carrier + */ +#define SOC_MCPWM_CARRIER_CLKS {SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} + +/** + * @brief Type of MCPWM carrier clock source + */ +typedef enum { + MCPWM_CARRIER_CLK_SRC_PLL96M = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the source clock */ + MCPWM_CARRIER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + MCPWM_CARRIER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + MCPWM_CARRIER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ +} soc_periph_mcpwm_carrier_clk_src_t; + ///////////////////////////////////////////////////// I2S ////////////////////////////////////////////////////////////// /** diff --git a/components/soc/esp32h4/include/soc/retention_periph_defs.h b/components/soc/esp32h4/include/soc/retention_periph_defs.h index 56379894b6..0abaf0a0e2 100644 --- a/components/soc/esp32h4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h4/include/soc/retention_periph_defs.h @@ -49,12 +49,13 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_GPSPI3 = 25, SLEEP_RETENTION_MODULE_LEDC = 26, SLEEP_RETENTION_MODULE_MCPWM0 = 27, - SLEEP_RETENTION_MODULE_SDM0 = 28, + SLEEP_RETENTION_MODULE_MCPWM1 = 28, + SLEEP_RETENTION_MODULE_SDM0 = 29, /* Modem module, which includes BLE and 802.15.4 */ - SLEEP_RETENTION_MODULE_BLE_MAC = 29, - SLEEP_RETENTION_MODULE_BT_BB = 30, - SLEEP_RETENTION_MODULE_802154_MAC = 31, + SLEEP_RETENTION_MODULE_BLE_MAC = 30, + SLEEP_RETENTION_MODULE_BT_BB = 31, + SLEEP_RETENTION_MODULE_802154_MAC = 32, SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 } periph_retention_module_t; @@ -87,6 +88,7 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_GPSPI3) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ + : ((m) == SLEEP_RETENTION_MODULE_MCPWM1) ? true \ : ((m) == SLEEP_RETENTION_MODULE_SDM0) ? true \ : false) diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 3724366db6..429546053c 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -39,7 +39,7 @@ #define SOC_AHB_GDMA_SUPPORTED 1 #define SOC_GPTIMER_SUPPORTED 1 #define SOC_PCNT_SUPPORTED 1 -// #define SOC_MCPWM_SUPPORTED 1 // TODO: [ESP32H4] IDF-12380 +#define SOC_MCPWM_SUPPORTED 1 #define SOC_TWAI_SUPPORTED 1 #define SOC_ETM_SUPPORTED 1 // #define SOC_PARLIO_SUPPORTED 1 // TODO: [ESP32H4] IDF-12345 IDF-12347 @@ -328,19 +328,11 @@ #define SOC_RMT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up RMT registers before sleep */ /*-------------------------- MCPWM CAPS --------------------------------------*/ -// #define SOC_MCPWM_GROUPS (1U) ///< 1 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals) -// #define SOC_MCPWM_TIMERS_PER_GROUP (3) ///< The number of timers that each group has -// #define SOC_MCPWM_OPERATORS_PER_GROUP (3) ///< The number of operators that each group has -// #define SOC_MCPWM_COMPARATORS_PER_OPERATOR (2) ///< The number of comparators that each operator has -// #define SOC_MCPWM_GENERATORS_PER_OPERATOR (2) ///< The number of generators that each operator has -// #define SOC_MCPWM_TRIGGERS_PER_OPERATOR (2) ///< The number of triggers that each operator has -// #define SOC_MCPWM_GPIO_FAULTS_PER_GROUP (3) ///< The number of fault signal detectors that each group has -// #define SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP (1) ///< The number of capture timers that each group has -// #define SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER (3) ///< The number of capture channels that each capture timer has -// #define SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP (3) ///< The number of GPIO synchros that each group has -// #define SOC_MCPWM_SWSYNC_CAN_PROPAGATE (1) ///< Software sync event can be routed to its output -// #define SOC_MCPWM_SUPPORT_ETM (1) ///< Support ETM (Event Task Matrix) -// #define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers +#define SOC_MCPWM_SWSYNC_CAN_PROPAGATE 1 ///< Software sync event can be routed to its output +#define SOC_MCPWM_SUPPORT_ETM 1 ///< Support ETM (Event Task Matrix) +#define SOC_MCPWM_SUPPORT_EVENT_COMPARATOR 1 ///< Support event comparator (based on ETM) +#define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP 1 ///< Capture timer shares clock with other PWM timers +#define SOC_MCPWM_SUPPORT_SLEEP_RETENTION 1 ///< Support back up registers before sleep /*------------------------ USB SERIAL JTAG CAPS ------------------------------*/ // #define SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP (1) /*!< Support to maintain minimum usb communication during light sleep */ // TODO: IDF-6395 @@ -527,7 +519,7 @@ #define SOC_PM_PAU_LINK_NUM (4) #define SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE (1) -#define SOC_PM_RETENTION_MODULE_NUM (32) +#define SOC_PM_RETENTION_MODULE_NUM (64) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) diff --git a/components/soc/esp32h4/register/soc/mcpwm_reg.h b/components/soc/esp32h4/register/soc/mcpwm_reg.h index abc8c2d380..92625a7880 100644 --- a/components/soc/esp32h4/register/soc/mcpwm_reg.h +++ b/components/soc/esp32h4/register/soc/mcpwm_reg.h @@ -11,6 +11,9 @@ extern "C" { #endif +// MCPWM base address macro for multi-group support +#define DR_REG_MCPWM_BASE(i) (DR_REG_MCPWM0_BASE + (i) * 0x1000) + /** MCPWM_TIMER0_CFG0_REG register * PWM timer0 period and update method configuration register. */ diff --git a/components/soc/esp32h4/register/soc/mcpwm_struct.h b/components/soc/esp32h4/register/soc/mcpwm_struct.h index bf0b5dfeed..cc0793c718 100644 --- a/components/soc/esp32h4/register/soc/mcpwm_struct.h +++ b/components/soc/esp32h4/register/soc/mcpwm_struct.h @@ -242,33 +242,19 @@ typedef union { uint32_t val; } mcpwm_genn_stmp_cfg_reg_t; -/** Type of genn_tstmp_a register - * Generatorn time stamp A's shadow register +/** Type of genn_tstmp register + * Generatorn time stamp shadow register (unified type for array access) */ typedef union { struct { - /** cmprn_a : R/W; bitpos: [15:0]; default: 0; - * Configures the value of PWM generator n time stamp A's shadow register. + /** cmprn : R/W; bitpos: [15:0]; default: 0; + * Configures the value of PWM generator n time stamp shadow register. */ - uint32_t cmprn_a:16; + uint32_t cmprn:16; uint32_t reserved_16:16; }; uint32_t val; -} mcpwm_genn_tstmp_a_reg_t; - -/** Type of genn_tstmp_b register - * Generatorn time stamp B's shadow register - */ -typedef union { - struct { - /** cmprn_b : R/W; bitpos: [15:0]; default: 0; - * Configures the value of PWM generator n time stamp B's shadow register. - */ - uint32_t cmprn_b:16; - uint32_t reserved_16:16; - }; - uint32_t val; -} mcpwm_genn_tstmp_b_reg_t; +} mcpwm_genn_tstmp_reg_t; /** Type of genn_cfg0 register * Generatorn fault event T0 and T1 configuration register @@ -371,217 +357,90 @@ typedef union { uint32_t val; } mcpwm_genn_force_reg_t; -/** Type of genn_a register - * PWMn output signal A actions configuration register - */ -typedef union { - struct { - /** genn_a_utez : R/W; bitpos: [1:0]; default: 0; - * Configures action on PWMn A triggered by event TEZ when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_utez:2; - /** genn_a_utep : R/W; bitpos: [3:2]; default: 0; - * Configures action on PWMn A triggered by event TEP when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_utep:2; - /** genn_a_utea : R/W; bitpos: [5:4]; default: 0; - * Configures action on PWMn A triggered by event TEA when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_utea:2; - /** genn_a_uteb : R/W; bitpos: [7:6]; default: 0; - * Configures action on PWMn A triggered by event TEB when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_uteb:2; - /** genn_a_ut0 : R/W; bitpos: [9:8]; default: 0; - * Configures action on PWMn A triggered by event_t0 when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_ut0:2; - /** genn_a_ut1 : R/W; bitpos: [11:10]; default: 0; - * Configures action on PWMn A triggered by event_t1 when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_ut1:2; - /** genn_a_dtez : R/W; bitpos: [13:12]; default: 0; - * Configures action on PWMn A triggered by event TEZ when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_dtez:2; - /** genn_a_dtep : R/W; bitpos: [15:14]; default: 0; - * Configures action on PWMn A triggered by event TEP when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_dtep:2; - /** genn_a_dtea : R/W; bitpos: [17:16]; default: 0; - * Configures action on PWMn A triggered by event TEA when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_dtea:2; - /** genn_a_dteb : R/W; bitpos: [19:18]; default: 0; - * Configures action on PWMn A triggered by event TEB when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_dteb:2; - /** genn_a_dt0 : R/W; bitpos: [21:20]; default: 0; - * Configures action on PWMn A triggered by event_t0 when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_dt0:2; - /** genn_a_dt1 : R/W; bitpos: [23:22]; default: 0; - * Configures action on PWMn A triggered by event_t1 when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle - */ - uint32_t genn_a_dt1:2; - uint32_t reserved_24:8; - }; - uint32_t val; -} mcpwm_genn_a_reg_t; -/** Type of genn_b register - * PWMn output signal B actions configuration register +/** Type of genn register + * PWMn output signal actions configuration register (unified type for array access) */ typedef union { struct { - /** genn_b_utez : R/W; bitpos: [1:0]; default: 0; - * Configures action on PWMn B triggered by event TEZ when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + /** genn_utez : R/W; bitpos: [1:0]; default: 0; + * Configures action on PWMn triggered by event TEZ when timer increasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_utez:2; - /** genn_b_utep : R/W; bitpos: [3:2]; default: 0; - * Configures action on PWMn B triggered by event TEP when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_utez:2; + /** genn_utep : R/W; bitpos: [3:2]; default: 0; + * Configures action on PWMn triggered by event TEP when timer increasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_utep:2; - /** genn_b_utea : R/W; bitpos: [5:4]; default: 0; - * Configures action on PWMn B triggered by event TEA when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_utep:2; + /** genn_utea : R/W; bitpos: [5:4]; default: 0; + * Configures action on PWMn triggered by event TEA when timer increasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_utea:2; - /** genn_b_uteb : R/W; bitpos: [7:6]; default: 0; - * Configures action on PWMn B triggered by event TEB when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_utea:2; + /** genn_uteb : R/W; bitpos: [7:6]; default: 0; + * Configures action on PWMn triggered by event TEB when timer increasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_uteb:2; - /** genn_b_ut0 : R/W; bitpos: [9:8]; default: 0; - * Configures action on PWMn B triggered by event_t0 when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_uteb:2; + /** genn_ut0 : R/W; bitpos: [9:8]; default: 0; + * Configures action on PWMn triggered by event_t0 when timer increasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_ut0:2; - /** genn_b_ut1 : R/W; bitpos: [11:10]; default: 0; - * Configures action on PWMn B triggered by event_t1 when timer increasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_ut0:2; + /** genn_ut1 : R/W; bitpos: [11:10]; default: 0; + * Configures action on PWMn triggered by event_t1 when timer increasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_ut1:2; - /** genn_b_dtez : R/W; bitpos: [13:12]; default: 0; - * Configures action on PWMn B triggered by event TEZ when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_ut1:2; + /** genn_dtez : R/W; bitpos: [13:12]; default: 0; + * Configures action on PWMn triggered by event TEZ when timer decreasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_dtez:2; - /** genn_b_dtep : R/W; bitpos: [15:14]; default: 0; - * Configures action on PWMn B triggered by event TEP when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_dtez:2; + /** genn_dtep : R/W; bitpos: [15:14]; default: 0; + * Configures action on PWMn triggered by event TEP when timer decreasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_dtep:2; - /** genn_b_dtea : R/W; bitpos: [17:16]; default: 0; - * Configures action on PWMn B triggered by event TEA when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_dtep:2; + /** genn_dtea : R/W; bitpos: [17:16]; default: 0; + * Configures action on PWMn triggered by event TEA when timer decreasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_dtea:2; - /** genn_b_dteb : R/W; bitpos: [19:18]; default: 0; - * Configures action on PWMn B triggered by event TEB when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_dtea:2; + /** genn_dteb : R/W; bitpos: [19:18]; default: 0; + * Configures action on PWMn triggered by event TEB when timer decreasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_dteb:2; - /** genn_b_dt0 : R/W; bitpos: [21:20]; default: 0; - * Configures action on PWMn B triggered by event_t0 when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_dteb:2; + /** genn_dt0 : R/W; bitpos: [21:20]; default: 0; + * Configures action on PWMn triggered by event_t0 when timer decreasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_dt0:2; - /** genn_b_dt1 : R/W; bitpos: [23:22]; default: 0; - * Configures action on PWMn B triggered by event_t1 when timer decreasing. - * 0: No change - * 1: Low - * 2: High - * 3: Toggle + uint32_t genn_dt0:2; + /** genn_dt1 : R/W; bitpos: [23:22]; default: 0; + * Configures action on PWMn triggered by event_t1 when timer decreasing. + * 0: No change, 1: Low, 2: High, 3: Toggle */ - uint32_t genn_b_dt1:2; + uint32_t genn_dt1:2; uint32_t reserved_24:8; }; uint32_t val; -} mcpwm_genn_b_reg_t; +} mcpwm_genn_reg_t; + +/** Type of opn_tstmp register + * Operator timestamp register (unified type for array access) + */ +typedef union { + struct { + /** opn_tstmp_e : R/W; bitpos: [15:0]; default: 0; + * Configures the value of PWM operator timestamp. + */ + uint32_t opn_tstmp_e:16; + uint32_t reserved_16:16; + }; + uint32_t val; +} mcpwm_opn_tstmp_reg_t; /** Type of dtn_cfg register * Dead time configuration register @@ -1498,34 +1357,6 @@ typedef union { uint32_t val; } mcpwm_evt_en2_reg_t; -/** Type of opn_tstmp_e1 register - * Generatorn timer stamp E1 value register - */ -typedef union { - struct { - /** opn_tstmp_e1 : R/W; bitpos: [15:0]; default: 0; - * Configures generatorn timer stamp E1 value register - */ - uint32_t opn_tstmp_e1:16; - uint32_t reserved_16:16; - }; - uint32_t val; -} mcpwm_opn_tstmp_e1_reg_t; - -/** Type of opn_tstmp_e2 register - * Generatorn timer stamp E2 value register - */ -typedef union { - struct { - /** opn_tstmp_e2 : R/W; bitpos: [15:0]; default: 0; - * Configures generatorn timer stamp E2 value register - */ - uint32_t opn_tstmp_e2:16; - uint32_t reserved_16:16; - }; - uint32_t val; -} mcpwm_opn_tstmp_e2_reg_t; - /** Type of clk register * Global configuration register */ @@ -2239,62 +2070,36 @@ typedef union { typedef struct { - volatile mcpwm_timern_cfg0_reg_t timer0_cfg0; - volatile mcpwm_timern_cfg1_reg_t timer0_cfg1; - volatile mcpwm_timern_sync_reg_t timer0_sync; - volatile mcpwm_timern_status_reg_t timer0_status; - volatile mcpwm_timern_cfg0_reg_t timer1_cfg0; - volatile mcpwm_timern_cfg1_reg_t timer1_cfg1; - volatile mcpwm_timern_sync_reg_t timer1_sync; - volatile mcpwm_timern_status_reg_t timer1_status; - volatile mcpwm_timern_cfg0_reg_t timer2_cfg0; - volatile mcpwm_timern_cfg1_reg_t timer2_cfg1; - volatile mcpwm_timern_sync_reg_t timer2_sync; - volatile mcpwm_timern_status_reg_t timer2_status; + volatile mcpwm_timern_cfg0_reg_t timern_cfg0; + volatile mcpwm_timern_cfg1_reg_t timern_cfg1; + volatile mcpwm_timern_sync_reg_t timern_sync; + volatile mcpwm_timern_status_reg_t timern_status; +} mcpwm_timer_regs_t; + +typedef struct { + volatile mcpwm_genn_stmp_cfg_reg_t gen_stmp_cfg; + volatile mcpwm_genn_tstmp_reg_t timestamp[2]; + volatile mcpwm_genn_cfg0_reg_t gen_cfg0; + volatile mcpwm_genn_force_reg_t gen_force; + volatile mcpwm_genn_reg_t generator[2]; + volatile mcpwm_dtn_cfg_reg_t dt_cfg; + volatile mcpwm_dtn_fed_cfg_reg_t dt_fed_cfg; + volatile mcpwm_dtn_red_cfg_reg_t dt_red_cfg; + volatile mcpwm_carriern_cfg_reg_t carrier_cfg; + volatile mcpwm_fhn_cfg0_reg_t fh_cfg0; + volatile mcpwm_fhn_cfg1_reg_t fh_cfg1; + volatile mcpwm_fhn_status_reg_t fh_status; +} mcpwm_operator_reg_t; + +typedef struct { + volatile mcpwm_opn_tstmp_reg_t timestamp[2]; +} mcpwm_operator_tstmp_reg_t; + +typedef struct mcpwm_dev_t { + volatile mcpwm_timer_regs_t timer[3]; volatile mcpwm_timer_synci_cfg_reg_t timer_synci_cfg; volatile mcpwm_operator_timersel_reg_t operator_timersel; - volatile mcpwm_genn_stmp_cfg_reg_t gen0_stmp_cfg; - volatile mcpwm_genn_tstmp_a_reg_t gen0_tstmp_a; - volatile mcpwm_genn_tstmp_b_reg_t gen0_tstmp_b; - volatile mcpwm_genn_cfg0_reg_t gen0_cfg0; - volatile mcpwm_genn_force_reg_t gen0_force; - volatile mcpwm_genn_a_reg_t gen0_a; - volatile mcpwm_genn_b_reg_t gen0_b; - volatile mcpwm_dtn_cfg_reg_t dt0_cfg; - volatile mcpwm_dtn_fed_cfg_reg_t dt0_fed_cfg; - volatile mcpwm_dtn_red_cfg_reg_t dt0_red_cfg; - volatile mcpwm_carriern_cfg_reg_t carrier0_cfg; - volatile mcpwm_fhn_cfg0_reg_t fh0_cfg0; - volatile mcpwm_fhn_cfg1_reg_t fh0_cfg1; - volatile mcpwm_fhn_status_reg_t fh0_status; - volatile mcpwm_genn_stmp_cfg_reg_t gen1_stmp_cfg; - volatile mcpwm_genn_tstmp_a_reg_t gen1_tstmp_a; - volatile mcpwm_genn_tstmp_b_reg_t gen1_tstmp_b; - volatile mcpwm_genn_cfg0_reg_t gen1_cfg0; - volatile mcpwm_genn_force_reg_t gen1_force; - volatile mcpwm_genn_a_reg_t gen1_a; - volatile mcpwm_genn_b_reg_t gen1_b; - volatile mcpwm_dtn_cfg_reg_t dt1_cfg; - volatile mcpwm_dtn_fed_cfg_reg_t dt1_fed_cfg; - volatile mcpwm_dtn_red_cfg_reg_t dt1_red_cfg; - volatile mcpwm_carriern_cfg_reg_t carrier1_cfg; - volatile mcpwm_fhn_cfg0_reg_t fh1_cfg0; - volatile mcpwm_fhn_cfg1_reg_t fh1_cfg1; - volatile mcpwm_fhn_status_reg_t fh1_status; - volatile mcpwm_genn_stmp_cfg_reg_t gen2_stmp_cfg; - volatile mcpwm_genn_tstmp_a_reg_t gen2_tstmp_a; - volatile mcpwm_genn_tstmp_b_reg_t gen2_tstmp_b; - volatile mcpwm_genn_cfg0_reg_t gen2_cfg0; - volatile mcpwm_genn_force_reg_t gen2_force; - volatile mcpwm_genn_a_reg_t gen2_a; - volatile mcpwm_genn_b_reg_t gen2_b; - volatile mcpwm_dtn_cfg_reg_t dt2_cfg; - volatile mcpwm_dtn_fed_cfg_reg_t dt2_fed_cfg; - volatile mcpwm_dtn_red_cfg_reg_t dt2_red_cfg; - volatile mcpwm_carriern_cfg_reg_t carrier2_cfg; - volatile mcpwm_fhn_cfg0_reg_t fh2_cfg0; - volatile mcpwm_fhn_cfg1_reg_t fh2_cfg1; - volatile mcpwm_fhn_status_reg_t fh2_status; + volatile mcpwm_operator_reg_t operators[3]; volatile mcpwm_fault_detect_reg_t fault_detect; volatile mcpwm_cap_timer_cfg_reg_t cap_timer_cfg; volatile mcpwm_cap_timer_phase_reg_t cap_timer_phase; @@ -2309,12 +2114,7 @@ typedef struct { volatile mcpwm_evt_en_reg_t evt_en; volatile mcpwm_task_en_reg_t task_en; volatile mcpwm_evt_en2_reg_t evt_en2; - volatile mcpwm_opn_tstmp_e1_reg_t op0_tstmp_e1; - volatile mcpwm_opn_tstmp_e2_reg_t op0_tstmp_e2; - volatile mcpwm_opn_tstmp_e1_reg_t op1_tstmp_e1; - volatile mcpwm_opn_tstmp_e2_reg_t op1_tstmp_e2; - volatile mcpwm_opn_tstmp_e1_reg_t op2_tstmp_e1; - volatile mcpwm_opn_tstmp_e2_reg_t op2_tstmp_e2; + volatile mcpwm_operator_tstmp_reg_t operators_timestamp[3]; volatile mcpwm_clk_reg_t clk; volatile mcpwm_version_reg_t version; } mcpwm_dev_t; diff --git a/docs/docs_not_updated/esp32h4.txt b/docs/docs_not_updated/esp32h4.txt index d75bf21a37..346316c842 100644 --- a/docs/docs_not_updated/esp32h4.txt +++ b/docs/docs_not_updated/esp32h4.txt @@ -127,8 +127,6 @@ api-reference/peripherals/bitscrambler.rst api-reference/peripherals/temp_sensor.rst api-reference/peripherals/usb_device.rst api-reference/peripherals/jpeg.rst -api-reference/peripherals/mcpwm.rst -api-reference/peripherals/usb_host.rst api-reference/peripherals/camera_driver.rst api-reference/peripherals/adc_oneshot.rst api-reference/peripherals/sdspi_share.rst diff --git a/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/README.md b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/README.md index 32e2ea19d0..22681cd506 100644 --- a/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/README.md +++ b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # MCPWM Brushed DC Motor Example (See the README.md file in the upper level 'examples' directory for more information about examples.) diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md index df843cf218..561d3df89b 100644 --- a/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md +++ b/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # MCPWM BLDC Motor Control with HALL Sensor Example diff --git a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/README.md b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/README.md index 7330023203..391a9ebb43 100644 --- a/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/README.md +++ b/examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # HC-SR04 Example based on MCPWM Capture diff --git a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/README.md b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/README.md index a8bd989793..3d93d9a0f2 100644 --- a/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/README.md +++ b/examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # MCPWM FOC SVPWM Generation Open Loop Example diff --git a/examples/peripherals/mcpwm/mcpwm_servo_control/README.md b/examples/peripherals/mcpwm/mcpwm_servo_control/README.md index 18cf4f774f..28289fa1c3 100644 --- a/examples/peripherals/mcpwm/mcpwm_servo_control/README.md +++ b/examples/peripherals/mcpwm/mcpwm_servo_control/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # MCPWM RC Servo Control Example (See the README.md file in the upper level 'examples' directory for more information about examples.) diff --git a/examples/peripherals/mcpwm/mcpwm_sync/README.md b/examples/peripherals/mcpwm/mcpwm_sync/README.md index f0c79f0eab..75bbae4cf7 100644 --- a/examples/peripherals/mcpwm/mcpwm_sync/README.md +++ b/examples/peripherals/mcpwm/mcpwm_sync/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # MCPWM Sync Example