Skip to content

Commit

Permalink
[bsp][nxp][mcxa153] the full implementation of eFlexPWM
Browse files Browse the repository at this point in the history
  • Loading branch information
hywing committed Dec 18, 2024
1 parent e476036 commit ecdab1f
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 46 deletions.
133 changes: 95 additions & 38 deletions bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,95 @@
*
* Change Logs:
* Date Author Notes
* 2024-08-1 hywing Initial version.
* 2024-12-18 hywing Initial version.
*/

#include <rtthread.h>
#include <rtdevice.h>
#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;

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;
}

Expand Down Expand Up @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,13 @@ menu "On-chip Peripheral Drivers"

if BSP_USING_PWM
config BSP_USING_PWM0
bool "Enable PWM0"
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
Expand Down
65 changes: 58 additions & 7 deletions bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down

0 comments on commit ecdab1f

Please sign in to comment.