mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Thu Dec 15 11:48:27 2016 +0000
Revision:
152:9a67f0b066fc
Parent:
149:156823d33999
This updates the lib to the mbed lib v131

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /**************************************************************************//**
<> 144:ef7eb2e8f9f7 2 * @file timer.c
<> 144:ef7eb2e8f9f7 3 * @version V1.00
<> 144:ef7eb2e8f9f7 4 * $Revision: 6 $
<> 144:ef7eb2e8f9f7 5 * $Date: 14/05/29 1:13p $
<> 144:ef7eb2e8f9f7 6 * @brief NUC472/NUC442 TIMER driver source file
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * @note
<> 144:ef7eb2e8f9f7 9 * Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
<> 144:ef7eb2e8f9f7 10 *****************************************************************************/
<> 144:ef7eb2e8f9f7 11 #include "NUC472_442.h"
<> 144:ef7eb2e8f9f7 12
<> 144:ef7eb2e8f9f7 13 /** @addtogroup NUC472_442_Device_Driver NUC472/NUC442 Device Driver
<> 144:ef7eb2e8f9f7 14 @{
<> 144:ef7eb2e8f9f7 15 */
<> 144:ef7eb2e8f9f7 16
<> 144:ef7eb2e8f9f7 17 /** @addtogroup NUC472_442_TIMER_Driver TIMER Driver
<> 144:ef7eb2e8f9f7 18 @{
<> 144:ef7eb2e8f9f7 19 */
<> 144:ef7eb2e8f9f7 20
<> 144:ef7eb2e8f9f7 21
<> 144:ef7eb2e8f9f7 22 /** @addtogroup NUC472_442_TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions
<> 144:ef7eb2e8f9f7 23 @{
<> 144:ef7eb2e8f9f7 24 */
<> 144:ef7eb2e8f9f7 25
<> 144:ef7eb2e8f9f7 26 /**
<> 144:ef7eb2e8f9f7 27 * @brief This API is used to configure timer to operate in specified mode
<> 144:ef7eb2e8f9f7 28 * and frequency. If timer cannot work in target frequency, a closest
<> 144:ef7eb2e8f9f7 29 * frequency will be chose and returned.
<> 144:ef7eb2e8f9f7 30 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 31 * @param[in] u32Mode Operation mode. Possible options are
<> 144:ef7eb2e8f9f7 32 * - \ref TIMER_ONESHOT_MODE
<> 144:ef7eb2e8f9f7 33 * - \ref TIMER_PERIODIC_MODE
<> 144:ef7eb2e8f9f7 34 * - \ref TIMER_TOGGLE_MODE
<> 144:ef7eb2e8f9f7 35 * - \ref TIMER_CONTINUOUS_MODE
<> 144:ef7eb2e8f9f7 36 * @param[in] u32Freq Target working frequency
<> 144:ef7eb2e8f9f7 37 * @return Real Timer working frequency
<> 144:ef7eb2e8f9f7 38 * @note After calling this API, Timer is \b NOT running yet. But could start timer running be calling
<> 144:ef7eb2e8f9f7 39 * \ref TIMER_Start macro or program registers directly
<> 144:ef7eb2e8f9f7 40 */
<> 144:ef7eb2e8f9f7 41 uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
<> 144:ef7eb2e8f9f7 42 {
<> 144:ef7eb2e8f9f7 43 uint32_t u32Clk = TIMER_GetModuleClock(timer);
<> 144:ef7eb2e8f9f7 44 uint32_t u32Cmpr = 0, u32Prescale = 0;
<> 144:ef7eb2e8f9f7 45
<> 144:ef7eb2e8f9f7 46 // Fastest possible timer working freq is u32Clk / 2. While cmpr = 2, pre-scale = 0
<> 144:ef7eb2e8f9f7 47 if(u32Freq > (u32Clk / 2)) {
<> 144:ef7eb2e8f9f7 48 u32Cmpr = 2;
<> 144:ef7eb2e8f9f7 49 } else {
<> 144:ef7eb2e8f9f7 50 if(u32Clk >= 0x4000000) {
<> 144:ef7eb2e8f9f7 51 u32Prescale = 7; // real prescaler value is 8
<> 144:ef7eb2e8f9f7 52 u32Clk >>= 3;
<> 144:ef7eb2e8f9f7 53 } else if(u32Clk >= 0x2000000) {
<> 144:ef7eb2e8f9f7 54 u32Prescale = 3; // real prescaler value is 4
<> 144:ef7eb2e8f9f7 55 u32Clk >>= 2;
<> 144:ef7eb2e8f9f7 56 } else if(u32Clk >= 0x1000000) {
<> 144:ef7eb2e8f9f7 57 u32Prescale = 1; // real prescaler value is 2
<> 144:ef7eb2e8f9f7 58 u32Clk >>= 1;
<> 144:ef7eb2e8f9f7 59 }
<> 144:ef7eb2e8f9f7 60
<> 144:ef7eb2e8f9f7 61 u32Cmpr = u32Clk / u32Freq;
<> 144:ef7eb2e8f9f7 62 }
<> 144:ef7eb2e8f9f7 63
<> 144:ef7eb2e8f9f7 64 timer->CTL = u32Mode | u32Prescale;
<> 144:ef7eb2e8f9f7 65 timer->CMP = u32Cmpr;
<> 144:ef7eb2e8f9f7 66
<> 144:ef7eb2e8f9f7 67 return(u32Clk / (u32Cmpr * (u32Prescale + 1)));
<> 144:ef7eb2e8f9f7 68 }
<> 144:ef7eb2e8f9f7 69
<> 144:ef7eb2e8f9f7 70 /**
<> 144:ef7eb2e8f9f7 71 * @brief This API stops Timer counting and disable the Timer interrupt function
<> 144:ef7eb2e8f9f7 72 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 73 * @return None
<> 144:ef7eb2e8f9f7 74 */
<> 144:ef7eb2e8f9f7 75 void TIMER_Close(TIMER_T *timer)
<> 144:ef7eb2e8f9f7 76 {
<> 144:ef7eb2e8f9f7 77 timer->CTL = 0;
<> 144:ef7eb2e8f9f7 78 timer->EXTCTL = 0;
<> 144:ef7eb2e8f9f7 79
<> 144:ef7eb2e8f9f7 80 }
<> 144:ef7eb2e8f9f7 81
<> 144:ef7eb2e8f9f7 82 /**
<> 144:ef7eb2e8f9f7 83 * @brief This API is used to create a delay loop for u32usec micro seconds
<> 144:ef7eb2e8f9f7 84 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 85 * @param[in] u32Usec Delay period in micro seconds with 10 usec every step. Valid values are between 10~1000000 (10 micro second ~ 1 second)
<> 144:ef7eb2e8f9f7 86 * @return None
<> 144:ef7eb2e8f9f7 87 * @note This API overwrites the register setting of the timer used to count the delay time.
<> 144:ef7eb2e8f9f7 88 * @note This API use polling mode. So there is no need to enable interrupt for the timer module used to generate delay
<> 144:ef7eb2e8f9f7 89 */
<> 144:ef7eb2e8f9f7 90 void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
<> 144:ef7eb2e8f9f7 91 {
<> 144:ef7eb2e8f9f7 92 uint32_t u32Clk = TIMER_GetModuleClock(timer);
<> 144:ef7eb2e8f9f7 93 uint32_t u32Prescale = 0, delay = SystemCoreClock / u32Clk + 1;
<> 144:ef7eb2e8f9f7 94 double fCmpr;
<> 144:ef7eb2e8f9f7 95
<> 144:ef7eb2e8f9f7 96 // Clear current timer configuration
<> 144:ef7eb2e8f9f7 97 timer->CTL = 0;
<> 144:ef7eb2e8f9f7 98 timer->EXTCTL = 0;
<> 144:ef7eb2e8f9f7 99
<> 144:ef7eb2e8f9f7 100 if(u32Clk == 10000) { // min delay is 100us if timer clock source is LIRC 10k
<> 144:ef7eb2e8f9f7 101 u32Usec = ((u32Usec + 99) / 100) * 100;
<> 144:ef7eb2e8f9f7 102 } else { // 10 usec every step
<> 144:ef7eb2e8f9f7 103 u32Usec = ((u32Usec + 9) / 10) * 10;
<> 144:ef7eb2e8f9f7 104 }
<> 144:ef7eb2e8f9f7 105
<> 144:ef7eb2e8f9f7 106 if(u32Clk >= 0x4000000) {
<> 144:ef7eb2e8f9f7 107 u32Prescale = 7; // real prescaler value is 8
<> 144:ef7eb2e8f9f7 108 u32Clk >>= 3;
<> 144:ef7eb2e8f9f7 109 } else if(u32Clk >= 0x2000000) {
<> 144:ef7eb2e8f9f7 110 u32Prescale = 3; // real prescaler value is 4
<> 144:ef7eb2e8f9f7 111 u32Clk >>= 2;
<> 144:ef7eb2e8f9f7 112 } else if(u32Clk >= 0x1000000) {
<> 144:ef7eb2e8f9f7 113 u32Prescale = 1; // real prescaler value is 2
<> 144:ef7eb2e8f9f7 114 u32Clk >>= 1;
<> 144:ef7eb2e8f9f7 115 }
<> 144:ef7eb2e8f9f7 116
<> 144:ef7eb2e8f9f7 117 // u32Usec * u32Clk might overflow if using uint32_t
<> 144:ef7eb2e8f9f7 118 fCmpr = ((double)u32Usec * (double)u32Clk) / 1000000.0;
<> 144:ef7eb2e8f9f7 119
<> 144:ef7eb2e8f9f7 120 timer->CMP = (uint32_t)fCmpr;
<> 144:ef7eb2e8f9f7 121 timer->CTL = TIMER_CTL_CNTEN_Msk | u32Prescale; // one shot mode
<> 144:ef7eb2e8f9f7 122
<> 144:ef7eb2e8f9f7 123 // When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
<> 144:ef7eb2e8f9f7 124 // And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
<> 144:ef7eb2e8f9f7 125 for(; delay > 0; delay--) {
<> 144:ef7eb2e8f9f7 126 __NOP();
<> 144:ef7eb2e8f9f7 127 }
<> 144:ef7eb2e8f9f7 128
<> 144:ef7eb2e8f9f7 129 while(timer->CTL & TIMER_CTL_ACTSTS_Msk);
<> 144:ef7eb2e8f9f7 130
<> 144:ef7eb2e8f9f7 131 }
<> 144:ef7eb2e8f9f7 132
<> 144:ef7eb2e8f9f7 133 /**
<> 144:ef7eb2e8f9f7 134 * @brief This API is used to enable timer capture function with specified mode and capture edge
<> 144:ef7eb2e8f9f7 135 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 136 * @param[in] u32CapMode Timer capture mode. Could be
<> 144:ef7eb2e8f9f7 137 * - \ref TIMER_CAPTURE_FREE_COUNTING_MODE
<> 144:ef7eb2e8f9f7 138 * - \ref TIMER_CAPTURE_COUNTER_RESET_MODE
<> 144:ef7eb2e8f9f7 139 * @param[in] u32Edge Timer capture edge. Possible values are
<> 144:ef7eb2e8f9f7 140 * - \ref TIMER_CAPTURE_FALLING_EDGE
<> 144:ef7eb2e8f9f7 141 * - \ref TIMER_CAPTURE_RISING_EDGE
<> 144:ef7eb2e8f9f7 142 * - \ref TIMER_CAPTURE_FALLING_THEN_RISING_EDGE
<> 144:ef7eb2e8f9f7 143 * - \ref TIMER_CAPTURE_RISING_THEN_FALLING_EDGE
<> 144:ef7eb2e8f9f7 144 * @return None
<> 144:ef7eb2e8f9f7 145 * @note Timer frequency should be configured separately by using \ref TIMER_Open API, or program registers directly
<> 144:ef7eb2e8f9f7 146 */
<> 144:ef7eb2e8f9f7 147 void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
<> 144:ef7eb2e8f9f7 148 {
<> 144:ef7eb2e8f9f7 149
<> 144:ef7eb2e8f9f7 150 timer->EXTCTL = (timer->EXTCTL & ~(TIMER_EXTCTL_CAPFUNCS_Msk |
<> 144:ef7eb2e8f9f7 151 TIMER_EXTCTL_CAPEDGE_Msk)) |
<> 144:ef7eb2e8f9f7 152 u32CapMode | u32Edge | TIMER_EXTCTL_CAPEN_Msk;
<> 144:ef7eb2e8f9f7 153 }
<> 144:ef7eb2e8f9f7 154
<> 144:ef7eb2e8f9f7 155 /**
<> 144:ef7eb2e8f9f7 156 * @brief This API is used to disable the Timer capture function
<> 144:ef7eb2e8f9f7 157 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 158 * @return None
<> 144:ef7eb2e8f9f7 159 */
<> 144:ef7eb2e8f9f7 160 void TIMER_DisableCapture(TIMER_T *timer)
<> 144:ef7eb2e8f9f7 161 {
<> 144:ef7eb2e8f9f7 162 timer->EXTCTL &= ~TIMER_EXTCTL_CAPEN_Msk;
<> 144:ef7eb2e8f9f7 163
<> 144:ef7eb2e8f9f7 164 }
<> 144:ef7eb2e8f9f7 165
<> 144:ef7eb2e8f9f7 166 /**
<> 144:ef7eb2e8f9f7 167 * @brief This function is used to enable the Timer counter function with specify detection edge
<> 144:ef7eb2e8f9f7 168 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 169 * @param[in] u32Edge Detection edge of counter pin. Could be ether
<> 144:ef7eb2e8f9f7 170 * - \ref TIMER_COUNTER_RISING_EDGE, or
<> 144:ef7eb2e8f9f7 171 * - \ref TIMER_COUNTER_FALLING_EDGE
<> 144:ef7eb2e8f9f7 172 * @return None
<> 144:ef7eb2e8f9f7 173 * @note Timer compare value should be configured separately by using \ref TIMER_SET_CMP_VALUE macro or program registers directly.
<> 144:ef7eb2e8f9f7 174 * @note While using event counter function, \ref TIMER_TOGGLE_MODE cannot set as timer operation mode.
<> 144:ef7eb2e8f9f7 175 */
<> 144:ef7eb2e8f9f7 176 void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
<> 144:ef7eb2e8f9f7 177 {
<> 144:ef7eb2e8f9f7 178 timer->EXTCTL = (timer->EXTCTL & ~TIMER_EXTCTL_CNTPHASE_Msk) | u32Edge;
<> 144:ef7eb2e8f9f7 179 timer->CTL |= TIMER_CTL_EXTCNTEN_Msk;
<> 144:ef7eb2e8f9f7 180 }
<> 144:ef7eb2e8f9f7 181
<> 144:ef7eb2e8f9f7 182 /**
<> 144:ef7eb2e8f9f7 183 * @brief This API is used to disable the Timer event counter function.
<> 144:ef7eb2e8f9f7 184 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 185 * @return None
<> 144:ef7eb2e8f9f7 186 */
<> 144:ef7eb2e8f9f7 187 void TIMER_DisableEventCounter(TIMER_T *timer)
<> 144:ef7eb2e8f9f7 188 {
<> 144:ef7eb2e8f9f7 189 timer->CTL &= ~TIMER_CTL_EXTCNTEN_Msk;
<> 144:ef7eb2e8f9f7 190 }
<> 144:ef7eb2e8f9f7 191
<> 144:ef7eb2e8f9f7 192 /**
<> 144:ef7eb2e8f9f7 193 * @brief This API is used to get the clock frequency of Timer
<> 144:ef7eb2e8f9f7 194 * @param[in] timer The base address of Timer module
<> 144:ef7eb2e8f9f7 195 * @return Timer clock frequency
<> 144:ef7eb2e8f9f7 196 * @note This API cannot return correct clock rate if timer source is external clock input.
<> 144:ef7eb2e8f9f7 197 */
<> 144:ef7eb2e8f9f7 198 uint32_t TIMER_GetModuleClock(TIMER_T *timer)
<> 144:ef7eb2e8f9f7 199 {
<> 144:ef7eb2e8f9f7 200 uint32_t u32Src;
<> 144:ef7eb2e8f9f7 201 const uint32_t au32Clk[] = {__HXT, __LXT, 0, 0, 0, __LIRC, 0, __HIRC};
<> 144:ef7eb2e8f9f7 202
<> 144:ef7eb2e8f9f7 203 if(timer == TIMER0)
<> 144:ef7eb2e8f9f7 204 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos;
<> 144:ef7eb2e8f9f7 205 else if(timer == TIMER1)
<> 144:ef7eb2e8f9f7 206 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos;
<> 144:ef7eb2e8f9f7 207 else if(timer == TIMER2)
<> 144:ef7eb2e8f9f7 208 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR2SEL_Msk) >> CLK_CLKSEL1_TMR2SEL_Pos;
<> 144:ef7eb2e8f9f7 209 else // Timer 3
<> 144:ef7eb2e8f9f7 210 u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR3SEL_Msk) >> CLK_CLKSEL1_TMR3SEL_Pos;
<> 144:ef7eb2e8f9f7 211
<> 144:ef7eb2e8f9f7 212 if(u32Src == 2) {
<> 144:ef7eb2e8f9f7 213 if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLKSEL_Msk)
<> 144:ef7eb2e8f9f7 214 return(SystemCoreClock / 2);
<> 144:ef7eb2e8f9f7 215 else
<> 144:ef7eb2e8f9f7 216 return(SystemCoreClock);
<> 144:ef7eb2e8f9f7 217 }
<> 144:ef7eb2e8f9f7 218
<> 144:ef7eb2e8f9f7 219 return(au32Clk[u32Src]);
<> 144:ef7eb2e8f9f7 220
<> 144:ef7eb2e8f9f7 221 }
<> 144:ef7eb2e8f9f7 222
<> 144:ef7eb2e8f9f7 223 /*@}*/ /* end of group NUC472_442_TIMER_EXPORTED_FUNCTIONS */
<> 144:ef7eb2e8f9f7 224
<> 144:ef7eb2e8f9f7 225 /*@}*/ /* end of group NUC472_442_TIMER_Driver */
<> 144:ef7eb2e8f9f7 226
<> 144:ef7eb2e8f9f7 227 /*@}*/ /* end of group NUC472_442_Device_Driver */
<> 144:ef7eb2e8f9f7 228
<> 144:ef7eb2e8f9f7 229 /*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/