summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsp/gd32/risc-v/gd32vw553h-eval/board/Kconfig25
-rw-r--r--bsp/gd32/risc-v/libraries/gd32_drivers/SConscript1
-rw-r--r--bsp/gd32/risc-v/libraries/gd32_drivers/config/hwtimer_config.h158
-rw-r--r--bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.c274
-rw-r--r--bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.h63
5 files changed, 521 insertions, 0 deletions
diff --git a/bsp/gd32/risc-v/gd32vw553h-eval/board/Kconfig b/bsp/gd32/risc-v/gd32vw553h-eval/board/Kconfig
index 55a7902eed..c2be7ff8ab 100644
--- a/bsp/gd32/risc-v/gd32vw553h-eval/board/Kconfig
+++ b/bsp/gd32/risc-v/gd32vw553h-eval/board/Kconfig
@@ -165,6 +165,31 @@ menu "On-chip Peripheral Drivers"
range 10 1000
endif
+ menuconfig BSP_USING_HWTIMER
+ bool "Enable timer"
+ default n
+ select RT_USING_HWTIMER
+ if BSP_USING_HWTIMER
+ config BSP_USING_HWTIMER0
+ bool "Enable TIM0"
+ default n
+ config BSP_USING_HWTIMER1
+ bool "Enable TIM1"
+ default n
+ config BSP_USING_HWTIMER2
+ bool "Enable TIM2"
+ default n
+ config BSP_USING_HWTIMER5
+ bool "Enable TIM5"
+ default n
+ config BSP_USING_HWTIMER15
+ bool "Enable TIM15"
+ default n
+ config BSP_USING_HWTIMER16
+ bool "Enable TIM16"
+ default n
+ endif
+
source "$(BSP_DIR)/../libraries/gd32_drivers/Kconfig"
endmenu
diff --git a/bsp/gd32/risc-v/libraries/gd32_drivers/SConscript b/bsp/gd32/risc-v/libraries/gd32_drivers/SConscript
index daae3a9fd9..6d92cf3946 100644
--- a/bsp/gd32/risc-v/libraries/gd32_drivers/SConscript
+++ b/bsp/gd32/risc-v/libraries/gd32_drivers/SConscript
@@ -53,6 +53,7 @@ if GetDepend(['RT_USING_PWM', 'SOC_GD32VW553H']):
src += ['drv_pwm.c']
path = [cwd]
+path += [cwd + "/config"]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
diff --git a/bsp/gd32/risc-v/libraries/gd32_drivers/config/hwtimer_config.h b/bsp/gd32/risc-v/libraries/gd32_drivers/config/hwtimer_config.h
new file mode 100644
index 0000000000..b7bb2b371f
--- /dev/null
+++ b/bsp/gd32/risc-v/libraries/gd32_drivers/config/hwtimer_config.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-01-30 pomin first version
+ */
+
+#ifndef __HWTIMER_CONFIG_H__
+#define __HWTIMER_CONFIG_H__
+
+#include <rtthread.h>
+#include <board.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "drv_hwtimer.h"
+
+#ifdef BSP_USING_HWTIMER0
+#ifndef HWTIMER0_CONFIG
+#define HWTIMER0_CONFIG \
+ { \
+ "timer0", \
+ { \
+ TIMER0, \
+ TIMER0_UP_IRQn, \
+ RCU_TIMER0, \
+ }, \
+ {0}, \
+ { \
+ 1000000, \
+ 1000, \
+ 0xffff, \
+ 0, /* count up mode */ \
+ } \
+ }
+#endif /* HWTIMER0_CONFIG */
+#endif /* BSP_USING_HWTIMER0 */
+
+
+#ifdef BSP_USING_HWTIMER1
+#ifndef HWTIMER1_CONFIG
+#define HWTIMER1_CONFIG \
+ { \
+ "timer1", \
+ { \
+ TIMER1, \
+ TIMER1_IRQn, \
+ RCU_TIMER1, \
+ }, \
+ {0}, \
+ { \
+ 1000000, \
+ 1000, \
+ 0xffff, \
+ 0, /* count up mode */ \
+ } \
+ }
+#endif /* HWTIMER1_CONFIG */
+#endif /* BSP_USING_HWTIMER1 */
+
+
+#ifdef BSP_USING_HWTIMER2
+#ifndef HWTIMER2_CONFIG
+#define HWTIMER2_CONFIG \
+ { \
+ "timer2", \
+ { \
+ TIMER2, \
+ TIMER2_IRQn, \
+ RCU_TIMER2, \
+ }, \
+ {0}, \
+ { \
+ 1000000, \
+ 1000, \
+ 0xffff, \
+ 0, /* count up mode */ \
+ } \
+ }
+#endif /* HWTIMER2_CONFIG */
+#endif /* BSP_USING_HWTIMER2 */
+
+
+#ifdef BSP_USING_HWTIMER5
+#ifndef HWTIMER5_CONFIG
+#define HWTIMER5_CONFIG \
+ { \
+ "timer5", \
+ { \
+ TIMER5, \
+ TIMER5_IRQn, \
+ RCU_TIMER5, \
+ }, \
+ {0}, \
+ { \
+ 1000000, \
+ 1000, \
+ 0xffff, \
+ 0, /* count up mode */ \
+ } \
+ }
+#endif /* HWTIMER5_CONFIG */
+#endif /* BSP_USING_HWTIMER5 */
+
+
+#ifdef BSP_USING_HWTIMER15
+#ifndef HWTIMER15_CONFIG
+#define HWTIMER15_CONFIG \
+ { \
+ "timer15", \
+ { \
+ TIMER15, \
+ TIMER15_IRQn, \
+ RCU_TIMER15, \
+ }, \
+ {0}, \
+ { \
+ 1000000, \
+ 1000, \
+ 0xffff, \
+ 0, /* count up mode */ \
+ } \
+ }
+#endif /* HWTIMER15_CONFIG */
+#endif /* BSP_USING_HWTIMER15 */
+
+
+#ifdef BSP_USING_HWTIMER16
+#ifndef HWTIMER16_CONFIG
+#define HWTIMER16_CONFIG \
+ { \
+ "timer16", \
+ { \
+ TIMER16, \
+ TIMER16_IRQn, \
+ RCU_TIMER16, \
+ }, \
+ {0}, \
+ { \
+ 1000000, \
+ 1000, \
+ 0xffff, \
+ 0, /* count up mode */ \
+ } \
+ }
+#endif /* HWTIMER16_CONFIG */
+#endif /* BSP_USING_HWTIMER16 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HWTIMER_CONFIG_H__ */
diff --git a/bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.c b/bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.c
new file mode 100644
index 0000000000..271a874d8d
--- /dev/null
+++ b/bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-01-30 pomin first version
+ */
+
+#include <board.h>
+#include <rtdevice.h>
+#include "drv_hwtimer.h"
+#include "hwtimer_config.h"
+
+#ifdef BSP_USING_HWTIMER
+
+/*
+ * static void __set_timerx_freq
+ * Set freq with timerx
+ *
+ * @param timerx the pointer of TIMER_TypeDef
+ * @param freq of the timer clock
+ * @retval None
+ */
+static void __set_timerx_freq(uint32_t timerx, uint32_t freq)
+{
+ uint32_t ap1freq, ap2freq;
+ uint16_t prescaler;
+ uint32_t temp;
+
+ if (timerx == TIMER0 || timerx == TIMER15 || timerx == TIMER16)
+ {
+ ap2freq = rcu_clock_freq_get(CK_APB2);
+ temp = RCU_CFG0 & RCU_CFG0_APB2PSC;
+ temp >>= 11;
+ /* whether should frequency doubling */
+ temp = (temp < 4) ? 0 : 1;
+
+ prescaler = (ap2freq << temp) / freq - 1;
+ }
+ else
+ {
+ ap1freq = rcu_clock_freq_get(CK_APB1);
+ temp = RCU_CFG0 & RCU_CFG0_APB1PSC;
+ temp >>= 8;
+ /* whether should frequency doubling */
+ temp = (temp < 4) ? 0 : 1;
+
+ prescaler = (ap1freq << temp) / freq - 1;
+ }
+
+ timer_prescaler_config(timerx, prescaler, TIMER_PSC_RELOAD_NOW);
+}
+
+static void gd32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
+{
+ uint32_t timer_base = (uint32_t)timer->parent.user_data;
+ timer_parameter_struct initpara;
+
+ if (state)
+ {
+ timer_internal_clock_config(timer_base);
+ timer_struct_para_init(&initpara);
+ initpara.period = timer->info->maxcnt;
+ timer_init(timer_base, &initpara);
+ __set_timerx_freq(timer_base, timer->info->maxfreq);
+ }
+}
+
+static rt_err_t gd32_hwtimer_start(struct rt_hwtimer_device *timer, \
+ rt_uint32_t cnt, rt_hwtimer_mode_t mode)
+{
+ uint32_t timer_base = (uint32_t)timer->parent.user_data;
+
+ if (mode == HWTIMER_MODE_ONESHOT)
+ {
+ timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_SINGLE);
+ }
+ else if (mode == HWTIMER_MODE_PERIOD)
+ {
+ timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_REPETITIVE);
+ }
+
+ timer_counter_value_config(timer_base, 0);
+ timer_autoreload_value_config(timer_base, cnt - 1);
+ timer_enable(timer_base);
+
+ return 0;
+}
+
+static void gd32_hwtimer_stop(struct rt_hwtimer_device *timer)
+{
+ uint32_t timer_base = (uint32_t)timer->parent.user_data;
+
+ timer_disable(timer_base);
+}
+
+static rt_uint32_t gd32_hwtimer_count_get(struct rt_hwtimer_device *timer)
+{
+ uint32_t timer_base = (uint32_t)timer->parent.user_data;
+ rt_uint32_t count;
+
+ count = timer_counter_read(timer_base);
+
+ return count;
+}
+
+static rt_err_t gd32_hwtimer_control(struct rt_hwtimer_device *timer, rt_uint32_t cmd, \
+ void *args)
+{
+ int ret = RT_EOK;
+ rt_int32_t freq;
+ rt_hwtimer_mode_t mode;
+
+ switch (cmd)
+ {
+ case HWTIMER_CTRL_FREQ_SET:
+ freq = *(rt_uint32_t *)args;
+ __set_timerx_freq((uint32_t)timer->parent.user_data, freq);
+ break;
+ default:
+ rt_kprintf("invalid cmd:%x\n", cmd);
+ ret = -RT_EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct rt_hwtimer_ops g_gd32_hwtimer_ops = {
+ gd32_hwtimer_init,
+ gd32_hwtimer_start,
+ gd32_hwtimer_stop,
+ gd32_hwtimer_count_get,
+ gd32_hwtimer_control,
+};
+
+static gd32_hwtimer_device g_gd32_hwtimer[] = {
+#ifdef BSP_USING_HWTIMER0
+ HWTIMER0_CONFIG,
+#endif
+#ifdef BSP_USING_HWTIMER1
+ HWTIMER1_CONFIG,
+#endif
+#ifdef BSP_USING_HWTIMER2
+ HWTIMER2_CONFIG,
+#endif
+#ifdef BSP_USING_HWTIMER5
+ HWTIMER5_CONFIG,
+#endif
+#ifdef BSP_USING_HWTIMER15
+ HWTIMER15_CONFIG,
+#endif
+#ifdef BSP_USING_HWTIMER16
+ HWTIMER16_CONFIG,
+#endif
+};
+
+#ifdef BSP_USING_HWTIMER0
+void TIMER0_UP_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HWTIMER1
+void TIMER1_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HWTIMER2
+void TIMER2_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HWTIMER3
+void TIMER3_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HWTIMER4
+void TIMER4_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HWTIMER5
+void TIMER5_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HWTIMER6
+void TIMER6_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HWTIMER7
+void TIMER7_UP_IRQHandler(void)
+{
+ rt_interrupt_enter();
+ rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev);
+ timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev.parent.user_data, \
+ TIMER_INT_UP);
+ rt_interrupt_leave();
+}
+#endif
+
+static int rt_hwtimer_init(void)
+{
+ int ret = 0, i = 0;
+
+ for (; i < sizeof(g_gd32_hwtimer) / sizeof(g_gd32_hwtimer[0]); i++)
+ {
+ g_gd32_hwtimer[i].hwtimer_dev.ops = &g_gd32_hwtimer_ops;
+ g_gd32_hwtimer[i].hwtimer_dev.info = &g_gd32_hwtimer[i].hwtimer_info;
+
+ rcu_periph_clock_enable(g_gd32_hwtimer[i].hw_data.rcu);
+ ECLIC_SetPriorityIRQ(g_gd32_hwtimer[i].hw_data.irqn, 0);
+ ECLIC_EnableIRQ(g_gd32_hwtimer[i].hw_data.irqn);
+ timer_interrupt_enable(g_gd32_hwtimer[i].hw_data.reg_base, TIMER_INT_UP);
+ ret = rt_device_hwtimer_register(&g_gd32_hwtimer[i].hwtimer_dev, \
+ g_gd32_hwtimer[i].dev_name, (void *)g_gd32_hwtimer[i].hw_data.reg_base);
+ if (RT_EOK != ret)
+ {
+ rt_kprintf("failed register %s, err=%d\n", g_gd32_hwtimer[i].dev_name, \
+ ret);
+ break;
+ }
+ }
+
+ return ret;
+}
+INIT_BOARD_EXPORT(rt_hwtimer_init);
+#endif
diff --git a/bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.h b/bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.h
new file mode 100644
index 0000000000..730877845b
--- /dev/null
+++ b/bsp/gd32/risc-v/libraries/gd32_drivers/drv_hwtimer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-01-30 pomin first version
+ */
+
+#ifndef __DRV_HWTIMER_H__
+#define __DRV_HWTIMER_H__
+
+#include <rthw.h>
+#include <rtdevice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef RT_USING_HWTIMER
+
+typedef struct {
+ uint32_t reg_base;
+ IRQn_Type irqn;
+ rcu_periph_enum rcu;
+} gd32_hwtimer_data;
+
+typedef struct {
+ char dev_name[RT_NAME_MAX];
+ const gd32_hwtimer_data hw_data;
+ rt_hwtimer_t hwtimer_dev;
+ const struct rt_hwtimer_info hwtimer_info;
+} gd32_hwtimer_device;
+
+enum timer_index_E {
+#ifdef BSP_USING_HWTIMER0
+ TIM0_INDEX,
+#endif
+#ifdef BSP_USING_HWTIMER1
+ TIM1_INDEX,
+#endif
+#ifdef BSP_USING_HWTIMER2
+ TIM2_INDEX,
+#endif
+#ifdef BSP_USING_HWTIMER5
+ TIM5_INDEX,
+#endif
+#ifdef BSP_USING_HWTIMER15
+ TIM15_INDEX,
+#endif
+#ifdef BSP_USING_HWTIMER16
+ TIM16_INDEX,
+#endif
+};
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRV_HWTIMER_H__ */