123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- /*
- * Copyright (C) 2020, Huada Semiconductor Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-30 CDT first version
- */
- #include <rtdevice.h>
- #include <rtdbg.h>
- #ifdef RT_USING_HWTIMER
- #if !defined(BSP_USING_TIMER1) && !defined(BSP_USING_TIMER2) && !defined(BSP_USING_TIMER3) && \
- !defined(BSP_USING_TIMER4) && !defined(BSP_USING_TIMER5) && !defined(BSP_USING_TIMER6) && \
- !defined(BSP_USING_TIMER7) && !defined(BSP_USING_TIMER8) && !defined(BSP_USING_TIMER9) && \
- !defined(BSP_USING_TIMER10) && !defined(BSP_USING_TIMER11) && !defined(BSP_USING_TIMER12)
- #error "Please define at least one BSP_USING_TIMERx"
- /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable TIMER */
- #endif
- #include "drv_hwtimer.h"
- #include "drv_irq.h"
- enum
- {
- #ifdef BSP_USING_TIMER1
- TIMER1_INDEX,
- #endif
- #ifdef BSP_USING_TIMER2
- TIMER2_INDEX,
- #endif
- #ifdef BSP_USING_TIMER3
- TIMER3_INDEX,
- #endif
- #ifdef BSP_USING_TIMER4
- TIMER4_INDEX,
- #endif
- #ifdef BSP_USING_TIMER5
- TIMER5_INDEX,
- #endif
- #ifdef BSP_USING_TIMER6
- TIMER6_INDEX,
- #endif
- #ifdef BSP_USING_TIMER7
- TIMER7_INDEX,
- #endif
- #ifdef BSP_USING_TIMER8
- TIMER8_INDEX,
- #endif
- #ifdef BSP_USING_TIMER9
- TIMER9_INDEX,
- #endif
- #ifdef BSP_USING_TIMER10
- TIMER10_INDEX,
- #endif
- #ifdef BSP_USING_TIMER11
- TIMER11_INDEX,
- #endif
- #ifdef BSP_USING_TIMER12
- TIMER12_INDEX,
- #endif
- };
- #ifdef BSP_USING_TIMER1
- static void timer1_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER2
- static void timer2_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER3
- static void timer3_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER4
- static void timer4_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER5
- static void timer5_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER6
- static void timer6_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER7
- static void timer7_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER8
- static void timer8_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER9
- static void timer9_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER10
- static void timer10_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER11
- static void timer11_irq_handler(void);
- #endif
- #ifdef BSP_USING_TIMER12
- static void timer12_irq_handler(void);
- #endif
- struct hc32_hwtimer_config
- {
- rt_hwtimer_t time_device;
- M4_TMRA_TypeDef *timer_periph;
- struct hc32_irq_config irq_config;
- func_ptr_t irq_callback;
- uint32_t extend_div;
- uint32_t extend_cnt;
- char *name;
- };
- #ifndef HC32_TIMER_CONFIG
- #define HC32_TIMER_CONFIG(periph, irq, label, src, irq_info) \
- { \
- .timer_periph = periph, \
- .irq_callback = irq, \
- .name = label, \
- .irq_config = irq_info, \
- .irq_config.int_src = src, \
- }
- #endif /* HC32_TIMER_CONFIG */
- static struct hc32_hwtimer_config hwtimer_obj[] =
- {
- #ifdef BSP_USING_TIMER1
- HC32_TIMER_CONFIG(M4_TMRA_1, timer1_irq_handler, "timer1", INT_TMRA_1_OVF, TIMER1_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER2
- HC32_TIMER_CONFIG(M4_TMRA_2, timer2_irq_handler, "timer2", INT_TMRA_2_OVF, TIMER2_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER3
- HC32_TIMER_CONFIG(M4_TMRA_3, timer3_irq_handler, "timer3", INT_TMRA_3_OVF, TIMER3_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER4
- HC32_TIMER_CONFIG(M4_TMRA_4, timer4_irq_handler, "timer4", INT_TMRA_4_OVF, TIMER4_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER5
- HC32_TIMER_CONFIG(M4_TMRA_5, timer5_irq_handler, "timer5", INT_TMRA_5_OVF, TIMER5_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER6
- HC32_TIMER_CONFIG(M4_TMRA_6, timer6_irq_handler, "timer6", INT_TMRA_6_OVF, TIMER6_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER7
- HC32_TIMER_CONFIG(M4_TMRA_7, timer7_irq_handler, "timer7", INT_TMRA_7_OVF, TIMER7_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER8
- HC32_TIMER_CONFIG(M4_TMRA_8, timer8_irq_handler, "timer8", INT_TMRA_8_OVF, TIMER8_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER9
- HC32_TIMER_CONFIG(M4_TMRA_9, timer9_irq_handler, "timer9", INT_TMRA_9_OVF, TIMER9_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER10
- HC32_TIMER_CONFIG(M4_TMRA_10, timer10_irq_handler, "timer10", INT_TMRA_10_OVF, TIMER10_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER11
- HC32_TIMER_CONFIG(M4_TMRA_11, timer11_irq_handler, "timer11", INT_TMRA_11_OVF, TIMER11_IRQ_CONFIG),
- #endif
- #ifdef BSP_USING_TIMER12
- HC32_TIMER_CONFIG(M4_TMRA_12, timer12_irq_handler, "timer12", INT_TMRA_12_OVF, TIMER12_IRQ_CONFIG),
- #endif
- };
- static void hc32_timer_irq_handler(struct hc32_hwtimer_config *timer_config)
- {
- if ((++timer_config->extend_cnt) >= timer_config->extend_div)
- {
- timer_config->extend_cnt = 0;
- rt_device_hwtimer_isr(&timer_config->time_device);
- }
- TMRA_ClrStatus(timer_config->timer_periph, (TMRA_FLAG_OVF | TMRA_FLAG_UNF));
- }
- #ifdef BSP_USING_TIMER1
- static void timer1_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER1_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER2
- static void timer2_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER2_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER3
- static void timer3_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER3_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER4
- static void timer4_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER4_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER5
- static void timer5_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER5_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER6
- static void timer6_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER6_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER7
- static void timer7_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER7_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER8
- static void timer8_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER8_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER9
- static void timer9_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER9_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER10
- static void timer10_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER10_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER11
- static void timer11_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER11_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_TIMER12
- static void timer12_irq_handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- hc32_timer_irq_handler(&hwtimer_obj[TIMER12_INDEX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- static rt_uint16_t hc32_timer_get_unit_number(M4_TMRA_TypeDef *TMRAx)
- {
- rt_uint16_t unit_num;
- const rt_uint32_t unit_step = 0x400U;
- if (((rt_uint32_t)TMRAx) >= ((rt_uint32_t)M4_TMRA_1))
- {
- unit_num = (((rt_uint32_t)TMRAx) - ((rt_uint32_t)M4_TMRA_1)) / unit_step;
- }
- else
- {
- unit_num = (((rt_uint32_t)TMRAx) - ((rt_uint32_t)M4_TMRA_5)) / unit_step + 4;
- }
- return unit_num;
- }
- static void hc32_timer_clock_config(M4_TMRA_TypeDef *TMRAx, en_functional_state_t enNewState)
- {
- rt_uint32_t timer_periph;
- rt_uint16_t unit_num;
- unit_num = hc32_timer_get_unit_number(TMRAx);
- timer_periph = PWC_FCG2_TMRA_1 << unit_num;
- PWC_Fcg2PeriphClockCmd(timer_periph, enNewState);
- }
- static void hc32_timer_get_div_value(M4_TMRA_TypeDef *TMRAx, uint32_t freq, uint16_t *div, uint32_t *extend_div)
- {
- stc_clk_freq_t stcClkFreq;
- rt_uint32_t divisor, remainder;
- rt_uint16_t div_val;
- rt_uint32_t clk_freq;
- rt_uint16_t unit_num;
- CLK_GetClockFreq(&stcClkFreq);
- unit_num = hc32_timer_get_unit_number(TMRAx);
- if (unit_num >= 4)
- {
- clk_freq = stcClkFreq.pclk1Freq;
- }
- else
- {
- clk_freq = stcClkFreq.pclk0Freq;
- }
- divisor = clk_freq / freq;
- remainder = clk_freq % freq;
- for (div_val=1; div_val<=1024; div_val<<=1)
- {
- if (((divisor % 2) == 0) && (remainder == 0))
- {
- remainder = divisor % 2;
- divisor = divisor / 2;
- }
- else
- {
- break;
- }
- }
- *extend_div = divisor;
- *div = (__CLZ(__RBIT(div_val))) << TMRA_BCSTR_CKDIV_POS;
- }
- static void hc32_timer_interrupt_config(struct rt_hwtimer_device *timer, en_functional_state_t enNewState)
- {
- struct hc32_hwtimer_config *timer_config = RT_NULL;
- timer_config = (struct hc32_hwtimer_config *)timer;
- if (INT_MAX == timer_config->irq_config.int_src)
- {
- LOG_D("%s interrupt init failed", timer_config->name);
- return;
- }
- if (Enable == enNewState)
- {
- /* Enable the specified interrupts of Timer */
- hc32_install_irq_handler(&timer_config->irq_config, timer_config->irq_callback, RT_FALSE);
- NVIC_EnableIRQ(timer_config->irq_config.irq);
- TMRA_IntCmd(timer_config->timer_periph, TMRA_INT_OVF, Enable);
- }
- else
- {
- /* Disable the specified interrupts of Timer */
- TMRA_IntCmd(timer_config->timer_periph, TMRA_INT_OVF, Disable);
- NVIC_DisableIRQ(timer_config->irq_config.irq);
- }
- }
- static void hc32_timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
- {
- stc_tmra_init_t stcTmraInit;
- struct hc32_hwtimer_config *timer_config = RT_NULL;
- RT_ASSERT(timer != RT_NULL);
- timer_config = (struct hc32_hwtimer_config *)timer;
- if (state)
- {
- /* Enable Timer peripheral clock. */
- hc32_timer_clock_config(timer_config->timer_periph, Enable);
- TMRA_DeInit(timer_config->timer_periph);
- TMRA_StructInit(&stcTmraInit);
- stcTmraInit.u32CntDir = TMRA_DIR_UP;
- TMRA_Init(timer_config->timer_periph, &stcTmraInit);
- LOG_D("%s init success", timer_config->name);
- }
- else
- {
- TMRA_DeInit(timer_config->timer_periph);
- hc32_timer_interrupt_config(timer, Disable);
- /* Disable Timer peripheral clock. */
- hc32_timer_clock_config(timer_config->timer_periph, Disable);
- }
- }
- static rt_err_t hc32_timer_start(struct rt_hwtimer_device *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
- {
- rt_err_t result = RT_EOK;
- struct hc32_hwtimer_config *timer_config = RT_NULL;
- RT_ASSERT(timer != RT_NULL);
- timer_config = (struct hc32_hwtimer_config *)timer;
- if (mode == HWTIMER_MODE_ONESHOT)
- {
- TMRA_SetOvfOperation(timer_config->timer_periph, TMRA_OVF_CNT_STOP);
- }
- else
- {
- TMRA_SetOvfOperation(timer_config->timer_periph, TMRA_OVF_CNT_CONTINUE);
- }
- timer_config->extend_cnt = 0;
- TMRA_SetCntVal(timer_config->timer_periph, 0);
- TMRA_SetPeriodVal(timer_config->timer_periph, cnt - 1);
- hc32_timer_interrupt_config(timer, Enable);
- TMRA_Start(timer_config->timer_periph);
- return result;
- }
- static void hc32_timer_stop(struct rt_hwtimer_device *timer)
- {
- struct hc32_hwtimer_config *timer_config = RT_NULL;
- RT_ASSERT(timer != RT_NULL);
- timer_config = (struct hc32_hwtimer_config *)timer;
- /* stop timer */
- TMRA_Stop(timer_config->timer_periph);
- hc32_timer_interrupt_config(timer, Disable);
- TMRA_SetCntVal(timer_config->timer_periph, 0);
- }
- static rt_uint32_t hc32_timer_get_counter(struct rt_hwtimer_device *timer)
- {
- rt_uint32_t count_val;
- rt_uint32_t period_val;
- float temp;
- struct hc32_hwtimer_config *timer_config = RT_NULL;
- RT_ASSERT(timer != RT_NULL);
- timer_config = (struct hc32_hwtimer_config *)timer;
- period_val = TMRA_GetPeriodVal(timer_config->timer_periph);
- count_val = TMRA_GetCntVal(timer_config->timer_periph);
- temp = (timer_config->extend_cnt * period_val + count_val);
- temp = temp / (timer_config->extend_div * period_val) * period_val;
- count_val = (rt_uint32_t)temp;
- return count_val;
- }
- static rt_err_t hc32_timer_ctrl(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args)
- {
- struct hc32_hwtimer_config *timer_config = RT_NULL;
- rt_err_t result = RT_EOK;
- RT_ASSERT(timer != RT_NULL);
- RT_ASSERT(args != RT_NULL);
- timer_config = (struct hc32_hwtimer_config *)timer;
- switch (cmd)
- {
- case HWTIMER_CTRL_FREQ_SET:
- {
- rt_uint32_t freq;
- rt_uint16_t div_val;
- rt_uint32_t extend_div_val;
- /* set timer frequency */
- freq = *((rt_uint32_t *)args);
- hc32_timer_get_div_value(timer_config->timer_periph, freq, &div_val, &extend_div_val);
- TMRA_SetPCLKDiv(timer_config->timer_periph, div_val);
- timer_config->extend_div = extend_div_val;
- }
- break;
- default:
- {
- result = -RT_ENOSYS;
- }
- break;
- }
- return result;
- }
- static const struct rt_hwtimer_ops hwtimer_ops =
- {
- .init = hc32_timer_init,
- .start = hc32_timer_start,
- .stop = hc32_timer_stop,
- .count_get = hc32_timer_get_counter,
- .control = hc32_timer_ctrl,
- };
- static const struct rt_hwtimer_info hwtimer_info =
- {
- .maxfreq = 30000000,
- .minfreq = 1000,
- .maxcnt = 0xFFFF,
- .cntmode = HWTIMER_CNTMODE_UP,
- };
- static int rt_hwtimer_init(void)
- {
- int i = 0;
- int result = RT_EOK;
- for (i = 0; i < sizeof(hwtimer_obj) / sizeof(hwtimer_obj[0]); i++)
- {
- hwtimer_obj[i].time_device.info = &hwtimer_info;
- hwtimer_obj[i].time_device.ops = &hwtimer_ops;
- if (rt_device_hwtimer_register(&hwtimer_obj[i].time_device, hwtimer_obj[i].name, hwtimer_obj[i].timer_periph) == RT_EOK)
- {
- LOG_D("%s register success", hwtimer_obj[i].name);
- }
- else
- {
- LOG_E("%s register failed", hwtimer_obj[i].name);
- result = -RT_ERROR;
- }
- }
- return result;
- }
- INIT_BOARD_EXPORT(rt_hwtimer_init);
- #endif /* RT_USING_HWTIMER */
|