From 61a2bf615426afa62227eeb24b4767c42349f8d8 Mon Sep 17 00:00:00 2001 From: hywing <2112093745@qq.com> Date: Thu, 1 Aug 2024 23:42:21 +0800 Subject: [PATCH] [bsp][nxp][mcxa153] add pwm driver --- bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c | 129 ++++++++++++++++++ bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.h | 19 +++ bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig | 24 +--- .../board/MCUX_Config/board/pin_mux.c | 34 +++++ 4 files changed, 186 insertions(+), 20 deletions(-) create mode 100644 bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c create mode 100644 bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.h diff --git a/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c new file mode 100644 index 0000000000..b0f30b7d98 --- /dev/null +++ b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-08-1 hywing Initial version. + */ + +#include +#include +#include "fsl_ctimer.h" + +#ifdef RT_USING_PWM + +typedef struct +{ + struct rt_device_pwm pwm_device; + CTIMER_Type *ct_instance; + uint32_t timerClock; + const ctimer_match_t pwmPeriodChannel; + ctimer_match_t matchChannel; + 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, + .name = "pwm0", + } +#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); + 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); + 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); + return 0; +} + +static rt_err_t mcx_drv_pwm_control(struct rt_device_pwm *device, int cmd, void *args) +{ + mcx_pwm_obj_t *pwm = device->parent.user_data; + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)args; + + switch (cmd) + { + case PWM_CMD_ENABLE: + return mcx_drv_pwm_enable(pwm, configuration); + + case PWM_CMD_DISABLE: + return mcx_drv_pwm_disable(pwm, configuration); + + case PWM_CMD_SET: + return mcx_drv_pwm_set(pwm, configuration); + + case PWM_CMD_GET: + return mcx_drv_pwm_get(pwm, configuration); + + default: + return -RT_EINVAL; + } + + return RT_EOK; +} + +static struct rt_pwm_ops mcx_pwm_ops = +{ + .control = mcx_drv_pwm_control, +}; + +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++) + { + 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) + { + return ret; + } + } + return RT_EOK; +} + +INIT_DEVICE_EXPORT(mcx_pwm_init); + +#endif /* RT_USING_PWM */ diff --git a/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.h b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.h new file mode 100644 index 0000000000..e6dad6d193 --- /dev/null +++ b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_pwm.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-02-26 Yilin Sun Initial version. + */ + +#ifndef __DRV_PWM_H__ +#define __DRV_PWM_H__ + +#include +#include + +int mcx_pwm_init(void); + +#endif diff --git a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig index 25b0fbb767..59adb4aaa6 100644 --- a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig +++ b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig @@ -125,28 +125,12 @@ menu "On-chip Peripheral Drivers" config BSP_USING_PWM bool "Enable PWM" select RT_USING_PWM - default y + default N if BSP_USING_PWM - config BSP_USING_CTIMER1_MAT0 - bool "Enable CIMER1 Match0 as PWM output" - default y - - config BSP_USING_CTIMER2_MAT0 - bool "Enable CIMER2 Match0 as PWM output" - default n - - config BSP_USING_CTIMER2_MAT1 - bool "Enable CIMER2 Match1 as PWM output" - default n - - config BSP_USING_CTIMER2_MAT2 - bool "Enable CIMER2 Match2 as PWM output" - default n - - config BSP_USING_CTIMER3_MAT2 - bool "Enable CIMER3 Match2 as PWM output" - default n + config BSP_USING_PWM0 + bool "Enable PWM0" + 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 3e14f1e076..d6f6f20b84 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 @@ -43,10 +43,15 @@ void BOARD_InitPins(void) CLOCK_EnableClock(kCLOCK_GateGPIO1); CLOCK_EnableClock(kCLOCK_GateGPIO2); CLOCK_EnableClock(kCLOCK_GateGPIO3); + + CLOCK_SetClockDiv(kCLOCK_DivCTIMER1, 1u); + CLOCK_AttachClk(kFRO_HF_to_CTIMER1); RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPUART1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPUART2_RST_SHIFT_RSTn); + + RESET_ReleasePeripheralReset(kCTIMER1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); @@ -107,4 +112,33 @@ void BOARD_InitPins(void) kPORT_UnlockRegister}; /* PORT0_3 (pin 52) is configured as LPUART0_TXD */ PORT_SetPinConfig(PORT0, 3U, &port0_3_pin52_config); + +#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 */ + 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 CT1_MAT2 */ + kPORT_MuxAlt4, + /* 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); +#endif }