summaryrefslogtreecommitdiff
path: root/bsp
diff options
context:
space:
mode:
Diffstat (limited to 'bsp')
-rw-r--r--bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript3
-rw-r--r--bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_timer.c288
-rw-r--r--bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig19
3 files changed, 310 insertions, 0 deletions
diff --git a/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript
index 6f2f6c5427..994c5dcf63 100644
--- a/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript
+++ b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript
@@ -19,6 +19,9 @@ if GetDepend('BSP_USING_CAN'):
if GetDepend('BSP_USING_ECAP'):
src += ['drv_ecap.c']
+if GetDepend('BSP_USING_TIM'):
+ src += ['drv_timer.c']
+
group = DefineGroup('HAL_Drivers', src, depend = [''], CPPPATH = path)
Return('group')
diff --git a/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_timer.c b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_timer.c
new file mode 100644
index 0000000000..683d8888a0
--- /dev/null
+++ b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_timer.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-05-16 oxlm First Version
+ */
+
+#include <board.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "drv_config.h"
+#include "tim.h"
+#include "rcc.h"
+
+#ifdef BSP_USING_TIM
+
+#define DRV_DEBUG
+#define LOG_TAG "drv.timer"
+#include <drv_log.h>
+
+struct ns800_clock_timer
+{
+ rt_clock_timer_t timer;
+ void *instance;
+ IRQn_Type irqno;
+ void (*irq_handler)(void);
+ char *name;
+ rt_clock_timer_mode_t mode;
+};
+
+enum
+{
+#ifdef BSP_USING_TIM1
+ TIM1_INDEX,
+#endif
+#ifdef BSP_USING_TIM2
+ TIM2_INDEX,
+#endif
+};
+
+#ifdef BSP_USING_TIM1
+void TIM1_IRQHandler(void);
+#endif
+#ifdef BSP_USING_TIM2
+void TIM2_IRQHandler(void);
+#endif
+
+static struct ns800_clock_timer ns800_timers[] =
+{
+#ifdef BSP_USING_TIM1
+ {.instance = TIM1, .irqno = TIM1_IRQn, .irq_handler = TIM1_IRQHandler, .name = "timer1"},
+#endif
+#ifdef BSP_USING_TIM2
+ {.instance = TIM2, .irqno = TIM2_IRQn, .irq_handler = TIM2_IRQHandler, .name = "timer2"},
+#endif
+};
+
+#define NS800_TIMER_NUM (sizeof(ns800_timers) / sizeof(ns800_timers[0]))
+
+static void ns800_clock_timer_isr(void *param)
+{
+ rt_interrupt_enter();
+
+ struct ns800_clock_timer *tim = (struct ns800_clock_timer *)param;
+ TIM_TypeDef *htim = (TIM_TypeDef *)tim->instance;
+
+ if (TIM_getFlags(htim, TIM_FLAG_UPDATE))
+ {
+ TIM_clearFlags(htim, TIM_FLAG_UPDATE);
+ rt_clock_timer_isr(&tim->timer);
+
+ if (tim->mode == CLOCK_TIMER_MODE_ONESHOT)
+ {
+ TIM_disableCounter(htim);
+ }
+ }
+
+ rt_interrupt_leave();
+ __DSB();
+}
+
+#ifdef BSP_USING_TIM1
+void TIM1_IRQHandler(void)
+{
+ ns800_clock_timer_isr(&ns800_timers[TIM1_INDEX]);
+}
+#endif
+#ifdef BSP_USING_TIM2
+void TIM2_IRQHandler(void)
+{
+ ns800_clock_timer_isr(&ns800_timers[TIM2_INDEX]);
+}
+#endif
+
+static void ns800_clock_timer_init(rt_clock_timer_t *timer, rt_uint32_t state)
+{
+ struct ns800_clock_timer *tim = (struct ns800_clock_timer *)timer->parent.user_data;
+ TIM_TypeDef *htim = (TIM_TypeDef *)tim->instance;
+
+ if (state)
+ {
+ __IO uint32_t cfg =
+ TIM_PWMMODE_ONEPOINT |
+ TIM_CLOCKDIVISION_DIV1 |
+ TIM_AUTORELOADPRELOAD_ENABLE |
+ TIM_COUNTERMODE_UP |
+ TIM_ONEPULSEMODE_REPETITIVE;
+
+ TIM_configTimeBase(htim, 200 - 1, 100 - 1, cfg);
+ TIM_clearFlags(htim, TIM_FLAG_UPDATE);
+ TIM_enableInterruptSource(htim, TIM_IT_UPDATE);
+ }
+ else
+ {
+ TIM_disableInterruptSource(htim, TIM_IT_UPDATE);
+ TIM_disableCounter(htim);
+ }
+}
+
+static rt_err_t ns800_clock_timer_start(rt_clock_timer_t *timer, rt_uint32_t cnt, rt_clock_timer_mode_t mode)
+{
+ struct ns800_clock_timer *tim = (struct ns800_clock_timer *)timer->parent.user_data;
+ tim->mode = mode;
+
+ TIM_TypeDef *htim = (TIM_TypeDef *)tim->instance;
+
+ if (cnt > 0xFFFF)
+ {
+ cnt = 0xFFFF;
+ }
+
+ TIM_setAutoReload(htim, cnt - 1);
+ TIM_setCounter(htim, 0);
+ TIM_enableCounter(htim);
+
+ return RT_EOK;
+}
+
+static void ns800_clock_timer_stop(rt_clock_timer_t *timer)
+{
+ struct ns800_clock_timer *tim = (struct ns800_clock_timer *)timer->parent.user_data;
+
+ TIM_disableCounter((TIM_TypeDef *)tim->instance);
+}
+
+static rt_uint32_t ns800_clock_timer_count_get(rt_clock_timer_t *timer)
+{
+ struct ns800_clock_timer *tim = (struct ns800_clock_timer *)timer->parent.user_data;
+
+ return TIM_getCounter((TIM_TypeDef *)tim->instance);
+}
+
+static uint32_t __get_timer_src_clk(TIM_TypeDef *htim)
+{
+ if (htim == TIM1)
+ {
+ uint32_t pclk = RCC_getPclk2Frequency();
+
+ return (RCC_getApb2ClkDiv() == RCC_APB2_4_HCLK_DIV1) ? pclk : (pclk << 1);
+ }
+ else if (htim == TIM2)
+ {
+ uint32_t pclk = RCC_getPclk2Frequency();
+
+ return (RCC_getApb2ClkDiv() == RCC_APB2_4_HCLK_DIV1) ? pclk : (pclk << 1);
+ }
+
+ return 0;
+}
+
+static rt_err_t __set_timerx_freq(rt_clock_timer_t *timer, uint32_t freq)
+{
+ struct ns800_clock_timer *tim = timer->parent.user_data;
+ TIM_TypeDef *htim = (TIM_TypeDef *)tim->instance;
+ uint32_t timer_clk;
+ uint32_t psc;
+
+ if (freq == 0)
+ {
+ return -RT_ERROR;
+ }
+
+ timer_clk = __get_timer_src_clk(htim);
+ if (timer_clk == 0)
+ {
+ LOG_E("timer %s does not use internal RCC clock source or clock query failed", tim->name);
+ return -RT_ERROR;
+ }
+
+ psc = (timer_clk / freq) - 1;
+ TIM_setPrescaler(htim, psc);
+
+ return RT_EOK;
+}
+
+static rt_err_t ns800_clock_timer_control(rt_clock_timer_t *timer, rt_uint32_t cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ rt_int32_t freq;
+
+ switch (cmd)
+ {
+ case CLOCK_TIMER_CTRL_FREQ_SET:
+ freq = *(rt_uint32_t *)args;
+ __set_timerx_freq(timer, freq);
+ break;
+ case CLOCK_TIMER_CTRL_INFO_GET:
+ *(struct rt_clock_timer_info *)args = *timer->info;
+ err = RT_EOK;
+ break;
+ case CLOCK_TIMER_CTRL_MODE_SET:
+ timer->mode = *(rt_uint32_t *)args;
+ break;
+ case CLOCK_TIMER_CTRL_STOP:
+ ns800_clock_timer_stop(timer);
+ break;
+ }
+
+ return err;
+}
+
+static const struct rt_clock_timer_info ns800_clock_timer_info[] =
+{
+#ifdef BSP_USING_TIM1
+ {
+ .maxfreq = 200000000UL,
+ .minfreq = 1UL,
+ .maxcnt = 0xFFFF,
+ .cntmode = CLOCK_TIMER_CNTMODE_UP,
+ },
+#endif
+#ifdef BSP_USING_TIM2
+ {
+ .maxfreq = 200000000UL,
+ .minfreq = 1UL,
+ .maxcnt = 0xFFFF,
+ .cntmode = CLOCK_TIMER_CNTMODE_UP,
+ },
+#endif
+};
+
+static const struct rt_clock_timer_ops ns800_clock_timer_ops =
+{
+ .init = ns800_clock_timer_init,
+ .start = ns800_clock_timer_start,
+ .stop = ns800_clock_timer_stop,
+ .count_get = ns800_clock_timer_count_get,
+ .control = ns800_clock_timer_control,
+};
+
+int rt_hw_clock_timer_init(void)
+{
+ rt_err_t ret = RT_EOK;
+
+ if (NS800_TIMER_NUM == 0)
+ {
+ return RT_EOK;
+ }
+
+ uint8_t i;
+ IRQn_Type last_irq = (IRQn_Type)0;
+
+ for (i = 0; i < NS800_TIMER_NUM; i++)
+ {
+ ns800_timers[i].timer.info = &ns800_clock_timer_info[i];
+ ns800_timers[i].timer.ops = &ns800_clock_timer_ops;
+
+ ret = rt_clock_timer_register(&ns800_timers[i].timer,
+ ns800_timers[i].name,
+ &ns800_timers[i]);
+
+ if ((ret == RT_EOK) && (ns800_timers[i].irqno != last_irq))
+ {
+ Interrupt_register(ns800_timers[i].irqno, ns800_timers[i].irq_handler);
+ Interrupt_enable(ns800_timers[i].irqno);
+ last_irq = ns800_timers[i].irqno;
+ }
+ }
+
+ return RT_EOK;
+}
+
+INIT_DEVICE_EXPORT(rt_hw_clock_timer_init);
+
+#endif /* BSP_USING_TIM */
diff --git a/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig b/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig
index c4bbdf3080..e3ca09b573 100644
--- a/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig
+++ b/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig
@@ -105,4 +105,23 @@ menu "On-chip Peripheral Drivers"
endif
+ menuconfig BSP_USING_TIM
+ bool "Enable TIM (Hardware Timer)"
+ select RT_USING_CLOCK_TIME
+ default n
+ help
+ Enable hardware timer TIM driver
+
+ if BSP_USING_TIM
+ menu "TIM Timer Configuration"
+ config BSP_USING_TIM1
+ bool "Enable TIM1"
+ default n
+ config BSP_USING_TIM2
+ bool "Enable TIM2"
+ default n
+ endmenu
+
+ endif
+
endmenu