diff --git a/bsp/raspberry-pico/Kconfig b/bsp/raspberry-pico/Kconfig index 523fa9f2ad..1e61d7ce03 100644 --- a/bsp/raspberry-pico/Kconfig +++ b/bsp/raspberry-pico/Kconfig @@ -237,6 +237,166 @@ menu "On-chip Peripheral Drivers" default n endif + menuconfig BSP_USING_PWM + bool "Enable PWM(A:CH_0 B:CH_1)" + default n + select RT_USING_PWM + if BSP_USING_PWM + config BSP_USING_PWM0 + bool "Enable PWM0" + default n + if BSP_USING_PWM0 + config BSP_PWM0_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 0 + config BSP_PWM0_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 1 + config BSP_PWM0_A_ALL + bool "pwm slice use all A pin" + default n + config BSP_PWM0_B_ALL + bool "pwm slice use all B pin" + default n + endif + + config BSP_USING_PWM1 + bool "Enable PWM1" + default n + if BSP_USING_PWM1 + config BSP_PWM_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 2 + config BSP_PWM1_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 3 + config BSP_PWM1_A_ALL + bool "pwm slice use all A pin" + default n + config BSP_PWM1_B_ALL + bool "pwm slice use all B pin" + default n + endif + + config BSP_USING_PWM2 + bool "Enable PWM2" + default n + if BSP_USING_PWM2 + config BSP_PWM2_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 4 + config BSP_PWM2_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 5 + config BSP_PWM2_A_ALL + bool "pwm slice use all A pin" + default n + config BSP_PWM2_B_ALL + bool "pwm slice use all B pin" + default n + endif + + config BSP_USING_PWM3 + bool "Enable PWM3" + default n + if BSP_USING_PWM3 + config BSP_PWM3_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 6 + config BSP_PWM3_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 7 + config BSP_PWM3_A_ALL + bool "pwm slice use all A pin" + default n + config BSP_PWM3_B_ALL + bool "pwm slice use all B pin" + default n + endif + + config BSP_USING_PWM4 + bool "Enable PWM4" + default n + if BSP_USING_PWM4 + config BSP_PWM4_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 8 + config BSP_PWM4_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 9 + config BSP_PWM4_A_ALL + bool "pwm slice use all A pin" + default n + config BSP_PWM4_B_ALL + bool "pwm slice use all B pin" + default n + endif + + config BSP_USING_PWM5 + bool "Enable PWM5" + default n + if BSP_USING_PWM5 + config BSP_PWM5_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 10 + config BSP_PWM5_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 11 + config BSP_PWM5_A_ALL + bool "pwm slice use all A pin" + default n + config BSP_PWM5_B_ALL + bool "pwm slice use all B pin" + default n + endif + + config BSP_USING_PWM6 + bool "Enable PWM6" + default n + if BSP_USING_PWM6 + config BSP_PWM6_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 12 + config BSP_PWM6_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 13 + config BSP_PWM6_A_ALL + bool "pwm slice use all A pin" + default n + config BSP_PWM6_B_ALL + bool "pwm slice use all B pin" + default n + endif + + config BSP_USING_PWM7 + bool "Enable PWM7" + default n + if BSP_USING_PWM7 + config BSP_PWM7_A_PIN + int "pwm slice A pin number (GP)" + range 0 29 + default 14 + config BSP_PWM7_B_PIN + int "pwm slice B pin number (GP)" + range 0 29 + default 15 + endif + endif + menuconfig BSP_USING_I2C bool "Enable I2C" select RT_USING_I2C diff --git a/bsp/raspberry-pico/drivers/SConscript b/bsp/raspberry-pico/drivers/SConscript index 63f598cd84..a05cd2aed2 100644 --- a/bsp/raspberry-pico/drivers/SConscript +++ b/bsp/raspberry-pico/drivers/SConscript @@ -31,6 +31,9 @@ if GetDepend('BSP_USING_I2C'): if GetDepend('BSP_USING_ON_CHIP_FLASH'): src += ['drv_flash.c'] +if GetDepend('BSP_USING_PWM'): + src += ['drv_pwm.c'] + group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) Return('group') diff --git a/bsp/raspberry-pico/drivers/drv_pwm.c b/bsp/raspberry-pico/drivers/drv_pwm.c new file mode 100644 index 0000000000..22251aa42a --- /dev/null +++ b/bsp/raspberry-pico/drivers/drv_pwm.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-10-20 ChuShicheng first version + */ +#include "drv_pwm.h" +#include "board.h" +#include "hardware/pwm.h" + +#ifdef BSP_USING_PWM + +#define DBG_LEVEL DBG_LOG +#include +#define LOG_TAG "DRV.PWM" + +struct pico_pwm +{ + struct rt_device_pwm pwm_device; + rt_uint8_t slice_num; + rt_uint8_t pin_a; + rt_uint8_t pin_b; + rt_uint8_t a_all_flag; /* 1: Two pins simultaneously output PWM A channel */ + rt_uint8_t b_all_flag; /* 1: Two pins simultaneously output PWM B channel */ + char *name; +}; + +static struct pico_pwm pico_pwm_obj[] = +{ +#ifdef BSP_USING_PWM0 + { + .name = "pwm0", + .slice_num = 0, + .pin_a = BSP_PWM0_A_PIN, + .pin_b = BSP_PWM0_B_PIN, +#ifdef BSP_PWM0_A_ALL + .a_all_flag = 1, +#endif /* BSP_PWM0_A_ALL */ +#ifdef BSP_PWM0_B_ALL + .b_all_flag = 1, +#endif /* BSP_PWM0_B_ALL */ + }, +#endif /* BSP_USING_PWM0 */ +#ifdef BSP_USING_PWM1 + { + .name = "pwm1", + .slice_num = 1, + .pin_a = BSP_PWM1_A_PIN, + .pin_b = BSP_PWM1_B_PIN, +#ifdef BSP_PWM1_A_ALL + .a_all_flag = 1, +#endif /* BSP_PWM1_A_ALL */ +#ifdef BSP_PWM1_B_ALL + .b_all_flag = 1, +#endif /* BSP_PWM1_B_ALL */ + }, +#endif /* BSP_USING_PWM1 */ +#ifdef BSP_USING_PWM2 + { + .name = "pwm2", + .slice_num = 2, + .pin_a = BSP_PWM2_A_PIN, + .pin_b = BSP_PWM2_B_PIN, +#ifdef BSP_PWM2_A_ALL + .a_all_flag = 1, +#endif /* BSP_PWM2_A_ALL */ +#ifdef BSP_PWM2_B_ALL + .b_all_flag = 1, +#endif /* BSP_PWM2_B_ALL */ + }, +#endif /* BSP_USING_PWM2 */ +#ifdef BSP_USING_PWM3 + { + .name = "pwm3", + .slice_num = 3, + .pin_a = BSP_PWM3_A_PIN, + .pin_b = BSP_PWM3_B_PIN, +#ifdef BSP_PWM3_A_ALL + .a_all_flag = 1, +#endif /* BSP_PWM3_A_ALL */ +#ifdef BSP_PWM3_B_ALL + .b_all_flag = 1, +#endif /* BSP_PWM3_B_ALL */ + }, +#endif /* BSP_USING_PWM3 */ +#ifdef BSP_USING_PWM4 + { + .name = "pwm4", + .slice_num = 4, + .pin_a = BSP_PWM4_A_PIN, + .pin_b = BSP_PWM4_B_PIN, +#ifdef BSP_PWM4_A_ALL + .a_all_flag = 1, +#endif /* BSP_PWM4_A_ALL */ +#ifdef BSP_PWM4_B_ALL + .b_all_flag = 1, +#endif /* BSP_PWM4_B_ALL */ + }, +#endif /* BSP_USING_PWM4 */ +#ifdef BSP_USING_PWM5 + { + .name = "pwm5", + .slice_num = 5, + .pin_a = BSP_PWM5_A_PIN, + .pin_b = BSP_PWM5_B_PIN, +#ifdef BSP_PWM5_A_ALL + .a_all_flag = 1, +#endif /* BSP_PWM5_A_ALL */ +#ifdef BSP_PWM5_B_ALL + .b_all_flag = 1, +#endif /* BSP_PWM5_B_ALL */ + }, +#endif /* BSP_USING_PWM5 */ +#ifdef BSP_USING_PWM6 + { + .name = "pwm6", + .slice_num = 6, + .pin_a = BSP_PWM6_A_PIN, + .pin_b = BSP_PWM6_B_PIN, +#ifdef BSP_PWM6_A_ALL + .a_all_flag = 1, +#endif /* BSP_PWM6_A_ALL */ +#ifdef BSP_PWM6_B_ALL + .b_all_flag = 1, +#endif /* BSP_PWM6_B_ALL */ + }, +#endif /* BSP_USING_PWM6 */ +#ifdef BSP_USING_PWM7 + { + .name = "pwm7", + .slice_num = 7, + .pin_a = BSP_PWM7_A_PIN, + .pin_b = BSP_PWM7_B_PIN, + }, +#endif /* BSP_USING_PWM7 */ +}; + + +static rt_err_t _pwm_set(rt_uint8_t slice_num, struct rt_pwm_configuration *configuration) +{ + uint32_t period_hz = 1000000000 / configuration->period; + uint32_t pulse = 1000000000 / configuration->pulse; + + pwm_config config = pwm_get_default_config(); + pwm_config_set_clkdiv(&config, 1.33f); + pwm_init(slice_num, &config, true); + pwm_set_wrap(slice_num, 100000000 / period_hz); + pwm_set_chan_level(slice_num, configuration->channel, 100000000 / pulse); + + return RT_EOK; +} + +static rt_err_t _pwm_get(rt_uint8_t slice_num, struct rt_pwm_configuration *configuration) +{ + uint32_t period_hz = pwm_hw->slice[slice_num].top; + + configuration->period = period_hz * 10; + + configuration->pulse = pwm_hw->slice[slice_num].cc * 10; + + return RT_EOK; +} + +static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct pico_pwm *_pwm = rt_container_of(device, struct pico_pwm, pwm_device); + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; + + switch (cmd) + { + case PWM_CMD_ENABLE: + pwm_set_enabled (_pwm->slice_num, RT_TRUE); + return RT_EOK; + case PWM_CMD_DISABLE: + pwm_set_enabled (_pwm->slice_num, RT_FALSE); + return RT_EOK; + case PWM_CMD_SET: + return _pwm_set(_pwm->slice_num, configuration); + case PWM_CMD_GET: + return _pwm_get(_pwm->slice_num, configuration); + default: + return -RT_EINVAL; + } +} + +static struct rt_pwm_ops _pwm_ops = +{ + _pwm_control +}; + +int rt_hw_pwm_init(void) +{ + int result = RT_EOK; + + for (int i = 0; i < sizeof(pico_pwm_obj) / sizeof(pico_pwm_obj[0]); i++) + { + if(pico_pwm_obj[i].a_all_flag) + { + gpio_set_function(pico_pwm_obj[i].slice_num * 2, GPIO_FUNC_PWM); + gpio_set_function(pico_pwm_obj[i].slice_num * 2 + 16, GPIO_FUNC_PWM); + } + else + { + gpio_set_function(pico_pwm_obj[i].pin_a, GPIO_FUNC_PWM); + } + if(pico_pwm_obj[i].b_all_flag) + { + gpio_set_function(pico_pwm_obj[i].slice_num * 2 + 1, GPIO_FUNC_PWM); + gpio_set_function(pico_pwm_obj[i].slice_num * 2 + 17, GPIO_FUNC_PWM); + } + else + { + gpio_set_function(pico_pwm_obj[i].pin_b, GPIO_FUNC_PWM); + } + result = rt_device_pwm_register(&pico_pwm_obj[i].pwm_device, pico_pwm_obj[i].name, &_pwm_ops, 0); + if(result != RT_EOK) + { + LOG_E("%s register fail.", pico_pwm_obj[i].name); + } + } + + return result; +} +INIT_DEVICE_EXPORT(rt_hw_pwm_init); + +#endif /* BSP_USING_PWM */ diff --git a/bsp/raspberry-pico/drivers/drv_pwm.h b/bsp/raspberry-pico/drivers/drv_pwm.h new file mode 100644 index 0000000000..b624008b7c --- /dev/null +++ b/bsp/raspberry-pico/drivers/drv_pwm.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-10-20 ChuShicheng first version + */ + +#ifndef __DRV_PWM_H__ +#define __DRV_PWM_H__ + +#include + +int rt_hw_pwm_init(void); + +#endif /* __DRV_PWM_H__ */