NUC472_NUC442_BSP V3.03.004
The Board Support Package for NUC472/NUC442
timer.c
Go to the documentation of this file.
1/**************************************************************************/
12#include "NUC472_442.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 >= 0x4000000)
55 {
56 u32Prescale = 7; // real prescaler value is 8
57 u32Clk >>= 3;
58 }
59 else if(u32Clk >= 0x2000000)
60 {
61 u32Prescale = 3; // real prescaler value is 4
62 u32Clk >>= 2;
63 }
64 else if(u32Clk >= 0x1000000)
65 {
66 u32Prescale = 1; // real prescaler value is 2
67 u32Clk >>= 1;
68 }
69
70 u32Cmpr = u32Clk / u32Freq;
71 }
72
73 timer->CTL = u32Mode | u32Prescale;
74 timer->CMP = u32Cmpr;
75
76 return(u32Clk / (u32Cmpr * (u32Prescale + 1)));
77}
78
84void TIMER_Close(TIMER_T *timer)
85{
86 timer->CTL = 0;
87 timer->EXTCTL = 0;
88
89}
90
103int32_t TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
104{
105 uint32_t u32Clk = TIMER_GetModuleClock(timer), i = 0UL;
106 uint32_t u32Cntr, u32Delay, u32Prescale = 0, delay = SystemCoreClock / u32Clk + 1;
107 double fCmpr;
108
109 // Clear current timer configuration
110 timer->CTL = 0;
111 timer->EXTCTL = 0;
112
113 if(u32Clk == 10000) // min delay is 100us if timer clock source is LIRC 10k
114 {
115 u32Usec = ((u32Usec + 99) / 100) * 100;
116 }
117 else // 10 usec every step
118 {
119 u32Usec = ((u32Usec + 9) / 10) * 10;
120 }
121
122 if(u32Clk >= 0x4000000)
123 {
124 u32Prescale = 7; // real prescaler value is 8
125 u32Clk >>= 3;
126 }
127 else if(u32Clk >= 0x2000000)
128 {
129 u32Prescale = 3; // real prescaler value is 4
130 u32Clk >>= 2;
131 }
132 else if(u32Clk >= 0x1000000)
133 {
134 u32Prescale = 1; // real prescaler value is 2
135 u32Clk >>= 1;
136 }
137
138 // u32Usec * u32Clk might overflow if using uint32_t
139 fCmpr = ((double)u32Usec * (double)u32Clk) / 1000000.0;
140
141 timer->CMP = (uint32_t)fCmpr;
142 timer->CTL = TIMER_CTL_CNTEN_Msk | u32Prescale; // one shot mode
143
144 // When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
145 // And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
146 for(; delay > 0; delay--)
147 {
148 __NOP();
149 }
150
151 /* Add a bail out counter here in case timer clock source is disabled accidentally.
152 Prescale counter reset every ECLK * (prescale value + 1).
153 The u32Delay here is to make sure timer counter value changed when prescale counter reset */
154 u32Delay = (SystemCoreClock / TIMER_GetModuleClock(timer)) * (u32Prescale + 1);
155 u32Cntr = timer->CNT;
156 while(timer->CTL & TIMER_CTL_ACTSTS_Msk)
157 {
158 /* Bailed out if timer stop counting e.g. Some interrupt handler close timer clock source. */
159 if(u32Cntr == timer->CNT)
160 {
161 if(i++ > u32Delay)
162 {
163 return TIMER_TIMEOUT_ERR;
164 }
165 }
166 else
167 {
168 i = 0;
169 u32Cntr = timer->CNT;
170 }
171 }
172 return 0;
173}
174
188void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
189{
190
191 timer->EXTCTL = (timer->EXTCTL & ~(TIMER_EXTCTL_CAPFUNCS_Msk |
193 u32CapMode | u32Edge | TIMER_EXTCTL_CAPEN_Msk;
194}
195
202{
203 timer->EXTCTL &= ~TIMER_EXTCTL_CAPEN_Msk;
204
205}
206
217void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
218{
219 timer->EXTCTL = (timer->EXTCTL & ~TIMER_EXTCTL_CNTPHASE_Msk) | u32Edge;
220 timer->CTL |= TIMER_CTL_EXTCNTEN_Msk;
221}
222
229{
230 timer->CTL &= ~TIMER_CTL_EXTCNTEN_Msk;
231}
232
240{
241 uint32_t u32Src;
242 const uint32_t au32Clk[] = {__HXT, __LXT, 0, 0, 0, __LIRC, 0, __HIRC};
243
244 if(timer == TIMER0)
245 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos;
246 else if(timer == TIMER1)
247 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos;
248 else if(timer == TIMER2)
249 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR2SEL_Msk) >> CLK_CLKSEL1_TMR2SEL_Pos;
250 else // Timer 3
251 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR3SEL_Msk) >> CLK_CLKSEL1_TMR3SEL_Pos;
252
253 if(u32Src == 2)
254 {
255 if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLKSEL_Msk)
256 return(SystemCoreClock / 2);
257 else
258 return(SystemCoreClock);
259 }
260
261 return(au32Clk[u32Src]);
262
263}
264 /* end of group NUC472_442_TIMER_EXPORTED_FUNCTIONS */
266 /* end of group NUC472_442_TIMER_Driver */
268 /* end of group NUC472_442_Device_Driver */
270
271/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
#define CLK_CLKSEL1_TMR1SEL_Msk
Definition: NUC472_442.h:3800
#define CLK_CLKSEL1_TMR0SEL_Msk
Definition: NUC472_442.h:3797
#define TIMER_EXTCTL_CAPFUNCS_Msk
Definition: NUC472_442.h:25145
#define CLK_CLKSEL1_TMR2SEL_Pos
Definition: NUC472_442.h:3802
#define TIMER_EXTCTL_CAPEDGE_Msk
Definition: NUC472_442.h:25139
#define CLK_CLKSEL1_TMR1SEL_Pos
Definition: NUC472_442.h:3799
#define TIMER_CTL_EXTCNTEN_Msk
Definition: NUC472_442.h:25100
#define CLK_CLKSEL1_TMR3SEL_Msk
Definition: NUC472_442.h:3806
#define CLK_CLKSEL0_PCLKSEL_Msk
Definition: NUC472_442.h:3767
#define TIMER_CTL_ACTSTS_Msk
Definition: NUC472_442.h:25103
#define TIMER_CTL_CNTEN_Msk
Definition: NUC472_442.h:25115
#define CLK_CLKSEL1_TMR3SEL_Pos
Definition: NUC472_442.h:3805
#define TIMER_EXTCTL_CAPEN_Msk
Definition: NUC472_442.h:25142
#define CLK_CLKSEL1_TMR0SEL_Pos
Definition: NUC472_442.h:3796
#define CLK_CLKSEL1_TMR2SEL_Msk
Definition: NUC472_442.h:3803
#define CLK
Definition: NUC472_442.h:28798
#define TIMER1
Definition: NUC472_442.h:28838
#define TIMER2
Definition: NUC472_442.h:28839
#define TIMER0
Definition: NUC472_442.h:28837
#define TIMER_TIMEOUT_ERR
Definition: timer.h:47
void TIMER_DisableCapture(TIMER_T *timer)
This API is used to disable the Timer capture function.
Definition: timer.c:201
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:228
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
This API is used to get the clock frequency of Timer.
Definition: timer.c:239
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:217
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:188
void TIMER_Close(TIMER_T *timer)
This API stops Timer counting and disable the Timer interrupt function.
Definition: timer.c:84
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:103
__IO uint32_t CMP
Definition: NUC472_442.h:24971
__IO uint32_t CTL
Definition: NUC472_442.h:24954
__IO uint32_t EXTCTL
Definition: NUC472_442.h:25059
__I uint32_t CNT
Definition: NUC472_442.h:25006
#define __HIRC
#define __HXT
#define __LIRC
uint32_t SystemCoreClock
#define __LXT