123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-02-25 iysheng first version
- */
- #include <board.h>
- #include <rtdevice.h>
- #include <drivers/hwtimer.h>
- #ifdef BSP_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_HWTIMER3
- TIM3_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER4
- TIM4_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER5
- TIM5_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER6
- TIM6_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER7
- TIM7_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER8
- TIM8_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER9
- TIM9_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER10
- TIM10_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER11
- TIM11_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER12
- TIM12_INDEX,
- #endif
- #ifdef BSP_USING_HWTIMER13
- TIM13_INDEX,
- #endif
- };
- /*
- * 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 == TIMER7 || timerx == TIMER8 \
- || timerx == TIMER9 || timerx == TIMER10)
- {
- 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
- {
- "timer0",
- {
- TIMER0,
- TIMER0_UP_IRQn,
- RCU_TIMER0,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER1
- {
- "timer1",
- {
- TIMER1,
- TIMER1_IRQn,
- RCU_TIMER1,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER2
- {
- "timer2",
- {
- TIMER2,
- TIMER2_IRQn,
- RCU_TIMER2,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER3
- {
- "timer3",
- {
- TIMER3,
- TIMER3_IRQn,
- RCU_TIMER3,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER4
- {
- "timer4",
- {
- TIMER4,
- TIMER4_IRQn,
- RCU_TIMER4,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER5
- {
- "timer5",
- {
- TIMER5,
- TIMER5_IRQn,
- RCU_TIMER5,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER6
- {
- "timer6",
- {
- TIMER6,
- TIMER6_IRQn,
- RCU_TIMER6,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER7
- {
- "timer7",
- {
- TIMER7,
- TIMER7_UP_IRQn,
- RCU_TIMER7,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER8
- {
- "timer8",
- {
- TIMER8,
- TIMER8_IRQn,
- RCU_TIMER8,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER9
- {
- "timer9",
- {
- TIMER9,
- TIMER9_IRQn,
- RCU_TIMER9,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER10
- {
- "timer10",
- {
- TIMER10,
- TIMER10_IRQn,
- RCU_TIMER10,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER11
- {
- "timer11",
- {
- TIMER11,
- TIMER11_IRQn,
- RCU_TIMER11,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER12
- {
- "timer12",
- {
- TIMER12,
- TIMER12_IRQn,
- RCU_TIMER12,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #endif
- #ifdef BSP_USING_HWTIMER13
- {
- "timer13",
- {
- TIMER13,
- TIMER13_IRQn,
- RCU_TIMER13,
- },
- {0},
- {
- 1000000,
- 1000,
- 0xffff,
- 0, /* count up mode */
- }
- },
- #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);
- NVIC_SetPriority(g_gd32_hwtimer[i].hw_data.irqn, 0);
- NVIC_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
|