|
@@ -1,628 +1,963 @@
|
|
|
-/*
|
|
|
- * Copyright (c) 2006-2022, RT-Thread Development Team
|
|
|
- *
|
|
|
- * SPDX-License-Identifier: Apache-2.0
|
|
|
- *
|
|
|
- * Change Logs:
|
|
|
- * Date Author Notes
|
|
|
- * 2021-09-23 charlown first version
|
|
|
- * 2022-10-14 hg0720 the first version which add from wch
|
|
|
- */
|
|
|
-
|
|
|
-#include <rtthread.h>
|
|
|
-#include <rtdevice.h>
|
|
|
-#include <drivers/rt_drv_pwm.h>
|
|
|
-#include <drivers/hwtimer.h>
|
|
|
-#include <board.h>
|
|
|
-
|
|
|
-#ifdef BSP_USING_PWM
|
|
|
-
|
|
|
-#define LOG_TAG "drv.pwm"
|
|
|
-#include <drv_log.h>
|
|
|
-
|
|
|
-#ifndef ITEM_NUM
|
|
|
-#define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
|
|
|
-#endif
|
|
|
-
|
|
|
-#define MAX_COUNTER 65535
|
|
|
-#define MIN_COUNTER 2
|
|
|
-#define MIN_PULSE 2
|
|
|
-
|
|
|
-struct rtdevice_pwm_device
|
|
|
-{
|
|
|
- struct rt_device_pwm parent;
|
|
|
- TIM_TypeDef* periph;
|
|
|
- rt_uint8_t channel[4];
|
|
|
- char* name;
|
|
|
-};
|
|
|
-
|
|
|
-void ch32_tim_clock_init(TIM_TypeDef* timx)
|
|
|
-{
|
|
|
- if (timx == TIM1)
|
|
|
- {
|
|
|
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
|
|
|
- }
|
|
|
- if (timx == TIM2)
|
|
|
- {
|
|
|
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
|
|
- }
|
|
|
- if (timx == TIM3)
|
|
|
- {
|
|
|
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
|
|
- }
|
|
|
- if (timx == TIM4)
|
|
|
- {
|
|
|
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-rt_uint32_t ch32_tim_clock_get(TIM_TypeDef* timx)
|
|
|
-{
|
|
|
- RCC_ClocksTypeDef RCC_Clocks;
|
|
|
- RCC_GetClocksFreq(&RCC_Clocks);
|
|
|
-
|
|
|
- /*tim1~4 all in HCLK*/
|
|
|
- return RCC_Clocks.HCLK_Frequency;
|
|
|
-}
|
|
|
-
|
|
|
-struct rt_hwtimer_info hwtimer_info1 =
|
|
|
-{
|
|
|
- .maxfreq = 1000000,
|
|
|
- .minfreq = 2000,
|
|
|
- .maxcnt = 0xFFFF,
|
|
|
- .cntmode = HWTIMER_CNTMODE_UP,
|
|
|
-};
|
|
|
-
|
|
|
-struct rt_hwtimer_info hwtimer_info2 =
|
|
|
-{
|
|
|
- .maxfreq = 1000000,
|
|
|
- .minfreq = 2000,
|
|
|
- .maxcnt = 0xFFFF,
|
|
|
- .cntmode = HWTIMER_CNTMODE_UP,
|
|
|
-
|
|
|
-};
|
|
|
-
|
|
|
-struct rt_hwtimer_info hwtimer_info3 =
|
|
|
-{
|
|
|
- .maxfreq = 1000000,
|
|
|
- .minfreq = 2000,
|
|
|
- .maxcnt = 0xFFFF,
|
|
|
- .cntmode = HWTIMER_CNTMODE_UP,
|
|
|
-
|
|
|
-};
|
|
|
-
|
|
|
-struct rt_hwtimer_info hwtimer_info4 =
|
|
|
-{
|
|
|
- .maxfreq = 1000000,
|
|
|
- .minfreq = 2000,
|
|
|
- .maxcnt = 0xFFFF,
|
|
|
- .cntmode = HWTIMER_CNTMODE_UP,
|
|
|
-
|
|
|
-};
|
|
|
-
|
|
|
-struct rt_hwtimer_info* ch32_hwtimer_info_config_get(TIM_TypeDef* timx)
|
|
|
-{
|
|
|
- struct rt_hwtimer_info* info = RT_NULL;
|
|
|
-
|
|
|
- if (timx == TIM1)
|
|
|
- {
|
|
|
- info = &hwtimer_info1;
|
|
|
- }
|
|
|
- else if (timx == TIM2)
|
|
|
- {
|
|
|
- info = &hwtimer_info2;
|
|
|
- }
|
|
|
- else if (timx == TIM3)
|
|
|
- {
|
|
|
- info = &hwtimer_info3;
|
|
|
- }
|
|
|
- else if (timx == TIM4)
|
|
|
- {
|
|
|
- info = &hwtimer_info4;
|
|
|
- }
|
|
|
-
|
|
|
- return info;
|
|
|
-}
|
|
|
-
|
|
|
-void ch32_pwm_io_init(TIM_TypeDef* timx, rt_uint8_t channel)
|
|
|
-{
|
|
|
- GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
-
|
|
|
- if (timx == TIM1)
|
|
|
- {
|
|
|
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
-
|
|
|
- if (channel == TIM_Channel_1)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_2)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_3)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_4)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (timx == TIM2)
|
|
|
- {
|
|
|
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
-
|
|
|
- if (channel == TIM_Channel_1)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_2)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_3)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_4)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (timx == TIM3)
|
|
|
- {
|
|
|
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
|
|
-
|
|
|
- if (channel == TIM_Channel_1)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_2)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_3)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_4)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (timx == TIM4)
|
|
|
- {
|
|
|
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
|
|
-
|
|
|
- if (channel == TIM_Channel_1)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_2)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_3)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- if (channel == TIM_Channel_4)
|
|
|
- {
|
|
|
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
|
|
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
- GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * channel = 0xFF: the channel is not use.
|
|
|
- */
|
|
|
-struct rtdevice_pwm_device pwm_device_list[] =
|
|
|
-{
|
|
|
-#ifdef BSP_USING_TIM1_PWM
|
|
|
- {
|
|
|
- .periph = TIM1,
|
|
|
- .name = "pwm1",
|
|
|
-#ifdef BSP_USING_TIM1_PWM_CH1
|
|
|
- .channel[0] = TIM_Channel_1,
|
|
|
-#else
|
|
|
- .channel[0] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM1_PWM_CH2
|
|
|
- .channel[1] = TIM_Channel_2,
|
|
|
-#else
|
|
|
- .channel[1] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM1_PWM_CH3
|
|
|
- .channel[2] = TIM_Channel_3,
|
|
|
-#else
|
|
|
- .channel[2] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM1_PWM_CH4
|
|
|
- .channel[3] = TIM_Channel_4,
|
|
|
-#else
|
|
|
- .channel[3] = 0xFF,
|
|
|
-#endif
|
|
|
- },
|
|
|
-#endif /* BSP_USING_TIM1_PWM */
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM2_PWM
|
|
|
- {
|
|
|
- .periph = TIM2,
|
|
|
- .name = "pwm2",
|
|
|
-#ifdef BSP_USING_TIM2_PWM_CH1
|
|
|
- .channel[0] = TIM_Channel_1,
|
|
|
-#else
|
|
|
- .channel[0] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM2_PWM_CH2
|
|
|
- .channel[1] = TIM_Channel_2,
|
|
|
-#else
|
|
|
- .channel[1] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM2_PWM_CH3
|
|
|
- .channel[2] = TIM_Channel_3,
|
|
|
-#else
|
|
|
- .channel[2] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM2_PWM_CH4
|
|
|
- .channel[3] = TIM_Channel_4,
|
|
|
-#else
|
|
|
- .channel[3] = 0xFF,
|
|
|
-#endif
|
|
|
- },
|
|
|
-#endif /* BSP_USING_TIM2_PWM */
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM3_PWM
|
|
|
- {
|
|
|
- .periph = TIM3,
|
|
|
- .name = "pwm3",
|
|
|
-#ifdef BSP_USING_TIM3_PWM_CH1
|
|
|
- .channel[0] = TIM_Channel_1,
|
|
|
-#else
|
|
|
- .channel[0] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM3_PWM_CH2
|
|
|
- .channel[1] = TIM_Channel_2,
|
|
|
-#else
|
|
|
- .channel[1] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM3_PWM_CH3
|
|
|
- .channel[2] = TIM_Channel_3,
|
|
|
-#else
|
|
|
- .channel[2] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM3_PWM_CH4
|
|
|
- .channel[3] = TIM_Channel_4,
|
|
|
-#else
|
|
|
- .channel[3] = 0xFF,
|
|
|
-#endif
|
|
|
- },
|
|
|
-#endif /* BSP_USING_TIM3_PWM */
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM4_PWM
|
|
|
- {
|
|
|
- .periph = TIM4,
|
|
|
- .name = "pwm4",
|
|
|
-#ifdef BSP_USING_TIM4_PWM_CH1
|
|
|
- .channel[0] = TIM_Channel_1,
|
|
|
-#else
|
|
|
- .channel[0] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM4_PWM_CH2
|
|
|
- .channel[1] = TIM_Channel_2,
|
|
|
-#else
|
|
|
- .channel[1] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM4_PWM_CH3
|
|
|
- .channel[2] = TIM_Channel_3,
|
|
|
-#else
|
|
|
- .channel[2] = 0xFF,
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef BSP_USING_TIM4_PWM_CH4
|
|
|
- .channel[3] = TIM_Channel_4,
|
|
|
-#else
|
|
|
- .channel[3] = 0xFF,
|
|
|
-#endif
|
|
|
- },
|
|
|
-#endif /* BSP_USING_TIM4_PWM */
|
|
|
-};
|
|
|
-
|
|
|
-static rt_err_t ch32_pwm_device_enable(struct rt_device_pwm* device, struct rt_pwm_configuration* configuration, rt_bool_t enable)
|
|
|
-{
|
|
|
- struct rtdevice_pwm_device* pwm_device;
|
|
|
- rt_uint32_t channel_index;
|
|
|
- rt_uint16_t ccx_state;
|
|
|
-
|
|
|
- pwm_device = (struct rtdevice_pwm_device*)device;
|
|
|
- channel_index = configuration->channel;
|
|
|
-
|
|
|
- if (enable == RT_TRUE)
|
|
|
- {
|
|
|
- ccx_state = TIM_CCx_Enable;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ccx_state = TIM_CCx_Disable;
|
|
|
- }
|
|
|
-
|
|
|
- if (channel_index <= 4 && channel_index > 0)
|
|
|
- {
|
|
|
- if (pwm_device->channel[channel_index - 1] == 0xFF)
|
|
|
- {
|
|
|
- return RT_EINVAL;
|
|
|
- }
|
|
|
- TIM_CCxCmd(pwm_device->periph, pwm_device->channel[channel_index - 1], ccx_state);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return RT_EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- TIM_Cmd(pwm_device->periph, ENABLE);
|
|
|
-
|
|
|
- return RT_EOK;
|
|
|
-}
|
|
|
-
|
|
|
-static rt_err_t ch32_pwm_device_get(struct rt_device_pwm* device, struct rt_pwm_configuration* configuration)
|
|
|
-{
|
|
|
- struct rtdevice_pwm_device* pwm_device;
|
|
|
- rt_uint32_t arr_counter, ccr_counter, prescaler, sample_freq;
|
|
|
- rt_uint32_t channel_index;
|
|
|
- rt_uint32_t tim_clock;
|
|
|
-
|
|
|
- pwm_device = (struct rtdevice_pwm_device*)device;
|
|
|
- tim_clock = ch32_tim_clock_get(pwm_device->periph);
|
|
|
- channel_index = configuration->channel;
|
|
|
- arr_counter = pwm_device->periph->ATRLR + 1;
|
|
|
- prescaler = pwm_device->periph->PSC + 1;
|
|
|
- sample_freq = (tim_clock / prescaler) / arr_counter;
|
|
|
-
|
|
|
- /* unit:ns */
|
|
|
- configuration->period = 1000000000 / sample_freq;
|
|
|
-
|
|
|
- if (channel_index == 1)
|
|
|
- {
|
|
|
- ccr_counter = pwm_device->periph->CH1CVR + 1;
|
|
|
- configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
- }
|
|
|
- else if (channel_index == 2)
|
|
|
- {
|
|
|
- ccr_counter = pwm_device->periph->CH2CVR + 1;
|
|
|
- configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
- }
|
|
|
- else if (channel_index == 3)
|
|
|
- {
|
|
|
- ccr_counter = pwm_device->periph->CH3CVR + 1;
|
|
|
- configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
- }
|
|
|
- else if (channel_index == 4)
|
|
|
- {
|
|
|
- ccr_counter = pwm_device->periph->CH4CVR + 1;
|
|
|
- configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return RT_EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- return RT_EOK;
|
|
|
-}
|
|
|
-
|
|
|
-static rt_err_t ch32_pwm_device_set(struct rt_device_pwm* device, struct rt_pwm_configuration* configuration)
|
|
|
-{
|
|
|
- struct rtdevice_pwm_device* pwm_device;
|
|
|
- rt_uint32_t arr_counter, ccr_counter, prescaler, sample_freq;
|
|
|
- rt_uint32_t channel_index;
|
|
|
- rt_uint32_t tim_clock;
|
|
|
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitType;
|
|
|
- TIM_OCInitTypeDef TIM_OCInitType;
|
|
|
-
|
|
|
- pwm_device = (struct rtdevice_pwm_device*)device;
|
|
|
- tim_clock = ch32_tim_clock_get(pwm_device->periph);
|
|
|
- channel_index = configuration->channel;
|
|
|
-
|
|
|
- /* change to freq, unit:Hz */
|
|
|
- sample_freq = 1000000000 / configuration->period;
|
|
|
-
|
|
|
- /* counter = (tim_clk / prescaler) / sample_freq */
|
|
|
- /* normally, tim_clk is not need div, if arr_counter over 65536, need div. */
|
|
|
- prescaler = 1;
|
|
|
- arr_counter = (tim_clock / prescaler) / sample_freq;
|
|
|
-
|
|
|
- if (arr_counter > MAX_COUNTER)
|
|
|
- {
|
|
|
- /* need div tim_clock
|
|
|
- * and round up the prescaler value.
|
|
|
- * (tim_clock >> 16) = tim_clock / 65536
|
|
|
- */
|
|
|
- if ((tim_clock >> 16) % sample_freq == 0)
|
|
|
- prescaler = (tim_clock >> 16) / sample_freq;
|
|
|
- else
|
|
|
- prescaler = (tim_clock >> 16) / sample_freq + 1;
|
|
|
-
|
|
|
- /* counter = (tim_clk / prescaler) / sample_freq */
|
|
|
- arr_counter = (tim_clock / prescaler) / sample_freq;
|
|
|
- }
|
|
|
- /* ccr_counter = duty cycle * arr_counter */
|
|
|
- ccr_counter = (configuration->pulse * 100 / configuration->period) * arr_counter / 100;
|
|
|
-
|
|
|
- /* check arr_counter > 1, cxx_counter > 1 */
|
|
|
- if (arr_counter < MIN_COUNTER)
|
|
|
- {
|
|
|
- arr_counter = MIN_COUNTER;
|
|
|
- }
|
|
|
- if (ccr_counter < MIN_PULSE)
|
|
|
- {
|
|
|
- ccr_counter = MIN_PULSE;
|
|
|
- }
|
|
|
-
|
|
|
- /* TMRe base configuration */
|
|
|
- TIM_TimeBaseStructInit(&TIM_TimeBaseInitType);
|
|
|
- TIM_TimeBaseInitType.TIM_Period = arr_counter - 1;
|
|
|
- TIM_TimeBaseInitType.TIM_Prescaler = prescaler - 1;
|
|
|
- TIM_TimeBaseInitType.TIM_ClockDivision = TIM_CKD_DIV1;
|
|
|
- TIM_TimeBaseInitType.TIM_CounterMode = TIM_CounterMode_Up;
|
|
|
- TIM_TimeBaseInit(pwm_device->periph, &TIM_TimeBaseInitType);
|
|
|
-
|
|
|
- TIM_OCStructInit(&TIM_OCInitType);
|
|
|
- TIM_OCInitType.TIM_OCMode = TIM_OCMode_PWM1;
|
|
|
- TIM_OCInitType.TIM_OutputState = TIM_OutputState_Enable;
|
|
|
- TIM_OCInitType.TIM_Pulse = ccr_counter - 1;
|
|
|
- TIM_OCInitType.TIM_OCPolarity = TIM_OCPolarity_High;
|
|
|
-
|
|
|
- if (channel_index == 1)
|
|
|
- {
|
|
|
- TIM_OC1Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
- TIM_OC1PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
- }
|
|
|
- else if (channel_index == 2)
|
|
|
- {
|
|
|
- TIM_OC2Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
- TIM_OC2PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
- }
|
|
|
- else if (channel_index == 3)
|
|
|
- {
|
|
|
- TIM_OC3Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
- TIM_OC3PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
- }
|
|
|
- else if (channel_index == 4)
|
|
|
- {
|
|
|
- TIM_OC4Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
- TIM_OC4PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return RT_EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- TIM_ARRPreloadConfig(pwm_device->periph, ENABLE);
|
|
|
- TIM_CtrlPWMOutputs(pwm_device->periph, ENABLE);
|
|
|
-
|
|
|
- return RT_EOK;
|
|
|
-}
|
|
|
-
|
|
|
-static rt_err_t drv_pwm_control(struct rt_device_pwm* device, int cmd, void* arg)
|
|
|
-{
|
|
|
- struct rt_pwm_configuration* configuration;
|
|
|
-
|
|
|
- configuration = (struct rt_pwm_configuration*)arg;
|
|
|
-
|
|
|
- switch (cmd)
|
|
|
- {
|
|
|
- case PWM_CMD_ENABLE:
|
|
|
- return ch32_pwm_device_enable(device, configuration, RT_TRUE);
|
|
|
- case PWM_CMD_DISABLE:
|
|
|
- return ch32_pwm_device_enable(device, configuration, RT_FALSE);
|
|
|
- case PWM_CMD_SET:
|
|
|
- return ch32_pwm_device_set(device, configuration);
|
|
|
- case PWM_CMD_GET:
|
|
|
- return ch32_pwm_device_get(device, configuration);
|
|
|
- default:
|
|
|
- return RT_EINVAL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static struct rt_pwm_ops pwm_ops =
|
|
|
-{
|
|
|
- .control = drv_pwm_control
|
|
|
-};
|
|
|
-
|
|
|
-static int rt_hw_pwm_init(void)
|
|
|
-{
|
|
|
- int result = RT_EOK;
|
|
|
- int index = 0;
|
|
|
- int channel_index;
|
|
|
-
|
|
|
- for (index = 0; index < ITEM_NUM(pwm_device_list); index++)
|
|
|
- {
|
|
|
- ch32_tim_clock_init(pwm_device_list[index].periph);
|
|
|
- for (channel_index = 0; channel_index < sizeof(pwm_device_list[index].channel); channel_index++)
|
|
|
- {
|
|
|
- if (pwm_device_list[index].channel[channel_index] != 0xFF)
|
|
|
- {
|
|
|
- ch32_pwm_io_init(pwm_device_list[index].periph, pwm_device_list[index].channel[channel_index]);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (rt_device_pwm_register(&pwm_device_list[index].parent, pwm_device_list[index].name, &pwm_ops, RT_NULL) == RT_EOK)
|
|
|
- {
|
|
|
- LOG_D("%s register success", pwm_device_list[index].name);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- LOG_D("%s register failed", pwm_device_list[index].name);
|
|
|
- result = -RT_ERROR;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-INIT_BOARD_EXPORT(rt_hw_pwm_init);
|
|
|
-
|
|
|
-#endif /* BSP_USING_PWM */
|
|
|
+/*
|
|
|
+ * Copyright (c) 2006-2022, RT-Thread Development Team
|
|
|
+ *
|
|
|
+ * SPDX-License-Identifier: Apache-2.0
|
|
|
+ *
|
|
|
+ * Change Logs:
|
|
|
+ * Date Author Notes
|
|
|
+ * 2021-09-23 charlown first version
|
|
|
+ * 2022-10-14 hg0720 the first version which add from wch
|
|
|
+ * 2022-10-20 MXH add the remaining timers
|
|
|
+ */
|
|
|
+
|
|
|
+#include "drv_pwm.h"
|
|
|
+
|
|
|
+#ifdef BSP_USING_PWM
|
|
|
+
|
|
|
+#define LOG_TAG "drv.pwm"
|
|
|
+#include <drv_log.h>
|
|
|
+
|
|
|
+void ch32_tim_clock_init(TIM_TypeDef* timx)
|
|
|
+{
|
|
|
+#ifdef BSP_USING_TIM1_PWM
|
|
|
+ if (timx == TIM1)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM1_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM
|
|
|
+ if (timx == TIM2)
|
|
|
+ {
|
|
|
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM2_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM
|
|
|
+ if (timx == TIM3)
|
|
|
+ {
|
|
|
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM3_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM
|
|
|
+ if (timx == TIM4)
|
|
|
+ {
|
|
|
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM4_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM
|
|
|
+ if (timx == TIM5)
|
|
|
+ {
|
|
|
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM5_PWM */
|
|
|
+
|
|
|
+ /* TIM6 and TIM7 don't support PWM Mode. */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM
|
|
|
+ if (timx == TIM8)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM8_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM
|
|
|
+ if (timx == TIM9)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM9_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM
|
|
|
+ if (timx == TIM10)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM10_PWM */
|
|
|
+}
|
|
|
+
|
|
|
+rt_uint32_t ch32_tim_clock_get(TIM_TypeDef* timx)
|
|
|
+{
|
|
|
+ RCC_ClocksTypeDef RCC_Clocks;
|
|
|
+ RCC_GetClocksFreq(&RCC_Clocks);
|
|
|
+
|
|
|
+ /*tim1~10 all in HCLK*/
|
|
|
+ return RCC_Clocks.HCLK_Frequency;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * NOTE: some pwm pins of some timers are reused,
|
|
|
+ * please keep caution when using pwm
|
|
|
+ */
|
|
|
+
|
|
|
+void ch32_pwm_io_init(TIM_TypeDef* timx, rt_uint8_t channel)
|
|
|
+{
|
|
|
+ GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM
|
|
|
+ if (timx == TIM1)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM1_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM
|
|
|
+ if (timx == TIM2)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM2_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM
|
|
|
+ if (timx == TIM3)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM3_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM
|
|
|
+ if (timx == TIM4)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM4_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM
|
|
|
+ if (timx == TIM5)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM5_PWM */
|
|
|
+
|
|
|
+ /* TIM6 and TIM7 don't support PWM Mode. */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM
|
|
|
+ if (timx == TIM8)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
|
|
|
+
|
|
|
+/* I don't test it, because there is a 10M-PHY ETH port on my board,
|
|
|
+ * which uses the following four pins.
|
|
|
+ * You can try it on a board without a 10M-PHY ETH port. */
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM8_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM
|
|
|
+ if (timx == TIM9)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM9_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM
|
|
|
+ if (timx == TIM10)
|
|
|
+ {
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH1
|
|
|
+ if (channel == TIM_Channel_1)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH2
|
|
|
+ if (channel == TIM_Channel_2)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH3
|
|
|
+ if (channel == TIM_Channel_3)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH4
|
|
|
+ if (channel == TIM_Channel_4)
|
|
|
+ {
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH4 */
|
|
|
+ }
|
|
|
+#endif/* BSP_USING_TIM10_PWM */
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * channel = FLAG_NOT_INIT: the channel is not use.
|
|
|
+ */
|
|
|
+struct rtdevice_pwm_device pwm_device_list[] =
|
|
|
+{
|
|
|
+#ifdef BSP_USING_TIM1_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM1,
|
|
|
+ .name = "pwm1",
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM1_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM1_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM1_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM2,
|
|
|
+ .name = "pwm2",
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM2_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM2_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM2_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM3,
|
|
|
+ .name = "pwm3",
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM3_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM3_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM3_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM4,
|
|
|
+ .name = "pwm4",
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM4_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM4_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM4_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM5,
|
|
|
+ .name = "pwm5",
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM5_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM5_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM5_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM8,
|
|
|
+ .name = "pwm8",
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM8_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM8_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM8_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM9,
|
|
|
+ .name = "pwm9",
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM9_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM9_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM9_PWM */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM
|
|
|
+ {
|
|
|
+ .periph = TIM10,
|
|
|
+ .name = "pwm10",
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH1
|
|
|
+ .channel[0] = TIM_Channel_1,
|
|
|
+#else
|
|
|
+ .channel[0] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH1 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH2
|
|
|
+ .channel[1] = TIM_Channel_2,
|
|
|
+#else
|
|
|
+ .channel[1] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH2 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH3
|
|
|
+ .channel[2] = TIM_Channel_3,
|
|
|
+#else
|
|
|
+ .channel[2] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH3 */
|
|
|
+
|
|
|
+#ifdef BSP_USING_TIM10_PWM_CH4
|
|
|
+ .channel[3] = TIM_Channel_4,
|
|
|
+#else
|
|
|
+ .channel[3] = FLAG_NOT_INIT,
|
|
|
+#endif/* BSP_USING_TIM10_PWM_CH4 */
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_TIM10_PWM */
|
|
|
+};
|
|
|
+
|
|
|
+static rt_err_t ch32_pwm_device_enable(struct rt_device_pwm* device, struct rt_pwm_configuration* configuration, rt_bool_t enable)
|
|
|
+{
|
|
|
+ struct rtdevice_pwm_device* pwm_device;
|
|
|
+ rt_uint32_t channel_index;
|
|
|
+ rt_uint16_t ccx_state;
|
|
|
+
|
|
|
+ pwm_device = (struct rtdevice_pwm_device*)device;
|
|
|
+ channel_index = configuration->channel;
|
|
|
+
|
|
|
+ if (enable == RT_TRUE)
|
|
|
+ {
|
|
|
+ ccx_state = TIM_CCx_Enable;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ccx_state = TIM_CCx_Disable;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (channel_index <= 4 && channel_index > 0)
|
|
|
+ {
|
|
|
+ if (pwm_device->channel[channel_index - 1] == FLAG_NOT_INIT)
|
|
|
+ {
|
|
|
+ return -RT_EINVAL;
|
|
|
+ }
|
|
|
+ TIM_CCxCmd(pwm_device->periph, pwm_device->channel[channel_index - 1], ccx_state);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return -RT_EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ TIM_Cmd(pwm_device->periph, ENABLE);
|
|
|
+
|
|
|
+ return RT_EOK;
|
|
|
+}
|
|
|
+
|
|
|
+static rt_err_t ch32_pwm_device_get(struct rt_device_pwm* device, struct rt_pwm_configuration* configuration)
|
|
|
+{
|
|
|
+ struct rtdevice_pwm_device* pwm_device;
|
|
|
+ rt_uint32_t arr_counter, ccr_counter, prescaler, sample_freq;
|
|
|
+ rt_uint32_t channel_index;
|
|
|
+ rt_uint32_t tim_clock;
|
|
|
+
|
|
|
+ pwm_device = (struct rtdevice_pwm_device*)device;
|
|
|
+ tim_clock = ch32_tim_clock_get(pwm_device->periph);
|
|
|
+ channel_index = configuration->channel;
|
|
|
+ arr_counter = pwm_device->periph->ATRLR + 1;
|
|
|
+ prescaler = pwm_device->periph->PSC + 1;
|
|
|
+ sample_freq = (tim_clock / prescaler) / arr_counter;
|
|
|
+
|
|
|
+ /* unit:ns */
|
|
|
+ configuration->period = 1000000000 / sample_freq;
|
|
|
+
|
|
|
+ if (channel_index == 1)
|
|
|
+ {
|
|
|
+ ccr_counter = pwm_device->periph->CH1CVR + 1;
|
|
|
+ configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
+ }
|
|
|
+ else if (channel_index == 2)
|
|
|
+ {
|
|
|
+ ccr_counter = pwm_device->periph->CH2CVR + 1;
|
|
|
+ configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
+ }
|
|
|
+ else if (channel_index == 3)
|
|
|
+ {
|
|
|
+ ccr_counter = pwm_device->periph->CH3CVR + 1;
|
|
|
+ configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
+ }
|
|
|
+ else if (channel_index == 4)
|
|
|
+ {
|
|
|
+ ccr_counter = pwm_device->periph->CH4CVR + 1;
|
|
|
+ configuration->pulse = ((ccr_counter * 100) / arr_counter) * configuration->period / 100;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return -RT_EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return RT_EOK;
|
|
|
+}
|
|
|
+
|
|
|
+static rt_err_t ch32_pwm_device_set(struct rt_device_pwm* device, struct rt_pwm_configuration* configuration)
|
|
|
+{
|
|
|
+ struct rtdevice_pwm_device* pwm_device;
|
|
|
+ rt_uint32_t arr_counter, ccr_counter, prescaler, sample_freq;
|
|
|
+ rt_uint32_t channel_index;
|
|
|
+ rt_uint32_t tim_clock;
|
|
|
+ TIM_TimeBaseInitTypeDef TIM_TimeBaseInitType;
|
|
|
+ TIM_OCInitTypeDef TIM_OCInitType;
|
|
|
+
|
|
|
+ pwm_device = (struct rtdevice_pwm_device*)device;
|
|
|
+ tim_clock = ch32_tim_clock_get(pwm_device->periph);
|
|
|
+ channel_index = configuration->channel;
|
|
|
+
|
|
|
+ /* change to freq, unit:Hz */
|
|
|
+ sample_freq = 1000000000 / configuration->period;
|
|
|
+
|
|
|
+ /* counter = (tim_clk / prescaler) / sample_freq */
|
|
|
+ /* normally, tim_clk is not need div, if arr_counter over 65536, need div. */
|
|
|
+ prescaler = 1;
|
|
|
+ arr_counter = (tim_clock / prescaler) / sample_freq;
|
|
|
+
|
|
|
+ if (arr_counter > MAX_COUNTER)
|
|
|
+ {
|
|
|
+ /* need div tim_clock
|
|
|
+ * and round up the prescaler value.
|
|
|
+ * (tim_clock >> 16) = tim_clock / 65536
|
|
|
+ */
|
|
|
+ if ((tim_clock >> 16) % sample_freq == 0)
|
|
|
+ prescaler = (tim_clock >> 16) / sample_freq;
|
|
|
+ else
|
|
|
+ prescaler = (tim_clock >> 16) / sample_freq + 1;
|
|
|
+
|
|
|
+ /* counter = (tim_clk / prescaler) / sample_freq */
|
|
|
+ arr_counter = (tim_clock / prescaler) / sample_freq;
|
|
|
+ }
|
|
|
+ /* ccr_counter = duty cycle * arr_counter */
|
|
|
+ ccr_counter = (configuration->pulse * 100 / configuration->period) * arr_counter / 100;
|
|
|
+
|
|
|
+ /* check arr_counter > 1, cxx_counter > 1 */
|
|
|
+ if (arr_counter < MIN_COUNTER)
|
|
|
+ {
|
|
|
+ arr_counter = MIN_COUNTER;
|
|
|
+ }
|
|
|
+ if (ccr_counter < MIN_PULSE)
|
|
|
+ {
|
|
|
+ ccr_counter = MIN_PULSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* TMRe base configuration */
|
|
|
+ TIM_TimeBaseStructInit(&TIM_TimeBaseInitType);
|
|
|
+ TIM_TimeBaseInitType.TIM_Period = arr_counter - 1;
|
|
|
+ TIM_TimeBaseInitType.TIM_Prescaler = prescaler - 1;
|
|
|
+ TIM_TimeBaseInitType.TIM_ClockDivision = TIM_CKD_DIV1;
|
|
|
+ TIM_TimeBaseInitType.TIM_CounterMode = TIM_CounterMode_Up;
|
|
|
+ TIM_TimeBaseInit(pwm_device->periph, &TIM_TimeBaseInitType);
|
|
|
+
|
|
|
+ TIM_OCStructInit(&TIM_OCInitType);
|
|
|
+ TIM_OCInitType.TIM_OCMode = TIM_OCMode_PWM1;
|
|
|
+ TIM_OCInitType.TIM_OutputState = TIM_OutputState_Enable;
|
|
|
+ TIM_OCInitType.TIM_Pulse = ccr_counter - 1;
|
|
|
+ TIM_OCInitType.TIM_OCPolarity = TIM_OCPolarity_High;
|
|
|
+
|
|
|
+ if (channel_index == 1)
|
|
|
+ {
|
|
|
+ TIM_OC1Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
+ TIM_OC1PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
+ }
|
|
|
+ else if (channel_index == 2)
|
|
|
+ {
|
|
|
+ TIM_OC2Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
+ TIM_OC2PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
+ }
|
|
|
+ else if (channel_index == 3)
|
|
|
+ {
|
|
|
+ TIM_OC3Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
+ TIM_OC3PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
+ }
|
|
|
+ else if (channel_index == 4)
|
|
|
+ {
|
|
|
+ TIM_OC4Init(pwm_device->periph, &TIM_OCInitType);
|
|
|
+ TIM_OC4PreloadConfig(pwm_device->periph, TIM_OCPreload_Disable);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return -RT_EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ TIM_ARRPreloadConfig(pwm_device->periph, ENABLE);
|
|
|
+ TIM_CtrlPWMOutputs(pwm_device->periph, ENABLE);
|
|
|
+
|
|
|
+ return RT_EOK;
|
|
|
+}
|
|
|
+
|
|
|
+static rt_err_t drv_pwm_control(struct rt_device_pwm* device, int cmd, void* arg)
|
|
|
+{
|
|
|
+ struct rt_pwm_configuration* configuration;
|
|
|
+
|
|
|
+ configuration = (struct rt_pwm_configuration*)arg;
|
|
|
+
|
|
|
+ switch (cmd)
|
|
|
+ {
|
|
|
+ case PWM_CMD_ENABLE:
|
|
|
+ return ch32_pwm_device_enable(device, configuration, RT_TRUE);
|
|
|
+ case PWM_CMD_DISABLE:
|
|
|
+ return ch32_pwm_device_enable(device, configuration, RT_FALSE);
|
|
|
+ case PWM_CMD_SET:
|
|
|
+ return ch32_pwm_device_set(device, configuration);
|
|
|
+ case PWM_CMD_GET:
|
|
|
+ return ch32_pwm_device_get(device, configuration);
|
|
|
+ default:
|
|
|
+ return -RT_EINVAL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static struct rt_pwm_ops pwm_ops =
|
|
|
+{
|
|
|
+ .control = drv_pwm_control
|
|
|
+};
|
|
|
+
|
|
|
+static int rt_hw_pwm_init(void)
|
|
|
+{
|
|
|
+ int result = RT_EOK;
|
|
|
+ int index = 0;
|
|
|
+ int channel_index;
|
|
|
+
|
|
|
+ for (index = 0; index < ITEM_NUM(pwm_device_list); index++)
|
|
|
+ {
|
|
|
+ ch32_tim_clock_init(pwm_device_list[index].periph);
|
|
|
+ for (channel_index = 0; channel_index < sizeof(pwm_device_list[index].channel); channel_index++)
|
|
|
+ {
|
|
|
+ if (pwm_device_list[index].channel[channel_index] != FLAG_NOT_INIT)
|
|
|
+ {
|
|
|
+ ch32_pwm_io_init(pwm_device_list[index].periph, pwm_device_list[index].channel[channel_index]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rt_device_pwm_register(&pwm_device_list[index].parent, pwm_device_list[index].name, &pwm_ops, RT_NULL) == RT_EOK)
|
|
|
+ {
|
|
|
+ LOG_D("%s register success", pwm_device_list[index].name);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LOG_D("%s register failed", pwm_device_list[index].name);
|
|
|
+ result = -RT_ERROR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+INIT_BOARD_EXPORT(rt_hw_pwm_init);
|
|
|
+
|
|
|
+#endif /* BSP_USING_PWM */
|