added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 2 * @file em_letimer.c
<> 144:ef7eb2e8f9f7 3 * @brief Low Energy Timer (LETIMER) Peripheral API
<> 144:ef7eb2e8f9f7 4 * @version 4.2.1
<> 144:ef7eb2e8f9f7 5 *******************************************************************************
<> 144:ef7eb2e8f9f7 6 * @section License
<> 144:ef7eb2e8f9f7 7 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
<> 144:ef7eb2e8f9f7 8 *******************************************************************************
<> 144:ef7eb2e8f9f7 9 *
<> 144:ef7eb2e8f9f7 10 * Permission is granted to anyone to use this software for any purpose,
<> 144:ef7eb2e8f9f7 11 * including commercial applications, and to alter it and redistribute it
<> 144:ef7eb2e8f9f7 12 * freely, subject to the following restrictions:
<> 144:ef7eb2e8f9f7 13 *
<> 144:ef7eb2e8f9f7 14 * 1. The origin of this software must not be misrepresented; you must not
<> 144:ef7eb2e8f9f7 15 * claim that you wrote the original software.
<> 144:ef7eb2e8f9f7 16 * 2. Altered source versions must be plainly marked as such, and must not be
<> 144:ef7eb2e8f9f7 17 * misrepresented as being the original software.
<> 144:ef7eb2e8f9f7 18 * 3. This notice may not be removed or altered from any source distribution.
<> 144:ef7eb2e8f9f7 19 *
<> 144:ef7eb2e8f9f7 20 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
<> 144:ef7eb2e8f9f7 21 * obligation to support this Software. Silicon Labs is providing the
<> 144:ef7eb2e8f9f7 22 * Software "AS IS", with no express or implied warranties of any kind,
<> 144:ef7eb2e8f9f7 23 * including, but not limited to, any implied warranties of merchantability
<> 144:ef7eb2e8f9f7 24 * or fitness for any particular purpose or warranties against infringement
<> 144:ef7eb2e8f9f7 25 * of any proprietary rights of a third party.
<> 144:ef7eb2e8f9f7 26 *
<> 144:ef7eb2e8f9f7 27 * Silicon Labs will not be liable for any consequential, incidental, or
<> 144:ef7eb2e8f9f7 28 * special damages, or any other relief, or for any claim by any third party,
<> 144:ef7eb2e8f9f7 29 * arising from your use of this Software.
<> 144:ef7eb2e8f9f7 30 *
<> 144:ef7eb2e8f9f7 31 ******************************************************************************/
<> 144:ef7eb2e8f9f7 32
<> 144:ef7eb2e8f9f7 33 #include "em_letimer.h"
<> 144:ef7eb2e8f9f7 34 #if defined(LETIMER_COUNT) && (LETIMER_COUNT > 0)
<> 144:ef7eb2e8f9f7 35 #include "em_cmu.h"
<> 144:ef7eb2e8f9f7 36 #include "em_assert.h"
<> 144:ef7eb2e8f9f7 37
<> 144:ef7eb2e8f9f7 38 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 39 * @addtogroup EM_Library
<> 144:ef7eb2e8f9f7 40 * @{
<> 144:ef7eb2e8f9f7 41 ******************************************************************************/
<> 144:ef7eb2e8f9f7 42
<> 144:ef7eb2e8f9f7 43 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 44 * @addtogroup LETIMER
<> 144:ef7eb2e8f9f7 45 * @brief Low Energy Timer (LETIMER) Peripheral API
<> 144:ef7eb2e8f9f7 46 * @{
<> 144:ef7eb2e8f9f7 47 ******************************************************************************/
<> 144:ef7eb2e8f9f7 48
<> 144:ef7eb2e8f9f7 49 /*******************************************************************************
<> 144:ef7eb2e8f9f7 50 ******************************* DEFINES ***********************************
<> 144:ef7eb2e8f9f7 51 ******************************************************************************/
<> 144:ef7eb2e8f9f7 52
<> 144:ef7eb2e8f9f7 53 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
<> 144:ef7eb2e8f9f7 54
<> 144:ef7eb2e8f9f7 55 /** Validation of valid comparator register for assert statements. */
<> 144:ef7eb2e8f9f7 56 #define LETIMER_COMP_REG_VALID(reg) (((reg) <= 1))
<> 144:ef7eb2e8f9f7 57
<> 144:ef7eb2e8f9f7 58 /** Validation of LETIMER register block pointer reference for assert statements. */
<> 144:ef7eb2e8f9f7 59 #define LETIMER_REF_VALID(ref) ((ref) == LETIMER0)
<> 144:ef7eb2e8f9f7 60
<> 144:ef7eb2e8f9f7 61 /** Validation of valid repeat counter register for assert statements. */
<> 144:ef7eb2e8f9f7 62 #define LETIMER_REP_REG_VALID(reg) (((reg) <= 1))
<> 144:ef7eb2e8f9f7 63
<> 144:ef7eb2e8f9f7 64 /** @endcond */
<> 144:ef7eb2e8f9f7 65
<> 144:ef7eb2e8f9f7 66
<> 144:ef7eb2e8f9f7 67 /*******************************************************************************
<> 144:ef7eb2e8f9f7 68 ************************** LOCAL FUNCTIONS ********************************
<> 144:ef7eb2e8f9f7 69 ******************************************************************************/
<> 144:ef7eb2e8f9f7 70
<> 144:ef7eb2e8f9f7 71 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
<> 144:ef7eb2e8f9f7 72
<> 144:ef7eb2e8f9f7 73 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 74 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 75 * @brief
<> 144:ef7eb2e8f9f7 76 * Wait for ongoing sync of register(s) to low frequency domain to complete.
<> 144:ef7eb2e8f9f7 77 *
<> 144:ef7eb2e8f9f7 78 * @note
<> 144:ef7eb2e8f9f7 79 * This only applies to the Gecko Family, see the reference manual
<> 144:ef7eb2e8f9f7 80 * chapter about Access to Low Energy Peripherals (Asynchronos Registers)
<> 144:ef7eb2e8f9f7 81 * for details.
<> 144:ef7eb2e8f9f7 82 *
<> 144:ef7eb2e8f9f7 83 * @param[in] letimer
<> 144:ef7eb2e8f9f7 84 * Pointer to LETIMER peripheral register block
<> 144:ef7eb2e8f9f7 85 *
<> 144:ef7eb2e8f9f7 86 * @param[in] mask
<> 144:ef7eb2e8f9f7 87 * Bitmask corresponding to SYNCBUSY register defined bits, indicating
<> 144:ef7eb2e8f9f7 88 * registers that must complete any ongoing synchronization.
<> 144:ef7eb2e8f9f7 89 ******************************************************************************/
<> 144:ef7eb2e8f9f7 90 __STATIC_INLINE void regSync(LETIMER_TypeDef *letimer, uint32_t mask)
<> 144:ef7eb2e8f9f7 91 {
<> 144:ef7eb2e8f9f7 92 #if defined(_LETIMER_FREEZE_MASK)
<> 144:ef7eb2e8f9f7 93 /* Avoid deadlock if modifying the same register twice when freeze mode is */
<> 144:ef7eb2e8f9f7 94 /* activated. */
<> 144:ef7eb2e8f9f7 95 if (letimer->FREEZE & LETIMER_FREEZE_REGFREEZE)
<> 144:ef7eb2e8f9f7 96 return;
<> 144:ef7eb2e8f9f7 97 #endif
<> 144:ef7eb2e8f9f7 98
<> 144:ef7eb2e8f9f7 99 /* Wait for any pending previous write operation to have been completed */
<> 144:ef7eb2e8f9f7 100 /* in low frequency domain, only required for Gecko Family of devices */
<> 144:ef7eb2e8f9f7 101 while (letimer->SYNCBUSY & mask)
<> 144:ef7eb2e8f9f7 102 ;
<> 144:ef7eb2e8f9f7 103 }
<> 144:ef7eb2e8f9f7 104 #endif
<> 144:ef7eb2e8f9f7 105
<> 144:ef7eb2e8f9f7 106 /** @endcond */
<> 144:ef7eb2e8f9f7 107
<> 144:ef7eb2e8f9f7 108 /*******************************************************************************
<> 144:ef7eb2e8f9f7 109 ************************** GLOBAL FUNCTIONS *******************************
<> 144:ef7eb2e8f9f7 110 ******************************************************************************/
<> 144:ef7eb2e8f9f7 111
<> 144:ef7eb2e8f9f7 112 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 113 * @brief
<> 144:ef7eb2e8f9f7 114 * Get LETIMER compare register value.
<> 144:ef7eb2e8f9f7 115 *
<> 144:ef7eb2e8f9f7 116 * @param[in] letimer
<> 144:ef7eb2e8f9f7 117 * Pointer to LETIMER peripheral register block
<> 144:ef7eb2e8f9f7 118 *
<> 144:ef7eb2e8f9f7 119 * @param[in] comp
<> 144:ef7eb2e8f9f7 120 * Compare register to get, either 0 or 1
<> 144:ef7eb2e8f9f7 121 *
<> 144:ef7eb2e8f9f7 122 * @return
<> 144:ef7eb2e8f9f7 123 * Compare register value, 0 if invalid register selected.
<> 144:ef7eb2e8f9f7 124 ******************************************************************************/
<> 144:ef7eb2e8f9f7 125 uint32_t LETIMER_CompareGet(LETIMER_TypeDef *letimer, unsigned int comp)
<> 144:ef7eb2e8f9f7 126 {
<> 144:ef7eb2e8f9f7 127 uint32_t ret;
<> 144:ef7eb2e8f9f7 128
<> 144:ef7eb2e8f9f7 129 EFM_ASSERT(LETIMER_REF_VALID(letimer) && LETIMER_COMP_REG_VALID(comp));
<> 144:ef7eb2e8f9f7 130
<> 144:ef7eb2e8f9f7 131 /* Initialize selected compare value */
<> 144:ef7eb2e8f9f7 132 switch (comp)
<> 144:ef7eb2e8f9f7 133 {
<> 144:ef7eb2e8f9f7 134 case 0:
<> 144:ef7eb2e8f9f7 135 ret = letimer->COMP0;
<> 144:ef7eb2e8f9f7 136 break;
<> 144:ef7eb2e8f9f7 137
<> 144:ef7eb2e8f9f7 138 case 1:
<> 144:ef7eb2e8f9f7 139 ret = letimer->COMP1;
<> 144:ef7eb2e8f9f7 140 break;
<> 144:ef7eb2e8f9f7 141
<> 144:ef7eb2e8f9f7 142 default:
<> 144:ef7eb2e8f9f7 143 /* Unknown compare register selected */
<> 144:ef7eb2e8f9f7 144 ret = 0;
<> 144:ef7eb2e8f9f7 145 break;
<> 144:ef7eb2e8f9f7 146 }
<> 144:ef7eb2e8f9f7 147
<> 144:ef7eb2e8f9f7 148 return(ret);
<> 144:ef7eb2e8f9f7 149 }
<> 144:ef7eb2e8f9f7 150
<> 144:ef7eb2e8f9f7 151
<> 144:ef7eb2e8f9f7 152 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 153 * @brief
<> 144:ef7eb2e8f9f7 154 * Set LETIMER compare register value.
<> 144:ef7eb2e8f9f7 155 *
<> 144:ef7eb2e8f9f7 156 * @note
<> 144:ef7eb2e8f9f7 157 * The setting of a compare register requires synchronization into the
<> 144:ef7eb2e8f9f7 158 * low frequency domain. If the same register is modified before a previous
<> 144:ef7eb2e8f9f7 159 * update has completed, this function will stall until the previous
<> 144:ef7eb2e8f9f7 160 * synchronization has completed. This only applies to the Gecko Family, see
<> 144:ef7eb2e8f9f7 161 * comment in the LETIMER_Sync() internal function call.
<> 144:ef7eb2e8f9f7 162 *
<> 144:ef7eb2e8f9f7 163 * @param[in] letimer
<> 144:ef7eb2e8f9f7 164 * Pointer to LETIMER peripheral register block
<> 144:ef7eb2e8f9f7 165 *
<> 144:ef7eb2e8f9f7 166 * @param[in] comp
<> 144:ef7eb2e8f9f7 167 * Compare register to set, either 0 or 1
<> 144:ef7eb2e8f9f7 168 *
<> 144:ef7eb2e8f9f7 169 * @param[in] value
<> 144:ef7eb2e8f9f7 170 * Initialization value (<= 0x0000ffff)
<> 144:ef7eb2e8f9f7 171 ******************************************************************************/
<> 144:ef7eb2e8f9f7 172 void LETIMER_CompareSet(LETIMER_TypeDef *letimer,
<> 144:ef7eb2e8f9f7 173 unsigned int comp,
<> 144:ef7eb2e8f9f7 174 uint32_t value)
<> 144:ef7eb2e8f9f7 175 {
<> 144:ef7eb2e8f9f7 176 volatile uint32_t *compReg;
<> 144:ef7eb2e8f9f7 177
<> 144:ef7eb2e8f9f7 178 EFM_ASSERT(LETIMER_REF_VALID(letimer)
<> 144:ef7eb2e8f9f7 179 && LETIMER_COMP_REG_VALID(comp)
<> 144:ef7eb2e8f9f7 180 && ((value & ~(_LETIMER_COMP0_COMP0_MASK
<> 144:ef7eb2e8f9f7 181 >> _LETIMER_COMP0_COMP0_SHIFT))
<> 144:ef7eb2e8f9f7 182 == 0));
<> 144:ef7eb2e8f9f7 183
<> 144:ef7eb2e8f9f7 184 /* Initialize selected compare value */
<> 144:ef7eb2e8f9f7 185 switch (comp)
<> 144:ef7eb2e8f9f7 186 {
<> 144:ef7eb2e8f9f7 187 case 0:
<> 144:ef7eb2e8f9f7 188 compReg = &(letimer->COMP0);
<> 144:ef7eb2e8f9f7 189 break;
<> 144:ef7eb2e8f9f7 190
<> 144:ef7eb2e8f9f7 191 case 1:
<> 144:ef7eb2e8f9f7 192 compReg = &(letimer->COMP1);
<> 144:ef7eb2e8f9f7 193 break;
<> 144:ef7eb2e8f9f7 194
<> 144:ef7eb2e8f9f7 195 default:
<> 144:ef7eb2e8f9f7 196 /* Unknown compare register selected, abort */
<> 144:ef7eb2e8f9f7 197 return;
<> 144:ef7eb2e8f9f7 198 }
<> 144:ef7eb2e8f9f7 199
<> 144:ef7eb2e8f9f7 200 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 201 /* LF register about to be modified require sync. busy check */
<> 144:ef7eb2e8f9f7 202 regSync(letimer, comp ? LETIMER_SYNCBUSY_COMP1 : LETIMER_SYNCBUSY_COMP0);
<> 144:ef7eb2e8f9f7 203 #endif
<> 144:ef7eb2e8f9f7 204
<> 144:ef7eb2e8f9f7 205 *compReg = value;
<> 144:ef7eb2e8f9f7 206 }
<> 144:ef7eb2e8f9f7 207
<> 144:ef7eb2e8f9f7 208
<> 144:ef7eb2e8f9f7 209 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 210 * @brief
<> 144:ef7eb2e8f9f7 211 * Start/stop LETIMER.
<> 144:ef7eb2e8f9f7 212 *
<> 144:ef7eb2e8f9f7 213 * @note
<> 144:ef7eb2e8f9f7 214 * The enabling/disabling of the LETIMER modifies the LETIMER CMD register
<> 144:ef7eb2e8f9f7 215 * which requires synchronization into the low frequency domain. If this
<> 144:ef7eb2e8f9f7 216 * register is modified before a previous update to the same register has
<> 144:ef7eb2e8f9f7 217 * completed, this function will stall until the previous synchronization has
<> 144:ef7eb2e8f9f7 218 * completed. This only applies to the Gecko Family, see comment in the
<> 144:ef7eb2e8f9f7 219 * LETIMER_Sync() internal function call.
<> 144:ef7eb2e8f9f7 220 *
<> 144:ef7eb2e8f9f7 221 * @param[in] letimer
<> 144:ef7eb2e8f9f7 222 * Pointer to LETIMER peripheral register block.
<> 144:ef7eb2e8f9f7 223 *
<> 144:ef7eb2e8f9f7 224 * @param[in] enable
<> 144:ef7eb2e8f9f7 225 * true to enable counting, false to disable.
<> 144:ef7eb2e8f9f7 226 ******************************************************************************/
<> 144:ef7eb2e8f9f7 227 void LETIMER_Enable(LETIMER_TypeDef *letimer, bool enable)
<> 144:ef7eb2e8f9f7 228 {
<> 144:ef7eb2e8f9f7 229 EFM_ASSERT(LETIMER_REF_VALID(letimer));
<> 144:ef7eb2e8f9f7 230
<> 144:ef7eb2e8f9f7 231 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 232 /* LF register about to be modified require sync. busy check */
<> 144:ef7eb2e8f9f7 233 regSync(letimer, LETIMER_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 234 #endif
<> 144:ef7eb2e8f9f7 235
<> 144:ef7eb2e8f9f7 236 if (enable)
<> 144:ef7eb2e8f9f7 237 {
<> 144:ef7eb2e8f9f7 238 letimer->CMD = LETIMER_CMD_START;
<> 144:ef7eb2e8f9f7 239 }
<> 144:ef7eb2e8f9f7 240 else
<> 144:ef7eb2e8f9f7 241 {
<> 144:ef7eb2e8f9f7 242 letimer->CMD = LETIMER_CMD_STOP;
<> 144:ef7eb2e8f9f7 243 }
<> 144:ef7eb2e8f9f7 244 }
<> 144:ef7eb2e8f9f7 245
<> 144:ef7eb2e8f9f7 246 #if defined(_LETIMER_FREEZE_MASK)
<> 144:ef7eb2e8f9f7 247 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 248 * @brief
<> 144:ef7eb2e8f9f7 249 * LETIMER register synchronization freeze control.
<> 144:ef7eb2e8f9f7 250 *
<> 144:ef7eb2e8f9f7 251 * @details
<> 144:ef7eb2e8f9f7 252 * Some LETIMER registers require synchronization into the low frequency (LF)
<> 144:ef7eb2e8f9f7 253 * domain. The freeze feature allows for several such registers to be
<> 144:ef7eb2e8f9f7 254 * modified before passing them to the LF domain simultaneously (which
<> 144:ef7eb2e8f9f7 255 * takes place when the freeze mode is disabled).
<> 144:ef7eb2e8f9f7 256 *
<> 144:ef7eb2e8f9f7 257 * @note
<> 144:ef7eb2e8f9f7 258 * When enabling freeze mode, this function will wait for all current
<> 144:ef7eb2e8f9f7 259 * ongoing LETIMER synchronization to LF domain to complete (Normally
<> 144:ef7eb2e8f9f7 260 * synchronization will not be in progress.) However for this reason, when
<> 144:ef7eb2e8f9f7 261 * using freeze mode, modifications of registers requiring LF synchronization
<> 144:ef7eb2e8f9f7 262 * should be done within one freeze enable/disable block to avoid unecessary
<> 144:ef7eb2e8f9f7 263 * stalling.
<> 144:ef7eb2e8f9f7 264 *
<> 144:ef7eb2e8f9f7 265 * @param[in] letimer
<> 144:ef7eb2e8f9f7 266 * Pointer to LETIMER peripheral register block.
<> 144:ef7eb2e8f9f7 267 *
<> 144:ef7eb2e8f9f7 268 * @param[in] enable
<> 144:ef7eb2e8f9f7 269 * @li true - enable freeze, modified registers are not propagated to the
<> 144:ef7eb2e8f9f7 270 * LF domain
<> 144:ef7eb2e8f9f7 271 * @li false - disables freeze, modified registers are propagated to LF
<> 144:ef7eb2e8f9f7 272 * domain
<> 144:ef7eb2e8f9f7 273 ******************************************************************************/
<> 144:ef7eb2e8f9f7 274 void LETIMER_FreezeEnable(LETIMER_TypeDef *letimer, bool enable)
<> 144:ef7eb2e8f9f7 275 {
<> 144:ef7eb2e8f9f7 276 if (enable)
<> 144:ef7eb2e8f9f7 277 {
<> 144:ef7eb2e8f9f7 278 /*
<> 144:ef7eb2e8f9f7 279 * Wait for any ongoing LF synchronization to complete. This is just to
<> 144:ef7eb2e8f9f7 280 * protect against the rare case when a user
<> 144:ef7eb2e8f9f7 281 * - modifies a register requiring LF sync
<> 144:ef7eb2e8f9f7 282 * - then enables freeze before LF sync completed
<> 144:ef7eb2e8f9f7 283 * - then modifies the same register again
<> 144:ef7eb2e8f9f7 284 * since modifying a register while it is in sync progress should be
<> 144:ef7eb2e8f9f7 285 * avoided.
<> 144:ef7eb2e8f9f7 286 */
<> 144:ef7eb2e8f9f7 287 while (letimer->SYNCBUSY)
<> 144:ef7eb2e8f9f7 288 ;
<> 144:ef7eb2e8f9f7 289
<> 144:ef7eb2e8f9f7 290 letimer->FREEZE = LETIMER_FREEZE_REGFREEZE;
<> 144:ef7eb2e8f9f7 291 }
<> 144:ef7eb2e8f9f7 292 else
<> 144:ef7eb2e8f9f7 293 {
<> 144:ef7eb2e8f9f7 294 letimer->FREEZE = 0;
<> 144:ef7eb2e8f9f7 295 }
<> 144:ef7eb2e8f9f7 296 }
<> 144:ef7eb2e8f9f7 297 #endif /* defined(_LETIMER_FREEZE_MASK) */
<> 144:ef7eb2e8f9f7 298
<> 144:ef7eb2e8f9f7 299 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 300 * @brief
<> 144:ef7eb2e8f9f7 301 * Initialize LETIMER.
<> 144:ef7eb2e8f9f7 302 *
<> 144:ef7eb2e8f9f7 303 * @details
<> 144:ef7eb2e8f9f7 304 * Note that the compare/repeat values must be set separately with
<> 144:ef7eb2e8f9f7 305 * LETIMER_CompareSet() and LETIMER_RepeatSet(). That should probably be done
<> 144:ef7eb2e8f9f7 306 * prior to the use of this function if configuring the LETIMER to start when
<> 144:ef7eb2e8f9f7 307 * initialization is completed.
<> 144:ef7eb2e8f9f7 308 *
<> 144:ef7eb2e8f9f7 309 * @note
<> 144:ef7eb2e8f9f7 310 * The initialization of the LETIMER modifies the LETIMER CTRL/CMD registers
<> 144:ef7eb2e8f9f7 311 * which require synchronization into the low frequency domain. If any of those
<> 144:ef7eb2e8f9f7 312 * registers are modified before a previous update to the same register has
<> 144:ef7eb2e8f9f7 313 * completed, this function will stall until the previous synchronization has
<> 144:ef7eb2e8f9f7 314 * completed. This only applies to the Gecko Family, see comment in the
<> 144:ef7eb2e8f9f7 315 * LETIMER_Sync() internal function call.
<> 144:ef7eb2e8f9f7 316 *
<> 144:ef7eb2e8f9f7 317 * @param[in] letimer
<> 144:ef7eb2e8f9f7 318 * Pointer to LETIMER peripheral register block.
<> 144:ef7eb2e8f9f7 319 *
<> 144:ef7eb2e8f9f7 320 * @param[in] init
<> 144:ef7eb2e8f9f7 321 * Pointer to LETIMER initialization structure.
<> 144:ef7eb2e8f9f7 322 ******************************************************************************/
<> 144:ef7eb2e8f9f7 323 void LETIMER_Init(LETIMER_TypeDef *letimer, const LETIMER_Init_TypeDef *init)
<> 144:ef7eb2e8f9f7 324 {
<> 144:ef7eb2e8f9f7 325 uint32_t tmp = 0;
<> 144:ef7eb2e8f9f7 326
<> 144:ef7eb2e8f9f7 327 EFM_ASSERT(LETIMER_REF_VALID(letimer));
<> 144:ef7eb2e8f9f7 328
<> 144:ef7eb2e8f9f7 329 /* Stop timer if specified to be disabled and running */
<> 144:ef7eb2e8f9f7 330 if (!(init->enable) && (letimer->STATUS & LETIMER_STATUS_RUNNING))
<> 144:ef7eb2e8f9f7 331 {
<> 144:ef7eb2e8f9f7 332 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 333 /* LF register about to be modified require sync. busy check */
<> 144:ef7eb2e8f9f7 334 regSync(letimer, LETIMER_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 335 #endif
<> 144:ef7eb2e8f9f7 336 letimer->CMD = LETIMER_CMD_STOP;
<> 144:ef7eb2e8f9f7 337 }
<> 144:ef7eb2e8f9f7 338
<> 144:ef7eb2e8f9f7 339 /* Configure DEBUGRUN flag, sets whether or not counter should be
<> 144:ef7eb2e8f9f7 340 * updated when debugger is active */
<> 144:ef7eb2e8f9f7 341 if (init->debugRun)
<> 144:ef7eb2e8f9f7 342 {
<> 144:ef7eb2e8f9f7 343 tmp |= LETIMER_CTRL_DEBUGRUN;
<> 144:ef7eb2e8f9f7 344 }
<> 144:ef7eb2e8f9f7 345
<> 144:ef7eb2e8f9f7 346 #if defined(LETIMER_CTRL_RTCC0TEN)
<> 144:ef7eb2e8f9f7 347 if (init->rtcComp0Enable)
<> 144:ef7eb2e8f9f7 348 {
<> 144:ef7eb2e8f9f7 349 tmp |= LETIMER_CTRL_RTCC0TEN;
<> 144:ef7eb2e8f9f7 350 }
<> 144:ef7eb2e8f9f7 351
<> 144:ef7eb2e8f9f7 352 if (init->rtcComp1Enable)
<> 144:ef7eb2e8f9f7 353 {
<> 144:ef7eb2e8f9f7 354 tmp |= LETIMER_CTRL_RTCC1TEN;
<> 144:ef7eb2e8f9f7 355 }
<> 144:ef7eb2e8f9f7 356 #endif
<> 144:ef7eb2e8f9f7 357
<> 144:ef7eb2e8f9f7 358 if (init->comp0Top)
<> 144:ef7eb2e8f9f7 359 {
<> 144:ef7eb2e8f9f7 360 tmp |= LETIMER_CTRL_COMP0TOP;
<> 144:ef7eb2e8f9f7 361 }
<> 144:ef7eb2e8f9f7 362
<> 144:ef7eb2e8f9f7 363 if (init->bufTop)
<> 144:ef7eb2e8f9f7 364 {
<> 144:ef7eb2e8f9f7 365 tmp |= LETIMER_CTRL_BUFTOP;
<> 144:ef7eb2e8f9f7 366 }
<> 144:ef7eb2e8f9f7 367
<> 144:ef7eb2e8f9f7 368 if (init->out0Pol)
<> 144:ef7eb2e8f9f7 369 {
<> 144:ef7eb2e8f9f7 370 tmp |= LETIMER_CTRL_OPOL0;
<> 144:ef7eb2e8f9f7 371 }
<> 144:ef7eb2e8f9f7 372
<> 144:ef7eb2e8f9f7 373 if (init->out1Pol)
<> 144:ef7eb2e8f9f7 374 {
<> 144:ef7eb2e8f9f7 375 tmp |= LETIMER_CTRL_OPOL1;
<> 144:ef7eb2e8f9f7 376 }
<> 144:ef7eb2e8f9f7 377
<> 144:ef7eb2e8f9f7 378 tmp |= init->ufoa0 << _LETIMER_CTRL_UFOA0_SHIFT;
<> 144:ef7eb2e8f9f7 379 tmp |= init->ufoa1 << _LETIMER_CTRL_UFOA1_SHIFT;
<> 144:ef7eb2e8f9f7 380 tmp |= init->repMode << _LETIMER_CTRL_REPMODE_SHIFT;
<> 144:ef7eb2e8f9f7 381
<> 144:ef7eb2e8f9f7 382 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 383 /* LF register about to be modified require sync. busy check */
<> 144:ef7eb2e8f9f7 384 regSync(letimer, LETIMER_SYNCBUSY_CTRL);
<> 144:ef7eb2e8f9f7 385 #endif
<> 144:ef7eb2e8f9f7 386 letimer->CTRL = tmp;
<> 144:ef7eb2e8f9f7 387
<> 144:ef7eb2e8f9f7 388 /* Start timer if specified to be enabled and not already running */
<> 144:ef7eb2e8f9f7 389 if (init->enable && !(letimer->STATUS & LETIMER_STATUS_RUNNING))
<> 144:ef7eb2e8f9f7 390 {
<> 144:ef7eb2e8f9f7 391 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 392 /* LF register about to be modified require sync. busy check */
<> 144:ef7eb2e8f9f7 393 regSync(letimer, LETIMER_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 394 #endif
<> 144:ef7eb2e8f9f7 395 letimer->CMD = LETIMER_CMD_START;
<> 144:ef7eb2e8f9f7 396 }
<> 144:ef7eb2e8f9f7 397 }
<> 144:ef7eb2e8f9f7 398
<> 144:ef7eb2e8f9f7 399
<> 144:ef7eb2e8f9f7 400 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 401 * @brief
<> 144:ef7eb2e8f9f7 402 * Get LETIMER repeat register value.
<> 144:ef7eb2e8f9f7 403 *
<> 144:ef7eb2e8f9f7 404 * @param[in] letimer
<> 144:ef7eb2e8f9f7 405 * Pointer to LETIMER peripheral register block
<> 144:ef7eb2e8f9f7 406 *
<> 144:ef7eb2e8f9f7 407 * @param[in] rep
<> 144:ef7eb2e8f9f7 408 * Repeat register to get, either 0 or 1
<> 144:ef7eb2e8f9f7 409 *
<> 144:ef7eb2e8f9f7 410 * @return
<> 144:ef7eb2e8f9f7 411 * Repeat register value, 0 if invalid register selected.
<> 144:ef7eb2e8f9f7 412 ******************************************************************************/
<> 144:ef7eb2e8f9f7 413 uint32_t LETIMER_RepeatGet(LETIMER_TypeDef *letimer, unsigned int rep)
<> 144:ef7eb2e8f9f7 414 {
<> 144:ef7eb2e8f9f7 415 uint32_t ret;
<> 144:ef7eb2e8f9f7 416
<> 144:ef7eb2e8f9f7 417 EFM_ASSERT(LETIMER_REF_VALID(letimer) && LETIMER_REP_REG_VALID(rep));
<> 144:ef7eb2e8f9f7 418
<> 144:ef7eb2e8f9f7 419 /* Initialize selected compare value */
<> 144:ef7eb2e8f9f7 420 switch (rep)
<> 144:ef7eb2e8f9f7 421 {
<> 144:ef7eb2e8f9f7 422 case 0:
<> 144:ef7eb2e8f9f7 423 ret = letimer->REP0;
<> 144:ef7eb2e8f9f7 424 break;
<> 144:ef7eb2e8f9f7 425
<> 144:ef7eb2e8f9f7 426 case 1:
<> 144:ef7eb2e8f9f7 427 ret = letimer->REP1;
<> 144:ef7eb2e8f9f7 428 break;
<> 144:ef7eb2e8f9f7 429
<> 144:ef7eb2e8f9f7 430 default:
<> 144:ef7eb2e8f9f7 431 /* Unknown compare register selected */
<> 144:ef7eb2e8f9f7 432 ret = 0;
<> 144:ef7eb2e8f9f7 433 break;
<> 144:ef7eb2e8f9f7 434 }
<> 144:ef7eb2e8f9f7 435
<> 144:ef7eb2e8f9f7 436 return(ret);
<> 144:ef7eb2e8f9f7 437 }
<> 144:ef7eb2e8f9f7 438
<> 144:ef7eb2e8f9f7 439
<> 144:ef7eb2e8f9f7 440 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 441 * @brief
<> 144:ef7eb2e8f9f7 442 * Set LETIMER repeat counter register value.
<> 144:ef7eb2e8f9f7 443 *
<> 144:ef7eb2e8f9f7 444 * @note
<> 144:ef7eb2e8f9f7 445 * The setting of a repeat counter register requires synchronization into the
<> 144:ef7eb2e8f9f7 446 * low frequency domain. If the same register is modified before a previous
<> 144:ef7eb2e8f9f7 447 * update has completed, this function will stall until the previous
<> 144:ef7eb2e8f9f7 448 * synchronization has completed. This only applies to the Gecko Family, see
<> 144:ef7eb2e8f9f7 449 * comment in the LETIMER_Sync() internal function call.
<> 144:ef7eb2e8f9f7 450 *
<> 144:ef7eb2e8f9f7 451 * @param[in] letimer
<> 144:ef7eb2e8f9f7 452 * Pointer to LETIMER peripheral register block
<> 144:ef7eb2e8f9f7 453 *
<> 144:ef7eb2e8f9f7 454 * @param[in] rep
<> 144:ef7eb2e8f9f7 455 * Repeat counter register to set, either 0 or 1
<> 144:ef7eb2e8f9f7 456 *
<> 144:ef7eb2e8f9f7 457 * @param[in] value
<> 144:ef7eb2e8f9f7 458 * Initialization value (<= 0x0000ffff)
<> 144:ef7eb2e8f9f7 459 ******************************************************************************/
<> 144:ef7eb2e8f9f7 460 void LETIMER_RepeatSet(LETIMER_TypeDef *letimer,
<> 144:ef7eb2e8f9f7 461 unsigned int rep,
<> 144:ef7eb2e8f9f7 462 uint32_t value)
<> 144:ef7eb2e8f9f7 463 {
<> 144:ef7eb2e8f9f7 464 volatile uint32_t *repReg;
<> 144:ef7eb2e8f9f7 465 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 466 uint32_t syncbusy;
<> 144:ef7eb2e8f9f7 467 #endif
<> 144:ef7eb2e8f9f7 468 EFM_ASSERT(LETIMER_REF_VALID(letimer)
<> 144:ef7eb2e8f9f7 469 && LETIMER_REP_REG_VALID(rep)
<> 144:ef7eb2e8f9f7 470 && ((value & ~(_LETIMER_REP0_REP0_MASK
<> 144:ef7eb2e8f9f7 471 >> _LETIMER_REP0_REP0_SHIFT))
<> 144:ef7eb2e8f9f7 472 == 0));
<> 144:ef7eb2e8f9f7 473
<> 144:ef7eb2e8f9f7 474 /* Initialize selected compare value */
<> 144:ef7eb2e8f9f7 475 switch (rep)
<> 144:ef7eb2e8f9f7 476 {
<> 144:ef7eb2e8f9f7 477 case 0:
<> 144:ef7eb2e8f9f7 478 repReg = &(letimer->REP0);
<> 144:ef7eb2e8f9f7 479 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 480 syncbusy = LETIMER_SYNCBUSY_REP0;
<> 144:ef7eb2e8f9f7 481 #endif
<> 144:ef7eb2e8f9f7 482 break;
<> 144:ef7eb2e8f9f7 483
<> 144:ef7eb2e8f9f7 484 case 1:
<> 144:ef7eb2e8f9f7 485 repReg = &(letimer->REP1);
<> 144:ef7eb2e8f9f7 486 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 487 syncbusy = LETIMER_SYNCBUSY_REP1;
<> 144:ef7eb2e8f9f7 488 #endif
<> 144:ef7eb2e8f9f7 489 break;
<> 144:ef7eb2e8f9f7 490
<> 144:ef7eb2e8f9f7 491 default:
<> 144:ef7eb2e8f9f7 492 /* Unknown compare register selected, abort */
<> 144:ef7eb2e8f9f7 493 return;
<> 144:ef7eb2e8f9f7 494 }
<> 144:ef7eb2e8f9f7 495
<> 144:ef7eb2e8f9f7 496 #if defined(_EFM32_GECKO_FAMILY)
<> 144:ef7eb2e8f9f7 497 /* LF register about to be modified require sync. busy check */
<> 144:ef7eb2e8f9f7 498 regSync(letimer, syncbusy);
<> 144:ef7eb2e8f9f7 499 #endif
<> 144:ef7eb2e8f9f7 500
<> 144:ef7eb2e8f9f7 501 *repReg = value;
<> 144:ef7eb2e8f9f7 502 }
<> 144:ef7eb2e8f9f7 503
<> 144:ef7eb2e8f9f7 504
<> 144:ef7eb2e8f9f7 505 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 506 * @brief
<> 144:ef7eb2e8f9f7 507 * Reset LETIMER to same state as after a HW reset.
<> 144:ef7eb2e8f9f7 508 *
<> 144:ef7eb2e8f9f7 509 * @note
<> 144:ef7eb2e8f9f7 510 * The ROUTE register is NOT reset by this function, in order to allow for
<> 144:ef7eb2e8f9f7 511 * centralized setup of this feature.
<> 144:ef7eb2e8f9f7 512 *
<> 144:ef7eb2e8f9f7 513 * @param[in] letimer
<> 144:ef7eb2e8f9f7 514 * Pointer to LETIMER peripheral register block.
<> 144:ef7eb2e8f9f7 515 ******************************************************************************/
<> 144:ef7eb2e8f9f7 516 void LETIMER_Reset(LETIMER_TypeDef *letimer)
<> 144:ef7eb2e8f9f7 517 {
<> 144:ef7eb2e8f9f7 518 #if defined(_LETIMER_FREEZE_MASK)
<> 144:ef7eb2e8f9f7 519 /* Freeze registers to avoid stalling for LF synchronization */
<> 144:ef7eb2e8f9f7 520 LETIMER_FreezeEnable(letimer, true);
<> 144:ef7eb2e8f9f7 521 #endif
<> 144:ef7eb2e8f9f7 522
<> 144:ef7eb2e8f9f7 523 /* Make sure disabled first, before resetting other registers */
<> 144:ef7eb2e8f9f7 524 letimer->CMD = LETIMER_CMD_STOP | LETIMER_CMD_CLEAR
<> 144:ef7eb2e8f9f7 525 | LETIMER_CMD_CTO0 | LETIMER_CMD_CTO1;
<> 144:ef7eb2e8f9f7 526 letimer->CTRL = _LETIMER_CTRL_RESETVALUE;
<> 144:ef7eb2e8f9f7 527 letimer->COMP0 = _LETIMER_COMP0_RESETVALUE;
<> 144:ef7eb2e8f9f7 528 letimer->COMP1 = _LETIMER_COMP1_RESETVALUE;
<> 144:ef7eb2e8f9f7 529 letimer->REP0 = _LETIMER_REP0_RESETVALUE;
<> 144:ef7eb2e8f9f7 530 letimer->REP1 = _LETIMER_REP1_RESETVALUE;
<> 144:ef7eb2e8f9f7 531 letimer->IEN = _LETIMER_IEN_RESETVALUE;
<> 144:ef7eb2e8f9f7 532 letimer->IFC = _LETIMER_IFC_MASK;
<> 144:ef7eb2e8f9f7 533 /* Do not reset route register, setting should be done independently */
<> 144:ef7eb2e8f9f7 534
<> 144:ef7eb2e8f9f7 535 #if defined(_LETIMER_FREEZE_MASK)
<> 144:ef7eb2e8f9f7 536 /* Unfreeze registers, pass new settings on to LETIMER */
<> 144:ef7eb2e8f9f7 537 LETIMER_FreezeEnable(letimer, false);
<> 144:ef7eb2e8f9f7 538 #endif
<> 144:ef7eb2e8f9f7 539 }
<> 144:ef7eb2e8f9f7 540
<> 144:ef7eb2e8f9f7 541
<> 144:ef7eb2e8f9f7 542 /** @} (end addtogroup LETIMER) */
<> 144:ef7eb2e8f9f7 543 /** @} (end addtogroup EM_Library) */
<> 144:ef7eb2e8f9f7 544 #endif /* defined(LETIMER_COUNT) && (LETIMER_COUNT > 0) */