diff --git a/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c index e49cf89b2c2..d540dc20fd6 100644 --- a/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c +++ b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c @@ -5,22 +5,27 @@ * * Change Logs: * Date Author Notes - * 2024-08-1 hywing Initial version. + * 2024-12-18 hywing Initial version. */ #include #include -#include "fsl_ctimer.h" +#include "fsl_pwm.h" #ifdef RT_USING_PWM +#define BOARD_PWM_BASEADDR (FLEXPWM0) +#define PWM_SRC_CLK_FREQ (CLOCK_GetFreq(kCLOCK_BusClk)) +#define FLEX_PWM_CLOCK_DEVIDER (kPWM_Prescale_Divide_2) +#define FLEX_PWM_FAULT_LEVEL true + typedef struct { struct rt_device_pwm pwm_device; - CTIMER_Type *ct_instance; - uint32_t timerClock; - const ctimer_match_t pwmPeriodChannel; - ctimer_match_t matchChannel; + pwm_submodule_t submodule; + pwm_module_control_t control; + pwm_channels_t channel; + pwm_clock_prescale_t prescale; char *name; } mcx_pwm_obj_t; @@ -28,49 +33,67 @@ static mcx_pwm_obj_t mcx_pwm_list[]= { #ifdef BSP_USING_PWM0 { - .ct_instance = CTIMER1, - .timerClock = 0, - .pwmPeriodChannel = kCTIMER_Match_3, - .matchChannel = kCTIMER_Match_2, + .submodule = kPWM_Module_0, + .control = kPWM_Control_Module_0, + .channel = kPWM_PwmA, + .prescale = FLEX_PWM_CLOCK_DEVIDER, .name = "pwm0", - } + }, +#endif +#ifdef BSP_USING_PWM1 + { + .submodule = kPWM_Module_1, + .control = kPWM_Control_Module_1, + .channel = kPWM_PwmA, + .prescale = FLEX_PWM_CLOCK_DEVIDER, + .name = "pwm1", + }, +#endif +#ifdef BSP_USING_PWM2 + { + .submodule = kPWM_Module_2, + .control = kPWM_Control_Module_2, + .channel = kPWM_PwmA, + .prescale = FLEX_PWM_CLOCK_DEVIDER, + .name = "pwm2", + }, #endif }; -volatile uint32_t g_pwmPeriod = 0U; -volatile uint32_t g_pulsePeriod = 0U; - static rt_err_t mcx_drv_pwm_get(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) { return RT_EOK; } -status_t CTIMER_GetPwmPeriodValue(uint32_t pwmFreqHz, uint8_t dutyCyclePercent, uint32_t timerClock_Hz) -{ - g_pwmPeriod = (timerClock_Hz / pwmFreqHz) - 1U; - g_pulsePeriod = (g_pwmPeriod + 1U) * (100 - dutyCyclePercent) / 100; - return kStatus_Success; -} - static rt_err_t mcx_drv_pwm_set(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) { - CTIMER_Type *ct = pwm->ct_instance; - uint32_t pwmFreqHz = 1000000000 / configuration->period; uint8_t dutyCyclePercent = configuration->pulse * 100 / configuration->period; - CTIMER_GetPwmPeriodValue(pwmFreqHz, dutyCyclePercent, pwm->timerClock); - CTIMER_SetupPwmPeriod(ct, kCTIMER_Match_3, kCTIMER_Match_2, g_pwmPeriod, g_pulsePeriod, false); + pwm_signal_param_t pwmSignal[1]; + uint32_t pwmFrequencyInHz = 1000000000 / configuration->period; + + pwmSignal[0].pwmChannel = pwm->channel; + pwmSignal[0].level = kPWM_HighTrue; + pwmSignal[0].dutyCyclePercent = dutyCyclePercent; + pwmSignal[0].deadtimeValue = 0; + pwmSignal[0].faultState = kPWM_PwmFaultState0; + pwmSignal[0].pwmchannelenable = true; + + PWM_SetupPwm(BOARD_PWM_BASEADDR, pwm->submodule, pwmSignal, 1, kPWM_SignedCenterAligned, pwmFrequencyInHz, PWM_SRC_CLK_FREQ); + PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, pwm->submodule, pwm->channel, kPWM_SignedCenterAligned, dutyCyclePercent); + PWM_SetPwmLdok(BOARD_PWM_BASEADDR, pwm->control, true); + return 0; } static rt_err_t mcx_drv_pwm_enable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) { - CTIMER_StartTimer(pwm->ct_instance); + PWM_StartTimer(BOARD_PWM_BASEADDR, pwm->control); return 0; } static rt_err_t mcx_drv_pwm_disable(mcx_pwm_obj_t *pwm, struct rt_pwm_configuration *configuration) { - CTIMER_StopTimer(pwm->ct_instance); + PWM_StopTimer(BOARD_PWM_BASEADDR, pwm->control); return 0; } @@ -108,21 +131,55 @@ static struct rt_pwm_ops mcx_pwm_ops = int mcx_pwm_init(void) { rt_err_t ret; - char name_buf[8]; - - ctimer_config_t config; - CTIMER_GetDefaultConfig(&config); - for (uint8_t i = 0; i < ARRAY_SIZE(mcx_pwm_list); i++) + pwm_config_t pwmConfig; + pwm_fault_param_t faultConfig; + PWM_GetDefaultConfig(&pwmConfig); + pwmConfig.prescale = FLEX_PWM_CLOCK_DEVIDER; + pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; + + int i; + for (i = 0; i < sizeof(mcx_pwm_list) / sizeof(mcx_pwm_list[0]); i++) { - mcx_pwm_list[i].timerClock = CLOCK_GetCTimerClkFreq(1U) / (config.prescale + 1); - CTIMER_Init(mcx_pwm_list[i].ct_instance, &config); - ret = rt_device_pwm_register(&mcx_pwm_list[i].pwm_device, mcx_pwm_list[i].name, &mcx_pwm_ops, &mcx_pwm_list[i]); - if (ret != RT_EOK) + pwm_config_t pwmConfig; + pwm_fault_param_t faultConfig; + PWM_GetDefaultConfig(&pwmConfig); + pwmConfig.prescale = mcx_pwm_list[i].prescale; + pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; + if (PWM_Init(BOARD_PWM_BASEADDR, mcx_pwm_list[i].submodule, &pwmConfig) == kStatus_Fail) { - return ret; + rt_kprintf("PWM Init Failed\n"); } + ret = rt_device_pwm_register(&mcx_pwm_list[i].pwm_device, mcx_pwm_list[i].name, &mcx_pwm_ops, &mcx_pwm_list[i]); } - return RT_EOK; + + /* + * config->faultClearingMode = kPWM_Automatic; + * config->faultLevel = false; + * config->enableCombinationalPath = true; + * config->recoverMode = kPWM_NoRecovery; + */ + PWM_FaultDefaultConfig(&faultConfig); + faultConfig.faultLevel = FLEX_PWM_FAULT_LEVEL; + + /* Sets up the PWM fault protection */ + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_0, &faultConfig); + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_1, &faultConfig); + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_2, &faultConfig); + PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_3, &faultConfig); + + /* Set PWM fault disable mapping for submodule 0/1/2 */ + PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0, + kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3); + PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_1, kPWM_PwmA, kPWM_faultchannel_0, + kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3); + PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_2, kPWM_PwmA, kPWM_faultchannel_0, + kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3); + + + /* Set the load okay bit for all submodules to load registers from their buffer */ + PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2, true); + + return ret; } INIT_DEVICE_EXPORT(mcx_pwm_init); diff --git a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig index 28395131bdc..1e70e21f455 100644 --- a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig +++ b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig @@ -125,12 +125,18 @@ menu "On-chip Peripheral Drivers" config BSP_USING_PWM bool "Enable PWM" select RT_USING_PWM - default N + default n if BSP_USING_PWM config BSP_USING_PWM0 - bool "Enable PWM0" - default N + bool "Enable eFlex PWM0" + default n + config BSP_USING_PWM1 + bool "Enable eFlex PWM1" + default n + config BSP_USING_PWM2 + bool "Enable eFlex PWM2" + default n endif endmenu diff --git a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c index f157f43763e..9b3d63fafb6 100644 --- a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c +++ b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c @@ -60,6 +60,7 @@ void BOARD_InitPins(void) RESET_ReleasePeripheralReset(kLPSPI1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPI2C0_RST_SHIFT_RSTn); + RESET_ReleasePeripheralReset(kFLEXPWM0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); @@ -225,9 +226,7 @@ void BOARD_InitPins(void) #endif #ifdef BSP_USING_PWM0 - ctimer_config_t config; - CTIMER_Init(CTIMER1, &config); - const port_pin_config_t port1_4_pin62_config = {/* Internal pull-up/down resistor is disabled */ + const port_pin_config_t port3_0_pin46_config = {/* Internal pull-up/down resistor is disabled */ kPORT_PullDisable, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, @@ -241,16 +240,68 @@ void BOARD_InitPins(void) kPORT_LowDriveStrength, /* Normal drive strength is configured */ kPORT_NormalDriveStrength, - /* Pin is configured as CT1_MAT2 */ - kPORT_MuxAlt4, + /* Pin is configured as PWM0_A0 */ + kPORT_MuxAlt5, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; - /* PORT1_4 (pin 62) is configured as CT1_MAT2 */ - PORT_SetPinConfig(PORT1, 4U, &port1_4_pin62_config); + /* PORT3_0 (pin 38) is configured as PWM0_A0 */ + PORT_SetPinConfig(PORT3, 0U, &port3_0_pin46_config); +#endif +#ifdef BSP_USING_PWM1 + const port_pin_config_t port3_8_pin42_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as PWM0_A0 */ + kPORT_MuxAlt5, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_8 (pin 42) is configured as PWM0_A1 */ + PORT_SetPinConfig(PORT3, 8U, &port3_8_pin42_config); +#endif +#ifdef BSP_USING_PWM2 + const port_pin_config_t port3_10_pin40_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as PWM0_A0 */ + kPORT_MuxAlt5, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_10 (pin 40) is configured as PWM0_A2 */ + PORT_SetPinConfig(PORT3, 10U, &port3_10_pin40_config); #endif #ifdef BSP_USING_SPI0