728 lines
23 KiB
C
728 lines
23 KiB
C
|
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* NOTICE
|
||
|
* The hal is not public api, don't use in application code.
|
||
|
* See readme.md in soc/include/hal/readme.md
|
||
|
******************************************************************************/
|
||
|
|
||
|
// The LL layer for ESP32 MCPWM register operations
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <soc/mcpwm_periph.h>
|
||
|
#include "soc/mcpwm_periph.h"
|
||
|
#include "hal/mcpwm_types.h"
|
||
|
#include "soc/mcpwm_caps.h"
|
||
|
#include "hal/hal_defs.h"
|
||
|
|
||
|
#include "esp_types.h"
|
||
|
|
||
|
/// Get the address of peripheral registers
|
||
|
#define MCPWM_LL_GET_HW(ID) (((ID)==0)? &MCPWM0: &MCPWM1)
|
||
|
|
||
|
|
||
|
/********************* Global *******************/
|
||
|
/**
|
||
|
* Initialize common registers.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_init(mcpwm_dev_t *mcpwm)
|
||
|
{
|
||
|
mcpwm->update_cfg.global_up_en = 1;
|
||
|
mcpwm->update_cfg.global_force_up = 1;
|
||
|
mcpwm->update_cfg.global_force_up = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the prescale of the PWM main clock to the input clock.
|
||
|
*
|
||
|
* Input clock is 160MHz, PWM main clock cycle = 6.25ns*(prescale + 1).
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param prescale Prescale factor, 0-255.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_set_clock_prescale(mcpwm_dev_t *mcpwm, int prescale)
|
||
|
{
|
||
|
mcpwm->clk_cfg.prescale = prescale;
|
||
|
}
|
||
|
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_LL_INTR_CAP0, MCPWM_CAP0_INT_RAW);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_LL_INTR_CAP1, MCPWM_CAP1_INT_RAW);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_LL_INTR_CAP2, MCPWM_CAP2_INT_RAW);
|
||
|
|
||
|
/**
|
||
|
* Get raw interrupt status.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @return The triggered interrupts, ORed by active interrupts.
|
||
|
*/
|
||
|
static inline mcpwm_intr_t mcpwm_ll_get_intr(mcpwm_dev_t *mcpwm)
|
||
|
{
|
||
|
return mcpwm->int_raw.val;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear the interrupts.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param intr Bitwise ORed interrupts to clear.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_clear_intr(mcpwm_dev_t* mcpwm, mcpwm_intr_t intr)
|
||
|
{
|
||
|
mcpwm->int_clr.val = intr;
|
||
|
}
|
||
|
|
||
|
/********************* Timer *******************/
|
||
|
/**
|
||
|
* Set the prescale of the Timer_x clock to the PWM main clock.
|
||
|
*
|
||
|
* Timer clock frequency = PWM main clock frequency/(prescale + 1).
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer The timer to set the prescale, 0-2.
|
||
|
* @param prescale Prescale factor, 0-255.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_timer_set_prescale(mcpwm_dev_t* mcpwm, int timer, uint32_t prescale)
|
||
|
{
|
||
|
mcpwm->timer[timer].period.prescale = prescale;
|
||
|
}
|
||
|
|
||
|
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_UP_COUNTER, 1);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_DOWN_COUNTER, 2);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_UP_DOWN_COUNTER, 3);
|
||
|
|
||
|
/**
|
||
|
* Set the counting mode for the PWM timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer The timer to change counting mode, 0-2.
|
||
|
* @param mode Counting mode to use.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer, mcpwm_counter_type_t mode)
|
||
|
{
|
||
|
mcpwm->timer[timer].mode.mode = mode;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Start a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer The timer to start, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_timer_start(mcpwm_dev_t *mcpwm, int timer)
|
||
|
{
|
||
|
mcpwm->timer[timer].mode.start = 2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Stop a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer The timer to stop, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_timer_stop(mcpwm_dev_t *mcpwm, int timer)
|
||
|
{
|
||
|
mcpwm->timer[timer].mode.start = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the overflow period of a timer.
|
||
|
*
|
||
|
* The overflow rate will be Frequency of timer / period.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer The timer to set period, 0-2.
|
||
|
* @param period Total timer count of each period, 0-65535.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_timer_set_period(mcpwm_dev_t *mcpwm, int timer, uint32_t period)
|
||
|
{
|
||
|
|
||
|
mcpwm->timer[timer].period.period = period;
|
||
|
mcpwm->timer[timer].period.upmethod = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the period setting of a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer The timer to get the period, 0-2.
|
||
|
* @return Period setting value.
|
||
|
*/
|
||
|
static inline uint32_t mcpwm_ll_timer_get_period(mcpwm_dev_t *mcpwm, int timer)
|
||
|
{
|
||
|
return mcpwm->timer[timer].period.period;
|
||
|
}
|
||
|
|
||
|
/********************* Sync *******************/
|
||
|
/**
|
||
|
* Enable the synchronization feature for a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer Timer to set, 0-2.
|
||
|
* @param enable true to enable, otherwise false.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_sync_enable(mcpwm_dev_t *mcpwm, int timer, bool enable)
|
||
|
{
|
||
|
if (enable) {
|
||
|
mcpwm->timer[timer].sync.out_sel = 0;
|
||
|
mcpwm->timer[timer].sync.in_en = 1;
|
||
|
} else {
|
||
|
mcpwm->timer[timer].sync.in_en = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the phase (counter value) to reload when the sync signal triggers.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer Timer to set, 0-2.
|
||
|
* @param reload_val The reloaded value.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_sync_set_phase(mcpwm_dev_t *mcpwm, int timer, uint32_t reload_val)
|
||
|
{
|
||
|
mcpwm->timer[timer].sync.timer_phase = reload_val;
|
||
|
}
|
||
|
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_SELECT_SYNC0, 4);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_SELECT_SYNC1, 5);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_SELECT_SYNC2, 6);
|
||
|
/**
|
||
|
* Set the sync signal source for a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param timer The timer to set, 0-2.
|
||
|
* @param sync_sig The synchronization signal to use.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_sync_set_input(mcpwm_dev_t *mcpwm, int timer, mcpwm_sync_signal_t sync_sig)
|
||
|
{
|
||
|
if (timer == 0) {
|
||
|
mcpwm->timer_synci_cfg.t0_in_sel = sync_sig;
|
||
|
} else if (timer == 1) {
|
||
|
mcpwm->timer_synci_cfg.t1_in_sel = sync_sig;
|
||
|
} else { //MCPWM_TIMER_2
|
||
|
mcpwm->timer_synci_cfg.t2_in_sel = sync_sig;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/********************* Comparator *******************/
|
||
|
/**
|
||
|
* Select a timer for the specified operator to use.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to choose timer, 0-2.
|
||
|
* @param timer The timer to use, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int op, int timer)
|
||
|
{
|
||
|
if (op == 0) {
|
||
|
mcpwm->timer_sel.operator0_sel = timer;
|
||
|
} else if (op == 1) {
|
||
|
mcpwm->timer_sel.operator1_sel = timer;
|
||
|
} else {
|
||
|
mcpwm->timer_sel.operator2_sel = timer;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the update method of the compare value of a timer
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op Operator to set, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_operator_set_compare_upmethod(mcpwm_dev_t *mcpwm, int op)
|
||
|
{
|
||
|
mcpwm->channel[op].cmpr_cfg.a_upmethod = BIT(0);
|
||
|
mcpwm->channel[op].cmpr_cfg.b_upmethod = BIT(0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get one of the compare value of a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to get, 0-2.
|
||
|
* @param cmp_n Comparer id to get, 0-1.
|
||
|
* @return The set compare value.
|
||
|
*/
|
||
|
static inline uint32_t mcpwm_ll_operator_get_compare(mcpwm_dev_t *mcpwm, int op, int cmp_n)
|
||
|
{
|
||
|
return (mcpwm->channel[op].cmpr_value[cmp_n].cmpr_val);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set one of the compare value of a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param cmp_n The comparer to set value, 0-1.
|
||
|
* @param compare The compare value, 0-65535.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_operator_set_compare(mcpwm_dev_t *mcpwm, int op, int cmp_n, uint32_t compare)
|
||
|
{
|
||
|
mcpwm->channel[op].cmpr_value[cmp_n].cmpr_val = compare;
|
||
|
}
|
||
|
|
||
|
/********************* Generator *******************/
|
||
|
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_NO_CHANGE, 0);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_FORCE_LOW, 1);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_FORCE_HIGH, 2);
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_ACTION_TOGGLE, 3);
|
||
|
/**
|
||
|
* Set the action will be taken by a operator when its timer counts to zero.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set action, 0-2.
|
||
|
* @param gen One generator of the operator to take the action, 0-1.
|
||
|
* @param action Action to take.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_gen_set_zero_action(mcpwm_dev_t *mcpwm, int op, int gen, mcpwm_output_action_t action)
|
||
|
{
|
||
|
mcpwm->channel[op].generator[gen].utez = action;
|
||
|
mcpwm->channel[op].generator[gen].dtez = action;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the action will be taken by a operator when its timer counts to the period value.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set action, 0-2.
|
||
|
* @param gen One generator of the operator to take the action, 0-1.
|
||
|
* @param action Action to take.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_gen_set_period_action(mcpwm_dev_t *mcpwm, int op, int gen, mcpwm_output_action_t action)
|
||
|
{
|
||
|
mcpwm->channel[op].generator[gen].utep = action;
|
||
|
mcpwm->channel[op].generator[gen].dtep = action;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the action will be taken by a operator when its timer counts to the compare value.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set action, 0-2.
|
||
|
* @param gen One generator of the operator to take the action, 0-1.
|
||
|
* @param cmp_n The comparer to use.
|
||
|
* @param up_action The action to take when the counter is counting up.
|
||
|
* @param down_action The action to take when the counter is counting down.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_gen_set_cmp_action(mcpwm_dev_t *mcpwm, int op, int gen,
|
||
|
int cmp_n, mcpwm_output_action_t up_action, mcpwm_output_action_t down_action)
|
||
|
{
|
||
|
if (cmp_n == 0) {
|
||
|
mcpwm->channel[op].generator[gen].utea = up_action;
|
||
|
mcpwm->channel[op].generator[gen].dtea = down_action;
|
||
|
} else {
|
||
|
mcpwm->channel[op].generator[gen].uteb = up_action;
|
||
|
mcpwm->channel[op].generator[gen].dteb = down_action;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/********************* Fault *******************/
|
||
|
/**
|
||
|
* Enable the fault detection feature for an input signal.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param fault_sig One of the signals to select, 0-2.
|
||
|
* @param level The active level of the fault-detection signal.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_fault_enable(mcpwm_dev_t *mcpwm, int fault_sig, bool level)
|
||
|
{
|
||
|
if (fault_sig == 0) {
|
||
|
mcpwm->fault_detect.f0_en = 1;
|
||
|
mcpwm->fault_detect.f0_pole = level;
|
||
|
} else if (fault_sig == 1) {
|
||
|
mcpwm->fault_detect.f1_en = 1;
|
||
|
mcpwm->fault_detect.f1_pole = level;
|
||
|
} else { //MCPWM_SELECT_F2
|
||
|
mcpwm->fault_detect.f2_en = 1;
|
||
|
mcpwm->fault_detect.f2_pole = level;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Disable the fault detection of an input signal.
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param fault_sig The signal to disable, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_fault_disable(mcpwm_dev_t *mcpwm, int fault_sig)
|
||
|
{
|
||
|
if (fault_sig == 0) {
|
||
|
mcpwm->fault_detect.f0_en = 0;
|
||
|
} else if (fault_sig == 1) {
|
||
|
mcpwm->fault_detect.f1_en = 0;
|
||
|
} else { //MCPWM_SELECT_F2
|
||
|
mcpwm->fault_detect.f2_en = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear the oneshot fault status of an operator.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to clear, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int op)
|
||
|
{
|
||
|
mcpwm->channel[op].tz_cfg1.clr_ost = 1;
|
||
|
mcpwm->channel[op].tz_cfg1.clr_ost = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Use the oneshot mode to handle the fault when it occurs
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to handle the fault signal, 0-2.
|
||
|
* @param signal The fault signal to set, 0-2.
|
||
|
* @param enable true to enable oneshot, otherwise false.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_fault_oneshot_enable_signal(mcpwm_dev_t *mcpwm, int op, int signal, bool enable)
|
||
|
{
|
||
|
if (signal == 0) {
|
||
|
mcpwm->channel[op].tz_cfg0.f0_ost = enable;
|
||
|
} else if (signal == 1) {
|
||
|
mcpwm->channel[op].tz_cfg0.f1_ost = enable;
|
||
|
} else { //MCPWM_SELECT_F2
|
||
|
mcpwm->channel[op].tz_cfg0.f2_ost = enable;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get the oneshot enabled status of the operator
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to check, 0-2.
|
||
|
* @param signal The fault signal to get, 0-2.
|
||
|
*/
|
||
|
static inline bool mcpwm_ll_fault_oneshot_signal_enabled(mcpwm_dev_t *mcpwm, int op, int signal)
|
||
|
{
|
||
|
if (signal == 0) {
|
||
|
return mcpwm->channel[op].tz_cfg0.f0_ost;
|
||
|
} else if (signal == 1) {
|
||
|
return mcpwm->channel[op].tz_cfg0.f1_ost;
|
||
|
} else { //MCPWM_SELECT_F2
|
||
|
return mcpwm->channel[op].tz_cfg0.f2_ost;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Use the CBC (cycle-by-cycle) mode to handle the fault when it occurs.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to handle the fault signal, 0-2.
|
||
|
* @param signal The fault signal to set, 0-2.
|
||
|
* @param enable true to enable cbc mode, otherwise false.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_fault_cbc_enable_signal(mcpwm_dev_t *mcpwm, int op, int signal, bool enable)
|
||
|
{
|
||
|
if (signal == 0) {
|
||
|
mcpwm->channel[op].tz_cfg0.f0_cbc = enable;
|
||
|
} else if (signal == 1) {
|
||
|
mcpwm->channel[op].tz_cfg0.f1_cbc = enable;
|
||
|
} else { //MCPWM_SELECT_F2
|
||
|
mcpwm->channel[op].tz_cfg0.f2_cbc = enable;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the action that will be taken when the fault is handled by oneshot.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to handle the fault signal, 0-2.
|
||
|
* @param gen The generator to take the action, 0-1.
|
||
|
* @param up_action Action to take when fault happens when counting up.
|
||
|
* @param down_action Action to take when fault happens when counting down.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_fault_set_oneshot_action(mcpwm_dev_t *mcpwm, int op, int gen,
|
||
|
mcpwm_output_action_t up_action, mcpwm_output_action_t down_action)
|
||
|
{
|
||
|
if (gen == 0) {
|
||
|
mcpwm->channel[op].tz_cfg0.a_ost_u = up_action;
|
||
|
mcpwm->channel[op].tz_cfg0.a_ost_d = down_action;
|
||
|
} else {
|
||
|
mcpwm->channel[op].tz_cfg0.b_ost_u = up_action;
|
||
|
mcpwm->channel[op].tz_cfg0.b_ost_d = down_action;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the action that will be taken when the fault is handled cycle by cycle.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to handle the fault signal, 0-2.
|
||
|
* @param gen The generator to take the action, 0-1.
|
||
|
* @param up_action Action to take when fault happens when counting up.
|
||
|
* @param down_action Action to take when fault happens when counting down.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_fault_set_cyc_action(mcpwm_dev_t *mcpwm, int op, int gen,
|
||
|
mcpwm_output_action_t up_action, mcpwm_output_action_t down_action)
|
||
|
{
|
||
|
mcpwm->channel[op].tz_cfg1.cbcpulse = BIT(0); //immediately
|
||
|
if (gen == 0) {
|
||
|
mcpwm->channel[op].tz_cfg0.a_cbc_u = up_action;
|
||
|
mcpwm->channel[op].tz_cfg0.a_cbc_d = down_action;
|
||
|
} else {
|
||
|
mcpwm->channel[op].tz_cfg0.b_cbc_u = up_action;
|
||
|
mcpwm->channel[op].tz_cfg0.b_cbc_d = down_action;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/********************* Dead Zone (deadtime) *******************/
|
||
|
/**
|
||
|
* Initialize the dead zone feature.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to initialize, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_deadtime_init(mcpwm_dev_t *mcpwm, int op)
|
||
|
{
|
||
|
mcpwm->channel[op].db_cfg.fed_upmethod = BIT(0);
|
||
|
mcpwm->channel[op].db_cfg.red_upmethod = BIT(0);
|
||
|
mcpwm->channel[op].db_cfg.clk_sel = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the output dead zone mode applying to the outputs of a timer.
|
||
|
*
|
||
|
* If the desired internal connection is not provided, you can write your own inside this function.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param mode Dead zone mode to use.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_set_deadtime_mode(mcpwm_dev_t *mcpwm,
|
||
|
int op, mcpwm_deadtime_type_t mode)
|
||
|
{
|
||
|
#define MCPWM_LL_DEADTIME_REG_MASK (MCPWM_DT0_DEB_MODE_M | MCPWM_DT0_A_OUTSWAP_M | MCPWM_DT0_B_OUTSWAP_M | \
|
||
|
MCPWM_DT0_RED_INSEL_M | MCPWM_DT0_FED_INSEL_M | MCPWM_DT0_RED_OUTINVERT_M | MCPWM_DT0_FED_OUTINVERT_M | \
|
||
|
MCPWM_DT0_A_OUTBYPASS_M | MCPWM_DT0_B_OUTBYPASS_M)
|
||
|
|
||
|
static uint32_t deadtime_mode_settings[MCPWM_DEADTIME_TYPE_MAX] = {
|
||
|
[MCPWM_BYPASS_RED] = 0b010010000 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_BYPASS_FED] = 0b100000000 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_ACTIVE_HIGH_MODE] = 0b000010000 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_ACTIVE_LOW_MODE] = 0b001110000 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE] = 0b001010000 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_ACTIVE_LOW_COMPLIMENT_MODE] = 0b000101000 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_ACTIVE_RED_FED_FROM_PWMXA] = 0b000000011 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_ACTIVE_RED_FED_FROM_PWMXB] = 0b000001011 << MCPWM_DT0_DEB_MODE_S,
|
||
|
[MCPWM_DEADTIME_BYPASS] = 0b110000000 << MCPWM_DT0_DEB_MODE_S,
|
||
|
};
|
||
|
mcpwm->channel[op].db_cfg.val =
|
||
|
(mcpwm->channel[op].db_cfg.val & (~MCPWM_LL_DEADTIME_REG_MASK)) | deadtime_mode_settings[mode];
|
||
|
|
||
|
#undef MCPWM_LL_DEADTIME_REG_MASK
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the delay of the falling edge on the output.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param fed Falling delay, by PWM main clock.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int op, uint32_t fed)
|
||
|
{
|
||
|
mcpwm->channel[op].db_fed_cfg.fed = fed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the delay of the rising edge on the output.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param fed Rising delay, by PWM main clock.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int op, uint32_t red)
|
||
|
{
|
||
|
mcpwm->channel[op].db_red_cfg.red = red;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Disable (bypass) the dead zone feature.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_deadtime_bypass(mcpwm_dev_t *mcpwm, int op)
|
||
|
{
|
||
|
mcpwm_ll_set_deadtime_mode(mcpwm, op, MCPWM_DEADTIME_BYPASS);
|
||
|
}
|
||
|
|
||
|
/********************* Carrier *******************/
|
||
|
/**
|
||
|
* Initialize the carrier feature.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_carrier_init(mcpwm_dev_t *mcpwm, int op)
|
||
|
{
|
||
|
mcpwm->channel[op].carrier_cfg.in_invert = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enable the carrier feature for a timer.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param enable true to enable, otherwise false.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int op, bool enable)
|
||
|
{
|
||
|
mcpwm->channel[op].carrier_cfg.en = enable;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the prescale of the carrier timer.
|
||
|
*
|
||
|
* The carrier period will be Frequency of PWM main clock/(carrier_period+1).
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param carrier_period The prescale of the carrier clock, 0-15.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int op, uint8_t carrier_period)
|
||
|
{
|
||
|
mcpwm->channel[op].carrier_cfg.prescale = carrier_period;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the duty rate of the carrier.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param carrier_duty Duty rate will be (carrier_duty/8)*100%. 0-7.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int op, uint8_t carrier_duty)
|
||
|
{
|
||
|
mcpwm->channel[op].carrier_cfg.duty = carrier_duty;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Invert output of the carrier.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param invert true to invert, otherwise false.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int op, bool invert)
|
||
|
{
|
||
|
mcpwm->channel[op].carrier_cfg.out_invert = invert;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the oneshot pulse width of the carrier.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param op The operator to set, 0-2.
|
||
|
* @param pulse_width The width of the oneshot pulse, by carrier period. 0 to disable the oneshot pulse.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int op, uint8_t pulse_width)
|
||
|
{
|
||
|
mcpwm->channel[op].carrier_cfg.oshtwth = pulse_width;
|
||
|
}
|
||
|
|
||
|
/********************* Capture *******************/
|
||
|
/**
|
||
|
* Enable the capture feature for a signal
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param cap_sig Signal to enable, 0-2.
|
||
|
* @param enable true to enable, otherwise false.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_capture_enable(mcpwm_dev_t *mcpwm, int cap_sig, int enable)
|
||
|
{
|
||
|
if (enable) {
|
||
|
mcpwm->cap_timer_cfg.timer_en = 1;
|
||
|
mcpwm->cap_cfg_ch[cap_sig].en = 1;
|
||
|
} else {
|
||
|
mcpwm->cap_cfg_ch[cap_sig].en = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the captured value.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param cap_sig Of which signal to get the captured value.
|
||
|
* @return The captured value
|
||
|
*/
|
||
|
static inline uint32_t mcpwm_ll_get_capture_val(mcpwm_dev_t *mcpwm, int cap_sig)
|
||
|
{
|
||
|
return mcpwm->cap_val_ch[cap_sig];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the set capture edge.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param cap_sig Which signal the edge capture is applied.
|
||
|
* @return Capture signal edge: 1 - positive edge, 2 - negtive edge
|
||
|
*/
|
||
|
static inline mcpwm_capture_on_edge_t mcpwm_ll_get_captured_edge(mcpwm_dev_t *mcpwm, int cap_sig)
|
||
|
{
|
||
|
bool edge;
|
||
|
if (cap_sig == 0) {
|
||
|
edge = mcpwm->cap_status.cap0_edge;
|
||
|
} else if (cap_sig == 1) {
|
||
|
edge = mcpwm->cap_status.cap0_edge;
|
||
|
} else { //2
|
||
|
edge = mcpwm->cap_status.cap0_edge;
|
||
|
}
|
||
|
return (edge? MCPWM_NEG_EDGE: MCPWM_POS_EDGE);
|
||
|
}
|
||
|
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_NEG_EDGE, BIT(0));
|
||
|
STATIC_HAL_REG_CHECK(MCPWM, MCPWM_POS_EDGE, BIT(1));
|
||
|
|
||
|
/**
|
||
|
* Select the edge to capture.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param cap_sig The signal to capture, 0-2.
|
||
|
* @param cap_edge The edge to capture, bitwise.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_capture_select_edge(mcpwm_dev_t *mcpwm, int cap_sig,
|
||
|
mcpwm_capture_on_edge_t cap_edge)
|
||
|
{
|
||
|
mcpwm->cap_cfg_ch[cap_sig].mode = cap_edge;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the prescale of the input signal to capture.
|
||
|
*
|
||
|
* @param mcpwm Address of the MCPWM peripheral registers.
|
||
|
* @param cap_sig The prescaled signal to capture, 0-2.
|
||
|
* @param prescale Prescal value, 0 to disable.
|
||
|
*/
|
||
|
static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int cap_sig, uint32_t prescale)
|
||
|
{
|
||
|
mcpwm->cap_cfg_ch[cap_sig].prescale = prescale;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Utility function, get the `mcpwm_intr_t` interrupt enum of a specific capture signal.
|
||
|
*
|
||
|
* @param bit x for CAPx.
|
||
|
* @return the corresponding `mcpwm_intr_t`.
|
||
|
*/
|
||
|
static inline mcpwm_intr_t mcpwm_ll_get_cap_intr_def(int bit)
|
||
|
{
|
||
|
return BIT(bit+MCPWM_CAP0_INT_RAW_S);
|
||
|
}
|