diff --git a/bsp/ESP32_C3/drivers/Kconfig b/bsp/ESP32_C3/drivers/Kconfig index cbe0cde821..85ad0c6649 100644 --- a/bsp/ESP32_C3/drivers/Kconfig +++ b/bsp/ESP32_C3/drivers/Kconfig @@ -96,6 +96,36 @@ menu "On-chip Peripheral Drivers" default n endif + menuconfig BSP_USING_PWM + bool "Enable PWM" + default n + select RT_USING_PWM + if BSP_USING_PWM + menuconfig BSP_USING_PWM0 + bool "Enable PWM0" + default n + if BSP_USING_PWM0 + config BSP_LEDC_CH0_GPIO + int "LEDC CH0 GPIO PIN SET" + default 12 + config BSP_LEDC_CH1_GPIO + int "LEDC CH1 GPIO PIN SET" + default 6 + config BSP_LEDC_CH2_GPIO + int "LEDC CH2 GPIO PIN SET" + default 2 + config BSP_LEDC_CH3_GPIO + int "LEDC CH3 GPIO PIN SET" + default 10 + config BSP_LEDC_CH4_GPIO + int "LEDC CH4 GPIO PIN SET" + default 8 + config BSP_LEDC_CH5_GPIO + int "LEDC CH5 GPIO PIN SET" + default 18 + endif + endif + endmenu config BSP_ENABLE_GDBSTUB diff --git a/bsp/ESP32_C3/drivers/drv_adc.c b/bsp/ESP32_C3/drivers/drv_adc.c index efd0705ea0..7d8190dfe7 100644 --- a/bsp/ESP32_C3/drivers/drv_adc.c +++ b/bsp/ESP32_C3/drivers/drv_adc.c @@ -25,7 +25,7 @@ #define GET_UNIT(x) ((x>>3) & 0x1) /* esp i2c dirver class */ -static struct esp_adc +struct esp_adc { struct rt_adc_ops ops; struct rt_adc_device adc_device; diff --git a/bsp/ESP32_C3/drivers/drv_pwm.c b/bsp/ESP32_C3/drivers/drv_pwm.c new file mode 100644 index 0000000000..acbf1bf4be --- /dev/null +++ b/bsp/ESP32_C3/drivers/drv_pwm.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-11-26 ChuShicheng first version + */ + +#include +#include "drv_pwm.h" +#include "driver/ledc.h" + + +#ifdef BSP_USING_PWM + +#define DBG_LEVEL DBG_LOG +#include +#define LOG_TAG "DRV.PWM" + +#define LEDC_MODE LEDC_LOW_SPEED_MODE +#define LEDC_DUTY_DEFAULT (4095) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095 +#define LEDC_FREQUENCY_DEFAULT (5000) // Frequency in Hertz. Set frequency at 5 kHz + +struct esp_pwm +{ + struct rt_device_pwm pwm_device; + rt_uint8_t timer_num; + char *name; +}; + +static struct esp_pwm esp_pwm_obj[] = +{ +#ifdef BSP_USING_PWM0 + { + .name = "pwm0", + .timer_num = 0, + } +#endif /* BSP_USING_PWM0 */ +}; + +static rt_err_t _pwm_set(struct esp_pwm *obj, struct rt_pwm_configuration *configuration) +{ + float period = configuration->period; + float pulse = configuration->pulse; + float duty = 8191 * (pulse / period); // ((2 ** 13) - 1) * (pulse / period_hz) + float period_hz = 1000000000 / configuration->period; + + ledc_timer_config_t ledc_timer = { + .speed_mode = LEDC_MODE, + .timer_num = obj->timer_num, + .duty_resolution = LEDC_TIMER_13_BIT, + .freq_hz = (uint32_t)period_hz, // Set output frequency at 5 kHz + .clk_cfg = LEDC_AUTO_CLK + }; + ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); + + ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, configuration->channel, (uint32_t)duty)); + // Update duty to apply the new value + ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, configuration->channel)); + + return RT_EOK; +} + +static rt_err_t _pwm_get(struct esp_pwm *obj, struct rt_pwm_configuration *configuration) +{ + uint32_t period_hz = ledc_get_freq(LEDC_MODE, obj->timer_num); + LOG_W("period_hz:%d", period_hz); + uint32_t duty = ledc_get_duty(LEDC_MODE, configuration->channel); + LOG_W("duty:%d", duty); + + configuration->period = 1000000000 / period_hz; + configuration->pulse = duty * configuration->period / 8191; + LOG_W("pulse:%d", configuration->pulse); + + return RT_EOK; +} + +static void pwm_enabled(struct esp_pwm *obj, struct rt_pwm_configuration *configuration, rt_uint8_t enable) +{ + if(enable) + { + ledc_timer_config_t ledc_timer = { + .speed_mode = LEDC_MODE, + .timer_num = obj->timer_num, + .duty_resolution = LEDC_TIMER_13_BIT, + .freq_hz = LEDC_FREQUENCY_DEFAULT, // Set output frequency at 5 kHz + .clk_cfg = LEDC_AUTO_CLK + }; + ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); + + // Prepare and then apply the LEDC PWM channel configuration + ledc_channel_config_t ledc_channel = { + .speed_mode = LEDC_MODE, + .channel = configuration->channel, + .timer_sel = obj->timer_num, + .intr_type = LEDC_INTR_DISABLE, + .duty = LEDC_DUTY_DEFAULT, // ((2 ** 13) - 1) * (pulse / period_hz) + .hpoint = 0 + }; + switch (configuration->channel) + { + case LEDC_CHANNEL_0: + ledc_channel.gpio_num = BSP_LEDC_CH0_GPIO; + break; + case LEDC_CHANNEL_1: + ledc_channel.gpio_num = BSP_LEDC_CH1_GPIO; + break; + case LEDC_CHANNEL_2: + ledc_channel.gpio_num = BSP_LEDC_CH2_GPIO; + break; + case LEDC_CHANNEL_3: + ledc_channel.gpio_num = BSP_LEDC_CH3_GPIO; + break; + case LEDC_CHANNEL_4: + ledc_channel.gpio_num = BSP_LEDC_CH4_GPIO; + break; + case LEDC_CHANNEL_5: + ledc_channel.gpio_num = BSP_LEDC_CH5_GPIO; + break; + default: + break; + } + ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); + } + else + { + ESP_ERROR_CHECK(ledc_stop(LEDC_MODE, configuration->channel, 0)); + } +} + +static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct esp_pwm *_pwm = rt_container_of(device, struct esp_pwm, pwm_device); + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; + + switch (cmd) + { + case PWM_CMD_ENABLE: + pwm_enabled(_pwm, configuration, RT_TRUE); + return RT_EOK; + case PWM_CMD_DISABLE: + pwm_enabled(_pwm, configuration, RT_FALSE); + return RT_EOK; + case PWM_CMD_SET: + return _pwm_set(_pwm, configuration); + case PWM_CMD_GET: + return _pwm_get(_pwm, 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(esp_pwm_obj) / sizeof(esp_pwm_obj[0]); i++) + { + esp_pwm_obj[i].timer_num = i; + result = rt_device_pwm_register(&esp_pwm_obj[i].pwm_device, esp_pwm_obj[i].name, &_pwm_ops, 0); + if(result != RT_EOK) + { + LOG_E("%s register fail.", esp_pwm_obj[i].name); + } + } + + return result; +} +INIT_DEVICE_EXPORT(rt_hw_pwm_init); + +#endif /* BSP_USING_PWM */ diff --git a/bsp/ESP32_C3/drivers/drv_pwm.h b/bsp/ESP32_C3/drivers/drv_pwm.h new file mode 100644 index 0000000000..ad0652474b --- /dev/null +++ b/bsp/ESP32_C3/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__ */