1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2015-09-02 heyuanjie87 the first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "lpc_timer.h"
14 #include "lpc_clkpwr.h"
15 #include "drv_hwtimer.h"
16
17 #ifdef RT_USING_HWTIMER
18
NVIC_Configuration(void)19 static void NVIC_Configuration(void)
20 {
21 NVIC_EnableIRQ(TIMER0_IRQn);
22 }
23
timer_init(rt_hwtimer_t * timer,rt_uint32_t state)24 static void timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
25 {
26 LPC_TIM_TypeDef *tim;
27 TIM_TIMERCFG_Type cfg;
28
29 tim = (LPC_TIM_TypeDef *)timer->parent.user_data;
30
31 TIM_DeInit(tim);
32
33 if (state == 1)
34 {
35 NVIC_Configuration();
36
37 cfg.PrescaleOption = TIM_PRESCALE_TICKVAL;
38 cfg.PrescaleValue = 0xFFFF;
39 TIM_Init(tim, TIM_TIMER_MODE, &cfg);
40 }
41 }
42
timer_start(rt_hwtimer_t * timer,rt_uint32_t t,rt_hwtimer_mode_t opmode)43 static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
44 {
45 LPC_TIM_TypeDef *tim;
46 TIM_MATCHCFG_Type match;
47
48 tim = (LPC_TIM_TypeDef *)timer->parent.user_data;
49
50 match.MatchChannel = 0;
51 match.IntOnMatch = ENABLE;
52 match.ResetOnMatch = ENABLE;
53 match.StopOnMatch = (opmode == HWTIMER_MODE_ONESHOT) ? ENABLE : DISABLE;
54 match.ExtMatchOutputType = 0;
55 match.MatchValue = t;
56
57 TIM_ConfigMatch(tim, &match);
58 TIM_Cmd(tim, ENABLE);
59
60 return RT_EOK;
61 }
62
timer_stop(rt_hwtimer_t * timer)63 static void timer_stop(rt_hwtimer_t *timer)
64 {
65 LPC_TIM_TypeDef *tim;
66
67 tim = (LPC_TIM_TypeDef *)timer->parent.user_data;
68
69 TIM_Cmd(tim, DISABLE);
70 }
71
timer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)72 static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
73 {
74 LPC_TIM_TypeDef *tim;
75 rt_err_t err = RT_EOK;
76
77 tim = (LPC_TIM_TypeDef *)timer->parent.user_data;
78
79 switch (cmd)
80 {
81 case HWTIMER_CTRL_FREQ_SET:
82 {
83 uint32_t clk;
84 uint32_t pre;
85
86 clk = CLKPWR_GetCLK(CLKPWR_CLKTYPE_PER);
87 pre = clk / *((uint32_t *)arg) - 1;
88 tim->PR = pre;
89 }
90 break;
91 default:
92 {
93 err = -RT_ENOSYS;
94 }
95 break;
96 }
97
98 return err;
99 }
100
timer_counter_get(rt_hwtimer_t * timer)101 static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
102 {
103 LPC_TIM_TypeDef *tim;
104
105 tim = (LPC_TIM_TypeDef *)timer->parent.user_data;
106
107 return tim->TC;
108 }
109
110 static const struct rt_hwtimer_info _info =
111 {
112 1000000, /* the maximum count frequency can be set */
113 2000, /* the minimum count frequency can be set */
114 0xFFFFFF, /* the maximum counter value */
115 HWTIMER_CNTMODE_UP,/* Increment or Decreasing count mode */
116 };
117
118 static const struct rt_hwtimer_ops _ops =
119 {
120 timer_init,
121 timer_start,
122 timer_stop,
123 timer_counter_get,
124 timer_ctrl,
125 };
126
127 static rt_hwtimer_t _timer0;
128
rt_hw_hwtimer_init(void)129 int rt_hw_hwtimer_init(void)
130 {
131 _timer0.info = &_info;
132 _timer0.ops = &_ops;
133
134 rt_device_hwtimer_register(&_timer0, "timer0", LPC_TIM0);
135
136 return 0;
137 }
138
TIMER0_IRQHandler(void)139 void TIMER0_IRQHandler(void)
140 {
141 if (TIM_GetIntStatus(LPC_TIM0, TIM_MR0_INT) != RESET)
142 {
143 TIM_ClearIntPending(LPC_TIM0, TIM_MR0_INT);
144 rt_device_hwtimer_isr(&_timer0);
145 }
146 }
147
148 INIT_BOARD_EXPORT(rt_hw_hwtimer_init);
149
150 #endif /* RT_USING_HWTIMER */
151