mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
0cbcb9f5ea
Implement the requirement asked in https://www.esp32.com/viewtopic.php?f=13&t=35919
1703 lines
57 KiB
C
1703 lines
57 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* NOTICE
|
|
* The hal is not public api, don't use in application code.
|
|
* See readme.md in hal/include/hal/readme.md
|
|
******************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#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
|
|
|
|
// Get MCPWM group register base address
|
|
#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : NULL)
|
|
|
|
// 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 [1][MCPWM_CMPR_ETM_EVENT_MAX]){{ \
|
|
[MCPWM_CMPR_ETM_EVENT_EQUAL] = MCPWM_EVT_OP0_TEA + 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)
|
|
{
|
|
(void)group_id;
|
|
PCR.pwm_conf.pwm_clk_en = enable;
|
|
}
|
|
|
|
/**
|
|
* @brief Reset the MCPWM module
|
|
*
|
|
* @param group_id Group ID
|
|
*/
|
|
static inline void mcpwm_ll_reset_register(int group_id)
|
|
{
|
|
(void)group_id;
|
|
PCR.pwm_conf.pwm_rst_en = 1;
|
|
PCR.pwm_conf.pwm_rst_en = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the clock source for MCPWM
|
|
*
|
|
* @param mcpwm Peripheral instance address
|
|
* @param clk_src Clock source for the MCPWM peripheral
|
|
*/
|
|
static inline void mcpwm_ll_group_set_clock_source(mcpwm_dev_t *mcpwm, soc_module_clk_t clk_src)
|
|
{
|
|
(void)mcpwm; // only one MCPWM instance
|
|
switch (clk_src) {
|
|
case SOC_MOD_CLK_XTAL:
|
|
PCR.pwm_clk_conf.pwm_clkm_sel = 0;
|
|
break;
|
|
case SOC_MOD_CLK_PLL_F96M:
|
|
PCR.pwm_clk_conf.pwm_clkm_sel = 2;
|
|
break;
|
|
default:
|
|
HAL_ASSERT(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Enable MCPWM module clock
|
|
*
|
|
* @param mcpwm Peripheral instance address
|
|
* @param en true to enable, false to disable
|
|
*/
|
|
static inline void mcpwm_ll_group_enable_clock(mcpwm_dev_t *mcpwm, bool en)
|
|
{
|
|
(void)mcpwm; // only one MCPWM instance
|
|
PCR.pwm_clk_conf.pwm_clkm_en = en;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the MCPWM group clock prescale
|
|
*
|
|
* @param mcpwm Peripheral instance address
|
|
* @param prescale Prescale value
|
|
*/
|
|
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int prescale)
|
|
{
|
|
(void)mcpwm; // only one MCPWM instance
|
|
// group clock: PWM_clk = source_clock / (prescale)
|
|
HAL_ASSERT(prescale <= 256 && prescale > 0);
|
|
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.pwm_clk_conf, pwm_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 Interupt 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].timer_cfg0, timer_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].timer_cfg0, timer_period, peak - 1);
|
|
} else { // in symmetric mode, period = [0,peak-1] + [peak,1]
|
|
HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_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].timer_cfg0.timer_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].timer_cfg0.timer_period_upmethod |= 0x01;
|
|
} else {
|
|
mcpwm->timer[timer_id].timer_cfg0.timer_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].timer_cfg0.timer_period_upmethod |= 0x02;
|
|
} else {
|
|
mcpwm->timer[timer_id].timer_cfg0.timer_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].timer_cfg1.timer_mod = 0;
|
|
break;
|
|
case MCPWM_TIMER_COUNT_MODE_UP:
|
|
mcpwm->timer[timer_id].timer_cfg1.timer_mod = 1;
|
|
break;
|
|
case MCPWM_TIMER_COUNT_MODE_DOWN:
|
|
mcpwm->timer[timer_id].timer_cfg1.timer_mod = 2;
|
|
break;
|
|
case MCPWM_TIMER_COUNT_MODE_UP_DOWN:
|
|
mcpwm->timer[timer_id].timer_cfg1.timer_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].timer_cfg1.timer_start = 0;
|
|
break;
|
|
case MCPWM_TIMER_STOP_FULL:
|
|
mcpwm->timer[timer_id].timer_cfg1.timer_start = 1;
|
|
break;
|
|
case MCPWM_TIMER_START_NO_STOP:
|
|
mcpwm->timer[timer_id].timer_cfg1.timer_start = 2;
|
|
break;
|
|
case MCPWM_TIMER_START_STOP_EMPTY:
|
|
mcpwm->timer[timer_id].timer_cfg1.timer_start = 3;
|
|
break;
|
|
case MCPWM_TIMER_START_STOP_FULL:
|
|
mcpwm->timer[timer_id].timer_cfg1.timer_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].timer_cfg1.timer_mod == 0) {
|
|
return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value);
|
|
}
|
|
if (mcpwm->timer[timer_id].timer_status.timer_direction) { // down direction
|
|
return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value) + 1) %
|
|
(HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1);
|
|
}
|
|
// up direction
|
|
return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value) +
|
|
HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period)) %
|
|
(HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_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].timer_status.timer_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].timer_sync.timer_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].timer_sync.timer_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].timer_sync.timer_synco_sel = 1;
|
|
break;
|
|
case MCPWM_TIMER_EVENT_FULL:
|
|
mcpwm->timer[timer_id].timer_sync.timer_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].timer_sync.timer_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].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_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].timer_sync, timer_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].timer_sync.timer_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], cmpr, 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.gen_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.gen_cfg_upmethod |= 1 << 0;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_cfg0.gen_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.gen_cfg_upmethod |= 1 << 1;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_cfg0.gen_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.gen_cfg_upmethod |= 1 << 2;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_cfg0.gen_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.gen_cfg_upmethod |= 1 << 3;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_cfg0.gen_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.gen_a_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_a_nciforce;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_force.gen_b_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_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.gen_cntuforce_upmethod = 0; // update force method immediately
|
|
if (generator_id == 0) {
|
|
mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = 0;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_force.gen_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.gen_a_nciforce_mode = 0;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_force.gen_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.gen_cntuforce_upmethod = 0; // update force method immediately
|
|
if (generator_id == 0) {
|
|
mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = level + 1;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_force.gen_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.gen_a_nciforce_mode = level + 1;
|
|
} else {
|
|
mcpwm->operators[operator_id].gen_force.gen_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.db_clk_sel = 0;
|
|
break;
|
|
case MCPWM_LL_DEADTIME_CLK_SRC_TIMER:
|
|
mcpwm->operators[operator_id].dt_cfg.db_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.db_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.db_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.db_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.db_deb_mode << 8) | (mcpwm->operators[operator_id].dt_cfg.db_b_outswap << 7) |
|
|
(mcpwm->operators[operator_id].dt_cfg.db_a_outswap << 6) | (mcpwm->operators[operator_id].dt_cfg.db_fed_insel << 5) |
|
|
(mcpwm->operators[operator_id].dt_cfg.db_red_insel << 4) | (mcpwm->operators[operator_id].dt_cfg.db_fed_outinvert << 3) |
|
|
(mcpwm->operators[operator_id].dt_cfg.db_red_outinvert << 2) | (mcpwm->operators[operator_id].dt_cfg.db_a_outbypass << 1) |
|
|
(mcpwm->operators[operator_id].dt_cfg.db_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, db_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, db_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.db_fed_upmethod = 0;
|
|
mcpwm->operators[operator_id].dt_cfg.db_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.db_fed_upmethod |= 1 << 0;
|
|
mcpwm->operators[operator_id].dt_cfg.db_red_upmethod |= 1 << 0;
|
|
} else {
|
|
mcpwm->operators[operator_id].dt_cfg.db_fed_upmethod &= ~(1 << 0);
|
|
mcpwm->operators[operator_id].dt_cfg.db_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.db_fed_upmethod |= 1 << 1;
|
|
mcpwm->operators[operator_id].dt_cfg.db_red_upmethod |= 1 << 1;
|
|
} else {
|
|
mcpwm->operators[operator_id].dt_cfg.db_fed_upmethod &= ~(1 << 1);
|
|
mcpwm->operators[operator_id].dt_cfg.db_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.db_fed_upmethod |= 1 << 2;
|
|
mcpwm->operators[operator_id].dt_cfg.db_red_upmethod |= 1 << 2;
|
|
} else {
|
|
mcpwm->operators[operator_id].dt_cfg.db_fed_upmethod &= ~(1 << 2);
|
|
mcpwm->operators[operator_id].dt_cfg.db_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.db_fed_upmethod |= 1 << 3;
|
|
mcpwm->operators[operator_id].dt_cfg.db_red_upmethod |= 1 << 3;
|
|
} else {
|
|
mcpwm->operators[operator_id].dt_cfg.db_fed_upmethod &= ~(1 << 3);
|
|
mcpwm->operators[operator_id].dt_cfg.db_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.chopper_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.chopper_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.chopper_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.chopper_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.chopper_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.chopper_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.tz_clr_ost = 0;
|
|
mcpwm->operators[operator_id].fh_cfg1.tz_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.tz_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.tz_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.tz_force_cbc = ~mcpwm->operators[operator_id].fh_cfg1.tz_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.tz_force_ost = ~mcpwm->operators[operator_id].fh_cfg1.tz_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.tz_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.tz_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)) ;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
|
|
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
|
|
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm)
|
|
{
|
|
(void)mcpwm; // only one MCPWM instance
|
|
return HAL_FORCE_READ_U32_REG_FIELD(PCR.pwm_clk_conf, pwm_div_num) + 1;
|
|
}
|
|
|
|
static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id)
|
|
{
|
|
mcpwm_timer_cfg0_reg_t cfg0;
|
|
cfg0.val = mcpwm->timer[timer_id].timer_cfg0.val;
|
|
return cfg0.timer_prescale + 1;
|
|
}
|
|
|
|
static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, bool symmetric)
|
|
{
|
|
return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + (symmetric ? 0 : 1);
|
|
}
|
|
|
|
static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id)
|
|
{
|
|
switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) {
|
|
case 1:
|
|
return MCPWM_TIMER_COUNT_MODE_UP;
|
|
case 2:
|
|
return MCPWM_TIMER_COUNT_MODE_DOWN;
|
|
case 3:
|
|
return MCPWM_TIMER_COUNT_MODE_UP_DOWN;
|
|
case 0:
|
|
default:
|
|
return MCPWM_TIMER_COUNT_MODE_PAUSE;
|
|
}
|
|
}
|
|
|
|
static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id)
|
|
{
|
|
return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], cmpr);
|
|
}
|
|
|
|
__attribute__((always_inline))
|
|
static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm)
|
|
{
|
|
return (mcpwm->int_st.val >> 27) & 0x07;
|
|
}
|
|
|
|
__attribute__((always_inline))
|
|
static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask)
|
|
{
|
|
mcpwm->int_clr.val = (capture_mask & 0x07) << 27;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|