2021-05-23 20:09:38 -04:00
/*
2024-03-19 03:51:15 -04:00
* SPDX - FileCopyrightText : 2015 - 2024 Espressif Systems ( Shanghai ) CO LTD
2021-05-23 20:09:38 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
2017-03-29 04:39:35 -04:00
2021-01-07 04:36:54 -05:00
# include "sdkconfig.h"
2017-03-29 04:39:35 -04:00
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
2021-01-07 04:36:54 -05:00
# include "esp_log.h"
# include "esp_err.h"
# include "esp_check.h"
# include "esp_rom_gpio.h"
2022-05-28 05:02:07 -04:00
# include "esp_intr_alloc.h"
2021-01-07 04:36:54 -05:00
# include "soc/mcpwm_periph.h"
2024-03-19 03:51:15 -04:00
# include "soc/io_mux_reg.h"
2019-11-17 07:53:29 -05:00
# include "hal/mcpwm_hal.h"
2021-03-15 22:55:05 -04:00
# include "hal/gpio_hal.h"
2021-01-07 04:36:54 -05:00
# include "hal/mcpwm_ll.h"
2022-05-28 05:02:07 -04:00
# include "driver/mcpwm_types_legacy.h"
2022-05-28 05:27:02 -04:00
# include "driver/gpio.h"
2021-10-25 05:13:46 -04:00
# include "esp_private/periph_ctrl.h"
2024-03-19 03:51:15 -04:00
# include "esp_private/gpio.h"
2022-09-05 02:40:58 -04:00
# include "esp_private/esp_clk.h"
2024-03-19 03:51:15 -04:00
# include "esp_clk_tree.h"
2017-03-29 04:39:35 -04:00
2022-05-28 05:02:07 -04:00
static const char * TAG = " mcpwm(legacy) " ;
2017-03-29 04:39:35 -04:00
2022-07-20 06:18:47 -04:00
_Static_assert ( MCPWM_UNIT_MAX = = SOC_MCPWM_GROUPS , " MCPWM unit number not equal to chip capabilities " ) ;
2019-11-17 07:53:29 -05:00
# define MCPWM_DRIVER_INIT_ERROR "MCPWM DRIVER NOT INITIALIZED"
2021-01-07 04:34:59 -05:00
# define MCPWM_GROUP_NUM_ERROR "MCPWM GROUP NUM ERROR"
2021-05-10 03:18:29 -04:00
# define MCPWM_PRESCALE_ERROR "MCPWM PRESCALE ERROR"
2017-03-29 04:39:35 -04:00
# define MCPWM_TIMER_ERROR "MCPWM TIMER NUM ERROR"
2021-01-07 04:34:59 -05:00
# define MCPWM_CAPTURE_ERROR "MCPWM CAPTURE NUM ERROR"
2017-03-29 04:39:35 -04:00
# define MCPWM_PARAM_ADDR_ERROR "MCPWM PARAM ADDR ERROR"
# define MCPWM_DUTY_TYPE_ERROR "MCPWM DUTY TYPE ERROR"
# define MCPWM_GPIO_ERROR "MCPWM GPIO NUM ERROR"
2019-11-17 07:53:29 -05:00
# define MCPWM_GEN_ERROR "MCPWM GENERATOR ERROR"
2021-01-07 04:34:59 -05:00
# define MCPWM_DT_ERROR "MCPWM DEADTIME TYPE ERROR"
2021-07-13 08:13:17 -04:00
# define MCPWM_CAP_EXIST_ERROR "MCPWM USER CAP INT SERVICE ALREADY EXISTS"
2017-03-29 04:39:35 -04:00
2022-05-28 05:27:02 -04:00
# ifdef CONFIG_MCPWM_ISR_IRAM_SAFE
2021-08-25 05:45:46 -04:00
# define MCPWM_ISR_ATTR IRAM_ATTR
2022-05-28 05:27:02 -04:00
# define MCPWM_INTR_FLAG ESP_INTR_FLAG_IRAM
2021-08-25 05:45:46 -04:00
# else
# define MCPWM_ISR_ATTR
# define MCPWM_INTR_FLAG 0
# endif
2023-09-13 07:13:01 -04:00
# if SOC_PERIPH_CLK_CTRL_SHARED
# define MCPWM_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
# else
# define MCPWM_CLOCK_SRC_ATOMIC()
# endif
# if !SOC_RCC_IS_INDEPENDENT
# define MCPWM_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
# else
# define MCPWM_RCC_ATOMIC()
# endif
2023-01-06 01:17:04 -05:00
// Note: we can't modify the default MCPWM group resolution once it's determined
// otherwise we may break user's existing code which configures the dead-time based on this resolution, see `mcpwm_deadtime_enable`
# if CONFIG_IDF_TARGET_ESP32H2
# define MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ (12 * 1000 * 1000)
# else
# define MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ (10 * 1000 * 1000)
# endif
// Preset MCPWM Timer clock resolution (1MHz)
# define MCPWM_DEFAULT_TIMER_CLK_RESOLUTION_HZ (1 * 1000 * 1000)
2017-03-29 04:39:35 -04:00
2023-01-06 01:17:04 -05:00
ESP_STATIC_ASSERT ( SOC_MCPWM_OPERATORS_PER_GROUP > = SOC_MCPWM_TIMERS_PER_GROUP , " This driver assumes the timer num equals to the operator num. " ) ;
ESP_STATIC_ASSERT ( SOC_MCPWM_COMPARATORS_PER_OPERATOR > = SOC_MCPWM_GENERATORS_PER_OPERATOR , " This driver assumes the generator num equals to the generator num. " ) ;
ESP_STATIC_ASSERT ( SOC_MCPWM_GENERATORS_PER_OPERATOR = = 2 , " This driver assumes the generator num equals to 2. " ) ;
2019-11-17 07:53:29 -05:00
2021-01-07 04:36:54 -05:00
# define MCPWM_TIMER_ID_CHECK(mcpwm_num, timer_num) \
do { \
ESP_RETURN_ON_FALSE ( ( mcpwm_num ) < SOC_MCPWM_GROUPS , ESP_ERR_INVALID_ARG , TAG , MCPWM_GROUP_NUM_ERROR ) ; \
ESP_RETURN_ON_FALSE ( ( timer_num ) < SOC_MCPWM_TIMERS_PER_GROUP , ESP_ERR_INVALID_ARG , TAG , MCPWM_TIMER_ERROR ) ; \
} while ( 0 )
2019-11-17 07:53:29 -05:00
2021-01-07 04:36:54 -05:00
# define MCPWM_TIMER_CHECK(mcpwm_num, timer_num) \
do { \
MCPWM_TIMER_ID_CHECK ( mcpwm_num , timer_num ) ; \
ESP_RETURN_ON_FALSE ( context [ mcpwm_num ] . hal . dev , ESP_ERR_INVALID_STATE , TAG , MCPWM_DRIVER_INIT_ERROR ) ; \
} while ( 0 )
2019-11-17 07:53:29 -05:00
2021-01-07 04:36:54 -05:00
# define MCPWM_GEN_CHECK(mcpwm_num, timer_num, gen) \
do { \
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ; \
ESP_RETURN_ON_FALSE ( ( gen ) < MCPWM_GEN_MAX , ESP_ERR_INVALID_ARG , TAG , MCPWM_GEN_ERROR ) ; \
} while ( 0 )
2019-11-17 07:53:29 -05:00
2021-07-13 08:13:17 -04:00
typedef struct {
cap_isr_cb_t fn ; // isr function
void * args ; // isr function args
} cap_isr_func_t ;
2021-01-07 04:36:54 -05:00
typedef struct {
mcpwm_hal_context_t hal ;
portMUX_TYPE spinlock ;
2021-07-13 08:13:17 -04:00
_lock_t mutex_lock ;
const int group_id ;
2023-01-06 01:17:04 -05:00
int group_resolution_hz ;
int timer_resolution_hz [ SOC_MCPWM_TIMERS_PER_GROUP ] ;
2021-07-13 08:13:17 -04:00
intr_handle_t mcpwm_intr_handle ; // handler for ISR register, one per MCPWM group
cap_isr_func_t cap_isr_func [ SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER ] ; // handler for ISR callback, one for each cap ch
2023-09-13 07:13:01 -04:00
int module_ref_count ;
2021-01-07 04:36:54 -05:00
} mcpwm_context_t ;
2019-11-17 07:53:29 -05:00
2021-01-07 04:34:59 -05:00
static mcpwm_context_t context [ SOC_MCPWM_GROUPS ] = {
2022-05-28 05:27:02 -04:00
[ 0 ] = {
. hal = { MCPWM_LL_GET_HW ( 0 ) } ,
. spinlock = portMUX_INITIALIZER_UNLOCKED ,
. group_id = 0 ,
} ,
2022-09-20 03:34:45 -04:00
# if SOC_MCPWM_GROUPS > 1
2022-05-28 05:27:02 -04:00
[ 1 ] = {
. hal = { MCPWM_LL_GET_HW ( 1 ) } ,
. spinlock = portMUX_INITIALIZER_UNLOCKED ,
. group_id = 1 ,
2023-01-06 01:17:04 -05:00
} ,
2022-09-20 03:34:45 -04:00
# endif
2019-11-17 07:53:29 -05:00
} ;
2021-01-07 04:36:54 -05:00
typedef void ( * mcpwm_ll_gen_set_event_action_t ) ( mcpwm_dev_t * mcpwm , int op , int gen , int action ) ;
2019-11-17 07:53:29 -05:00
static inline void mcpwm_critical_enter ( mcpwm_unit_t mcpwm_num )
{
portENTER_CRITICAL ( & context [ mcpwm_num ] . spinlock ) ;
}
static inline void mcpwm_critical_exit ( mcpwm_unit_t mcpwm_num )
{
portEXIT_CRITICAL ( & context [ mcpwm_num ] . spinlock ) ;
}
2022-05-28 05:27:02 -04:00
static inline void mcpwm_mutex_lock ( mcpwm_unit_t mcpwm_num )
{
2021-07-13 08:13:17 -04:00
_lock_acquire ( & context [ mcpwm_num ] . mutex_lock ) ;
}
2022-05-28 05:27:02 -04:00
static inline void mcpwm_mutex_unlock ( mcpwm_unit_t mcpwm_num )
{
2021-07-13 08:13:17 -04:00
_lock_release ( & context [ mcpwm_num ] . mutex_lock ) ;
}
2023-09-13 07:13:01 -04:00
static void mcpwm_module_enable ( mcpwm_unit_t mcpwm_num )
{
mcpwm_critical_enter ( mcpwm_num ) ;
if ( context [ mcpwm_num ] . module_ref_count = = 0 ) {
MCPWM_RCC_ATOMIC ( ) {
mcpwm_ll_enable_bus_clock ( mcpwm_num , true ) ;
mcpwm_ll_reset_register ( mcpwm_num ) ;
}
2024-01-10 01:26:04 -05:00
MCPWM_CLOCK_SRC_ATOMIC ( ) {
mcpwm_ll_group_enable_clock ( mcpwm_num , true ) ;
}
2023-09-13 07:13:01 -04:00
}
context [ mcpwm_num ] . module_ref_count + + ;
mcpwm_critical_exit ( mcpwm_num ) ;
}
static void mcpwm_module_disable ( mcpwm_unit_t mcpwm_num )
{
mcpwm_critical_enter ( mcpwm_num ) ;
context [ mcpwm_num ] . module_ref_count - - ;
if ( context [ mcpwm_num ] . module_ref_count = = 0 ) {
MCPWM_RCC_ATOMIC ( ) {
mcpwm_ll_enable_bus_clock ( mcpwm_num , false ) ;
}
2024-01-10 01:26:04 -05:00
MCPWM_CLOCK_SRC_ATOMIC ( ) {
mcpwm_ll_group_enable_clock ( mcpwm_num , false ) ;
}
2023-09-13 07:13:01 -04:00
}
mcpwm_critical_exit ( mcpwm_num ) ;
}
2017-03-29 04:39:35 -04:00
esp_err_t mcpwm_gpio_init ( mcpwm_unit_t mcpwm_num , mcpwm_io_signals_t io_signal , int gpio_num )
{
2021-02-25 06:08:22 -05:00
if ( gpio_num < 0 ) { // ignore on minus gpio number
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2021-01-07 04:36:54 -05:00
ESP_RETURN_ON_FALSE ( mcpwm_num < SOC_MCPWM_GROUPS , ESP_ERR_INVALID_ARG , TAG , MCPWM_GROUP_NUM_ERROR ) ;
ESP_RETURN_ON_FALSE ( GPIO_IS_VALID_GPIO ( gpio_num ) , ESP_ERR_INVALID_ARG , TAG , MCPWM_GPIO_ERROR ) ;
2017-03-29 04:39:35 -04:00
2021-02-25 06:08:22 -05:00
if ( io_signal < = MCPWM2B ) { // Generator output signal
2021-01-07 04:36:54 -05:00
ESP_RETURN_ON_FALSE ( GPIO_IS_VALID_OUTPUT_GPIO ( gpio_num ) , ESP_ERR_INVALID_ARG , TAG , MCPWM_GPIO_ERROR ) ;
gpio_set_direction ( gpio_num , GPIO_MODE_OUTPUT ) ;
2021-02-25 06:08:22 -05:00
int operator_id = io_signal / 2 ;
int generator_id = io_signal % 2 ;
esp_rom_gpio_connect_out_signal ( gpio_num , mcpwm_periph_signals . groups [ mcpwm_num ] . operators [ operator_id ] . generators [ generator_id ] . pwm_sig , 0 , 0 ) ;
} else if ( io_signal < = MCPWM_SYNC_2 ) { // External sync input signal
2021-01-07 04:36:54 -05:00
gpio_set_direction ( gpio_num , GPIO_MODE_INPUT ) ;
2021-07-05 12:12:25 -04:00
int gpio_sync_id = io_signal - MCPWM_SYNC_0 ;
esp_rom_gpio_connect_in_signal ( gpio_num , mcpwm_periph_signals . groups [ mcpwm_num ] . gpio_synchros [ gpio_sync_id ] . sync_sig , 0 ) ;
2021-02-25 06:08:22 -05:00
} else if ( io_signal < = MCPWM_FAULT_2 ) { // Fault input signal
2021-01-07 04:36:54 -05:00
gpio_set_direction ( gpio_num , GPIO_MODE_INPUT ) ;
2021-02-25 06:08:22 -05:00
int fault_id = io_signal - MCPWM_FAULT_0 ;
2021-07-05 12:12:25 -04:00
esp_rom_gpio_connect_in_signal ( gpio_num , mcpwm_periph_signals . groups [ mcpwm_num ] . gpio_faults [ fault_id ] . fault_sig , 0 ) ;
2021-02-25 06:08:22 -05:00
} else if ( io_signal > = MCPWM_CAP_0 & & io_signal < = MCPWM_CAP_2 ) { // Capture input signal
2021-01-07 04:36:54 -05:00
gpio_set_direction ( gpio_num , GPIO_MODE_INPUT ) ;
2021-02-25 06:08:22 -05:00
int capture_id = io_signal - MCPWM_CAP_0 ;
esp_rom_gpio_connect_in_signal ( gpio_num , mcpwm_periph_signals . groups [ mcpwm_num ] . captures [ capture_id ] . cap_sig , 0 ) ;
2017-03-29 04:39:35 -04:00
}
2024-03-19 03:51:15 -04:00
gpio_func_sel ( gpio_num , PIN_FUNC_GPIO ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_set_pin ( mcpwm_unit_t mcpwm_num , const mcpwm_pin_config_t * mcpwm_pin )
{
2021-01-07 04:36:54 -05:00
ESP_RETURN_ON_FALSE ( mcpwm_num < SOC_MCPWM_GROUPS , ESP_ERR_INVALID_ARG , TAG , MCPWM_GROUP_NUM_ERROR ) ;
2017-03-29 04:39:35 -04:00
mcpwm_gpio_init ( mcpwm_num , MCPWM0A , mcpwm_pin - > mcpwm0a_out_num ) ; //MCPWM0A
mcpwm_gpio_init ( mcpwm_num , MCPWM0B , mcpwm_pin - > mcpwm0b_out_num ) ; //MCPWM0B
mcpwm_gpio_init ( mcpwm_num , MCPWM1A , mcpwm_pin - > mcpwm1a_out_num ) ; //MCPWM1A
mcpwm_gpio_init ( mcpwm_num , MCPWM1B , mcpwm_pin - > mcpwm1b_out_num ) ; //MCPWM1B
mcpwm_gpio_init ( mcpwm_num , MCPWM2A , mcpwm_pin - > mcpwm2a_out_num ) ; //MCPWM2A
mcpwm_gpio_init ( mcpwm_num , MCPWM2B , mcpwm_pin - > mcpwm2b_out_num ) ; //MCPWM2B
mcpwm_gpio_init ( mcpwm_num , MCPWM_SYNC_0 , mcpwm_pin - > mcpwm_sync0_in_num ) ; //SYNC0
mcpwm_gpio_init ( mcpwm_num , MCPWM_SYNC_1 , mcpwm_pin - > mcpwm_sync1_in_num ) ; //SYNC1
mcpwm_gpio_init ( mcpwm_num , MCPWM_SYNC_2 , mcpwm_pin - > mcpwm_sync2_in_num ) ; //SYNC2
mcpwm_gpio_init ( mcpwm_num , MCPWM_FAULT_0 , mcpwm_pin - > mcpwm_fault0_in_num ) ; //FAULT0
2020-06-23 16:56:50 -04:00
mcpwm_gpio_init ( mcpwm_num , MCPWM_FAULT_1 , mcpwm_pin - > mcpwm_fault1_in_num ) ; //FAULT1
mcpwm_gpio_init ( mcpwm_num , MCPWM_FAULT_2 , mcpwm_pin - > mcpwm_fault2_in_num ) ; //FAULT2
2017-03-29 04:39:35 -04:00
mcpwm_gpio_init ( mcpwm_num , MCPWM_CAP_0 , mcpwm_pin - > mcpwm_cap0_in_num ) ; //CAP0
mcpwm_gpio_init ( mcpwm_num , MCPWM_CAP_1 , mcpwm_pin - > mcpwm_cap1_in_num ) ; //CAP1
mcpwm_gpio_init ( mcpwm_num , MCPWM_CAP_2 , mcpwm_pin - > mcpwm_cap2_in_num ) ; //CAP2
return ESP_OK ;
}
esp_err_t mcpwm_start ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
2019-11-17 07:53:29 -05:00
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_timer_set_start_stop_command ( context [ mcpwm_num ] . hal . dev , timer_num , MCPWM_TIMER_START_NO_STOP ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_stop ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
2019-11-17 07:53:29 -05:00
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_timer_set_start_stop_command ( context [ mcpwm_num ] . hal . dev , timer_num , MCPWM_TIMER_STOP_EMPTY ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2023-01-06 01:17:04 -05:00
static inline uint32_t mcpwm_group_get_resolution ( mcpwm_unit_t mcpwm_num )
{
if ( context [ mcpwm_num ] . group_resolution_hz = = 0 ) {
context [ mcpwm_num ] . group_resolution_hz = MCPWM_DEFAULT_GROUP_CLK_RESOLUTION_HZ ;
}
return context [ mcpwm_num ] . group_resolution_hz ;
}
static inline uint32_t mcpwm_timer_get_resolution ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
if ( context [ mcpwm_num ] . timer_resolution_hz [ timer_num ] = = 0 ) {
context [ mcpwm_num ] . timer_resolution_hz [ timer_num ] = MCPWM_DEFAULT_TIMER_CLK_RESOLUTION_HZ ;
}
return context [ mcpwm_num ] . timer_resolution_hz [ timer_num ] ;
}
esp_err_t mcpwm_group_set_resolution ( mcpwm_unit_t mcpwm_num , uint32_t resolution )
2022-05-28 05:27:02 -04:00
{
2024-01-10 01:26:04 -05:00
mcpwm_module_enable ( mcpwm_num ) ;
2023-01-06 01:17:04 -05:00
uint32_t clk_src_hz = 0 ;
2023-04-23 03:49:59 -04:00
esp_clk_tree_src_get_freq_hz ( MCPWM_TIMER_CLK_SRC_DEFAULT , ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED , & clk_src_hz ) ;
2023-01-06 01:17:04 -05:00
int pre_scale_temp = clk_src_hz / resolution ;
2021-07-28 05:09:02 -04:00
ESP_RETURN_ON_FALSE ( pre_scale_temp > = 1 , ESP_ERR_INVALID_ARG , TAG , " invalid resolution " ) ;
2023-01-06 01:17:04 -05:00
context [ mcpwm_num ] . group_resolution_hz = clk_src_hz / pre_scale_temp ;
2023-09-13 07:13:01 -04:00
MCPWM_CLOCK_SRC_ATOMIC ( ) {
2024-03-19 03:51:15 -04:00
mcpwm_ll_group_set_clock_prescale ( mcpwm_num , pre_scale_temp ) ;
2023-09-13 07:13:01 -04:00
}
2021-07-28 05:09:02 -04:00
return ESP_OK ;
}
2023-01-06 01:17:04 -05:00
esp_err_t mcpwm_timer_set_resolution ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , uint32_t resolution )
2022-05-28 05:27:02 -04:00
{
2021-07-28 05:09:02 -04:00
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2023-01-06 01:17:04 -05:00
uint32_t group_resolution = mcpwm_group_get_resolution ( mcpwm_num ) ;
int pre_scale_temp = group_resolution / resolution ;
2021-07-28 05:09:02 -04:00
ESP_RETURN_ON_FALSE ( pre_scale_temp > = 1 , ESP_ERR_INVALID_ARG , TAG , " invalid resolution " ) ;
2023-01-06 01:17:04 -05:00
context [ mcpwm_num ] . timer_resolution_hz [ timer_num ] = context [ mcpwm_num ] . group_resolution_hz / pre_scale_temp ;
2021-07-28 05:09:02 -04:00
mcpwm_critical_enter ( mcpwm_num ) ;
2023-01-06 01:17:04 -05:00
mcpwm_ll_timer_set_clock_prescale ( hal - > dev , timer_num , pre_scale_temp ) ;
2021-07-28 05:09:02 -04:00
mcpwm_critical_exit ( mcpwm_num ) ;
return ESP_OK ;
}
2017-03-29 04:39:35 -04:00
esp_err_t mcpwm_set_frequency ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , uint32_t frequency )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_timer_update_period_at_once ( hal - > dev , timer_num ) ;
uint32_t previous_peak = mcpwm_ll_timer_get_peak ( hal - > dev , timer_num , false ) ;
2023-01-06 01:17:04 -05:00
uint32_t timer_resolution = mcpwm_timer_get_resolution ( mcpwm_num , timer_num ) ;
uint32_t new_peak = timer_resolution / frequency ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_timer_set_peak ( hal - > dev , timer_num , new_peak , false ) ;
// keep the duty cycle unchanged
float scale = ( ( float ) new_peak ) / previous_peak ;
// the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
uint32_t previous_cmp_a = mcpwm_ll_operator_get_compare_value ( hal - > dev , op , 0 ) ;
uint32_t previous_cmp_b = mcpwm_ll_operator_get_compare_value ( hal - > dev , op , 1 ) ;
// update compare value immediately
mcpwm_ll_operator_update_compare_at_once ( hal - > dev , op , 0 ) ;
mcpwm_ll_operator_update_compare_at_once ( hal - > dev , op , 1 ) ;
mcpwm_ll_operator_set_compare_value ( hal - > dev , op , 0 , ( uint32_t ) ( previous_cmp_a * scale ) ) ;
mcpwm_ll_operator_set_compare_value ( hal - > dev , op , 1 , ( uint32_t ) ( previous_cmp_b * scale ) ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2019-11-17 07:53:29 -05:00
esp_err_t mcpwm_set_duty ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_generator_t gen , float duty )
2017-03-29 04:39:35 -04:00
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
//the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
const int cmp = gen ;
MCPWM_GEN_CHECK ( mcpwm_num , timer_num , gen ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
uint32_t set_duty = mcpwm_ll_timer_get_peak ( hal - > dev , timer_num , false ) * duty / 100 ;
mcpwm_ll_operator_set_compare_value ( hal - > dev , op , cmp , set_duty ) ;
mcpwm_ll_operator_enable_update_compare_on_tez ( hal - > dev , op , cmp , true ) ;
2022-10-17 02:42:14 -04:00
mcpwm_ll_operator_enable_update_compare_on_tep ( hal - > dev , op , cmp , true ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2019-11-17 07:53:29 -05:00
esp_err_t mcpwm_set_duty_in_us ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_generator_t gen , uint32_t duty_in_us )
2017-03-29 04:39:35 -04:00
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
//the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
const int cmp = gen ;
MCPWM_GEN_CHECK ( mcpwm_num , timer_num , gen ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2022-08-29 03:18:06 -04:00
// to avid multiplication overflow, use uint64_t here
2023-01-06 01:17:04 -05:00
uint64_t timer_resolution = mcpwm_timer_get_resolution ( mcpwm_num , timer_num ) ;
uint64_t compare_val = timer_resolution * duty_in_us / 1000000 ;
2022-08-29 03:18:06 -04:00
mcpwm_ll_operator_set_compare_value ( hal - > dev , op , cmp , ( uint32_t ) compare_val ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_operator_enable_update_compare_on_tez ( hal - > dev , op , cmp , true ) ;
2022-10-17 02:42:14 -04:00
mcpwm_ll_operator_enable_update_compare_on_tep ( hal - > dev , op , cmp , true ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2019-11-17 07:53:29 -05:00
esp_err_t mcpwm_set_duty_type ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_generator_t gen ,
mcpwm_duty_type_t duty_type )
{
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_GEN_CHECK ( mcpwm_num , timer_num , gen ) ;
2021-01-07 04:36:54 -05:00
ESP_RETURN_ON_FALSE ( duty_type < MCPWM_DUTY_MODE_MAX , ESP_ERR_INVALID_ARG , TAG , MCPWM_DUTY_TYPE_ERROR ) ;
2021-01-22 03:15:06 -05:00
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2019-11-17 07:53:29 -05:00
2021-01-07 04:36:54 -05:00
//the driver currently always use the comparator A for PWMxA output, and comparator B for PWMxB output
2019-11-17 07:53:29 -05:00
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
switch ( mcpwm_ll_timer_get_count_mode ( hal - > dev , timer_num ) ) {
case MCPWM_TIMER_COUNT_MODE_UP :
if ( duty_type = = MCPWM_DUTY_MODE_0 ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_GEN_ACTION_HIGH ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_FULL , MCPWM_GEN_ACTION_KEEP ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_LOW ) ;
} else if ( duty_type = = MCPWM_DUTY_MODE_1 ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_GEN_ACTION_LOW ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_NO_CHANGE ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_HIGH ) ;
2022-05-28 05:02:07 -04:00
} else if ( duty_type = = MCPWM_DUTY_MODE_FORCE_LOW ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_LOW ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_LOW ) ;
2022-05-28 05:02:07 -04:00
} else if ( duty_type = = MCPWM_DUTY_MODE_FORCE_HIGH ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_HIGH ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_HIGH ) ;
}
break ;
case MCPWM_TIMER_COUNT_MODE_DOWN :
if ( duty_type = = MCPWM_DUTY_MODE_0 ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_NO_CHANGE ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_HIGH ) ;
} else if ( duty_type = = MCPWM_DUTY_MODE_1 ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_NO_CHANGE ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_LOW ) ;
2022-05-28 05:02:07 -04:00
} else if ( duty_type = = MCPWM_DUTY_MODE_FORCE_LOW ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_LOW ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_LOW ) ;
2022-05-28 05:02:07 -04:00
} else if ( duty_type = = MCPWM_DUTY_MODE_FORCE_HIGH ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_HIGH ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_HIGH ) ;
}
break ;
case MCPWM_TIMER_COUNT_MODE_UP_DOWN :
if ( duty_type = = MCPWM_DUTY_MODE_0 ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_HIGH ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_HIGH ) ;
} else if ( duty_type = = MCPWM_DUTY_MODE_1 ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_LOW ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_LOW ) ;
2022-05-28 05:02:07 -04:00
} else if ( duty_type = = MCPWM_DUTY_MODE_FORCE_LOW ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_LOW ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_LOW ) ;
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_LOW ) ;
2022-05-28 05:02:07 -04:00
} else if ( duty_type = = MCPWM_DUTY_MODE_FORCE_HIGH ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_EMPTY , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_timer_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , MCPWM_TIMER_EVENT_FULL , MCPWM_ACTION_FORCE_HIGH ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_DOWN , gen , MCPWM_ACTION_FORCE_HIGH ) ;
mcpwm_ll_generator_set_action_on_compare_event ( hal - > dev , op , gen , MCPWM_TIMER_DIRECTION_UP , gen , MCPWM_ACTION_FORCE_HIGH ) ;
}
break ;
default :
break ;
}
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_init ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , const mcpwm_config_t * mcpwm_conf )
{
2019-11-17 07:53:29 -05:00
const int op = timer_num ;
MCPWM_TIMER_ID_CHECK ( mcpwm_num , op ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2023-09-13 07:13:01 -04:00
mcpwm_module_enable ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_hal_init_config_t config = {
2022-05-28 04:59:59 -04:00
. group_id = mcpwm_num
2019-11-17 07:53:29 -05:00
} ;
2021-01-07 04:36:54 -05:00
mcpwm_hal_init ( hal , & config ) ;
2019-11-17 07:53:29 -05:00
2023-01-06 01:17:04 -05:00
uint32_t clk_src_hz = 0 ;
2023-04-23 03:49:59 -04:00
esp_clk_tree_src_get_freq_hz ( MCPWM_TIMER_CLK_SRC_DEFAULT , ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED , & clk_src_hz ) ;
2023-01-06 01:17:04 -05:00
uint32_t group_resolution = mcpwm_group_get_resolution ( mcpwm_num ) ;
uint32_t timer_resolution = mcpwm_timer_get_resolution ( mcpwm_num , timer_num ) ;
uint32_t group_pre_scale = clk_src_hz / group_resolution ;
uint32_t timer_pre_scale = group_resolution / timer_resolution ;
2023-09-13 07:13:01 -04:00
MCPWM_CLOCK_SRC_ATOMIC ( ) {
2024-03-19 03:51:15 -04:00
mcpwm_ll_group_set_clock_source ( mcpwm_num , ( soc_module_clk_t ) MCPWM_CAPTURE_CLK_SRC_DEFAULT ) ;
mcpwm_ll_group_set_clock_prescale ( mcpwm_num , group_pre_scale ) ;
2023-09-13 07:13:01 -04:00
}
2019-11-17 07:53:29 -05:00
mcpwm_critical_enter ( mcpwm_num ) ;
2023-01-06 01:17:04 -05:00
mcpwm_ll_timer_set_clock_prescale ( hal - > dev , timer_num , timer_pre_scale ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_timer_set_count_mode ( hal - > dev , timer_num , mcpwm_conf - > counter_mode ) ;
mcpwm_ll_timer_update_period_at_once ( hal - > dev , timer_num ) ;
2023-01-06 01:17:04 -05:00
mcpwm_ll_timer_set_peak ( hal - > dev , timer_num , timer_resolution / mcpwm_conf - > frequency , false ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_operator_connect_timer ( hal - > dev , timer_num , timer_num ) ; //the driver currently always use the timer x for operator x
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_set_duty ( mcpwm_num , timer_num , 0 , mcpwm_conf - > cmpr_a ) ;
mcpwm_set_duty ( mcpwm_num , timer_num , 1 , mcpwm_conf - > cmpr_b ) ;
mcpwm_set_duty_type ( mcpwm_num , timer_num , 0 , mcpwm_conf - > duty_mode ) ;
mcpwm_set_duty_type ( mcpwm_num , timer_num , 1 , mcpwm_conf - > duty_mode ) ;
mcpwm_start ( mcpwm_num , timer_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
uint32_t mcpwm_get_frequency ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
2022-10-08 23:10:19 -04:00
if ( mcpwm_num > = MCPWM_UNIT_MAX | | timer_num > = MCPWM_TIMER_MAX ) {
ESP_LOGE ( TAG , " Invalid MCPWM timer instance " ) ;
return 0 ;
}
2023-01-06 01:17:04 -05:00
uint32_t timer_resolution = mcpwm_timer_get_resolution ( mcpwm_num , timer_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2021-07-28 05:09:02 -04:00
uint32_t peak = mcpwm_ll_timer_get_peak ( hal - > dev , timer_num , false ) ;
2023-01-06 01:17:04 -05:00
uint32_t freq = timer_resolution / peak ;
2021-01-07 04:36:54 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2021-07-28 05:09:02 -04:00
return freq ;
2019-11-17 07:53:29 -05:00
}
float mcpwm_get_duty ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_generator_t gen )
{
2022-10-08 23:10:19 -04:00
if ( mcpwm_num > = MCPWM_UNIT_MAX | | timer_num > = MCPWM_TIMER_MAX | | gen > = MCPWM_GEN_MAX ) {
ESP_LOGE ( TAG , " Invalid MCPWM generator instance " ) ;
return 0 ;
}
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
2021-01-07 04:36:54 -05:00
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
float duty = 100.0 * mcpwm_ll_operator_get_compare_value ( hal - > dev , op , gen ) / mcpwm_ll_timer_get_peak ( hal - > dev , timer_num , false ) ;
mcpwm_critical_exit ( mcpwm_num ) ;
return duty ;
2019-11-17 07:53:29 -05:00
}
2017-03-29 04:39:35 -04:00
2022-05-28 05:27:02 -04:00
uint32_t mcpwm_get_duty_in_us ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_operator_t gen )
{
2022-10-08 23:10:19 -04:00
if ( mcpwm_num > = MCPWM_UNIT_MAX | | timer_num > = MCPWM_TIMER_MAX | | gen > = MCPWM_GEN_MAX ) {
ESP_LOGE ( TAG , " Invalid MCPWM generator instance " ) ;
return 0 ;
}
2023-01-06 01:17:04 -05:00
uint32_t timer_resolution = mcpwm_timer_get_resolution ( mcpwm_num , timer_num ) ;
2021-07-28 05:09:02 -04:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2023-01-06 01:17:04 -05:00
uint32_t duty = mcpwm_ll_operator_get_compare_value ( hal - > dev , op , gen ) * ( 1000000.0 / timer_resolution ) ;
2021-07-28 05:09:02 -04:00
mcpwm_critical_exit ( mcpwm_num ) ;
return duty ;
}
2019-11-17 07:53:29 -05:00
esp_err_t mcpwm_set_signal_high ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_generator_t gen )
{
//the driver currently always use the timer x for operator x
2022-05-28 05:02:07 -04:00
return mcpwm_set_duty_type ( mcpwm_num , timer_num , gen , MCPWM_DUTY_MODE_FORCE_HIGH ) ;
2017-03-29 04:39:35 -04:00
}
2019-11-17 07:53:29 -05:00
esp_err_t mcpwm_set_signal_low ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_generator_t gen )
{
//the driver currently always use the timer x for operator x
2022-05-28 05:02:07 -04:00
return mcpwm_set_duty_type ( mcpwm_num , timer_num , gen , MCPWM_DUTY_MODE_FORCE_LOW ) ;
2017-03-29 04:39:35 -04:00
}
esp_err_t mcpwm_carrier_enable ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_carrier_enable ( context [ mcpwm_num ] . hal . dev , op , true ) ;
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_carrier_disable ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_carrier_enable ( context [ mcpwm_num ] . hal . dev , op , false ) ;
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_carrier_set_period ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , uint8_t carrier_period )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_carrier_set_prescale ( context [ mcpwm_num ] . hal . dev , op , carrier_period + 1 ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2019-11-17 07:53:29 -05:00
2017-03-29 04:39:35 -04:00
esp_err_t mcpwm_carrier_set_duty_cycle ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , uint8_t carrier_duty )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_carrier_set_duty ( context [ mcpwm_num ] . hal . dev , op , carrier_duty ) ;
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2018-06-05 09:19:57 -04:00
esp_err_t mcpwm_carrier_oneshot_mode_enable ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , uint8_t pulse_width )
2017-03-29 04:39:35 -04:00
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_carrier_set_first_pulse_width ( context [ mcpwm_num ] . hal . dev , op , pulse_width + 1 ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_carrier_output_invert ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num ,
mcpwm_carrier_out_ivt_t carrier_ivt_mode )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_carrier_out_invert ( context [ mcpwm_num ] . hal . dev , op , carrier_ivt_mode ) ;
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_carrier_init ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , const mcpwm_carrier_config_t * carrier_conf )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2021-01-07 04:36:54 -05:00
mcpwm_carrier_enable ( mcpwm_num , timer_num ) ;
mcpwm_carrier_set_period ( mcpwm_num , timer_num , carrier_conf - > carrier_period ) ;
mcpwm_carrier_set_duty_cycle ( mcpwm_num , timer_num , carrier_conf - > carrier_duty ) ;
2022-05-28 05:02:07 -04:00
mcpwm_carrier_oneshot_mode_enable ( mcpwm_num , timer_num , carrier_conf - > pulse_width_in_os ) ;
2021-01-07 04:36:54 -05:00
mcpwm_carrier_output_invert ( mcpwm_num , timer_num , carrier_conf - > carrier_ivt_mode ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_carrier_in_invert ( hal - > dev , op , false ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_deadtime_enable ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_deadtime_type_t dt_mode ,
uint32_t red , uint32_t fed )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
2021-01-07 04:36:54 -05:00
ESP_RETURN_ON_FALSE ( dt_mode < MCPWM_DEADTIME_TYPE_MAX , ESP_ERR_INVALID_ARG , TAG , MCPWM_DT_ERROR ) ;
2019-11-17 07:53:29 -05:00
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_deadtime_enable_update_delay_on_tez ( hal - > dev , op , true ) ;
2021-07-05 12:12:25 -04:00
// The dead time delay unit equals to MCPWM group resolution
2022-05-28 04:59:59 -04:00
mcpwm_ll_operator_set_deadtime_clock_src ( hal - > dev , op , MCPWM_LL_DEADTIME_CLK_SRC_GROUP ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_deadtime_set_rising_delay ( hal - > dev , op , red + 1 ) ;
mcpwm_ll_deadtime_set_falling_delay ( hal - > dev , op , fed + 1 ) ;
switch ( dt_mode ) {
case MCPWM_BYPASS_RED :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , false ) ; // S0=0
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 0 , true ) ; // S1=1
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 0 , false ) ; // S2=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , false ) ; // S3=0
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4=0
mcpwm_ll_deadtime_fed_select_generator ( hal - > dev , op , 0 ) ; // S5=0
2021-01-07 04:36:54 -05:00
break ;
case MCPWM_BYPASS_FED :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , true ) ; // S0=1
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 0 , false ) ; // S1=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 0 , false ) ; // S2=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , false ) ; // S3=0
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4=0
mcpwm_ll_deadtime_fed_select_generator ( hal - > dev , op , 0 ) ; // S5=0
2021-01-07 04:36:54 -05:00
break ;
case MCPWM_ACTIVE_HIGH_MODE :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , false ) ; // S0=0
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 0 , false ) ; // S1=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 0 , false ) ; // S2=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , false ) ; // S3=0
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4=0
mcpwm_ll_deadtime_fed_select_generator ( hal - > dev , op , 0 ) ; // S5=0
2021-01-07 04:36:54 -05:00
break ;
case MCPWM_ACTIVE_LOW_MODE :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , false ) ; // S0=0
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 0 , false ) ; // S1=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 0 , true ) ; // S2=1
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , true ) ; // S3=1
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4=0
mcpwm_ll_deadtime_fed_select_generator ( hal - > dev , op , 0 ) ; // S5=0
2021-01-07 04:36:54 -05:00
break ;
case MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , false ) ; // S0=0
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 0 , false ) ; // S1=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 0 , false ) ; // S2=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , true ) ; // S3=1
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4=0
mcpwm_ll_deadtime_fed_select_generator ( hal - > dev , op , 0 ) ; // S5=0
2021-01-07 04:36:54 -05:00
break ;
case MCPWM_ACTIVE_LOW_COMPLIMENT_MODE :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , false ) ; // S0=0
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 0 , false ) ; // S1=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 0 , true ) ; // S2=1
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , false ) ; // S3=0
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4=0
mcpwm_ll_deadtime_fed_select_generator ( hal - > dev , op , 0 ) ; // S5=0
2021-01-07 04:36:54 -05:00
break ;
case MCPWM_ACTIVE_RED_FED_FROM_PWMXA :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , false ) ; // S0=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , false ) ; // S3=0
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4=0
mcpwm_ll_deadtime_swap_out_path ( hal - > dev , op , 0 , true ) ; // S6=1
mcpwm_ll_deadtime_swap_out_path ( hal - > dev , op , 1 , false ) ; // S7=0
mcpwm_ll_deadtime_enable_deb ( hal - > dev , op , true ) ; // S8=1
2021-01-07 04:36:54 -05:00
break ;
case MCPWM_ACTIVE_RED_FED_FROM_PWMXB :
2021-08-01 23:00:05 -04:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , false ) ; // S0=0
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , false ) ; // S3=0
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 1 ) ; // S4=1
mcpwm_ll_deadtime_swap_out_path ( hal - > dev , op , 0 , true ) ; // S6=1
mcpwm_ll_deadtime_swap_out_path ( hal - > dev , op , 1 , false ) ; // S7=0
mcpwm_ll_deadtime_enable_deb ( hal - > dev , op , true ) ; // S8=1
2021-01-07 04:36:54 -05:00
break ;
default :
break ;
}
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_deadtime_disable ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 1 , true ) ; // S0
mcpwm_ll_deadtime_bypass_path ( hal - > dev , op , 0 , true ) ; // S1
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 0 , false ) ; // S2
mcpwm_ll_deadtime_invert_outpath ( hal - > dev , op , 1 , false ) ; // S3
mcpwm_ll_deadtime_red_select_generator ( hal - > dev , op , 0 ) ; // S4
mcpwm_ll_deadtime_fed_select_generator ( hal - > dev , op , 0 ) ; // S5
mcpwm_ll_deadtime_swap_out_path ( hal - > dev , op , 0 , false ) ; // S6
mcpwm_ll_deadtime_swap_out_path ( hal - > dev , op , 1 , false ) ; // S7
mcpwm_ll_deadtime_enable_deb ( hal - > dev , op , false ) ; // S8
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_fault_init ( mcpwm_unit_t mcpwm_num , mcpwm_fault_input_level_t intput_level , mcpwm_fault_signal_t fault_sig )
{
2021-01-07 04:36:54 -05:00
ESP_RETURN_ON_FALSE ( mcpwm_num < SOC_MCPWM_GROUPS , ESP_ERR_INVALID_ARG , TAG , MCPWM_GROUP_NUM_ERROR ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_fault_enable_detection ( hal - > dev , fault_sig , true ) ;
mcpwm_ll_fault_set_active_level ( hal - > dev , fault_sig , intput_level ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_fault_deinit ( mcpwm_unit_t mcpwm_num , mcpwm_fault_signal_t fault_sig )
{
2021-01-07 04:36:54 -05:00
ESP_RETURN_ON_FALSE ( mcpwm_num < SOC_MCPWM_GROUPS , ESP_ERR_INVALID_ARG , TAG , MCPWM_GROUP_NUM_ERROR ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_fault_enable_detection ( hal - > dev , fault_sig , false ) ;
for ( int i = 0 ; i < SOC_MCPWM_OPERATORS_PER_GROUP ; i + + ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_brake_clear_ost ( hal - > dev , i ) ; // make sure operator has exit the ost fault state totally
2021-01-07 04:36:54 -05:00
}
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_fault_set_cyc_mode ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_fault_signal_t fault_sig ,
2019-11-17 07:53:29 -05:00
mcpwm_output_action_t action_on_pwmxa , mcpwm_output_action_t action_on_pwmxb )
{
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , op ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_brake_enable_cbc_mode ( hal - > dev , op , fault_sig , true ) ;
mcpwm_ll_brake_enable_cbc_refresh_on_tez ( hal - > dev , op , true ) ;
mcpwm_ll_brake_enable_oneshot_mode ( hal - > dev , op , fault_sig , false ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 0 , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_OPER_BRAKE_MODE_CBC , action_on_pwmxa ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 0 , MCPWM_TIMER_DIRECTION_UP , MCPWM_OPER_BRAKE_MODE_CBC , action_on_pwmxa ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 1 , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_OPER_BRAKE_MODE_CBC , action_on_pwmxb ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 1 , MCPWM_TIMER_DIRECTION_UP , MCPWM_OPER_BRAKE_MODE_CBC , action_on_pwmxb ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_fault_set_oneshot_mode ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_fault_signal_t fault_sig ,
mcpwm_action_on_pwmxa_t action_on_pwmxa , mcpwm_action_on_pwmxb_t action_on_pwmxb )
{
2019-11-17 07:53:29 -05:00
//the driver currently always use the timer x for operator x
const int op = timer_num ;
MCPWM_TIMER_CHECK ( mcpwm_num , op ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_brake_clear_ost ( hal - > dev , op ) ;
mcpwm_ll_brake_enable_oneshot_mode ( hal - > dev , op , fault_sig , true ) ;
mcpwm_ll_brake_enable_cbc_mode ( hal - > dev , op , fault_sig , false ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 0 , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_OPER_BRAKE_MODE_OST , action_on_pwmxa ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 0 , MCPWM_TIMER_DIRECTION_UP , MCPWM_OPER_BRAKE_MODE_OST , action_on_pwmxa ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 1 , MCPWM_TIMER_DIRECTION_DOWN , MCPWM_OPER_BRAKE_MODE_OST , action_on_pwmxb ) ;
mcpwm_ll_generator_set_action_on_brake_event ( hal - > dev , op , 1 , MCPWM_TIMER_DIRECTION_UP , MCPWM_OPER_BRAKE_MODE_OST , action_on_pwmxb ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2022-05-28 04:59:59 -04:00
static void MCPWM_ISR_ATTR mcpwm_default_isr_handler ( void * arg )
{
2021-07-13 08:13:17 -04:00
mcpwm_context_t * curr_context = ( mcpwm_context_t * ) arg ;
uint32_t intr_status = mcpwm_ll_intr_get_capture_status ( curr_context - > hal . dev ) ;
mcpwm_ll_intr_clear_capture_status ( curr_context - > hal . dev , intr_status ) ;
bool need_yield = false ;
for ( int i = 0 ; i < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER ; + + i ) {
if ( ( intr_status > > i ) & 0x1 ) {
if ( curr_context - > cap_isr_func [ i ] . fn ! = NULL ) {
cap_event_data_t edata ;
2022-05-28 04:59:59 -04:00
edata . cap_edge = mcpwm_ll_capture_get_edge ( curr_context - > hal . dev , i ) = = MCPWM_CAP_EDGE_NEG ? MCPWM_NEG_EDGE
: MCPWM_POS_EDGE ;
2021-07-13 08:13:17 -04:00
edata . cap_value = mcpwm_ll_capture_get_value ( curr_context - > hal . dev , i ) ;
if ( curr_context - > cap_isr_func [ i ] . fn ( curr_context - > group_id , i , & edata ,
2022-05-28 04:59:59 -04:00
curr_context - > cap_isr_func [ i ] . args ) ) {
2021-07-13 08:13:17 -04:00
need_yield = true ;
}
}
}
}
if ( need_yield ) {
portYIELD_FROM_ISR ( ) ;
}
}
esp_err_t mcpwm_capture_enable_channel ( mcpwm_unit_t mcpwm_num , mcpwm_capture_channel_id_t cap_channel , const mcpwm_capture_config_t * cap_conf )
{
ESP_RETURN_ON_FALSE ( mcpwm_num < SOC_MCPWM_GROUPS , ESP_ERR_INVALID_ARG , TAG , MCPWM_GROUP_NUM_ERROR ) ;
ESP_RETURN_ON_FALSE ( cap_channel < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER , ESP_ERR_INVALID_ARG , TAG , MCPWM_CAPTURE_ERROR ) ;
ESP_RETURN_ON_FALSE ( context [ mcpwm_num ] . cap_isr_func [ cap_channel ] . fn = = NULL , ESP_ERR_INVALID_STATE , TAG ,
MCPWM_CAP_EXIST_ERROR ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2024-03-25 02:11:33 -04:00
// enable MCPWM module in case user don't use `mcpwm_init` at all. always increase reference count
2023-09-13 07:13:01 -04:00
mcpwm_module_enable ( mcpwm_num ) ;
2021-07-13 08:13:17 -04:00
mcpwm_hal_init_config_t init_config = {
2022-05-28 04:59:59 -04:00
. group_id = mcpwm_num
2021-07-13 08:13:17 -04:00
} ;
mcpwm_hal_init ( hal , & init_config ) ;
2023-01-06 01:17:04 -05:00
uint32_t clk_src_hz = 0 ;
2023-04-23 03:49:59 -04:00
esp_clk_tree_src_get_freq_hz ( MCPWM_TIMER_CLK_SRC_DEFAULT , ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED , & clk_src_hz ) ;
2023-01-06 01:17:04 -05:00
uint32_t group_resolution = mcpwm_group_get_resolution ( mcpwm_num ) ;
uint32_t group_pre_scale = clk_src_hz / group_resolution ;
2023-09-13 07:13:01 -04:00
MCPWM_CLOCK_SRC_ATOMIC ( ) {
2024-03-19 03:51:15 -04:00
mcpwm_ll_group_set_clock_source ( mcpwm_num , ( soc_module_clk_t ) MCPWM_CAPTURE_CLK_SRC_DEFAULT ) ;
mcpwm_ll_group_set_clock_prescale ( mcpwm_num , group_pre_scale ) ;
2023-09-13 07:13:01 -04:00
}
2021-07-13 08:13:17 -04:00
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_capture_enable_timer ( hal - > dev , true ) ;
mcpwm_ll_capture_enable_channel ( hal - > dev , cap_channel , true ) ;
mcpwm_ll_capture_enable_negedge ( hal - > dev , cap_channel , cap_conf - > cap_edge & MCPWM_NEG_EDGE ) ;
mcpwm_ll_capture_enable_posedge ( hal - > dev , cap_channel , cap_conf - > cap_edge & MCPWM_POS_EDGE ) ;
mcpwm_ll_capture_set_prescale ( hal - > dev , cap_channel , cap_conf - > cap_prescale ) ;
2022-08-09 01:51:56 -04:00
// capture feature should be used with interrupt, so enable it by default
2022-05-28 04:59:59 -04:00
mcpwm_ll_intr_enable ( hal - > dev , MCPWM_LL_EVENT_CAPTURE ( cap_channel ) , true ) ;
2021-07-13 08:13:17 -04:00
mcpwm_ll_intr_clear_capture_status ( hal - > dev , 1 < < cap_channel ) ;
mcpwm_critical_exit ( mcpwm_num ) ;
mcpwm_mutex_lock ( mcpwm_num ) ;
context [ mcpwm_num ] . cap_isr_func [ cap_channel ] . fn = cap_conf - > capture_cb ;
context [ mcpwm_num ] . cap_isr_func [ cap_channel ] . args = cap_conf - > user_data ;
esp_err_t ret = ESP_OK ;
if ( context [ mcpwm_num ] . mcpwm_intr_handle = = NULL ) {
2021-08-25 05:45:46 -04:00
ret = esp_intr_alloc ( mcpwm_periph_signals . groups [ mcpwm_num ] . irq_id , MCPWM_INTR_FLAG ,
2022-05-28 04:59:59 -04:00
mcpwm_default_isr_handler ,
2024-01-10 01:26:04 -05:00
( void * ) ( context + mcpwm_num ) , & ( context [ mcpwm_num ] . mcpwm_intr_handle ) ) ;
2021-07-13 08:13:17 -04:00
}
mcpwm_mutex_unlock ( mcpwm_num ) ;
return ret ;
}
esp_err_t mcpwm_capture_disable_channel ( mcpwm_unit_t mcpwm_num , mcpwm_capture_channel_id_t cap_channel )
{
ESP_RETURN_ON_FALSE ( mcpwm_num < SOC_MCPWM_GROUPS , ESP_ERR_INVALID_ARG , TAG , MCPWM_GROUP_NUM_ERROR ) ;
ESP_RETURN_ON_FALSE ( cap_channel < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER , ESP_ERR_INVALID_ARG , TAG , MCPWM_CAPTURE_ERROR ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_capture_enable_channel ( hal - > dev , cap_channel , false ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_intr_enable ( hal - > dev , MCPWM_LL_EVENT_CAPTURE ( cap_channel ) , false ) ;
2021-07-13 08:13:17 -04:00
mcpwm_critical_exit ( mcpwm_num ) ;
mcpwm_mutex_lock ( mcpwm_num ) ;
context [ mcpwm_num ] . cap_isr_func [ cap_channel ] . fn = NULL ;
context [ mcpwm_num ] . cap_isr_func [ cap_channel ] . args = NULL ;
// if all user defined ISR callback is disabled, free the handle
bool should_free_handle = true ;
for ( int i = 0 ; i < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER ; + + i ) {
if ( context [ mcpwm_num ] . cap_isr_func [ i ] . fn ! = NULL ) {
should_free_handle = false ;
break ;
}
}
esp_err_t ret = ESP_OK ;
if ( should_free_handle ) {
ret = esp_intr_free ( context [ mcpwm_num ] . mcpwm_intr_handle ) ;
2022-05-28 04:59:59 -04:00
if ( ret ! = ESP_OK ) {
2021-07-13 08:13:17 -04:00
ESP_LOGE ( TAG , " failed to free interrupt handle " ) ;
}
context [ mcpwm_num ] . mcpwm_intr_handle = NULL ;
}
mcpwm_mutex_unlock ( mcpwm_num ) ;
// always decrease reference count
2023-09-13 07:13:01 -04:00
mcpwm_module_disable ( mcpwm_num ) ;
2021-07-13 08:13:17 -04:00
return ret ;
}
2021-08-25 05:45:46 -04:00
uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_value ( mcpwm_unit_t mcpwm_num , mcpwm_capture_signal_t cap_sig )
2017-03-29 04:39:35 -04:00
{
2022-10-25 22:23:31 -04:00
if ( mcpwm_num > = MCPWM_UNIT_MAX | | cap_sig > = SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER ) {
2022-10-08 23:10:19 -04:00
return 0 ;
}
2021-01-07 04:36:54 -05:00
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
return mcpwm_ll_capture_get_value ( hal - > dev , cap_sig ) ;
2017-03-29 04:39:35 -04:00
}
2022-09-05 02:40:58 -04:00
uint32_t mcpwm_capture_get_resolution ( mcpwm_unit_t mcpwm_num )
{
if ( mcpwm_num > = MCPWM_UNIT_MAX ) {
ESP_LOGE ( TAG , " Invalid MCPWM instance " ) ;
return 0 ;
}
# if SOC_MCPWM_CAPTURE_CLK_FROM_GROUP
2023-01-06 01:17:04 -05:00
return mcpwm_group_get_resolution ( mcpwm_num ) ;
2022-09-05 02:40:58 -04:00
# else
return esp_clk_apb_freq ( ) ;
# endif
}
2021-08-25 05:45:46 -04:00
uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_edge ( mcpwm_unit_t mcpwm_num , mcpwm_capture_signal_t cap_sig )
2017-03-29 04:39:35 -04:00
{
2022-10-25 22:23:31 -04:00
if ( mcpwm_num > = MCPWM_UNIT_MAX | | cap_sig > = SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER ) {
2022-10-08 23:10:19 -04:00
return 0 ;
}
2021-01-07 04:36:54 -05:00
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2022-05-28 04:59:59 -04:00
return mcpwm_ll_capture_get_edge ( hal - > dev , cap_sig ) = = MCPWM_CAP_EDGE_NEG ? 2 : 1 ;
2017-03-29 04:39:35 -04:00
}
2021-08-03 07:21:19 -04:00
esp_err_t mcpwm_sync_configure ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , const mcpwm_sync_config_t * sync_conf )
{
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
ESP_RETURN_ON_FALSE ( sync_conf - > sync_sig < = MCPWM_SELECT_GPIO_SYNC2 , ESP_ERR_INVALID_ARG , TAG , " invalid sync_sig " ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_timer_set_sync_phase_direction ( hal - > dev , timer_num , sync_conf - > count_direction ) ;
// sync TEP with current setting
uint32_t set_phase = 0 ;
set_phase = mcpwm_ll_timer_get_peak ( hal - > dev , timer_num , false ) * sync_conf - > timer_val / 1000 ;
mcpwm_ll_timer_set_sync_phase_value ( hal - > dev , timer_num , set_phase ) ;
2022-05-28 04:59:59 -04:00
if ( sync_conf - > sync_sig = = MCPWM_SELECT_NO_INPUT ) {
mcpwm_ll_timer_clear_sync_input ( hal - > dev , timer_num ) ;
2021-08-03 07:21:19 -04:00
} else if ( sync_conf - > sync_sig < = MCPWM_SELECT_TIMER2_SYNC ) {
2022-05-28 04:59:59 -04:00
mcpwm_ll_timer_set_timer_sync_input ( hal - > dev , timer_num , sync_conf - > sync_sig - MCPWM_SELECT_TIMER0_SYNC ) ;
2021-08-03 07:21:19 -04:00
} else {
2022-05-28 04:59:59 -04:00
mcpwm_ll_timer_set_gpio_sync_input ( hal - > dev , timer_num , sync_conf - > sync_sig - MCPWM_SELECT_GPIO_SYNC0 ) ;
2021-01-07 04:36:54 -05:00
}
mcpwm_ll_timer_enable_sync_input ( hal - > dev , timer_num , true ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
esp_err_t mcpwm_sync_disable ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
2019-11-17 07:53:29 -05:00
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_enter ( mcpwm_num ) ;
2021-01-07 04:36:54 -05:00
mcpwm_ll_timer_enable_sync_input ( hal - > dev , timer_num , false ) ;
2019-11-17 07:53:29 -05:00
mcpwm_critical_exit ( mcpwm_num ) ;
2017-03-29 04:39:35 -04:00
return ESP_OK ;
}
2019-11-17 07:53:29 -05:00
2021-08-03 07:21:19 -04:00
esp_err_t mcpwm_timer_trigger_soft_sync ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num )
{
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
mcpwm_ll_timer_trigger_soft_sync ( hal - > dev , timer_num ) ;
mcpwm_critical_exit ( mcpwm_num ) ;
return ESP_OK ;
}
2022-05-28 04:59:59 -04:00
esp_err_t mcpwm_sync_invert_gpio_synchro ( mcpwm_unit_t mcpwm_num , mcpwm_sync_signal_t sync_sig , bool invert )
{
2021-08-03 07:21:19 -04:00
ESP_RETURN_ON_FALSE ( sync_sig > = MCPWM_SELECT_GPIO_SYNC0 & & sync_sig < = MCPWM_SELECT_GPIO_SYNC2 ,
ESP_ERR_INVALID_ARG , TAG , " invalid sync sig " ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
2022-05-28 04:59:59 -04:00
mcpwm_ll_invert_gpio_sync_input ( hal - > dev , sync_sig - MCPWM_SELECT_GPIO_SYNC0 , invert ) ;
2021-08-03 07:21:19 -04:00
mcpwm_critical_exit ( mcpwm_num ) ;
return ESP_OK ;
}
esp_err_t mcpwm_set_timer_sync_output ( mcpwm_unit_t mcpwm_num , mcpwm_timer_t timer_num , mcpwm_timer_sync_trigger_t trigger )
{
MCPWM_TIMER_CHECK ( mcpwm_num , timer_num ) ;
mcpwm_hal_context_t * hal = & context [ mcpwm_num ] . hal ;
mcpwm_critical_enter ( mcpwm_num ) ;
switch ( trigger ) {
2022-05-28 04:59:59 -04:00
case MCPWM_SWSYNC_SOURCE_SYNCIN :
mcpwm_ll_timer_propagate_input_sync ( hal - > dev , timer_num ) ;
break ;
case MCPWM_SWSYNC_SOURCE_TEZ :
mcpwm_ll_timer_sync_out_on_timer_event ( hal - > dev , timer_num , MCPWM_TIMER_EVENT_EMPTY ) ;
break ;
case MCPWM_SWSYNC_SOURCE_TEP :
mcpwm_ll_timer_sync_out_on_timer_event ( hal - > dev , timer_num , MCPWM_TIMER_EVENT_FULL ) ;
break ;
case MCPWM_SWSYNC_SOURCE_DISABLED :
default :
mcpwm_ll_timer_disable_sync_out ( hal - > dev , timer_num ) ;
break ;
2021-08-03 07:21:19 -04:00
}
mcpwm_critical_exit ( mcpwm_num ) ;
return ESP_OK ;
}
2022-05-28 05:02:07 -04:00
/**
* @ brief This function will be called during start up , to check that this legacy mcpwm driver is not running along with the new MCPWM driver
*/
__attribute__ ( ( constructor ) )
static void check_mcpwm_driver_conflict ( void )
{
// This function was declared as weak here. The new MCPWM driver has the implementation.
// So if the new MCPWM driver is not linked in, then `mcpwm_acquire_group_handle()` should be NULL at runtime.
extern __attribute__ ( ( weak ) ) void * mcpwm_acquire_group_handle ( int group_id ) ;
if ( ( void * ) mcpwm_acquire_group_handle ! = NULL ) {
ESP_EARLY_LOGE ( TAG , " CONFLICT! driver_ng is not allowed to be used with the legacy driver " ) ;
abort ( ) ;
}
ESP_EARLY_LOGW ( TAG , " legacy driver is deprecated, please migrate to `driver/mcpwm_prelude.h` " ) ;
}