diff --git a/bsp/lpc55sxx/Libraries/drivers/drv_pwm.c b/bsp/lpc55sxx/Libraries/drivers/drv_pwm.c index 4abb65b1d0..0f8a4bb16a 100644 --- a/bsp/lpc55sxx/Libraries/drivers/drv_pwm.c +++ b/bsp/lpc55sxx/Libraries/drivers/drv_pwm.c @@ -7,12 +7,18 @@ * Date Author Notes * 2019-04-28 tyustli first version * 2019-07-15 Magicoe The first version for LPC55S6x, we can also use SCT as PWM - * + * 2023-02-28 Z8MAN8 Update docking to the RT-Thread device frame */ #include #ifdef RT_USING_PWM +#if !defined(BSP_USING_CTIMER1_MAT0) && !defined(BSP_USING_CTIMER1_MAT1) && \ + !defined(BSP_USING_CTIMER1_MAT2) +#error "Please define at least one BSP_USING_CTIMERx_MATx" +#else + #define BSP_USING_CTIMER1 +#endif #if !defined(BSP_USING_CTIMER2_MAT0) && !defined(BSP_USING_CTIMER2_MAT1) && \ !defined(BSP_USING_CTIMER2_MAT2) #error "Please define at least one BSP_USING_CTIMERx_MATx" @@ -30,6 +36,67 @@ #define DEFAULT_DUTY 50 #define DEFAULT_FREQ 1000 +enum +{ +#ifdef BSP_USING_CTIMER1 + PWM1_INDEX, +#endif +#ifdef BSP_USING_CTIMER2 + PWM2_INDEX, +#endif +}; + +struct lpc_pwm +{ + struct rt_device_pwm pwm_device; + CTIMER_Type * tim; + uint32_t channel; + char *name; +}; + +static struct lpc_pwm lpc_pwm_obj[] = +{ +#if defined(BSP_USING_CTIMER1_MAT0) || defined(BSP_USING_CTIMER1_MAT1) || \ + defined(BSP_USING_CTIMER1_MAT2) + { + .tim = CTIMER1, + .name = "pwm1", + .channel = RT_NULL + }, +#endif + +#if defined(BSP_USING_CTIMER2_MAT0) || defined(BSP_USING_CTIMER2_MAT1) || \ + defined(BSP_USING_CTIMER2_MAT2) + { + .tim = CTIMER2, + .name = "pwm2", + .channel = RT_NULL + }, +#endif +}; + +static void pwm_get_channel(void) +{ +#ifdef BSP_USING_CTIMER1_MAT0 + lpc_pwm_obj[PWM1_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_CTIMER1_MAT1 + lpc_pwm_obj[PWM1_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_CTIMER1_MAT2 + lpc_pwm_obj[PWM1_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_CTIMER2_MAT0 + lpc_pwm_obj[PWM2_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_CTIMER2_MAT1 + lpc_pwm_obj[PWM2_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_CTIMER2_MAT2 + lpc_pwm_obj[PWM2_INDEX].channel |= 1 << 2; +#endif +} + static rt_err_t lpc_drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg); static struct rt_pwm_ops lpc_drv_ops = @@ -66,18 +133,32 @@ static rt_err_t lpc_drv_pwm_get(struct rt_device_pwm *device, struct rt_pwm_conf base = (CTIMER_Type *)device->parent.user_data; -#ifdef BSP_USING_CTIMER2 /* get frequence */ - pwmClock = CLOCK_GetCTimerClkFreq(2U) ; -#endif - + if (base == CTIMER1) + { + pwmClock = CLOCK_GetCTimerClkFreq(1U) ; + } + else if(base == CTIMER2) + { + pwmClock = CLOCK_GetCTimerClkFreq(2U) ; + } get_frequence = pwmClock / (base->MR[kCTIMER_Match_3] + 1); - if(configuration->channel == 1) + if(configuration->channel == 0) + { + /* get dutycycle */ + get_duty = (100*(base->MR[kCTIMER_Match_3] + 1 - base->MR[kCTIMER_Match_0]))/(base->MR[kCTIMER_Match_3] + 1); + } + else if(configuration->channel == 1) { /* get dutycycle */ get_duty = (100*(base->MR[kCTIMER_Match_3] + 1 - base->MR[kCTIMER_Match_1]))/(base->MR[kCTIMER_Match_3] + 1); } + else if(configuration->channel == 2) + { + /* get dutycycle */ + get_duty = (100*(base->MR[kCTIMER_Match_3] + 1 - base->MR[kCTIMER_Match_2]))/(base->MR[kCTIMER_Match_3] + 1); + } /* get dutycycle */ /* conversion */ @@ -106,23 +187,38 @@ static rt_err_t lpc_drv_pwm_set(struct rt_device_pwm *device, struct rt_pwm_conf /* Timer counter is incremented on every APB bus clock */ config.prescale = 0; - if(configuration->channel == 1) + /* Get the PWM period match value and pulse width match value of DEFAULT_FREQ PWM signal with DEFAULT_DUTY dutycycle */ + /* Calculate PWM period match value */ + double tmp = configuration->period; + /* Target frequence. */ + tmp = 1000000000/tmp; + if (base == CTIMER1) + { + pwmPeriod = (( CLOCK_GetCTimerClkFreq(1U) / (config.prescale + 1) ) / (uint32_t)tmp) - 1; + } + else if (base == CTIMER2) { - /* Get the PWM period match value and pulse width match value of DEFAULT_FREQ PWM signal with DEFAULT_DUTY dutycycle */ - /* Calculate PWM period match value */ - double tmp = configuration->period; - /* Target frequence. */ - tmp = 1000000000/tmp; pwmPeriod = (( CLOCK_GetCTimerClkFreq(2U) / (config.prescale + 1) ) / (uint32_t)tmp) - 1; + } - /* Calculate pulse width match value */ - tmp = configuration->pulse; - pulsePeriod = (1.0 - tmp / configuration->period) * pwmPeriod; - /* Match on channel 3 will define the PWM period */ - base->MR[kCTIMER_Match_3] = pwmPeriod; - /* This will define the PWM pulse period */ + /* Calculate pulse width match value */ + tmp = configuration->pulse; + pulsePeriod = (1.0 - tmp / configuration->period) * pwmPeriod; + /* Match on channel 3 will define the PWM period */ + base->MR[kCTIMER_Match_3] = pwmPeriod; + + /* This will define the PWM pulse period */ + if(configuration->channel == 0) + { + base->MR[kCTIMER_Match_0] = pulsePeriod; + } + else if(configuration->channel == 1) + { base->MR[kCTIMER_Match_1] = pulsePeriod; - + } + else if(configuration->channel == 2) + { + base->MR[kCTIMER_Match_2] = pulsePeriod; } return RT_EOK; @@ -147,32 +243,54 @@ static rt_err_t lpc_drv_pwm_control(struct rt_device_pwm *device, int cmd, void } } -int rt_hw_pwm_init(void) +static rt_err_t rt_hw_pwm_init(struct lpc_pwm *device) { rt_err_t ret = RT_EOK; + CTIMER_Type *tim = RT_NULL; + uint32_t channel = RT_NULL; -#ifdef BSP_USING_CTIMER2 - - static struct rt_device_pwm pwm2_device; + static struct rt_device_pwm pwm_device; ctimer_config_t config; uint32_t pwmPeriod, pulsePeriod; - /* Use 12 MHz clock for some of the Ctimers */ - CLOCK_AttachClk(kMAIN_CLK_to_CTIMER2); - /* Run as a timer */ - config.mode = kCTIMER_TimerMode; - /* This field is ignored when mode is timer */ - config.input = kCTIMER_Capture_0; - /* Timer counter is incremented on every APB bus clock */ - config.prescale = 0; + tim = device->tim; + channel = device->channel; - CTIMER_Init(CTIMER2, &config); + if(tim == CTIMER1) + { + /* Use 12 MHz clock for some of the Ctimers */ + CLOCK_AttachClk(kMAIN_CLK_to_CTIMER1); -#ifdef BSP_USING_CTIMER2_MAT1 - /* Get the PWM period match value and pulse width match value of DEFAULT_FREQ PWM signal with DEFAULT_DUTY dutycycle */ - /* Calculate PWM period match value */ - pwmPeriod = (( CLOCK_GetCTimerClkFreq(2U) / (config.prescale + 1) ) / DEFAULT_FREQ) - 1; + /* Run as a timer */ + config.mode = kCTIMER_TimerMode; + /* This field is ignored when mode is timer */ + config.input = kCTIMER_Capture_0; + /* Timer counter is incremented on every APB bus clock */ + config.prescale = 0; + + CTIMER_Init(CTIMER1, &config); + /* Get the PWM period match value and pulse width match value of DEFAULT_FREQ PWM signal with DEFAULT_DUTY dutycycle */ + /* Calculate PWM period match value */ + pwmPeriod = (( CLOCK_GetCTimerClkFreq(1U) / (config.prescale + 1) ) / DEFAULT_FREQ) - 1; + } + else if (tim == CTIMER2) + { + /* Use 12 MHz clock for some of the Ctimers */ + CLOCK_AttachClk(kMAIN_CLK_to_CTIMER2); + + /* Run as a timer */ + config.mode = kCTIMER_TimerMode; + /* This field is ignored when mode is timer */ + config.input = kCTIMER_Capture_0; + /* Timer counter is incremented on every APB bus clock */ + config.prescale = 0; + + CTIMER_Init(CTIMER2, &config); + /* Get the PWM period match value and pulse width match value of DEFAULT_FREQ PWM signal with DEFAULT_DUTY dutycycle */ + /* Calculate PWM period match value */ + pwmPeriod = (( CLOCK_GetCTimerClkFreq(2U) / (config.prescale + 1) ) / DEFAULT_FREQ) - 1; + } /* Calculate pulse width match value */ if (DEFAULT_DUTY == 0) @@ -183,21 +301,57 @@ int rt_hw_pwm_init(void) { pulsePeriod = ((pwmPeriod + 1) * (100 - DEFAULT_DUTY)) / 100; } - CTIMER_SetupPwmPeriod(CTIMER2, kCTIMER_Match_3 , kCTIMER_Match_1, pwmPeriod, pulsePeriod, false); -#endif - ret = rt_device_pwm_register(&pwm2_device, "pwm2", &lpc_drv_ops, CTIMER2); - - if (ret != RT_EOK) + if (channel & 0x01) { - LOG_E("%s register failed", "pwm2"); + CTIMER_SetupPwmPeriod(tim, kCTIMER_Match_3 , kCTIMER_Match_0, pwmPeriod, pulsePeriod, false); + } + if (channel & 0x02) + { + CTIMER_SetupPwmPeriod(tim, kCTIMER_Match_3 , kCTIMER_Match_1, pwmPeriod, pulsePeriod, false); + } + if (channel & 0x04) + { + CTIMER_SetupPwmPeriod(tim, kCTIMER_Match_3 , kCTIMER_Match_2, pwmPeriod, pulsePeriod, false); } - -#endif /* BSP_USING_CTIMER2 */ - return ret; } -INIT_DEVICE_EXPORT(rt_hw_pwm_init); +static int lpc_pwm_init(void) +{ + int i = 0; + int result = RT_EOK; + pwm_get_channel(); + + for (i = 0; i < sizeof(lpc_pwm_obj) / sizeof(lpc_pwm_obj[0]); i++) + { + /* pwm init */ + if (rt_hw_pwm_init(&lpc_pwm_obj[i]) != RT_EOK) + { + LOG_E("%s init failed", lpc_pwm_obj[i].name); + result = -RT_ERROR; + goto __exit; + } + else + { + LOG_D("%s init success", lpc_pwm_obj[i].name); + + /* register pwm device */ + if (rt_device_pwm_register(&lpc_pwm_obj[i].pwm_device, lpc_pwm_obj[i].name, &lpc_drv_ops, lpc_pwm_obj[i].tim) == RT_EOK) + { + LOG_D("%s register success", lpc_pwm_obj[i].name); + } + else + { + LOG_E("%s register failed", lpc_pwm_obj[i].name); + result = -RT_ERROR; + } + } + } + +__exit: + return result; +} +INIT_DEVICE_EXPORT(lpc_pwm_init); #endif /* RT_USING_PWM */ diff --git a/bsp/lpc55sxx/Libraries/drivers/drv_pwm.h b/bsp/lpc55sxx/Libraries/drivers/drv_pwm.h index 264d464e76..7b1c5ea777 100644 --- a/bsp/lpc55sxx/Libraries/drivers/drv_pwm.h +++ b/bsp/lpc55sxx/Libraries/drivers/drv_pwm.h @@ -14,6 +14,4 @@ #include -int rt_hw_pwm_init(void); - #endif diff --git a/bsp/lpc55sxx/lpc55s69_nxp_evk/applications/arduino_pinout/pins_arduino.c b/bsp/lpc55sxx/lpc55s69_nxp_evk/applications/arduino_pinout/pins_arduino.c index 2d7d8bd4f9..430e32a289 100644 --- a/bsp/lpc55sxx/lpc55s69_nxp_evk/applications/arduino_pinout/pins_arduino.c +++ b/bsp/lpc55sxx/lpc55s69_nxp_evk/applications/arduino_pinout/pins_arduino.c @@ -29,8 +29,8 @@ const pin_map_t pin_map_table[]= {D3, GET_PINS(1,6)}, {D4, GET_PINS(1,7), "pwm2", 2}, /* PWM */ {D5, GET_PINS(1,4), "pwm2", 1}, /* PWM */ - {D6, GET_PINS(1,10)}, - {D7, GET_PINS(1,9), "pwm1", 0}, /* PWM */ + {D6, GET_PINS(1,10), "pwm1", 0}, /* PWM */ + {D7, GET_PINS(1,9)}, {D8, GET_PINS(1,8)}, {D9, GET_PINS(1,5)}, {D10, GET_PINS(1,1)}, diff --git a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig index ed014dbc0d..aff50947c0 100644 --- a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig +++ b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig @@ -212,21 +212,13 @@ menu "On-chip Peripheral Drivers" default y if BSP_USING_PWM - config BSP_USING_CTIMER0_MAT3 - bool "Enable CIMER0 Match3 as PWM output" - default y - config BSP_USING_CTIMER1_MAT0 bool "Enable CIMER1 Match0 as PWM output" default y - config BSP_USING_CTIMER1_MAT3 - bool "Enable CIMER1 Match3 as PWM output" - default n - config BSP_USING_CTIMER2_MAT0 bool "Enable CIMER2 Match0 as PWM output" - default y + default n config BSP_USING_CTIMER2_MAT1 bool "Enable CIMER2 Match1 as PWM output" @@ -272,11 +264,9 @@ menu "Onboard Peripheral Drivers" select BSP_USING_ADC0 select BSP_USING_PWM select BSP_USING_CTIMER1_MAT0 - select BSP_USING_CTIMER1_MAT3 select BSP_USING_CTIMER2_MAT0 select BSP_USING_CTIMER2_MAT1 select BSP_USING_CTIMER2_MAT2 - select BSP_USING_CTIMER3_MAT2 select BSP_USING_I2C select BSP_USING_I2C1 imply RTDUINO_USING_SERVO diff --git a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.c b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.c index f04b9753f5..2e717ceecb 100644 --- a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.c +++ b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.c @@ -338,13 +338,26 @@ void BOARD_InitPins(void) (~(IOCON_PIO_FUNC_MASK | IOCON_PIO_DIGIMODE_MASK))) /* Selects pin function. - * : PORT17 (pin 9) is configured as PIO1_7. */ - | IOCON_PIO_FUNC(PIO1_7_FUNC_ALT0) + * : PORT17 (pin 9) is configured as CTIMER2_MAT2. */ + | IOCON_PIO_FUNC(PIO1_7_FUNC_ALT3) /* Select Digital mode. * : Digital mode, digital input is enabled. */ | IOCON_PIO_DIGIMODE(PIO1_7_DIGIMODE_DIGITAL)); + IOCON->PIO[1][10] = ((IOCON->PIO[1][10] & + /* Mask bits to zero which are setting */ + (~(IOCON_PIO_FUNC_MASK | IOCON_PIO_DIGIMODE_MASK))) + + /* Selects pin function. + * : PORT110 (pin 40) is configured as CTIMER1_MAT0. */ + | IOCON_PIO_FUNC(PIO1_10_FUNC_ALT3) + + /* Select Digital mode. + * : Enable Digital mode. + * Digital input is enabled. */ + | IOCON_PIO_DIGIMODE(PIO1_10_DIGIMODE_DIGITAL)); + /* I2C4 */ IOCON_PinMuxSet(IOCON, 1U, 20, 5 | IOCON_PIO_MODE_INACT | IOCON_PIO_SLEW_STANDARD | IOCON_PIO_INV_DI | IOCON_PIO_DIGITAL_EN | IOCON_PIO_OPENDRAIN_DI); IOCON_PinMuxSet(IOCON, 1U, 21, 5 | IOCON_PIO_MODE_INACT | IOCON_PIO_SLEW_STANDARD | IOCON_PIO_INV_DI | IOCON_PIO_DIGITAL_EN | IOCON_PIO_OPENDRAIN_DI); diff --git a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.h b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.h index 6a9b78dc1c..39846c8c10 100644 --- a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.h +++ b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/MCUX_Config/board/pin_mux.h @@ -174,8 +174,14 @@ void BOARD_InitBootPins(void); * @brief Select Digital mode.: Digital mode, digital input is enabled. */ #define PIO1_7_DIGIMODE_DIGITAL 0x01u /*! - * @brief Selects pin function.: Alternative connection 0. */ -#define PIO1_7_FUNC_ALT0 0x00u + * @brief Selects pin function.: Alternative connection 3. */ +#define PIO1_7_FUNC_ALT3 0x03u +/*! + * @brief Select Digital mode.: Enable Digital mode. Digital input is enabled. */ +#define PIO1_10_DIGIMODE_DIGITAL 0x01u +/*! + * @brief Selects pin function.: Alternative connection 3. */ +#define PIO1_10_FUNC_ALT3 0x03u /*! * @brief Configures pin routing and optionally pin electrical features.