Nano100BN Series BSP  V3.03.002
The Board Support Package for Nano100BN Series
timer.c
Go to the documentation of this file.
1 /**************************************************************************/
12 #include "Nano100Series.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 >= 0x2000000)
55  {
56  u32Prescale = 3; // real prescaler value is 4
57  u32Clk >>= 2;
58  }
59  else if(u32Clk >= 0x1000000)
60  {
61  u32Prescale = 1; // real prescaler value is 2
62  u32Clk >>= 1;
63  }
64  u32Cmpr = u32Clk / u32Freq;
65  }
66  timer->CMPR = u32Cmpr;
67  timer->PRECNT = u32Prescale;
68  timer->CTL = u32Mode;
69 
70 
71  return(u32Clk / (u32Cmpr * (u32Prescale + 1)));
72 }
73 
79 void TIMER_Close(TIMER_T *timer)
80 {
81  timer->CTL = 0;
82  timer->IER = 0;
83 }
84 
93 void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
94 {
95  uint32_t u32Clk = TIMER_GetModuleClock(timer);
96  uint32_t u32Prescale = 0, delay = SystemCoreClock / u32Clk;
97  long long u64Cmpr;
98 
99  // Clear current timer configuration
100  timer->CTL = 0;
101 
102  if(u32Clk == 10000) // min delay is 100us if timer clock source is LIRC 10k
103  {
104  u32Usec = ((u32Usec + 99) / 100) * 100;
105  }
106  else // 10 usec every step
107  {
108  u32Usec = ((u32Usec + 9) / 10) * 10;
109  }
110 
111  if(u32Clk >= 0x2000000)
112  {
113  u32Prescale = 3; // real prescaler value is 4
114  u32Clk >>= 2;
115  }
116  else if(u32Clk >= 0x1000000)
117  {
118  u32Prescale = 1; // real prescaler value is 2
119  u32Clk >>= 1;
120  }
121 
122  // u32Usec * u32Clk might overflow if using uint32_t
123  u64Cmpr = ((long long)u32Usec * (long long)u32Clk) / (long long)1000000;
124 
125  timer->CMPR = (uint32_t)u64Cmpr;
126  timer->PRECNT = u32Prescale;
127  timer->CTL = TIMER_CTL_TMR_EN_Msk; // one shot mode
128 
129  // When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
130  // And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
131  for(; delay > 0; delay--)
132  {
133  __NOP();
134  }
135 
136  while(timer->CTL & TIMER_CTL_TMR_ACT_Msk);
137 
138 }
139 
155 void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
156 {
157 
158  timer->CTL = (timer->CTL & ~(TIMER_CTL_TCAP_MODE_Msk |
161  u32CapMode | u32Edge | TIMER_CTL_TCAP_EN_Msk;
162 }
163 
170 {
171  timer->CTL &= ~TIMER_CTL_TCAP_EN_Msk;
172 
173 }
174 
184 void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
185 {
186  timer->CTL = (timer->CTL & ~TIMER_CTL_EVENT_EDGE_Msk) | u32Edge;
187  timer->CTL |= TIMER_CTL_EVENT_EN_Msk;
188 }
189 
196 {
197  timer->CTL &= ~TIMER_CTL_EVENT_EN_Msk;
198 }
199 
207 {
208  uint32_t u32Src;
209  const uint32_t au32Clk[] = {__HXT, __LXT, __LIRC, 0}; // we don't know actual clock if external pin is clock source, set to 0 here
210 
211  if(timer == TIMER0)
212  u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0_S_Msk) >> CLK_CLKSEL1_TMR0_S_Pos;
213  else if(timer == TIMER1)
214  u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1_S_Msk) >> CLK_CLKSEL1_TMR1_S_Pos;
215  else if(timer == TIMER2)
216  u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR2_S_Msk) >> CLK_CLKSEL2_TMR2_S_Pos;
217  else // Timer 3
218  u32Src = (CLK->CLKSEL2 & CLK_CLKSEL2_TMR3_S_Msk) >> CLK_CLKSEL2_TMR3_S_Pos;
219 
220  if(u32Src < 4)
221  return au32Clk[u32Src];
222  else
223  return __HIRC;
224 
225 }
226 
241  uint32_t u32DropCount,
242  uint32_t u32Timeout,
243  uint32_t u32EnableInt)
244 {
245  TIMER_T *t; // store the timer base to configure compare value
246 
247  t = (timer == TIMER0) ? TIMER1 : TIMER3;
248 
249  t->CMPR = 0xFFFFFF;
250  t->IER = u32EnableInt ? TIMER_IER_TCAP_IE_Msk : 0;
252 
253  return;
254 }
261 {
262  timer->CTL &= ~TIMER_CTL_INTR_TRG_EN_Msk;
263 }
264 
273 void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src)
274 {
275  timer->CTL = (timer->CTL & ~TIMER_CTL_CAP_TRG_EN_Msk) | u32Src;
276 }
277 
287 void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
288 {
289  timer->CTL = (timer->CTL & ~(TIMER_CTL_PDMA_TEEN_Msk | TIMER_CTL_DAC_TEEN_Msk | TIMER_CTL_ADC_TEEN_Msk)) | u32Mask;
290 }
291  /* end of group NANO100_TIMER_EXPORTED_FUNCTIONS */
293  /* end of group NANO100_TIMER_Driver */
295  /* end of group NANO100_Device_Driver */
297 
298 /*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
uint32_t SystemCoreClock
void TIMER_DisableEventCounter(TIMER_T *timer)
This API is used to disable the Timer event counter function.
Definition: timer.c:195
#define TIMER_CTL_PDMA_TEEN_Msk
#define CLK_CLKSEL2_TMR2_S_Msk
#define CLK_CLKSEL1_TMR0_S_Pos
#define CLK
Pointer to CLK register structure.
#define TIMER_CTL_DAC_TEEN_Msk
#define TIMER_CTL_TCAP_EN_Msk
#define TIMER_CTL_TMR_EN_Msk
#define TIMER2
Pointer to TIMER2 register structure.
Nano100 series peripheral access layer header file. This file contains all the peripheral register's ...
#define CLK_CLKSEL1_TMR0_S_Msk
#define TIMER_CTL_EVENT_EDGE_Msk
__IO uint32_t IER
#define CLK_CLKSEL2_TMR3_S_Msk
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:155
#define CLK_CLKSEL1_TMR1_S_Pos
#define CLK_CLKSEL1_TMR1_S_Msk
#define TIMER_CTL_EVENT_EN_Msk
#define TIMER_CTL_CAP_TRG_EN_Msk
#define TIMER_CTL_TMR_ACT_Msk
#define TIMER_CTL_TCAP_CNT_MODE_Msk
#define __HIRC
void TIMER_DisableCapture(TIMER_T *timer)
This API is used to disable the Timer capture function.
Definition: timer.c:169
#define TIMER_IER_TCAP_IE_Msk
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
This API is used to get the clock frequency of Timer.
Definition: timer.c:206
#define TIMER3
Pointer to TIMER3 register structure.
#define TIMER1
Pointer to TIMER1 register structure.
#define __HXT
#define TIMER0
Pointer to TIMER0 register structure.
#define __LXT
#define TIMER_CTL_TCAP_EDGE_Msk
void TIMER_Close(TIMER_T *timer)
This API stops Timer counting and disable the Timer interrupt function.
Definition: timer.c:79
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:93
#define CLK_CLKSEL2_TMR2_S_Pos
#define CLK_CLKSEL2_TMR3_S_Pos
__IO uint32_t CMPR
__IO uint32_t PRECNT
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:240
#define TIMER_CTL_ADC_TEEN_Msk
void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
This function is used to set modules trigger by timer interrupt.
Definition: timer.c:287
#define TIMER_CTL_TCAP_MODE_Msk
__IO uint32_t CTL
void TIMER_DisableFreqCounter(TIMER_T *timer)
This function is used to disable the Timer frequency counter function.
Definition: timer.c:260
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:273
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:184
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 __LIRC
#define TIMER_CTL_INTR_TRG_EN_Msk