| Nano103 BSP V3.01.002 The Board Support Package for Nano103 Series

timer.c
Go to the documentation of this file.
1 /**************************************************************************/
12 #include "Nano103.h"
13
42 uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
43 {
44 uint32_t u32Clk = TIMER_GetModuleClock(timer);
45 uint32_t u32Cmpr = 0, u32Prescale = 0;
46
47 // Fastest possible timer working freq is u32Clk / 2. While cmpr = 2, pre-scale = 0
48 if(u32Freq > (u32Clk / 2))
49 {
50 u32Cmpr = 2;
51 }
52 else
53 {
54 if(u32Clk > 0xFFFFFF) // For Nano103, only needs to consider 36MHz at most
55 {
56 u32Prescale = 1;
57 u32Clk >>= 1;
58 }
59 u32Cmpr = u32Clk / u32Freq;
60 }
61 timer->CMP = u32Cmpr;
62 timer->PRECNT = u32Prescale;
63 timer->CTL = u32Mode;
64
65
66 return(u32Clk / (u32Cmpr * (u32Prescale + 1)));
67 }
68
74 void TIMER_Close(TIMER_T *timer)
75 {
76 timer->CTL = 0;
77 timer->INTEN = 0;
78 }
79
88 void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
89 {
90 uint32_t u32Clk = TIMER_GetModuleClock(timer);
91 uint32_t u32Prescale = 0, delay = SystemCoreClock / u32Clk;
92 long long u64Cmpr;
93
94 // Clear current timer configuration
95 timer->CTL = 0;
96
97 if(u32Clk == 10000) // min delay is 100us if timer clock source is LIRC 10k
98 {
99 u32Usec = ((u32Usec + 99) / 100) * 100;
100 }
101 else // 10 usec every step
102 {
103 u32Usec = ((u32Usec + 9) / 10) * 10;
104 }
105
106 if(u32Clk > 0xFFFFFF) // For Nano103, only needs to consider 32MHz at most
107 {
108 u32Prescale = 1;
109 u32Clk >>= 1;
110 }
111
112 // u32Usec * u32Clk might overflow if using uint32_t
113 u64Cmpr = (long long)u32Usec * (long long)u32Clk / (long long)1000000;
114
115 timer->CMP = (uint32_t)u64Cmpr;
116 timer->PRECNT = u32Prescale;
117 timer->CTL = TIMER_CTL_CNTEN_Msk; // one shot mode
118
119 // When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
120 // And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
121 for(; delay > 0; delay--)
122 {
123 __NOP();
124 }
125
126 while(timer->CTL & TIMER_CTL_ACTSTS_Msk);
127
128 }
129
145 void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
146 {
147
148 timer->CTL = (timer->CTL & ~(TIMER_CTL_CAPFUNCS_Msk |
149 TIMER_CTL_CAPCNTMD_Msk |
150 TIMER_CTL_CAPEDGE_Msk)) |
151 u32CapMode | u32Edge | TIMER_CTL_CAPEN_Msk;
152 }
153
159 void TIMER_DisableCapture(TIMER_T *timer)
160 {
161 timer->CTL &= ~TIMER_CTL_CAPEN_Msk;
162
163 }
164
174 void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
175 {
176 timer->CTL = (timer->CTL & ~TIMER_CTL_CNTPHASE_Msk) | u32Edge;
177 timer->CTL |= TIMER_CTL_EXTCNTEN_Msk;
178 }
179
185 void TIMER_DisableEventCounter(TIMER_T *timer)
186 {
187 timer->CTL &= ~TIMER_CTL_EXTCNTEN_Msk;
188 }
189
196 uint32_t TIMER_GetModuleClock(TIMER_T *timer)
197 {
198 uint32_t u32Src, u32Div;
199 const uint32_t au32Clk[] = {__HXT, __LXT, __LIRC, 0}; // we don't know actual clock if external pin is clock source, set to 0 here
200
201 if(timer == TIMER0)
202 {
203 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos;
204 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR0DIV_Msk) >> CLK_CLKDIV1_TMR0DIV_Pos;
205 }
206 else if(timer == TIMER1)
207 {
208 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos;
209 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR1DIV_Msk) >> CLK_CLKDIV1_TMR1DIV_Pos;
210 }
211 else if(timer == TIMER2)
212 {
213 u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR2SEL_Msk) >> CLK_CLKSEL2_TMR2SEL_Pos;
214 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR2DIV_Msk) >> CLK_CLKDIV1_TMR2DIV_Pos;
215 }
216 else // Timer 3
217 {
218 u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR3SEL_Msk) >> CLK_CLKSEL2_TMR3SEL_Pos;
219 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR3DIV_Msk) >> CLK_CLKDIV1_TMR3DIV_Pos;
220 }
221 u32Div++;
222 if(u32Src < 4)
223 return au32Clk[u32Src] / u32Div;
224 else if(u32Src == 4)
225 {
226 /* HIRC Source Selection */
227 if(CLK->CLKSEL0 & CLK_CLKSEL0_HIRCSEL_Msk)
228 {
229 /* Clock source from HIRC1 (36MHz) */
230 return __HIRC36M / u32Div;
231 }
232 else
233 {
234 /* Clock source from HIRC0 (12MHz) */
235 if(CLK->PWRCTL & CLK_PWRCTL_HIRC0FSEL_Msk)
236 return __HIRC16M / u32Div;
237 else
238 return __HIRC12M / u32Div;
239 }
240
241 }
242 else if(u32Src == 5) // MIRC
243 {
244 return __MIRC / u32Div;
245
246 }
247 else // HCLK
248 return CLK_GetHCLKFreq() / u32Div;
249
250 }
251
257 void TIMER_ResetCounter(TIMER_T *timer)
258 {
259 // A write with any value to TIMER CNT register will trigger timer counter reset
260 timer->CNT = 0;
261 }
262
280 void TIMER_EnableFreqCounter(TIMER_T *timer,
281 uint32_t u32DropCount,
282 uint32_t u32Timeout,
283 uint32_t u32EnableInt)
284 {
285 uint32_t mode = TIMER_CTL_INTRTGEN_Msk;
286 TIMER_T *t; // store the timer base to configure compare value
287
288 if(u32DropCount != 0 || u32Timeout >= 2)
289 mode |= TIMER_CTL_INTRTGMD_Msk;
290 if(u32Timeout < 2)
291 u32Timeout = 0xFFFFFF;
292
293 timer->ECTL = u32DropCount << TIMER_ECTL_EVNTDPCNT_Pos;
294 t = (timer == TIMER0) ? TIMER1 : TIMER3;
295
296 t->CMP = u32Timeout;
297 t->INTEN = u32EnableInt ? TIMER_INTEN_CAPIEN_Msk : 0;
298 timer->CTL = mode | TIMER_CTL_CNTEN_Msk;
299
300 return;
301 }
307 void TIMER_DisableFreqCounter(TIMER_T *timer)
308 {
309 timer->CTL &= ~(TIMER_CTL_INTRTGEN_Msk | TIMER_CTL_INTRTGMD_Msk);
310 }
311
320 void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src)
321 {
322 timer->CTL = (timer->CTL & ~TIMER_CTL_TRGSSEL_Msk) | u32Src;
323 }
324
334 void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
335 {
336 timer->CTL = (timer->CTL & ~(TIMER_CTL_TRGPWM_Msk | TIMER_CTL_TRGPDMA_Msk | TIMER_CTL_TRGADC_Msk)) | u32Mask;
337 }
338 /* end of group NANO103_TIMER_EXPORTED_FUNCTIONS */
340 /* end of group NANO103_TIMER_Driver */
342 /* end of group NANO103_Device_Driver */
344
345 /*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
CLK_CLKSEL2_TMR3SEL_Pos
#define CLK_CLKSEL2_TMR3SEL_Pos
Definition: Nano103.h:5112
TIMER2
#define TIMER2
Pointer to TIMER2 register structure.
Definition: Nano103.h:24866
TIMER_CTL_INTRTGMD_Msk
#define TIMER_CTL_INTRTGMD_Msk
Definition: Nano103.h:14303
TIMER_T::CTL
__IO uint32_t CTL
Definition: Nano103.h:14227
TIMER_INTEN_CAPIEN_Msk
#define TIMER_INTEN_CAPIEN_Msk
Definition: Nano103.h:14318
TIMER_CTL_TRGSSEL_Msk
#define TIMER_CTL_TRGSSEL_Msk
Definition: Nano103.h:14270
CLK_PWRCTL_HIRC0FSEL_Msk
#define CLK_PWRCTL_HIRC0FSEL_Msk
Definition: Nano103.h:4957
TIMER_Close
void TIMER_Close(TIMER_T *timer)
This API stops Timer counting and disable the Timer interrupt function.
Definition: timer.c:74
__HXT
#define __HXT
Definition: system_Nano103.h:26
TIMER_EnableEventCounter
void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
This function is used to enable the Timer counter function with specify detection edge.
Definition: timer.c:174
CLK_CLKSEL1_TMR0SEL_Msk
#define CLK_CLKSEL1_TMR0SEL_Msk
Definition: Nano103.h:5083
TIMER_CTL_EXTCNTEN_Msk
#define TIMER_CTL_EXTCNTEN_Msk
Definition: Nano103.h:14273
TIMER_Open
uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
This API is used to configure timer to operate in specified mode and frequency. If timer cannot work ...
Definition: timer.c:42
CLK_CLKSEL1_TMR1SEL_Pos
#define CLK_CLKSEL1_TMR1SEL_Pos
Definition: Nano103.h:5085
TIMER_EnableFreqCounter
void TIMER_EnableFreqCounter(TIMER_T *timer, uint32_t u32DropCount, uint32_t u32Timeout, uint32_t u32EnableInt)
This function is used to enable the Timer frequency counter function.
Definition: timer.c:280
CLK_CLKDIV1_TMR0DIV_Pos
#define CLK_CLKDIV1_TMR0DIV_Pos
Definition: Nano103.h:5145
TIMER_CTL_CNTEN_Msk
#define TIMER_CTL_CNTEN_Msk
Definition: Nano103.h:14246
CLK_CLKDIV1_TMR2DIV_Msk
#define CLK_CLKDIV1_TMR2DIV_Msk
Definition: Nano103.h:5152
TIMER_DisableEventCounter
void TIMER_DisableEventCounter(TIMER_T *timer)
This API is used to disable the Timer event counter function.
Definition: timer.c:185
TIMER_CTL_CAPEN_Msk
#define TIMER_CTL_CAPEN_Msk
Definition: Nano103.h:14282
__HIRC16M
#define __HIRC16M
Definition: system_Nano103.h:29
SystemCoreClock
uint32_t SystemCoreClock
Definition: system_Nano103.c:20
TIMER_CTL_CAPEDGE_Msk
#define TIMER_CTL_CAPEDGE_Msk
Definition: Nano103.h:14288
__LXT
#define __LXT
Definition: system_Nano103.h:27
TIMER1
#define TIMER1
Pointer to TIMER1 register structure.
Definition: Nano103.h:24865
TIMER_ResetCounter
void TIMER_ResetCounter(TIMER_T *timer)
This function is used to reset the Timer counter value.
Definition: timer.c:257
TIMER_T::PRECNT
__IO uint32_t PRECNT
Definition: Nano103.h:14228
TIMER_CTL_INTRTGEN_Msk
#define TIMER_CTL_INTRTGEN_Msk
Definition: Nano103.h:14300
CLK_CLKDIV1_TMR1DIV_Pos
#define CLK_CLKDIV1_TMR1DIV_Pos
Definition: Nano103.h:5148
TIMER_CTL_TRGPWM_Msk
#define TIMER_CTL_TRGPWM_Msk
Definition: Nano103.h:14306
TIMER_EnableCapture
void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
This API is used to enable timer capture function with specified mode and capture edge.
Definition: timer.c:145
TIMER_ECTL_EVNTDPCNT_Pos
#define TIMER_ECTL_EVNTDPCNT_Pos
Definition: Nano103.h:14344
CLK_CLKDIV1_TMR3DIV_Pos
#define CLK_CLKDIV1_TMR3DIV_Pos
Definition: Nano103.h:5154
CLK_CLKSEL1_TMR0SEL_Pos
#define CLK_CLKSEL1_TMR0SEL_Pos
Definition: Nano103.h:5082
CLK_CLKDIV1_TMR2DIV_Pos
#define CLK_CLKDIV1_TMR2DIV_Pos
Definition: Nano103.h:5151
TIMER_T::CMP
__IO uint32_t CMP
Definition: Nano103.h:14229
TIMER_CTL_TRGPDMA_Msk
#define TIMER_CTL_TRGPDMA_Msk
Definition: Nano103.h:14267
TIMER_CTL_CAPCNTMD_Msk
#define TIMER_CTL_CAPCNTMD_Msk
Definition: Nano103.h:14291
TIMER_CTL_ACTSTS_Msk
#define TIMER_CTL_ACTSTS_Msk
Definition: Nano103.h:14261
CLK_CLKSEL2_TMR2SEL_Pos
#define CLK_CLKSEL2_TMR2SEL_Pos
Definition: Nano103.h:5109
__LIRC
#define __LIRC
Definition: system_Nano103.h:30
TIMER_GetModuleClock
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
This API is used to get the clock frequency of Timer.
Definition: timer.c:196
TIMER_CTL_CNTPHASE_Msk
#define TIMER_CTL_CNTPHASE_Msk
Definition: Nano103.h:14276
TIMER_SetTriggerTarget
void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
This function is used to set modules trigger by timer interrupt.
Definition: timer.c:334
__MIRC
#define __MIRC
Definition: system_Nano103.h:32
CLK_GetHCLKFreq
uint32_t CLK_GetHCLKFreq(void)
This function get HCLK frequency. The frequency unit is Hz.
Definition: clk.c:126
CLK_CLKSEL2_TMR2SEL_Msk
#define CLK_CLKSEL2_TMR2SEL_Msk
Definition: Nano103.h:5110
TIMER3
#define TIMER3
Pointer to TIMER3 register structure.
Definition: Nano103.h:24867
TIMER_DisableCapture
void TIMER_DisableCapture(TIMER_T *timer)
This API is used to disable the Timer capture function.
Definition: timer.c:159
Nano103.h
NANO103 peripheral access layer header file. This file contains all the peripheral register's definit...
TIMER_CTL_CAPFUNCS_Msk
#define TIMER_CTL_CAPFUNCS_Msk
Definition: Nano103.h:14285
TIMER_T
Definition: Nano103.h:13684
TIMER_T::CNT
__IO uint32_t CNT
Definition: Nano103.h:14232
__HIRC36M
#define __HIRC36M
Definition: system_Nano103.h:31
CLK_CLKSEL0_HIRCSEL_Msk
#define CLK_CLKSEL0_HIRCSEL_Msk
Definition: Nano103.h:5071
CLK_CLKSEL1_TMR1SEL_Msk
#define CLK_CLKSEL1_TMR1SEL_Msk
Definition: Nano103.h:5086
TIMER_Delay
void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
This API is used to create a delay loop for u32usec micro seconds.
Definition: timer.c:88
TIMER_T::INTEN
__IO uint32_t INTEN
Definition: Nano103.h:14230
CLK_CLKSEL2_TMR3SEL_Msk
#define CLK_CLKSEL2_TMR3SEL_Msk
Definition: Nano103.h:5113
CLK_CLKDIV1_TMR1DIV_Msk
#define CLK_CLKDIV1_TMR1DIV_Msk
Definition: Nano103.h:5149
__HIRC12M
#define __HIRC12M
Definition: system_Nano103.h:28
CLK
#define CLK
Pointer to CLK register structure.
Definition: Nano103.h:24884
TIMER_DisableFreqCounter
void TIMER_DisableFreqCounter(TIMER_T *timer)
This function is used to disable the Timer frequency counter function.
Definition: timer.c:307
TIMER0
#define TIMER0
Pointer to TIMER0 register structure.
Definition: Nano103.h:24864
CLK_CLKDIV1_TMR0DIV_Msk
#define CLK_CLKDIV1_TMR0DIV_Msk
Definition: Nano103.h:5146
TIMER_CTL_TRGADC_Msk
#define TIMER_CTL_TRGADC_Msk
Definition: Nano103.h:14264
TIMER_SetTriggerSource
void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src)
This function is used to select the interrupt source used to trigger other modules.
Definition: timer.c:320
TIMER_T::ECTL
__IO uint32_t ECTL
Definition: Nano103.h:14237
CLK_CLKDIV1_TMR3DIV_Msk
#define CLK_CLKDIV1_TMR3DIV_Msk
Definition: Nano103.h:5155