lptmr_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
51 #include "lptmr_driver.h"
52 #include "lptmr_hw_access.h"
53 #include "clock_manager.h"
54 
55 /*******************************************************************************
56  * Definitions
57  ******************************************************************************/
58 /* Takes into consideration that LPTMR compare events take place
59  * when "the CNR equals the value of the CMR and increments" */
60 #define LPTMR_MAX_CMR_NTICKS (LPTMR_CMR_COMPARE_MASK + 1u)
61 #define LPTMR_MAX_PRESCALER (1u << LPTMR_PSR_PRESCALE_WIDTH)
62 
63 /*******************************************************************************
64  * Variables
65  ******************************************************************************/
66 
69 /* Table of base addresses for LPTMR instances */
70 static LPTMR_Type* const g_lptmrBase[LPTMR_INSTANCE_COUNT] = LPTMR_BASE_PTRS;
71 
72 /*******************************************************************************
73  * Private Functions
74  ******************************************************************************/
75 static inline uint8_t lptmr_cfg2p(
76  const lptmr_prescaler_t prescval,
77  const bool bypass
78  );
79 
80 static inline uint64_t lptmr_us2nn(
81  const uint32_t clkfreq,
82  const uint32_t us
83  );
84 
85 static inline uint64_t lptmr_compute_nticks(
86  uint64_t nn,
87  uint8_t p
88  );
89 
90 static inline bool nticks2compare_ticks(
91  uint64_t nticks,
92  uint16_t* ticks
93  );
94 
95 static uint32_t lptmr_GetClkFreq(
96  const lptmr_clocksource_t clkSrc,
97  const uint32_t instance
98  );
99 
100 static bool lptmr_Ticks2Us(
101  const uint32_t clkfreq,
102  const lptmr_prescaler_t pval,
103  const bool bypass,
104  const uint16_t ticks,
105  uint32_t* const us
106  );
107 
108 static bool lptmr_Us2Ticks(
109  const uint32_t clkfreq,
110  const lptmr_prescaler_t prescval,
111  const bool bypass,
112  const uint32_t us,
113  uint16_t* const ticks
114  );
115 
116 static bool lptmr_ChooseClkConfig(
117  const uint32_t clkfreq,
118  const uint32_t us,
119  lptmr_prescaler_t* const prescval,
120  bool* const bypass,
121  uint16_t* const ticks
122  );
123 
124 /*TIMER MODE CONFIGURATION******************************************************
125  *
126  * Timer Mode - Prescaler settings calculations
127  * --------------------------------------------
128  *
129  * Timer Mode configuration takes a period (timeout) value expressed in
130  * micro-seconds. To convert this to LPTMR prescaler (and compare value)
131  * settings, the closest match must be found.
132  * For best precision, the lowest prescaler that allows the corresponding
133  * compare value to fit in the 16-bit register will be chosen.
134  *
135  * Algorithm for choosing prescaler and compare values:
136  * =============================================================================
137  * In: tper_us (period in microseconds), fclk (input clock frequency in Hertz)
138  * Out: nticks (timer ticks), p (prescaler coefficient, 2^p = prescaler value)
139  * ---
140  * 1) Compute nn = tper_us * fclk / 1000000
141  * 2) for p = 0..16
142  * 2.1) nticks = nn / 2^p
143  * 2.2) if nticks < 0x10000
144  * 2.2.1) STOP, found nticks and p
145  * 3) nticks = 0xFFFF, p = 16
146  * =============================================================================
147  *
148  * A few names used throughout the static functions affecting Timer mode:
149  * nn - total number of timer ticks (undivided, unprescaled) that is necessary
150  * for a particular timeout.
151  * nn = (tper_us * fclk) / 1000000 = nticks * npresc
152  *
153  * tper_us - a period (or timeout) expressed in microsecond units. In most
154  * functions will be denoted as 'us' for microseconds.
155  *
156  * nticks - number of timer ticks that is necessary for a particular timeout,
157  * after prescaling
158  *
159  * npresc - prescaler value (1, 2, 4 ... 65536)
160  *
161  * p - prescaler coefficient, 2^p = npresc
162  *
163  * fclk - input clock frequency, in Hertz. In most function will be denoted as
164  * 'clkfreq'.
165  *END**************************************************************************/
166 
167 /*FUNCTION**********************************************************************
168  *
169  * Function Name : lptmr_cfg2p
170  * Description : Transform prescaler settings (bypass on/off, prescaler value)
171  * to prescaler coefficient value (2's power), p.
172  * Return: the value of p.
173  *END**************************************************************************/
174 static inline uint8_t lptmr_cfg2p(
175  const lptmr_prescaler_t prescval,
176  const bool bypass
177  )
178 {
179  uint8_t p = 0u;
180 
181  if (!bypass)
182  {
183  p = (uint8_t)(((uint8_t)prescval) + 1u);
184  }
185 
186  return p;
187 }
188 
189 /*FUNCTION**********************************************************************
190  *
191  * Function Name : lptmr_us2nn
192  * Description : Transform microseconds to undivided (unprescaled) timer units,
193  * nn.
194  * Return: the value of nn.
195  *END**************************************************************************/
196 static inline uint64_t lptmr_us2nn(
197  const uint32_t clkfreq,
198  const uint32_t us
199  )
200 {
201  /* Approximate the timeout in undivided (unprescaled) timer ticks.
202  - us is the timeout in microseconds (1/10^6 seconds)
203  - clkfreq is the frequency in Hertz
204  Operation:
205  nn = (us/1000000) * clkfreq
206  In C:
207  For better precision, first to the multiplication (us * clkfreq)
208  To overcome the truncation of the div operator in C, add half of the
209  denominator before the division. Hence:
210  nn = (us * clkfreq + 500000) / 1000000
211  */
212  /* There is no risk of overflow since us is 32-bit wide and clkfreq can be
213  a theoretical maximum of ~100 MHz (platform maximum), which is over the
214  maximum input of the LPTMR anyway
215  */
216  uint64_t nn = (uint64_t)( (uint64_t)us * (uint64_t)clkfreq );
217  nn = (nn + 500000u) / 1000000u;
218  return nn;
219 }
220 
221 /*FUNCTION**********************************************************************
222  *
223  * Function Name : lptmr_compute_nticks
224  * Description : Compute total number of divided (prescaled) timer ticks,
225  * nticks.
226  * Return: the value of nticks.
227  *END**************************************************************************/
228 static inline uint64_t lptmr_compute_nticks(
229  uint64_t nn,
230  uint8_t p
231  )
232 {
233  uint64_t npresc = (uint64_t) 1u << p;
234  DEV_ASSERT(npresc != 0u);
235 
236  /* integer division */
237  uint64_t nticks = ((nn + (npresc >> 1u)) / npresc);
238 
239  return nticks;
240 }
241 
242 /*FUNCTION**********************************************************************
243  *
244  * Function Name : nticks2compare_ticks
245  * Description : Transform the value of divided (prescaled) timer ticks, nticks
246  * to a 16-bit value to be written to the hardware register. Cap or underflow
247  * cause an error.
248  * Return: the success state.
249  * - true: no underflow or overflow detected
250  * - false: value written was capped, underflow or overflow detected
251  *
252  *END**************************************************************************/
253 static inline bool nticks2compare_ticks(
254  uint64_t nticks,
255  uint16_t* ticks
256  )
257 {
258  bool success = true;
259 
260  /* if nticks fits, write the value to ticks */
261  if (nticks <= LPTMR_MAX_CMR_NTICKS)
262  {
263  if (nticks == 0u)
264  {
265  /* timeout period (us) too low for prescaler settings */
266  *ticks = 0u;
267  success = false;
268  }
269  else{
270  /* According to RM, the LPTMR compare events take place when "the CNR equals the value of the CMR and increments".
271  * The additional increment is compensated here by decrementing the calculated compare value with 1, before being written to CMR. */
272  *ticks = (uint16_t)(nticks - 1u);
273  }
274  }
275  else {
276  /* timeout period (us) too high for prescaler settings */
277  *ticks = LPTMR_CMR_COMPARE_MASK;
278  success = false;
279  }
280 
281  return success;
282 }
283 
284 /*FUNCTION**********************************************************************
285  *
286  * Function Name : lptmr_GetClkFreq
287  * Description : Get the clock frequency for the selected clock source. If the
288  * selected clock source is not enabled, a frequency of 0 is returned.
289  * Return values:
290  * - the clock frequency or 0 if the clock is invalid.
291  *
292  *END**************************************************************************/
293 static uint32_t lptmr_GetClkFreq(const lptmr_clocksource_t clkSrc,
294  const uint32_t instance)
295 {
296  /* LPTMR PCC clock source names, for getting the input clock frequency */
297  static const clock_names_t lptmrPccClockName[LPTMR_INSTANCE_COUNT] = {LPTMR0_CLK};
298  clock_names_t inputClockName = SIRC_CLK;
299  uint32_t clkFreq;
300  status_t clkStatus;
301 
302  /* Get input clock name */
303  switch(clkSrc)
304  {
306  inputClockName = SIRC_CLK;
307  break;
309  inputClockName = SIM_LPO_1K_CLK;
310  break;
312  inputClockName = SIM_RTCCLK_CLK;
313  break;
315  inputClockName = lptmrPccClockName[instance];
316  break;
317  default:
318  /* Invalid clock source */
319  DEV_ASSERT(false);
320  break;
321  }
322 
323  /* Get input clock frequency */
324  if (inputClockName == SIRC_CLK)
325  {
326  clkStatus = CLOCK_SYS_GetFreq(SIRCDIV2_CLK, &clkFreq);
327  DEV_ASSERT(clkStatus == STATUS_SUCCESS);
328  (void) clkStatus;
329  DEV_ASSERT(clkFreq != 0u); /* If the GetFreq functions fails, clkfreq will be 0 */
330  }
331  else
332  {
333  clkStatus = CLOCK_SYS_GetFreq(inputClockName, &clkFreq);
334  DEV_ASSERT(clkStatus == STATUS_SUCCESS);
335  (void) clkStatus;
336  DEV_ASSERT(clkFreq != 0u); /* If the GetFreq functions fails, clkfreq will be 0 */
337  }
338 
339  return clkFreq;
340 }
341 
342 /*FUNCTION**********************************************************************
343  *
344  * Function Name : lptmr_Ticks2Us
345  * Description : Transform timer ticks to microseconds using the given
346  * prescaler settings. Clock frequency must be valid (different from 0).
347  * Possible return values:
348  * - true: conversion success
349  * - false: conversion failed, result did not fit in 32-bit.
350  *
351  *END**************************************************************************/
352 static bool lptmr_Ticks2Us(
353  const uint32_t clkfreq,
354  const lptmr_prescaler_t pval,
355  const bool bypass,
356  const uint16_t ticks,
357  uint32_t* const us
358  )
359 {
360  bool success = true;
361  uint8_t p = lptmr_cfg2p(pval, bypass);
362  uint64_t nn = ( (uint64_t)ticks + 1u ) << p;
363  uint64_t us_real = (nn * 1000000u) / (clkfreq);
364  uint32_t us_local;
365 
366  if ( us_real <= (0xFFFFFFFFu) )
367  {
368  us_local = (uint32_t)us_real;
369  }
370  else
371  {
372  us_local = 0xFFFFFFFFu;
373  success = false;
374  }
375 
376  *us = us_local;
377  return success;
378 }
379 
380 /*FUNCTION**********************************************************************
381  *
382  * Function Name : lptmr_Us2Ticks
383  * Description : Transform microseconds to timer ticks using the given
384  * prescaler settings. Input clock frequency, clkfreq, must be greater than 0.
385  * Possible return values:
386  * - true: conversion completed successfully
387  * - false: conversion failed, value did not fit in 16-bit.
388  *
389  *END**************************************************************************/
390 static bool lptmr_Us2Ticks(
391  const uint32_t clkfreq,
392  const lptmr_prescaler_t prescval,
393  const bool bypass,
394  const uint32_t us,
395  uint16_t* const ticks
396  )
397 {
398  bool success = true;
399  /* Transform prescaler configuration to prescaler coefficient p */
400  uint8_t p = lptmr_cfg2p(prescval, bypass);
401  /* Compute nn, the number of ticks necessary for the period in microseconds
402  without any prescaler */
403  uint64_t nn = lptmr_us2nn(clkfreq, us);
404  /* Compute nticks, total number of ticks with prescaler */
405  uint64_t nticks = lptmr_compute_nticks(nn, p);
406  /* Transform nticks to value to be written to register */
407  success = nticks2compare_ticks(nticks, ticks);
408  return success;
409 }
410 
411 /*FUNCTION**********************************************************************
412  *
413  * Function Name : lptmr_ChooseClkConfig
414  * Description : Choose clocking configuration (prescaler value, timer ticks)
415  * for the desired timeout period, given in microseconds. Input clock frequency,
416  * clkfreq, must be greater than 0.
417  * Possible return values:
418  * - true: configuration found
419  * - false: configuration mismatch, desired timeout period is too small or too
420  * big for the clock settings.
421  *
422  *END**************************************************************************/
423 static bool lptmr_ChooseClkConfig(
424  const uint32_t clkfreq,
425  const uint32_t us,
426  lptmr_prescaler_t* const prescval,
427  bool* const bypass,
428  uint16_t* const ticks
429  )
430 {
431  uint8_t p;
432  uint64_t nticks;
433  bool success;
434 
435  uint64_t nn = lptmr_us2nn(clkfreq, us);
436 
437  /* Find the lowest prescaler value that allows the compare value in 16-bits */
438  for (p = 0u; p <= LPTMR_MAX_PRESCALER; p++)
439  {
440  nticks = lptmr_compute_nticks(nn, p);
441 
442  if (nticks <= LPTMR_MAX_CMR_NTICKS)
443  {
444  /* Search finished, value will fit in the 16-bit register */
445  break;
446  }
447  }
448 
449  success = nticks2compare_ticks(nticks, ticks);
450 
451  /* Convert p to prescaler configuration */
452  if (p == 0u)
453  {
454  /* Prescaler value of 1 */
455  *bypass = true;
456  *prescval = LPTMR_PRESCALE_2;
457  }
458  else{
459  *bypass = false;
460  p--; /* Decrement to match lptmr_prescaler_t. */
461  *prescval = (lptmr_prescaler_t) p;
462  }
463 
464  return success;
465 }
466 
467 
468 /*******************************************************************************
469  * Public Functions
470  ******************************************************************************/
471 
472 
473 /*FUNCTION**********************************************************************
474  *
475  * Function Name : LPTMR_DRV_InitConfigStruct
476  * Description : Initialize a configuration structure with default values.
477  *
478  * Implements : LPTMR_DRV_InitConfigStruct_Activity
479  *END**************************************************************************/
480 void LPTMR_DRV_InitConfigStruct(lptmr_config_t * const config)
481 {
482  DEV_ASSERT(config != NULL);
483 
484  /* General parameters */
485  config->dmaRequest = false;
486  config->interruptEnable = false;
487  config->freeRun = false;
488  config->workMode = LPTMR_WORKMODE_TIMER;
489 
490  /* Counter parameters */
492  config->prescaler = LPTMR_PRESCALE_2;
493  config->bypassPrescaler = false;
494  config->compareValue = 0u;
496 
497  /* Pulse Counter specific parameters */
500 }
501 
502 /*FUNCTION**********************************************************************
503  *
504  * Function Name : LPTMR_DRV_Init
505  * Description : Initialize a LPTMR instance based on the input configuration
506  * structure.
507  *
508  * When (counterUnits == LPTMR_COUNTER_UNITS_MICROSECONDS) the function will
509  * automatically configure the timer for the input compareValue in microseconds.
510  * The input parameters for 'prescaler' and 'bypassPrescaler' will be ignored
511  * - their values will be adapted by the function, to best fit the input compareValue
512  * (in microseconds) for the operating clock frequency.
513  *
514  * LPTMR_COUNTER_UNITS_MICROSECONDS may only be used for LPTMR_WORKMODE_TIMER mode.
515  * Otherwise the function shall not convert 'compareValue' in ticks
516  * and this is likely to cause erroneous behavior.
517  *
518  * When (counterUnits == LPTMR_COUNTER_UNITS_TICKS) the function will use the
519  * 'prescaler' and 'bypassPrescaler' provided in the input configuration structure.
520  *
521  * When (counterUnits == LPTMR_COUNTER_UNITS_TICKS), 'compareValue' must be lower
522  * than 0xFFFFu. Only the least significant 16bits of 'compareValue' will be used.
523  * When (counterUnits == LPTMR_COUNTER_UNITS_MICROSECONDS), 'compareValue'
524  * may take any 32bits unsigned value.
525  *
526  * Implements : LPTMR_DRV_Init_Activity
527  *END**************************************************************************/
528 void LPTMR_DRV_Init(const uint32_t instance,
529  const lptmr_config_t * const config,
530  const bool startCounter)
531 {
532  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
533  DEV_ASSERT(config != NULL);
534 
535  LPTMR_Type* const base = g_lptmrBase[instance];
536 
537  LPTMR_DRV_SetConfig(instance, config);
538 
539  /* Start the counter if requested */
540  if (startCounter)
541  {
542  LPTMR_Enable(base);
543  }
544 }
545 
546 /*FUNCTION**********************************************************************
547  *
548  * Function Name : LPTMR_DRV_SetConfig
549  * Description : Configure a LPTMR instance based on the input configuration
550  * structure.
551  *
552  * When (counterUnits == LPTMR_COUNTER_UNITS_MICROSECONDS) the function will
553  * automatically configure the timer for the input compareValue in microseconds.
554  * The input parameters for 'prescaler' and 'bypassPrescaler' will be ignored
555  * - their values will be adapted by the function, to best fit the input compareValue
556  * (in microseconds) for the operating clock frequency.
557  *
558  * LPTMR_COUNTER_UNITS_MICROSECONDS may only be used for LPTMR_WORKMODE_TIMER mode.
559  * Otherwise the function shall not convert 'compareValue' in ticks
560  * and this is likely to cause erroneous behavior.
561  *
562  * When (counterUnits == LPTMR_COUNTER_UNITS_TICKS) the function will use the
563  * 'prescaler' and 'bypassPrescaler' provided in the input configuration structure.
564  *
565  * When (counterUnits == LPTMR_COUNTER_UNITS_TICKS), 'compareValue' must be lower
566  * than 0xFFFFu. Only the least significant 16bits of 'compareValue' will be used.
567  * When (counterUnits == LPTMR_COUNTER_UNITS_MICROSECONDS), 'compareValue'
568  * may take any 32bits unsigned value.
569  *
570  * Implements : LPTMR_DRV_SetConfig_Activity
571  *END**************************************************************************/
572 void LPTMR_DRV_SetConfig(const uint32_t instance,
573  const lptmr_config_t * const config)
574 {
575  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
576  DEV_ASSERT(config != NULL);
577 
578  LPTMR_Type* const base = g_lptmrBase[instance];
579  uint32_t configCmpValue = config->compareValue;
580  lptmr_workmode_t configWorkMode = config->workMode;
581  uint16_t cmpValueTicks = 0U;
582  lptmr_prescaler_t prescVal = config->prescaler;
583  bool prescBypass = config->bypassPrescaler;
584  lptmr_counter_units_t configCounterUnits = config->counterUnits;
585 
586  if(configWorkMode == LPTMR_WORKMODE_TIMER)
587  {
588  /* A valid clock must be selected when used in Timer Mode. */
589  uint32_t clkFreq;
590  clkFreq = lptmr_GetClkFreq(config->clockSelect, instance);
591  DEV_ASSERT(clkFreq != 0U); /* Clock frequency equal to '0', signals invalid value. */
592 
593  if(configCounterUnits == LPTMR_COUNTER_UNITS_MICROSECONDS)
594  {
595  bool chooseClkConfigStatus;
596 
597  /* When workmode is set to Timer Mode and compare value is provided in microseconds,
598  * then the input parameters for prescale value and prescaleBypass are ignored.
599  * The prescaleValue, prescaleBypass and cmpValue in ticks, are calculated to best fit
600  * the input configCmpValue (in us) for the current operating clk frequency. */
601  chooseClkConfigStatus = lptmr_ChooseClkConfig(clkFreq, configCmpValue, &prescVal, &prescBypass, &cmpValueTicks);
602  DEV_ASSERT(chooseClkConfigStatus == true);
603  (void) chooseClkConfigStatus;
604  }
605  else
606  {
607  DEV_ASSERT(configCounterUnits == LPTMR_COUNTER_UNITS_TICKS);
608  DEV_ASSERT(configCmpValue <= LPTMR_CMR_COMPARE_MASK); /* Compare Value in Tick Units must fit in CMR. */
609 
610  cmpValueTicks = (uint16_t)(configCmpValue & LPTMR_CMR_COMPARE_MASK);
611  }
612  }
613  else
614  {
615  /* If configWorkMode is not LPTMR_WORKMODE_TIMER, then it must be LPTMR_WORKMODE_PULSECOUNTER. */
616  DEV_ASSERT(configWorkMode == LPTMR_WORKMODE_PULSECOUNTER);
617 
618  /* Only LPTMR_COUNTER_UNITS_TICKS can be used when LPTMR is configured as Pulse Counter. */
620  /* A valid clock must be selected when glitch filter is enabled (prescaler not bypassed). */
621  DEV_ASSERT((lptmr_GetClkFreq(config->clockSelect, instance) != 0u) || prescBypass);
622  /* Glitch filter does not support LPTMR_PRESCALE_2. */
623  DEV_ASSERT(prescBypass || (prescVal != LPTMR_PRESCALE_2));
624 
625  DEV_ASSERT(configCmpValue <= LPTMR_CMR_COMPARE_MASK); /* Compare Value in Tick Units must fit in CMR. */
626 
627  cmpValueTicks = (uint16_t)(configCmpValue & LPTMR_CMR_COMPARE_MASK);
628  }
629 
630  /* Initialize and write configuration parameters. */
631  LPTMR_Init(base);
632 
633  LPTMR_SetDmaRequest (base, config->dmaRequest);
634  LPTMR_SetInterrupt (base, config->interruptEnable);
635  LPTMR_SetFreeRunning (base, config->freeRun);
636  LPTMR_SetWorkMode (base, configWorkMode);
637  LPTMR_SetPrescaler (base, prescVal);
638  LPTMR_SetBypass (base, prescBypass);
639  LPTMR_SetClockSelect (base, config->clockSelect);
640  LPTMR_SetCompareValue (base, cmpValueTicks);
641  LPTMR_SetPinSelect (base, config->pinSelect);
642  LPTMR_SetPinPolarity (base, config->pinPolarity);
643 }
644 
645 /*FUNCTION**********************************************************************
646  *
647  * Function Name : LPTMR_DRV_GetConfig
648  * Description : Get the current configuration of the LPTMR instance.
649  * Always returns compareValue in LPTMR_COUNTER_UNITS_TICKS.
650  *
651  * Implements : LPTMR_DRV_GetConfig_Activity
652  *END**************************************************************************/
653 void LPTMR_DRV_GetConfig(const uint32_t instance,
654  lptmr_config_t * const config)
655 {
656  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
657  DEV_ASSERT(config != NULL);
658 
659  const LPTMR_Type* const base = g_lptmrBase[instance];
660 
661  /* Read current configuration */
662  config->dmaRequest = LPTMR_GetDmaRequest(base);
663  config->interruptEnable = LPTMR_GetInterruptEnable(base);
664  config->freeRun = LPTMR_GetFreeRunning(base);
665  config->workMode = LPTMR_GetWorkMode(base);
666  config->prescaler = LPTMR_GetPrescaler(base);
667  config->bypassPrescaler = LPTMR_GetBypass(base);
668  config->clockSelect = LPTMR_GetClockSelect(base);
669  config->compareValue = LPTMR_GetCompareValue(base);
671  config->pinSelect = LPTMR_GetPinSelect(base);
672  config->pinPolarity = LPTMR_GetPinPolarity(base);
673 }
674 
675 
676 /*FUNCTION**********************************************************************
677  *
678  * Function Name : LPTMR_DRV_Deinit
679  * Description : De-initialize the LPTMR (stop the counter and reset all registers to default value).
680  *
681  * Implements : LPTMR_DRV_Deinit_Activity
682  *END**************************************************************************/
683 void LPTMR_DRV_Deinit(const uint32_t instance)
684 {
685  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
686 
687  LPTMR_Type* const base = g_lptmrBase[instance];
688  LPTMR_Disable(base);
689 
690  LPTMR_Init(base);
691 }
692 
693 
694 /*FUNCTION**********************************************************************
695  *
696  * Function Name : LPTMR_DRV_SetCompareValueByCount
697  * Description : Set the compare value in counter tick units, for a LPTMR instance.
698  * Possible return values:
699  * - STATUS_SUCCESS: completed successfully
700  * - STATUS_ERROR: cannot reconfigure compare value (TCF not set)
701  * - STATUS_TIMEOUT: compare value is smaller than current counter value
702  *
703  * Implements : LPTMR_DRV_SetCompareValueByCount_Activity
704  *END**************************************************************************/
705 status_t LPTMR_DRV_SetCompareValueByCount(const uint32_t instance,
706  const uint16_t compareValueByCount)
707 {
708  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
709 
710  LPTMR_Type* const base = g_lptmrBase[instance];
711  status_t statusCode = STATUS_SUCCESS;
712 
713  bool timerEnabled = LPTMR_GetEnable(base);
714  bool compareFlag = LPTMR_GetCompareFlag(base);
715 
716  uint16_t counterVal;
717 
718  /* Check if a valid clock is selected for the timer/glitch filter */
719 #if (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT))
720  bool bypass = LPTMR_GetBypass(base);
721  lptmr_workmode_t workMode = LPTMR_GetWorkMode(base);
722  (void) bypass;
723  (void) workMode;
724 #endif /* (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT)) */
725  DEV_ASSERT((lptmr_GetClkFreq(LPTMR_GetClockSelect(base), instance) != 0u) || \
726  (bypass && (workMode == LPTMR_WORKMODE_PULSECOUNTER)));
727 
728 
729  /* The compare value can only be written if counter is disabled or the compare flag is set. */
730  if (timerEnabled && !compareFlag)
731  {
732  statusCode = STATUS_ERROR;
733  }
734  else
735  {
736  /* Check if new value is below the current counter value */
737  LPTMR_SetCompareValue(base, compareValueByCount);
738  counterVal = LPTMR_GetCounterValue(base);
739  if (counterVal >= compareValueByCount)
740  {
741  statusCode = STATUS_TIMEOUT;
742  }
743  }
744 
745  return statusCode;
746 }
747 
748 
749 /*FUNCTION**********************************************************************
750  *
751  * Function Name : LPTMR_DRV_GetCompareValueByCount
752  * Description : Get the compare value of timer in ticks units.
753  *
754  * Implements : LPTMR_DRV_GetCompareValueByCount_Activity
755  *END**************************************************************************/
756 void LPTMR_DRV_GetCompareValueByCount(const uint32_t instance,
757  uint16_t * const compareValueByCount)
758 {
759  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
760 
761  const LPTMR_Type* const base = g_lptmrBase[instance];
762 
763  *compareValueByCount = LPTMR_GetCompareValue(base);
764 }
765 
766 
767 /*FUNCTION**********************************************************************
768  *
769  * Function Name : LPTMR_DRV_SetCompareValueUs
770  * Description : Set the compare value for Timer Mode in microseconds,
771  * for a LPTMR instance.
772  * Can be used only in Timer Mode.
773  * Possible return values:
774  * - STATUS_SUCCESS: completed successfully
775  * - STATUS_ERROR: cannot reconfigure compare value
776  * - STATUS_TIMEOUT: compare value greater then current counter value
777  *
778  * Implements : LPTMR_DRV_SetCompareValueByUs_Activity
779  *END**************************************************************************/
780 status_t LPTMR_DRV_SetCompareValueByUs(const uint32_t instance,
781  const uint32_t compareValueUs)
782 {
783  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
784 
785  status_t returnCode = STATUS_SUCCESS;
786  LPTMR_Type* const base = g_lptmrBase[instance];
787  bool timerEnabled, compareFlag;
788 
789  lptmr_clocksource_t clkSrc;
790  uint32_t clkFreq;
791  uint16_t cmpValTicks, currentCounterVal;
792  lptmr_prescaler_t prescVal;
793  bool prescBypass, conversionStatus;
794 
795  /* This function can only be used if LPTMR is configured in Timer Mode. */
796  DEV_ASSERT(LPTMR_GetWorkMode(base) == LPTMR_WORKMODE_TIMER);
797 
798  timerEnabled = LPTMR_GetEnable(base);
799  compareFlag = LPTMR_GetCompareFlag(base);
800  /* The compare value can only be written if counter is disabled or the compare flag is set. */
801  if (timerEnabled && !compareFlag)
802  {
803  returnCode = STATUS_ERROR;
804  }
805  else
806  {
807  clkSrc = LPTMR_GetClockSelect(base);
808  clkFreq = lptmr_GetClkFreq(clkSrc, instance);
809  DEV_ASSERT(clkFreq != 0U); /* Check the calculated clock frequency: '0' - invalid*/
810 
811  /* Get prescaler value and prescaler bypass state.*/
812  prescVal = LPTMR_GetPrescaler(base);
813  prescBypass = LPTMR_GetBypass(base);
814  /* Convert new compare value from microseconds to ticks. */
815  conversionStatus = lptmr_Us2Ticks(clkFreq, prescVal, prescBypass, compareValueUs, &cmpValTicks);
816  DEV_ASSERT(conversionStatus == true); /* Check the conversion status: compareValueUs doesn't fit for current prescaller. */
817  (void) conversionStatus;
818 
819  /* Write value and check if written successfully */
820  LPTMR_SetCompareValue(base, cmpValTicks);
821  currentCounterVal = LPTMR_GetCounterValue(base);
822 
823  if (currentCounterVal >= cmpValTicks)
824  {
825  returnCode = STATUS_TIMEOUT;
826  }
827  }
828 
829  return returnCode;
830 }
831 
832 /*FUNCTION**********************************************************************
833  *
834  * Function Name : LPTMR_DRV_GetCompareValueByUs
835  * Description : Get the compare value in microseconds representation.
836  * Can be used only in Timer Mode.
837  *
838  * Implements : LPTMR_DRV_GetCompareValueByUs_Activity
839  *END**************************************************************************/
840 void LPTMR_DRV_GetCompareValueByUs(const uint32_t instance,
841  uint32_t * const compareValueUs)
842 {
843  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
844  DEV_ASSERT(compareValueUs != NULL);
845 
846  const LPTMR_Type* const base = g_lptmrBase[instance];
847  lptmr_clocksource_t clkSrc;
848  uint32_t clkFreq;
849  uint16_t cmpValTicks;
850  lptmr_prescaler_t prescVal;
851  bool prescBypass, conversionStatus;
852 
853  /* This function can only be used if LPTMR is configured in Timer Mode. */
854  DEV_ASSERT(LPTMR_GetWorkMode(base) == LPTMR_WORKMODE_TIMER);
855 
856  clkSrc = LPTMR_GetClockSelect(base);
857  clkFreq = lptmr_GetClkFreq(clkSrc, instance);
858  /* The clock frequency must be valid. */
859  DEV_ASSERT(clkFreq != 0U);
860 
861  /* Get prescaler value and prescaler bypass state.*/
862  prescVal = LPTMR_GetPrescaler(base);
863  prescBypass = LPTMR_GetBypass(base);
864  cmpValTicks = LPTMR_GetCompareValue(base);
865 
866  /* Convert current compare value from ticks to microseconds. */
867  conversionStatus = lptmr_Ticks2Us(clkFreq, prescVal, prescBypass, cmpValTicks, compareValueUs);
868  DEV_ASSERT(conversionStatus == true); /* Check the conversion status. */
869  (void) conversionStatus;
870 }
871 
872 
873 /*FUNCTION**********************************************************************
874  *
875  * Function Name : LPTMR_DRV_GetCompareFlag
876  * Description : Get the current state of the Compare Flag of a LPTMR instance
877  *
878  * Implements : LPTMR_DRV_GetCompareFlag_Activity
879  *END**************************************************************************/
880 bool LPTMR_DRV_GetCompareFlag(const uint32_t instance)
881 {
882  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
883 
884  const LPTMR_Type* const base = g_lptmrBase[instance];
885  bool compareFlag = LPTMR_GetCompareFlag(base);
886 
887  return compareFlag;
888 }
889 
890 
891 /*FUNCTION**********************************************************************
892  *
893  * Function Name : LPTMR_DRV_ClearCompareFlag
894  * Description : Clear the Compare Flag.
895  *
896  * Implements : LPTMR_DRV_ClearCompareFlag_Activity
897  *END**************************************************************************/
898 void LPTMR_DRV_ClearCompareFlag(const uint32_t instance)
899 {
900  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
901 
902  LPTMR_Type* const base = g_lptmrBase[instance];
903 
904  LPTMR_ClearCompareFlag(base);
905 }
906 
907 
908 /*FUNCTION**********************************************************************
909  *
910  * Function Name : LPTMR_DRV_IsRunning
911  * Description : Get the running state of a LPTMR instance.
912  * Possible return values:
913  * - true: Timer/Counter started
914  * - false: Timer/Counter stopped
915  *
916  * Implements : LPTMR_DRV_IsRunning_Activity
917  *END**************************************************************************/
918 bool LPTMR_DRV_IsRunning(const uint32_t instance)
919 {
920  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
921 
922  const LPTMR_Type* const base = g_lptmrBase[instance];
923 
924  bool runningState = LPTMR_GetEnable(base);
925 
926  return runningState;
927 }
928 
929 
930 /*FUNCTION**********************************************************************
931  *
932  * Function Name : LPTMR_DRV_SetInterrupt
933  * Description : Enable/disable the LPTMR interrupt.
934  *
935  * Implements : LPTMR_DRV_SetInterrupt_Activity
936  *END**************************************************************************/
937 void LPTMR_DRV_SetInterrupt(const uint32_t instance,
938  const bool enableInterrupt)
939 {
940  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
941 
942  LPTMR_Type* const base = g_lptmrBase[instance];
943 
944  LPTMR_SetInterrupt(base, enableInterrupt);
945 }
946 
947 
948 /*FUNCTION**********************************************************************
949  *
950  * Function Name : LPTMR_DRV_GetCounterValueTicks
951  * Description : Get the current Counter Value in timer ticks representation.
952  * Return:
953  * - the counter value.
954  *
955  * Implements : LPTMR_DRV_GetCounterValueByCount_Activity
956  *END**************************************************************************/
957 uint16_t LPTMR_DRV_GetCounterValueByCount(const uint32_t instance)
958 {
959  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
960 
961  LPTMR_Type* const base = g_lptmrBase[instance];
962 
963  uint16_t counterVal = LPTMR_GetCounterValue(base);
964 
965  return counterVal;
966 }
967 
968 
969 /*FUNCTION**********************************************************************
970  *
971  * Function Name : LPTMR_DRV_StartCounter
972  * Description : Enable (start) the counter.
973  *
974  * Implements : LPTMR_DRV_StartCounter_Activity
975  *END**************************************************************************/
976 void LPTMR_DRV_StartCounter(const uint32_t instance)
977 {
978  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
979 
980  LPTMR_Type* const base = g_lptmrBase[instance];
981 
982  /* Check if a valid clock is selected for the timer/glitch filter */
983 #if (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT))
984  bool bypass = LPTMR_GetBypass(base);
985  lptmr_workmode_t workMode = LPTMR_GetWorkMode(base);
986  (void) bypass;
987  (void) workMode;
988 #endif /* (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT)) */
989  DEV_ASSERT((lptmr_GetClkFreq(LPTMR_GetClockSelect(base), instance) != 0u) || \
990  (bypass && (workMode == LPTMR_WORKMODE_PULSECOUNTER)));
991 
992  LPTMR_Enable(base);
993 }
994 
995 
996 /*FUNCTION**********************************************************************
997  *
998  * Function Name : LPTMR_DRV_StopCounter
999  * Description : Disable (stop) the counter.
1000  *
1001  * Implements : LPTMR_DRV_StopCounter_Activity
1002  *END**************************************************************************/
1003 void LPTMR_DRV_StopCounter(const uint32_t instance)
1004 {
1005  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
1006 
1007  LPTMR_Type* const base = g_lptmrBase[instance];
1008 
1009  LPTMR_Disable(base);
1010 }
1011 
1012 
1013 /*FUNCTION**********************************************************************
1014  *
1015  * Function Name : LPTMR_DRV_SetPinConfiguration
1016  * Description : Set the Input Pin configuration for Pulse Counter mode.
1017  *
1018  * Implements : LPTMR_DRV_SetPinConfiguration_Activity
1019  *END**************************************************************************/
1020 void LPTMR_DRV_SetPinConfiguration(const uint32_t instance,
1021  const lptmr_pinselect_t pinSelect,
1022  const lptmr_pinpolarity_t pinPolarity)
1023 {
1024  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
1025 
1026  LPTMR_Type* const base = g_lptmrBase[instance];
1027 
1028  LPTMR_SetPinSelect(base, pinSelect);
1029  LPTMR_SetPinPolarity(base, pinPolarity);
1030 }
1031 
1032 /*******************************************************************************
1033  * EOF
1034  ******************************************************************************/
void LPTMR_DRV_InitConfigStruct(lptmr_config_t *const config)
Initialize a configuration structure with default values.
lptmr_workmode_t workMode
Definition: lptmr_driver.h:119
void LPTMR_DRV_Init(const uint32_t instance, const lptmr_config_t *const config, const bool startCounter)
Initialize a LPTMR instance with values from an input configuration structure.
void LPTMR_DRV_SetInterrupt(const uint32_t instance, const bool enableInterrupt)
Enable/disable the LPTMR interrupt.
lptmr_pinpolarity_t pinPolarity
Definition: lptmr_driver.h:128
void LPTMR_DRV_StopCounter(const uint32_t instance)
Disable the LPTMR / Stop the counter.
#define LPTMR_MAX_CMR_NTICKS
Definition: lptmr_driver.c:60
lptmr_clocksource_t clockSelect
Definition: lptmr_driver.h:121
Defines the configuration structure for LPTMR.
Definition: lptmr_driver.h:113
void LPTMR_DRV_ClearCompareFlag(const uint32_t instance)
Clear the Compare Flag of a LPTMR instance.
lptmr_prescaler_t prescaler
Definition: lptmr_driver.h:122
lptmr_clocksource_t
Clock Source selection Implements : lptmr_clocksource_t_Class.
Definition: lptmr_driver.h:90
bool LPTMR_DRV_IsRunning(const uint32_t instance)
Get the run state of a LPTMR instance.
lptmr_workmode_t
Work Mode Implements : lptmr_workmode_t_Class.
Definition: lptmr_driver.h:60
#define LPTMR_CMR_COMPARE_MASK
Definition: S32K118.h:6485
lptmr_counter_units_t counterUnits
Definition: lptmr_driver.h:125
void LPTMR_DRV_GetCompareValueByUs(const uint32_t instance, uint32_t *const compareValueUs)
Get the compare value in microseconds, of a LPTMR instance.
lptmr_counter_units_t
Defines the LPTMR counter units available for configuring or reading the timer compare value...
Definition: lptmr_driver.h:102
lptmr_pinselect_t pinSelect
Definition: lptmr_driver.h:127
#define LPTMR_INSTANCE_COUNT
Definition: S32K118.h:6410
#define DEV_ASSERT(x)
Definition: devassert.h:77
lptmr_prescaler_t
Prescaler Selection Implements : lptmr_prescaler_t_Class.
Definition: lptmr_driver.h:68
uint32_t compareValue
Definition: lptmr_driver.h:124
void LPTMR_DRV_GetCompareValueByCount(const uint32_t instance, uint16_t *const compareValueByCount)
Get the compare value in counter tick units, of a LPTMR instance.
lptmr_pinpolarity_t
Pulse Counter input polarity Implements : lptmr_pinpolarity_t_Class.
Definition: lptmr_driver.h:52
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
void LPTMR_DRV_Deinit(const uint32_t instance)
De-initialize a LPTMR instance.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
uint16_t LPTMR_DRV_GetCounterValueByCount(const uint32_t instance)
Get the current counter value in counter tick units.
void LPTMR_DRV_StartCounter(const uint32_t instance)
Enable the LPTMR / Start the counter.
void LPTMR_DRV_SetConfig(const uint32_t instance, const lptmr_config_t *const config)
Configure a LPTMR instance.
void LPTMR_DRV_GetConfig(const uint32_t instance, lptmr_config_t *const config)
Get the current configuration of a LPTMR instance.
#define LPTMR_MAX_PRESCALER
Definition: lptmr_driver.c:61
lptmr_pinselect_t
Pulse Counter Input selection Implements : lptmr_pinselect_t_Class.
Definition: lptmr_driver.h:40
#define LPTMR_BASE_PTRS
Definition: S32K118.h:6421
clock_names_t
Clock names.
void LPTMR_DRV_SetPinConfiguration(const uint32_t instance, const lptmr_pinselect_t pinSelect, const lptmr_pinpolarity_t pinPolarity)
Set the Input Pin configuration for Pulse Counter mode.
status_t LPTMR_DRV_SetCompareValueByCount(const uint32_t instance, const uint16_t compareValueByCount)
Set the compare value in counter tick units, for a LPTMR instance.
status_t LPTMR_DRV_SetCompareValueByUs(const uint32_t instance, const uint32_t compareValueUs)
Set the compare value for Timer Mode in microseconds, for a LPTMR instance.
bool LPTMR_DRV_GetCompareFlag(const uint32_t instance)
Get the current state of the Compare Flag of a LPTMR instance.