Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
嗨,你的益达!
rt-thread
提交
ab8caed1
R
rt-thread
项目概览
嗨,你的益达!
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ab8caed1
编写于
6月 05, 2023
作者:
我是大厨
提交者:
mysterywolf
6月 06, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[bsp][gd32]添加 GD32F303 的 pwm 驱动
上级
849f0d4a
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
575 addition
and
0 deletion
+575
-0
bsp/gd32/arm/libraries/gd32_drivers/SConscript
bsp/gd32/arm/libraries/gd32_drivers/SConscript
+4
-0
bsp/gd32/arm/libraries/gd32_drivers/drv_pwm.c
bsp/gd32/arm/libraries/gd32_drivers/drv_pwm.c
+571
-0
未找到文件。
bsp/gd32/arm/libraries/gd32_drivers/SConscript
浏览文件 @
ab8caed1
...
@@ -48,6 +48,10 @@ if GetDepend('RT_USING_ADC'):
...
@@ -48,6 +48,10 @@ if GetDepend('RT_USING_ADC'):
# add sdio drivers.
# add sdio drivers.
if
GetDepend
(
'RT_USING_SDIO'
):
if
GetDepend
(
'RT_USING_SDIO'
):
src
+=
[
'drv_sdio.c'
]
src
+=
[
'drv_sdio.c'
]
# add pwm drivers.
if
GetDepend
(
'RT_USING_PWM'
):
src
+=
[
'drv_pwm.c'
]
path
=
[
cwd
]
path
=
[
cwd
]
...
...
bsp/gd32/arm/libraries/gd32_drivers/drv_pwm.c
0 → 100644
浏览文件 @
ab8caed1
/*
* Copyright (c) 2006-2023
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-06-05 zengjianwei first version
*/
#include <board.h>
#include <gd32f30x.h>
#include <rtdevice.h>
#include <rtthread.h>
#ifdef RT_USING_PWM
//#define DRV_DEBUG
#define LOG_TAG "drv.pwm"
#include <rtdbg.h>
#define MAX_PERIOD 65535
#define MIN_PERIOD 3
#define MIN_PULSE 2
typedef
struct
{
rt_int8_t
TimerIndex
;
// timer index:0~13
rt_uint32_t
Port
;
// gpio port:GPIOA/GPIOB/GPIOC/...
rt_uint32_t
pin
;
// gpio pin:GPIO_PIN_0~GPIO_PIN_15
rt_uint16_t
channel
;
// timer channel
char
*
name
;
}
TIMER_PORT_CHANNEL_MAP_S
;
struct
gd32_pwm
{
struct
rt_device_pwm
pwm_device
;
TIMER_PORT_CHANNEL_MAP_S
tim_handle
;
};
static
struct
gd32_pwm
gd32_pwm_obj
[]
=
{
#ifdef RT_USING_PWM1
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm1"
}},
#endif
#ifdef RT_USING_PWM2
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm2"
}},
#endif
#ifdef RT_USING_PWM3
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm3"
}},
#endif
#ifdef RT_USING_PWM4
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm4"
}},
#endif
#ifdef RT_USING_PWM5
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm5"
}},
#endif
#ifdef RT_USING_PWM6
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm6"
}},
#endif
#ifdef RT_USING_PWM7
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm7"
}},
#endif
#ifdef RT_USING_PWM8
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm8"
}},
#endif
#ifdef RT_USING_PWM9
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm9"
}},
#endif
#ifdef RT_USING_PWM10
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm10"
}},
#endif
#ifdef RT_USING_PWM11
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm11"
}},
#endif
#ifdef RT_USING_PWM12
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm12"
}},
#endif
#ifdef RT_USING_PWM13
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm13"
}},
#endif
#ifdef RT_USING_PWM14
{.
tim_handle
=
{
3
,
GPIOB
,
GPIO_PIN_8
,
2
,
"pwm14"
}},
#endif
};
typedef
struct
{
rt_uint32_t
Port
[
7
];
rt_int8_t
TimerIndex
[
14
];
}
TIMER_PERIPH_LIST_S
;
static
TIMER_PERIPH_LIST_S
gd32_timer_periph_list
=
{
.
Port
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
},
.
TimerIndex
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
},
};
/*
* 将所有用到的 gpio port 和 timer 不重复地列举出来,以方便后面不重复地初始化
*/
static
rt_err_t
pwm_find_timer_periph
(
void
)
{
rt_int16_t
i
,
j
,
k
;
/* find gpio port of defined table */
for
(
i
=
0
;
i
<
sizeof
(
gd32_pwm_obj
)
/
sizeof
(
gd32_pwm_obj
[
0
]);
++
i
)
{
/* find -1 of gd32_periph_list's member of Port */
for
(
j
=
0
;
j
<
sizeof
(
gd32_timer_periph_list
.
Port
)
/
sizeof
(
gd32_timer_periph_list
.
Port
[
0
]);
++
j
)
{
if
(
0
==
gd32_timer_periph_list
.
Port
[
j
])
{
break
;
}
}
if
(
j
>=
sizeof
(
gd32_timer_periph_list
.
Port
)
/
sizeof
(
gd32_timer_periph_list
.
Port
[
0
]))
{
LOG_E
(
"Can not find -1 of gd32_periph_list's member of Port!
\n
"
);
break
;
}
/* find the different of Port */
for
(
k
=
0
;
k
<
j
;
++
k
)
{
if
(
gd32_pwm_obj
[
i
].
tim_handle
.
Port
==
gd32_timer_periph_list
.
Port
[
k
])
{
break
;
}
}
/* if can not find the same Port */
if
(
k
==
j
)
{
gd32_timer_periph_list
.
Port
[
j
]
=
gd32_pwm_obj
[
i
].
tim_handle
.
Port
;
}
}
/* find timer periph of defined table */
for
(
i
=
0
;
i
<
sizeof
(
gd32_pwm_obj
)
/
sizeof
(
gd32_pwm_obj
[
0
]);
++
i
)
{
/* find -1 of gd32_periph_list's member of TimerIndex */
for
(
j
=
0
;
j
<
sizeof
(
gd32_timer_periph_list
.
TimerIndex
)
/
sizeof
(
gd32_timer_periph_list
.
TimerIndex
[
0
]);
++
j
)
{
if
(
-
1
==
gd32_timer_periph_list
.
TimerIndex
[
j
])
{
break
;
}
}
if
(
j
>=
sizeof
(
gd32_timer_periph_list
.
TimerIndex
)
/
sizeof
(
gd32_timer_periph_list
.
TimerIndex
[
0
]))
{
LOG_E
(
"Can not find -1 of gd32_periph_list's member of TimerIndex!
\n
"
);
break
;
}
/* find the different of TimerIndex */
for
(
k
=
0
;
k
<
j
;
++
k
)
{
if
(
gd32_pwm_obj
[
i
].
tim_handle
.
TimerIndex
==
gd32_timer_periph_list
.
TimerIndex
[
k
])
{
break
;
}
}
/* if can not find the same TimerIndex */
if
(
k
==
j
)
{
gd32_timer_periph_list
.
TimerIndex
[
j
]
=
gd32_pwm_obj
[
i
].
tim_handle
.
TimerIndex
;
}
}
return
RT_EOK
;
}
static
rt_uint32_t
index_to_timer
(
rt_int8_t
TimerIndex
)
{
switch
(
TimerIndex
)
{
case
0
:
return
TIMER0
;
case
1
:
return
TIMER1
;
case
2
:
return
TIMER2
;
case
3
:
return
TIMER3
;
case
4
:
return
TIMER4
;
case
5
:
return
TIMER5
;
case
6
:
return
TIMER6
;
case
7
:
return
TIMER7
;
case
8
:
return
TIMER8
;
case
9
:
return
TIMER9
;
case
10
:
return
TIMER10
;
case
11
:
return
TIMER11
;
case
12
:
return
TIMER12
;
case
13
:
return
TIMER13
;
default:
LOG_E
(
"Unsport timer periph!
\n
"
);
}
return
TIMER0
;
}
static
void
gpio_clock_enable
(
rt_uint32_t
Port
)
{
switch
(
Port
)
{
case
GPIOA
:
rcu_periph_clock_enable
(
RCU_GPIOA
);
break
;
case
GPIOB
:
rcu_periph_clock_enable
(
RCU_GPIOB
);
break
;
case
GPIOC
:
rcu_periph_clock_enable
(
RCU_GPIOC
);
break
;
case
GPIOD
:
rcu_periph_clock_enable
(
RCU_GPIOD
);
break
;
case
GPIOE
:
rcu_periph_clock_enable
(
RCU_GPIOE
);
break
;
case
GPIOF
:
rcu_periph_clock_enable
(
RCU_GPIOF
);
break
;
case
GPIOG
:
rcu_periph_clock_enable
(
RCU_GPIOG
);
break
;
default:
LOG_E
(
"Unsport gpio port!
\n
"
);
}
}
static
void
timer_clock_enable
(
rt_int8_t
TimerIndex
)
{
switch
(
TimerIndex
)
{
case
0
:
rcu_periph_clock_enable
(
RCU_TIMER0
);
break
;
case
1
:
rcu_periph_clock_enable
(
RCU_TIMER1
);
break
;
case
2
:
rcu_periph_clock_enable
(
RCU_TIMER2
);
break
;
case
3
:
rcu_periph_clock_enable
(
RCU_TIMER3
);
break
;
case
4
:
rcu_periph_clock_enable
(
RCU_TIMER4
);
break
;
case
5
:
rcu_periph_clock_enable
(
RCU_TIMER5
);
break
;
case
6
:
rcu_periph_clock_enable
(
RCU_TIMER6
);
break
;
case
7
:
rcu_periph_clock_enable
(
RCU_TIMER7
);
break
;
#ifndef GD32F30X_HD
case
8
:
rcu_periph_clock_enable
(
RCU_TIMER8
);
break
;
case
9
:
rcu_periph_clock_enable
(
RCU_TIMER9
);
break
;
case
10
:
rcu_periph_clock_enable
(
RCU_TIMER10
);
break
;
case
11
:
rcu_periph_clock_enable
(
RCU_TIMER11
);
break
;
case
12
:
rcu_periph_clock_enable
(
RCU_TIMER12
);
break
;
case
13
:
rcu_periph_clock_enable
(
RCU_TIMER13
);
break
;
#endif
default:
LOG_E
(
"Unsport timer periph!
\n
"
);
}
}
static
void
rcu_config
(
void
)
{
rt_int16_t
i
;
for
(
i
=
0
;
i
<
sizeof
(
gd32_timer_periph_list
.
Port
)
/
sizeof
(
gd32_timer_periph_list
.
Port
[
0
]);
++
i
)
{
if
(
0
==
gd32_timer_periph_list
.
Port
[
i
])
{
break
;
}
/* enable GPIO clock */
gpio_clock_enable
(
gd32_timer_periph_list
.
Port
[
i
]);
}
rcu_periph_clock_enable
(
RCU_AF
);
for
(
i
=
0
;
i
<
sizeof
(
gd32_timer_periph_list
.
TimerIndex
)
/
sizeof
(
gd32_timer_periph_list
.
TimerIndex
[
0
]);
++
i
)
{
if
(
-
1
==
gd32_timer_periph_list
.
TimerIndex
[
i
])
{
break
;
}
/* enable timer clock */
timer_clock_enable
(
gd32_timer_periph_list
.
TimerIndex
[
i
]);
timer_deinit
(
index_to_timer
(
gd32_timer_periph_list
.
TimerIndex
[
i
]));
}
}
static
void
gpio_config
(
void
)
{
rt_int16_t
i
;
/* config the GPIO as analog mode */
for
(
i
=
0
;
i
<
sizeof
(
gd32_pwm_obj
)
/
sizeof
(
gd32_pwm_obj
[
0
]);
++
i
)
{
gpio_init
(
gd32_pwm_obj
[
i
].
tim_handle
.
Port
,
GPIO_MODE_AF_PP
,
GPIO_OSPEED_50MHZ
,
gd32_pwm_obj
[
i
].
tim_handle
.
pin
);
}
}
static
void
timer_init_para
(
timer_parameter_struct
*
initpara
)
{
rt_int16_t
i
;
for
(
i
=
0
;
i
<
sizeof
(
gd32_timer_periph_list
.
TimerIndex
)
/
sizeof
(
gd32_timer_periph_list
.
TimerIndex
[
0
]);
++
i
)
{
/* config timer */
if
(
-
1
!=
gd32_timer_periph_list
.
TimerIndex
[
i
])
{
timer_init
(
index_to_timer
(
gd32_timer_periph_list
.
TimerIndex
[
i
]),
initpara
);
}
}
}
static
void
channel_output_config
(
timer_oc_parameter_struct
*
ocpara
)
{
rt_int16_t
i
;
rt_uint32_t
timer_periph
;
/* config the channel config */
for
(
i
=
0
;
i
<
sizeof
(
gd32_pwm_obj
)
/
sizeof
(
gd32_pwm_obj
[
0
]);
++
i
)
{
timer_periph
=
index_to_timer
(
gd32_pwm_obj
[
i
].
tim_handle
.
TimerIndex
);
timer_channel_output_config
(
timer_periph
,
gd32_pwm_obj
[
i
].
tim_handle
.
channel
,
ocpara
);
timer_channel_output_pulse_value_config
(
timer_periph
,
gd32_pwm_obj
[
i
].
tim_handle
.
channel
,
7999
);
timer_channel_output_mode_config
(
timer_periph
,
gd32_pwm_obj
[
i
].
tim_handle
.
channel
,
TIMER_OC_MODE_PWM0
);
timer_channel_output_shadow_config
(
timer_periph
,
gd32_pwm_obj
[
i
].
tim_handle
.
channel
,
TIMER_OC_SHADOW_DISABLE
);
/* auto-reload preload shadow reg enable */
// timer_auto_reload_shadow_enable(timer_periph);
timer_channel_output_state_config
(
timer_periph
,
gd32_pwm_obj
[
i
].
tim_handle
.
channel
,
TIMER_CCX_DISABLE
);
}
/* enable timer */
for
(
i
=
0
;
i
<
sizeof
(
gd32_timer_periph_list
.
TimerIndex
)
/
sizeof
(
gd32_timer_periph_list
.
TimerIndex
[
0
]);
++
i
)
{
if
(
-
1
!=
gd32_timer_periph_list
.
TimerIndex
[
i
])
{
timer_periph
=
index_to_timer
(
gd32_timer_periph_list
.
TimerIndex
[
i
]);
timer_enable
(
timer_periph
);
}
}
}
static
void
timer_config
(
void
)
{
timer_oc_parameter_struct
timer_ocintpara
;
timer_parameter_struct
timer_initpara
;
/* TIMER configuration */
timer_initpara
.
prescaler
=
119
;
timer_initpara
.
alignedmode
=
TIMER_COUNTER_EDGE
;
timer_initpara
.
counterdirection
=
TIMER_COUNTER_UP
;
timer_initpara
.
period
=
15999
;
timer_initpara
.
clockdivision
=
TIMER_CKDIV_DIV1
;
timer_initpara
.
repetitioncounter
=
0
;
timer_init_para
(
&
timer_initpara
);
/* CHX configuration in PWM mode */
timer_ocintpara
.
outputstate
=
TIMER_CCX_ENABLE
;
timer_ocintpara
.
outputnstate
=
TIMER_CCXN_DISABLE
;
timer_ocintpara
.
ocpolarity
=
TIMER_OC_POLARITY_HIGH
;
timer_ocintpara
.
ocnpolarity
=
TIMER_OCN_POLARITY_HIGH
;
timer_ocintpara
.
ocidlestate
=
TIMER_OC_IDLE_STATE_LOW
;
timer_ocintpara
.
ocnidlestate
=
TIMER_OCN_IDLE_STATE_LOW
;
channel_output_config
(
&
timer_ocintpara
);
}
static
rt_err_t
drv_pwm_enable
(
TIMER_PORT_CHANNEL_MAP_S
*
pstTimerMap
,
struct
rt_pwm_configuration
*
configuration
,
rt_bool_t
enable
)
{
if
(
!
enable
)
{
timer_channel_output_state_config
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
configuration
->
channel
,
TIMER_CCX_DISABLE
);
}
else
{
timer_channel_output_state_config
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
configuration
->
channel
,
TIMER_CCX_ENABLE
);
}
return
RT_EOK
;
}
static
rt_err_t
drv_pwm_get
(
TIMER_PORT_CHANNEL_MAP_S
*
pstTimerMap
,
struct
rt_pwm_configuration
*
configuration
)
{
rt_uint64_t
tim_clock
;
rt_uint16_t
psc
;
rt_uint32_t
chxcv
;
tim_clock
=
rcu_clock_freq_get
(
CK_SYS
);
psc
=
timer_prescaler_read
(
index_to_timer
(
pstTimerMap
->
TimerIndex
));
if
(
psc
==
TIMER_CKDIV_DIV2
)
{
tim_clock
=
tim_clock
/
2
;
}
else
if
(
psc
==
TIMER_CKDIV_DIV4
)
{
tim_clock
=
tim_clock
/
4
;
}
chxcv
=
timer_channel_capture_value_register_read
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
configuration
->
channel
);
/* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
tim_clock
/=
1000000UL
;
configuration
->
period
=
(
TIMER_CAR
(
index_to_timer
(
pstTimerMap
->
TimerIndex
))
+
1
)
*
(
psc
+
1
)
*
1000UL
/
tim_clock
;
configuration
->
pulse
=
(
chxcv
+
1
)
*
(
psc
+
1
)
*
1000UL
/
tim_clock
;
return
RT_EOK
;
}
static
rt_err_t
drv_pwm_set
(
TIMER_PORT_CHANNEL_MAP_S
*
pstTimerMap
,
struct
rt_pwm_configuration
*
configuration
)
{
rt_uint32_t
period
,
pulse
;
rt_uint64_t
tim_clock
,
psc
;
tim_clock
=
rcu_clock_freq_get
(
CK_SYS
);
/* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
tim_clock
/=
1000000UL
;
period
=
(
unsigned
long
long
)
configuration
->
period
*
tim_clock
/
1000ULL
;
psc
=
period
/
MAX_PERIOD
+
1
;
period
=
period
/
psc
;
timer_prescaler_config
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
psc
-
1
,
TIMER_PSC_RELOAD_NOW
);
if
(
period
<
MIN_PERIOD
)
{
period
=
MIN_PERIOD
;
}
timer_autoreload_value_config
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
period
-
1
);
pulse
=
(
unsigned
long
long
)
configuration
->
pulse
*
tim_clock
/
psc
/
1000ULL
;
if
(
pulse
<
MIN_PULSE
)
{
pulse
=
MIN_PULSE
;
}
else
if
(
pulse
>
period
)
{
pulse
=
period
;
}
timer_channel_output_pulse_value_config
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
configuration
->
channel
,
pulse
);
timer_counter_value_config
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
0
);
/* Update frequency value */
timer_event_software_generate
(
index_to_timer
(
pstTimerMap
->
TimerIndex
),
TIMER_EVENT_SRC_UPG
);
return
RT_EOK
;
}
static
rt_err_t
drv_pwm_control
(
struct
rt_device_pwm
*
device
,
int
cmd
,
void
*
arg
)
{
struct
rt_pwm_configuration
*
configuration
=
(
struct
rt_pwm_configuration
*
)
arg
;
TIMER_PORT_CHANNEL_MAP_S
*
pstTimerMap
=
(
TIMER_PORT_CHANNEL_MAP_S
*
)
device
->
parent
.
user_data
;
switch
(
cmd
)
{
case
PWM_CMD_ENABLE
:
return
drv_pwm_enable
(
pstTimerMap
,
configuration
,
RT_TRUE
);
case
PWM_CMD_DISABLE
:
return
drv_pwm_enable
(
pstTimerMap
,
configuration
,
RT_FALSE
);
case
PWM_CMD_SET
:
return
drv_pwm_set
(
pstTimerMap
,
configuration
);
case
PWM_CMD_GET
:
return
drv_pwm_get
(
pstTimerMap
,
configuration
);
default:
return
RT_EINVAL
;
}
}
static
struct
rt_pwm_ops
drv_ops
=
{
drv_pwm_control
};
static
rt_err_t
gd32_hw_pwm_init
(
void
)
{
pwm_find_timer_periph
();
rcu_config
();
gpio_config
();
timer_config
();
return
RT_EOK
;
}
static
int
gd32_pwm_init
(
void
)
{
int
i
=
0
;
int
result
=
RT_EOK
;
/* pwm init */
if
(
gd32_hw_pwm_init
()
!=
RT_EOK
)
{
LOG_E
(
"PWM init failed"
);
result
=
-
RT_ERROR
;
goto
__exit
;
}
LOG_D
(
"PWM init success"
);
for
(
i
=
0
;
i
<
sizeof
(
gd32_pwm_obj
)
/
sizeof
(
gd32_pwm_obj
[
0
]);
i
++
)
{
/* register pwm device */
if
(
rt_device_pwm_register
(
&
gd32_pwm_obj
[
i
].
pwm_device
,
gd32_pwm_obj
[
i
].
tim_handle
.
name
,
&
drv_ops
,
&
gd32_pwm_obj
[
i
].
tim_handle
)
==
RT_EOK
)
{
LOG_D
(
"%s register success"
,
gd32_pwm_obj
[
i
].
tim_handle
.
name
);
}
else
{
LOG_E
(
"%s register failed"
,
gd32_pwm_obj
[
i
].
tim_handle
.
name
);
result
=
-
RT_ERROR
;
}
}
__exit:
return
result
;
}
INIT_DEVICE_EXPORT
(
gd32_pwm_init
);
#endif
/* RT_USING_PWM */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录