Browse Source

bsp: [gd32] add GD32VW553 hw timer support. (#11157)

* bsp: [gd32] add GD32VW553 hw timer support.

* bsp: [gd32] add GD32VW553 hw timer config.
POMIN 1 giờ trước cách đây
mục cha
commit
bb1b52d469

+ 25 - 0
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

+ 1 - 0
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)
 

+ 158 - 0
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__ */

+ 274 - 0
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

+ 63 - 0
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__ */