NANO103 BSP V3.01.004
The Board Support Package for Nano103 Series
timer.c
Go to the documentation of this file.
1/**************************************************************************/
12#include "Nano103.h"
13
42uint32_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
74void TIMER_Close(TIMER_T *timer)
75{
76 timer->CTL = 0;
77 timer->INTEN = 0;
78}
79
91int32_t TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
92{
93 uint32_t u32Clk = TIMER_GetModuleClock(timer);
94 uint32_t u32Prescale = 0, u32Delay = SystemCoreClock / u32Clk;
95 long long u64Cmpr;
96 uint32_t u32Cntr, i = 0UL;
97
98 // Clear current timer configuration
99 timer->CTL = 0;
100
101 if(u32Clk == 10000) // min delay is 100us if timer clock source is LIRC 10k
102 {
103 u32Usec = ((u32Usec + 99) / 100) * 100;
104 }
105 else // 10 usec every step
106 {
107 u32Usec = ((u32Usec + 9) / 10) * 10;
108 }
109
110 if(u32Clk > 0xFFFFFF) // For Nano103, only needs to consider 32MHz at most
111 {
112 u32Prescale = 1;
113 u32Clk >>= 1;
114 }
115
116 // u32Usec * u32Clk might overflow if using uint32_t
117 u64Cmpr = (long long)u32Usec * (long long)u32Clk / (long long)1000000;
118
119 timer->CMP = (uint32_t)u64Cmpr;
120 timer->PRECNT = u32Prescale;
121 timer->CTL = TIMER_CTL_CNTEN_Msk; // one shot mode
122
123 // When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
124 // And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
125 for(u32Delay = (SystemCoreClock / u32Clk) + 1UL; u32Delay > 0UL; u32Delay--)
126 {
127 __NOP();
128 }
129
130 /* Add a bail out counter here in case timer clock source is disabled accidentally.
131 Prescale counter reset every ECLK * (prescale value + 1).
132 The u32Delay here is to make sure timer counter value changed when prescale counter reset */
133 u32Delay = (SystemCoreClock / TIMER_GetModuleClock(timer)) * (u32Prescale + 1);
134 u32Cntr = timer->CNT;
135 while(timer->CTL & TIMER_CTL_ACTSTS_Msk)
136 {
137 /* Bailed out if timer stop counting e.g. Some interrupt handler close timer clock source. */
138 if(u32Cntr == timer->CNT)
139 {
140 if(i++ > u32Delay)
141 {
142 return TIMER_TIMEOUT_ERR;
143 }
144 }
145 else
146 {
147 i = 0;
148 u32Cntr = timer->CNT;
149 }
150 }
151 return 0;
152}
153
169void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
170{
171
172 timer->CTL = (timer->CTL & ~(TIMER_CTL_CAPFUNCS_Msk |
175 u32CapMode | u32Edge | TIMER_CTL_CAPEN_Msk;
176}
177
184{
185 timer->CTL &= ~TIMER_CTL_CAPEN_Msk;
186
187}
188
198void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
199{
200 timer->CTL = (timer->CTL & ~TIMER_CTL_CNTPHASE_Msk) | u32Edge;
201 timer->CTL |= TIMER_CTL_EXTCNTEN_Msk;
202}
203
210{
211 timer->CTL &= ~TIMER_CTL_EXTCNTEN_Msk;
212}
213
221{
222 uint32_t u32Src, u32Div;
223 const uint32_t au32Clk[] = {__HXT, __LXT, __LIRC, 0}; // we don't know actual clock if external pin is clock source, set to 0 here
224
225 if(timer == TIMER0)
226 {
227 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos;
228 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR0DIV_Msk) >> CLK_CLKDIV1_TMR0DIV_Pos;
229 }
230 else if(timer == TIMER1)
231 {
232 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos;
233 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR1DIV_Msk) >> CLK_CLKDIV1_TMR1DIV_Pos;
234 }
235 else if(timer == TIMER2)
236 {
237 u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR2SEL_Msk) >> CLK_CLKSEL2_TMR2SEL_Pos;
238 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR2DIV_Msk) >> CLK_CLKDIV1_TMR2DIV_Pos;
239 }
240 else // Timer 3
241 {
242 u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR3SEL_Msk) >> CLK_CLKSEL2_TMR3SEL_Pos;
243 u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR3DIV_Msk) >> CLK_CLKDIV1_TMR3DIV_Pos;
244 }
245 u32Div++;
246 if(u32Src < 4)
247 return au32Clk[u32Src] / u32Div;
248 else if(u32Src == 4)
249 {
250 /* HIRC Source Selection */
251 if(CLK->CLKSEL0 & CLK_CLKSEL0_HIRCSEL_Msk)
252 {
253 /* Clock source from HIRC1 (36MHz) */
254 return __HIRC36M / u32Div;
255 }
256 else
257 {
258 /* Clock source from HIRC0 (12MHz) */
259 if(CLK->PWRCTL & CLK_PWRCTL_HIRC0FSEL_Msk)
260 return __HIRC16M / u32Div;
261 else
262 return __HIRC12M / u32Div;
263 }
264
265 }
266 else if(u32Src == 5) // MIRC
267 {
268 return __MIRC / u32Div;
269
270 }
271 else // HCLK
272 return CLK_GetHCLKFreq() / u32Div;
273
274}
275
282{
283 // A write with any value to TIMER CNT register will trigger timer counter reset
284 timer->CNT = 0;
285}
286
305 uint32_t u32DropCount,
306 uint32_t u32Timeout,
307 uint32_t u32EnableInt)
308{
309 uint32_t mode = TIMER_CTL_INTRTGEN_Msk;
310 TIMER_T *t; // store the timer base to configure compare value
311
312 if(u32DropCount != 0 || u32Timeout >= 2)
314 if(u32Timeout < 2)
315 u32Timeout = 0xFFFFFF;
316
317 timer->ECTL = u32DropCount << TIMER_ECTL_EVNTDPCNT_Pos;
318 t = (timer == TIMER0) ? TIMER1 : TIMER3;
319
320 t->CMP = u32Timeout;
321 t->INTEN = u32EnableInt ? TIMER_INTEN_CAPIEN_Msk : 0;
322 timer->CTL = mode | TIMER_CTL_CNTEN_Msk;
323
324 return;
325}
332{
334}
335
344void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src)
345{
346 timer->CTL = (timer->CTL & ~TIMER_CTL_TRGSSEL_Msk) | u32Src;
347}
348
358void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
359{
360 timer->CTL = (timer->CTL & ~(TIMER_CTL_TRGPWM_Msk | TIMER_CTL_TRGPDMA_Msk | TIMER_CTL_TRGADC_Msk)) | u32Mask;
361}
362 /* end of group NANO103_TIMER_EXPORTED_FUNCTIONS */
364 /* end of group NANO103_TIMER_Driver */
366 /* end of group NANO103_Device_Driver */
368
369/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
NANO103 peripheral access layer header file. This file contains all the peripheral register's definit...
#define TIMER_CTL_INTRTGEN_Msk
Definition: Nano103.h:7819
#define TIMER_INTEN_CAPIEN_Msk
Definition: Nano103.h:7837
#define TIMER_CTL_CAPCNTMD_Msk
Definition: Nano103.h:7810
#define TIMER_ECTL_EVNTDPCNT_Pos
Definition: Nano103.h:7863
#define TIMER_CTL_CAPFUNCS_Msk
Definition: Nano103.h:7804
#define TIMER_CTL_TRGADC_Msk
Definition: Nano103.h:7783
#define TIMER_CTL_EXTCNTEN_Msk
Definition: Nano103.h:7792
#define TIMER_CTL_TRGPDMA_Msk
Definition: Nano103.h:7786
#define TIMER_CTL_CAPEDGE_Msk
Definition: Nano103.h:7807
#define TIMER_CTL_INTRTGMD_Msk
Definition: Nano103.h:7822
#define TIMER_CTL_ACTSTS_Msk
Definition: Nano103.h:7780
#define TIMER_CTL_CNTEN_Msk
Definition: Nano103.h:7765
#define TIMER_CTL_CAPEN_Msk
Definition: Nano103.h:7801
#define TIMER_CTL_TRGPWM_Msk
Definition: Nano103.h:7825
uint32_t CLK_GetHCLKFreq(void)
This function get HCLK frequency. The frequency unit is Hz.
Definition: clk.c:127
#define CLK_CLKSEL1_TMR1SEL_Msk
Definition: Nano103.h:2811
#define CLK_CLKSEL1_TMR0SEL_Msk
Definition: Nano103.h:2808
#define CLK_CLKSEL2_TMR2SEL_Msk
Definition: Nano103.h:2835
#define CLK_CLKDIV1_TMR3DIV_Msk
Definition: Nano103.h:2880
#define CLK_CLKSEL2_TMR3SEL_Msk
Definition: Nano103.h:2838
#define CLK_CLKSEL1_TMR1SEL_Pos
Definition: Nano103.h:2810
#define CLK_CLKDIV1_TMR1DIV_Msk
Definition: Nano103.h:2874
#define CLK_CLKSEL2_TMR2SEL_Pos
Definition: Nano103.h:2834
#define CLK_PWRCTL_HIRC0FSEL_Msk
Definition: Nano103.h:2682
#define CLK_CLKDIV1_TMR2DIV_Pos
Definition: Nano103.h:2876
#define CLK_CLKDIV1_TMR0DIV_Pos
Definition: Nano103.h:2870
#define CLK_CLKDIV1_TMR2DIV_Msk
Definition: Nano103.h:2877
#define CLK_CLKDIV1_TMR0DIV_Msk
Definition: Nano103.h:2871
#define CLK_CLKDIV1_TMR3DIV_Pos
Definition: Nano103.h:2879
#define CLK_CLKSEL2_TMR3SEL_Pos
Definition: Nano103.h:2837
#define CLK_CLKSEL1_TMR0SEL_Pos
Definition: Nano103.h:2807
#define CLK_CLKDIV1_TMR1DIV_Pos
Definition: Nano103.h:2873
#define CLK_CLKSEL0_HIRCSEL_Msk
Definition: Nano103.h:2796
#define CLK
Pointer to CLK register structure.
Definition: Nano103.h:13802
#define TIMER1
Pointer to TIMER1 register structure.
Definition: Nano103.h:13783
#define TIMER3
Pointer to TIMER3 register structure.
Definition: Nano103.h:13785
#define TIMER2
Pointer to TIMER2 register structure.
Definition: Nano103.h:13784
#define TIMER0
Pointer to TIMER0 register structure.
Definition: Nano103.h:13782
#define TIMER_TIMEOUT_ERR
Definition: timer.h:53
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:344
void TIMER_DisableCapture(TIMER_T *timer)
This API is used to disable the Timer capture function.
Definition: timer.c:183
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
void TIMER_DisableEventCounter(TIMER_T *timer)
This API is used to disable the Timer event counter function.
Definition: timer.c:209
void TIMER_ResetCounter(TIMER_T *timer)
This function is used to reset the Timer counter value.
Definition: timer.c:281
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
This API is used to get the clock frequency of Timer.
Definition: timer.c:220
void TIMER_DisableFreqCounter(TIMER_T *timer)
This function is used to disable the Timer frequency counter function.
Definition: timer.c:331
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:198
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:169
void TIMER_Close(TIMER_T *timer)
This API stops Timer counting and disable the Timer interrupt function.
Definition: timer.c:74
void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
This function is used to set modules trigger by timer interrupt.
Definition: timer.c:358
int32_t TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
This API is used to create a delay loop for u32usec micro seconds.
Definition: timer.c:91
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:304
__IO uint32_t CNT
Definition: Nano103.h:7751
__IO uint32_t CMP
Definition: Nano103.h:7748
__IO uint32_t CTL
Definition: Nano103.h:7746
__IO uint32_t ECTL
Definition: Nano103.h:7756
__IO uint32_t PRECNT
Definition: Nano103.h:7747
__IO uint32_t INTEN
Definition: Nano103.h:7749
#define __HXT
#define __LIRC
uint32_t SystemCoreClock
#define __HIRC16M
#define __LXT
#define __HIRC36M
#define __HIRC12M
#define __MIRC