Nano102_112 Series BSP  V3.03.002
The Board Support Package for Nano102_112 Series
timer.c
Go to the documentation of this file.
1 /**************************************************************************/
12 #include "Nano1X2Series.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 Nano1x2, only needs to consider 32MHz at most
55  {
56  u32Prescale = 1;
57  u32Clk >>= 1;
58  }
59  u32Cmpr = u32Clk / u32Freq;
60  }
61  timer->CMPR = 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->IER = 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 Nano1x2, 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->CMPR = (uint32_t)u64Cmpr;
116  timer->PRECNT = u32Prescale;
117  timer->CTL = TIMER_CTL_TMR_EN_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_TMR_ACT_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_TCAP_MODE_Msk |
151  u32CapMode | u32Edge | TIMER_CTL_TCAP_EN_Msk;
152 }
153 
160 {
161  timer->CTL &= ~TIMER_CTL_TCAP_EN_Msk;
162 
163 }
164 
174 void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
175 {
176  timer->CTL = (timer->CTL & ~TIMER_CTL_EVENT_EDGE_Msk) | u32Edge;
177  timer->CTL |= TIMER_CTL_EVENT_EN_Msk;
178 }
179 
186 {
187  timer->CTL &= ~TIMER_CTL_EVENT_EN_Msk;
188 }
189 
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_TMR0_S_Msk) >> CLK_CLKSEL1_TMR0_S_Pos;
204  u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR0_N_Msk) >> CLK_CLKDIV1_TMR0_N_Pos;
205  }
206  else if(timer == TIMER1)
207  {
208  u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1_S_Msk) >> CLK_CLKSEL1_TMR1_S_Pos;
209  u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR1_N_Msk) >> CLK_CLKDIV1_TMR1_N_Pos;
210  }
211  else if(timer == TIMER2)
212  {
213  u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR2_S_Msk) >> CLK_CLKSEL2_TMR2_S_Pos;
214  u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR2_N_Msk) >> CLK_CLKDIV1_TMR2_N_Pos;
215  }
216  else // Timer 3
217  {
218  u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR3_S_Msk) >> CLK_CLKSEL2_TMR3_S_Pos;
219  u32Div = (CLK->CLKDIV1 & CLK_CLKDIV1_TMR3_N_Msk) >> CLK_CLKDIV1_TMR3_N_Pos;
220  }
221  u32Div++;
222  if(u32Src < 4)
223  return au32Clk[u32Src] / u32Div;
224  else if(u32Src == 4)
225  {
227  return __HIRC16M / u32Div;
228  else
229  return __HIRC12M / u32Div;
230  }
231  else
232  return CLK_GetHCLKFreq() / u32Div;
233 }
234 
241 {
242  // A write with any value to TIMER DR register will trigger timer counter reset
243  timer->DR = 0;
244 }
245 
264  uint32_t u32DropCount,
265  uint32_t u32Timeout,
266  uint32_t u32EnableInt)
267 {
268  uint32_t mode = TIMER_CTL_INTR_TRG_EN_Msk;
269  TIMER_T *t; // store the timer base to configure compare value
270 
271  if(u32DropCount != 0 || u32Timeout >= 2)
273  if(u32Timeout < 2)
274  u32Timeout = 0xFFFFFF;
275 
276  timer->ECTL = u32DropCount << TIMER_ECTL_EVNT_DROP_CNT_Pos;
277  t = (timer == TIMER0) ? TIMER1 : TIMER3;
278 
279  t->CMPR = u32Timeout;
280  t->IER = u32EnableInt ? TIMER_IER_TCAP_IE_Msk : 0;
281  timer->CTL = mode | TIMER_CTL_TMR_EN_Msk;
282 
283  return;
284 }
291 {
293 }
294 
303 void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src)
304 {
305  timer->CTL = (timer->CTL & ~TIMER_CTL_CAP_TRG_EN_Msk) | u32Src;
306 }
307 
316 void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
317 {
318  timer->CTL = (timer->CTL & ~(TIMER_CTL_PDMA_TEEN_Msk | TIMER_CTL_ADC_TEEN_Msk)) | u32Mask;
319 }
320  /* end of group NANO1X2_TIMER_EXPORTED_FUNCTIONS */
322  /* end of group NANO1X2_TIMER_Driver */
324  /* end of group NANO1X2_Device_Driver */
326 
327 /*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
#define TIMER_CTL_INTR_TRG_MODE_Msk
#define TIMER1
Pointer to TIMER1 register structure.
#define CLK_CLKDIV1_TMR2_N_Pos
#define TIMER_CTL_ADC_TEEN_Msk
#define CLK
Pointer to CLK register structure.
#define CLK_CLKDIV1_TMR2_N_Msk
#define CLK_CLKSEL1_TMR0_S_Pos
#define TIMER_ECTL_EVNT_DROP_CNT_Pos
#define CLK_CLKSEL1_TMR1_S_Msk
#define CLK_CLKDIV1_TMR0_N_Pos
#define CLK_CLKDIV1_TMR3_N_Msk
#define __LIRC
#define TIMER_CTL_EVENT_EDGE_Msk
#define TIMER_CTL_TCAP_CNT_MODE_Msk
#define CLK_CLKDIV1_TMR3_N_Pos
__IO uint32_t IER
#define __LXT
#define CLK_PWRCTL_HIRC_FSEL_Msk
#define CLK_CLKDIV1_TMR1_N_Pos
#define TIMER_CTL_INTR_TRG_EN_Msk
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
This API is used to get the clock frequency of Timer.
Definition: timer.c:196
#define __HIRC16M
#define CLK_CLKSEL2_TMR2_S_Msk
#define __HIRC12M
#define TIMER_CTL_TCAP_MODE_Msk
Nano102/112 peripheral access layer header file. This file contains all the peripheral register's def...
void TIMER_DisableCapture(TIMER_T *timer)
This API is used to disable the Timer capture function.
Definition: timer.c:159
#define TIMER_CTL_TCAP_EN_Msk
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:263
__IO uint32_t DR
uint32_t SystemCoreClock
void TIMER_Close(TIMER_T *timer)
This API stops Timer counting and disable the Timer interrupt function.
Definition: timer.c:74
#define TIMER_CTL_EVENT_EN_Msk
void TIMER_ResetCounter(TIMER_T *timer)
This function is used to reset the Timer counter value.
Definition: timer.c:240
void TIMER_DisableEventCounter(TIMER_T *timer)
This API is used to disable the Timer event counter function.
Definition: timer.c:185
__IO uint32_t ECTL
#define TIMER_CTL_CAP_TRG_EN_Msk
#define CLK_CLKSEL2_TMR3_S_Msk
#define TIMER0
Pointer to TIMER0 register structure.
#define CLK_CLKSEL2_TMR3_S_Pos
#define TIMER_CTL_TCAP_EDGE_Msk
#define CLK_CLKSEL1_TMR0_S_Msk
#define CLK_CLKSEL2_TMR2_S_Pos
#define CLK_CLKDIV1_TMR0_N_Msk
uint32_t CLK_GetHCLKFreq(void)
This function get HCLK frequency. The frequency unit is Hz.
Definition: clk.c:192
void TIMER_DisableFreqCounter(TIMER_T *timer)
This function is used to disable the Timer frequency counter function.
Definition: timer.c:290
#define TIMER3
Pointer to TIMER3 register structure.
__IO uint32_t CMPR
#define CLK_CLKSEL1_TMR1_S_Pos
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
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:303
void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
This function is used to set modules trigger by timer interrupt.
Definition: timer.c:316
#define TIMER_CTL_TMR_EN_Msk
__IO uint32_t PRECNT
#define TIMER_CTL_PDMA_TEEN_Msk
#define __HXT
#define TIMER2
Pointer to TIMER2 register structure.
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
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
#define TIMER_CTL_TMR_ACT_Msk
__IO uint32_t CTL
#define TIMER_IER_TCAP_IE_Msk
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
#define CLK_CLKDIV1_TMR1_N_Msk