S32 SDK
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_CLOCK;
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 params 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 config 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 32bit 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 params 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 config 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 32bit 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  /* The LPTMR instance cannot be reconfigured, unless it is disabled. */
587  DEV_ASSERT(LPTMR_GetEnable(base) == false);
588 
589  if(configWorkMode == LPTMR_WORKMODE_TIMER)
590  {
591  /* A valid clock must be selected when used in Timer Mode. */
592  uint32_t clkFreq;
593  clkFreq = lptmr_GetClkFreq(config->clockSelect, instance);
594  DEV_ASSERT(clkFreq != 0U); /* Clock frequency equal to '0', signals invalid value. */
595 
596  if(configCounterUnits == LPTMR_COUNTER_UNITS_MICROSECONDS)
597  {
598  bool chooseClkConfigStatus;
599 
600  /* When workmode is set to Timer Mode and compare value is provided in microseconds,
601  * then the input params for prescale value and prescaleBypass are ignored.
602  * The prescaleValue, prescaleBypass and cmpValue in ticks, are calculated to best fit
603  * the input configCmpValue (in us) for the current operating clk frequency. */
604  chooseClkConfigStatus = lptmr_ChooseClkConfig(clkFreq, configCmpValue, &prescVal, &prescBypass, &cmpValueTicks);
605  DEV_ASSERT(chooseClkConfigStatus == true);
606  (void) chooseClkConfigStatus;
607  }
608  else
609  {
610  DEV_ASSERT(configCounterUnits == LPTMR_COUNTER_UNITS_TICKS);
611  DEV_ASSERT(configCmpValue <= LPTMR_CMR_COMPARE_MASK); /* Compare Value in Tick Units must fit in CMR. */
612 
613  cmpValueTicks = (uint16_t)(configCmpValue & LPTMR_CMR_COMPARE_MASK);
614  }
615  }
616  else
617  {
618  /* If configWorkMode is not LPTMR_WORKMODE_TIMER, then it must be LPTMR_WORKMODE_PULSECOUNTER. */
619  DEV_ASSERT(configWorkMode == LPTMR_WORKMODE_PULSECOUNTER);
620 
621  /* Only LPTMR_COUNTER_UNITS_TICKS can be used when LPTMR is configured as Pulse Counter. */
623  /* A valid clock must be selected when glitch filter is enabled (prescaler not bypassed). */
624  DEV_ASSERT((lptmr_GetClkFreq(config->clockSelect, instance) != 0u) || prescBypass);
625  /* Glitch filter does not support LPTMR_PRESCALE_2. */
626  DEV_ASSERT(prescBypass || (prescVal != LPTMR_PRESCALE_2));
627 
628  DEV_ASSERT(configCmpValue <= LPTMR_CMR_COMPARE_MASK); /* Compare Value in Tick Units must fit in CMR. */
629 
630  cmpValueTicks = (uint16_t)(configCmpValue & LPTMR_CMR_COMPARE_MASK);
631  }
632 
633  /* Initialize and write configuration parameters. */
634  LPTMR_Init(base);
635 
636  LPTMR_SetDmaRequest (base, config->dmaRequest);
637  LPTMR_SetInterrupt (base, config->interruptEnable);
638  LPTMR_SetFreeRunning (base, config->freeRun);
639  LPTMR_SetWorkMode (base, configWorkMode);
640  LPTMR_SetPrescaler (base, prescVal);
641  LPTMR_SetBypass (base, prescBypass);
642  LPTMR_SetClockSelect (base, config->clockSelect);
643  LPTMR_SetCompareValue (base, cmpValueTicks);
644  LPTMR_SetPinSelect (base, config->pinSelect);
645  LPTMR_SetPinPolarity (base, config->pinPolarity);
646 }
647 
648 /*FUNCTION**********************************************************************
649  *
650  * Function Name : LPTMR_DRV_GetConfig
651  * Description : Get the current configuration of the LPTMR instance.
652  * Always returns compareValue in LPTMR_COUNTER_UNITS_TICKS.
653  *
654  * Implements : LPTMR_DRV_GetConfig_Activity
655  *END**************************************************************************/
656 void LPTMR_DRV_GetConfig(const uint32_t instance,
657  lptmr_config_t * const config)
658 {
659  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
660  DEV_ASSERT(config != NULL);
661 
662  const LPTMR_Type* const base = g_lptmrBase[instance];
663 
664  /* Read current configuration */
665  config->dmaRequest = LPTMR_GetDmaRequest(base);
666  config->interruptEnable = LPTMR_GetInterruptEnable(base);
667  config->freeRun = LPTMR_GetFreeRunning(base);
668  config->workMode = LPTMR_GetWorkMode(base);
669  config->prescaler = LPTMR_GetPrescaler(base);
670  config->bypassPrescaler = LPTMR_GetBypass(base);
671  config->clockSelect = LPTMR_GetClockSelect(base);
672  config->compareValue = LPTMR_GetCompareValue(base);
674  config->pinSelect = LPTMR_GetPinSelect(base);
675  config->pinPolarity = LPTMR_GetPinPolarity(base);
676 }
677 
678 
679 /*FUNCTION**********************************************************************
680  *
681  * Function Name : LPTMR_DRV_Deinit
682  * Description : De-initialize the LPTMR (stop the counter and reset config values to default).
683  *
684  * Implements : LPTMR_DRV_Deinit_Activity
685  *END**************************************************************************/
686 void LPTMR_DRV_Deinit(const uint32_t instance)
687 {
688  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
689 
690  LPTMR_Type* const base = g_lptmrBase[instance];
691  LPTMR_Disable(base);
692 
693  LPTMR_Init(base);
694 }
695 
696 
697 /*FUNCTION**********************************************************************
698  *
699  * Function Name : LPTMR_DRV_SetCompareValueByCount
700  * Description : Set the compare value in counter tick units, for a LPTMR instance.
701  * Possible return values:
702  * - STATUS_SUCCESS: completed successfully
703  * - STATUS_ERROR: cannot reconfigure compare value (TCF not set)
704  * - STATUS_TIMEOUT: compare value greater then current counter value
705  *
706  * Implements : LPTMR_DRV_SetCompareValueByCount_Activity
707  *END**************************************************************************/
708 status_t LPTMR_DRV_SetCompareValueByCount(const uint32_t instance,
709  const uint16_t compareValueByCount)
710 {
711  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
712 
713  LPTMR_Type* const base = g_lptmrBase[instance];
714  status_t statusCode = STATUS_SUCCESS;
715 
716  bool timerEnabled = LPTMR_GetEnable(base);
717  bool compareFlag = LPTMR_GetCompareFlag(base);
718 
719  uint16_t counterVal;
720 
721  /* Check if a valid clock is selected for the timer/glitch filter */
722 #if (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT))
723  bool bypass = LPTMR_GetBypass(base);
724  lptmr_workmode_t workMode = LPTMR_GetWorkMode(base);
725  (void) bypass;
726  (void) workMode;
727 #endif /* (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT)) */
728  DEV_ASSERT((lptmr_GetClkFreq(LPTMR_GetClockSelect(base), instance) != 0u) || \
729  (bypass && (workMode == LPTMR_WORKMODE_PULSECOUNTER)));
730 
731 
732  /* The compare value can only be written if counter is disabled or the compare flag is set. */
733  if (timerEnabled && !compareFlag)
734  {
735  statusCode = STATUS_ERROR;
736  }
737  else
738  {
739  /* Check if new value is below the current counter value */
740  LPTMR_SetCompareValue(base, compareValueByCount);
741  counterVal = LPTMR_GetCounterValue(base);
742  if (counterVal >= compareValueByCount)
743  {
744  statusCode = STATUS_TIMEOUT;
745  }
746  }
747 
748  return statusCode;
749 }
750 
751 
752 /*FUNCTION**********************************************************************
753  *
754  * Function Name : LPTMR_DRV_GetCompareValueByCount
755  * Description : Get the compare value in timer ticks units.
756  *
757  * Implements : LPTMR_DRV_GetCompareValueByCount_Activity
758  *END**************************************************************************/
759 void LPTMR_DRV_GetCompareValueByCount(const uint32_t instance,
760  uint16_t * const compareValueByCount)
761 {
762  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
763 
764  const LPTMR_Type* const base = g_lptmrBase[instance];
765 
766  *compareValueByCount = LPTMR_GetCompareValue(base);
767 }
768 
769 
770 /*FUNCTION**********************************************************************
771  *
772  * Function Name : LPTMR_DRV_SetCompareValueUs
773  * Description : Set the compare value for Timer Mode in microseconds,
774  * for a LPTMR instance.
775  * Can be used only in Timer Mode.
776  * Possible return values:
777  * - STATUS_SUCCESS: completed successfully
778  * - STATUS_ERROR: cannot reconfigure compare value
779  * - STATUS_TIMEOUT: compare value greater then current counter value
780  *
781  * Implements : LPTMR_DRV_SetCompareValueByUs_Activity
782  *END**************************************************************************/
783 status_t LPTMR_DRV_SetCompareValueByUs(const uint32_t instance,
784  const uint32_t compareValueUs)
785 {
786  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
787 
788  status_t returnCode = STATUS_SUCCESS;
789  LPTMR_Type* const base = g_lptmrBase[instance];
790  bool timerEnabled, compareFlag;
791 
792  lptmr_clocksource_t clkSrc;
793  uint32_t clkFreq;
794  uint16_t cmpValTicks, currentCounterVal;
795  lptmr_prescaler_t prescVal;
796  bool prescBypass, conversionStatus;
797 
798  /* This function can only be used if LPTMR is configured in Timer Mode. */
799  DEV_ASSERT(LPTMR_GetWorkMode(base) == LPTMR_WORKMODE_TIMER);
800 
801  timerEnabled = LPTMR_GetEnable(base);
802  compareFlag = LPTMR_GetCompareFlag(base);
803  /* The compare value can only be written if counter is disabled or the compare flag is set. */
804  if (timerEnabled && !compareFlag)
805  {
806  returnCode = STATUS_ERROR;
807  }
808  else
809  {
810  clkSrc = LPTMR_GetClockSelect(base);
811  clkFreq = lptmr_GetClkFreq(clkSrc, instance);
812  DEV_ASSERT(clkFreq != 0U); /* Check the calculated clock frequency: '0' - invalid*/
813 
814  /* Get prescaler value and prescaler bypass state.*/
815  prescVal = LPTMR_GetPrescaler(base);
816  prescBypass = LPTMR_GetBypass(base);
817  /* Convert new compare value from microseconds to ticks. */
818  conversionStatus = lptmr_Us2Ticks(clkFreq, prescVal, prescBypass, compareValueUs, &cmpValTicks);
819  DEV_ASSERT(conversionStatus == true); /* Check the conversion status: compareValueUs doesn't fit for current prescaller. */
820  (void) conversionStatus;
821 
822  /* Write value and check if written successfully */
823  LPTMR_SetCompareValue(base, cmpValTicks);
824  currentCounterVal = LPTMR_GetCounterValue(base);
825 
826  if (currentCounterVal >= cmpValTicks)
827  {
828  returnCode = STATUS_TIMEOUT;
829  }
830  }
831 
832  return returnCode;
833 }
834 
835 /*FUNCTION**********************************************************************
836  *
837  * Function Name : LPTMR_DRV_GetCompareValueByUs
838  * Description : Get the compare value in microseconds representation.
839  * Can be used only in Timer Mode.
840  *
841  * Implements : LPTMR_DRV_GetCompareValueByUs_Activity
842  *END**************************************************************************/
843 void LPTMR_DRV_GetCompareValueByUs(const uint32_t instance,
844  uint32_t * const compareValueUs)
845 {
846  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
847  DEV_ASSERT(compareValueUs != NULL);
848 
849  const LPTMR_Type* const base = g_lptmrBase[instance];
850  lptmr_clocksource_t clkSrc;
851  uint32_t clkFreq;
852  uint16_t cmpValTicks;
853  lptmr_prescaler_t prescVal;
854  bool prescBypass, conversionStatus;
855 
856  /* This function can only be used if LPTMR is configured in Timer Mode. */
857  DEV_ASSERT(LPTMR_GetWorkMode(base) == LPTMR_WORKMODE_TIMER);
858 
859  clkSrc = LPTMR_GetClockSelect(base);
860  clkFreq = lptmr_GetClkFreq(clkSrc, instance);
861  /* The clock frequency must be valid. */
862  DEV_ASSERT(clkFreq != 0U);
863 
864  /* Get prescaler value and prescaler bypass state.*/
865  prescVal = LPTMR_GetPrescaler(base);
866  prescBypass = LPTMR_GetBypass(base);
867  cmpValTicks = LPTMR_GetCompareValue(base);
868 
869  /* Convert current compare value from ticks to microseconds. */
870  conversionStatus = lptmr_Ticks2Us(clkFreq, prescVal, prescBypass, cmpValTicks, compareValueUs);
871  DEV_ASSERT(conversionStatus == true); /* Check the conversion status. */
872  (void) conversionStatus;
873 }
874 
875 
876 /*FUNCTION**********************************************************************
877  *
878  * Function Name : LPTMR_DRV_GetCompareFlag
879  * Description : Get the current state of the Compare Flag of a LPTMR instance
880  *
881  * Implements : LPTMR_DRV_GetCompareFlag_Activity
882  *END**************************************************************************/
883 bool LPTMR_DRV_GetCompareFlag(const uint32_t instance)
884 {
885  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
886 
887  const LPTMR_Type* const base = g_lptmrBase[instance];
888  bool compareFlag = LPTMR_GetCompareFlag(base);
889 
890  return compareFlag;
891 }
892 
893 
894 /*FUNCTION**********************************************************************
895  *
896  * Function Name : LPTMR_DRV_ClearCompareFlag
897  * Description : Clear the Compare Flag.
898  *
899  * Implements : LPTMR_DRV_ClearCompareFlag_Activity
900  *END**************************************************************************/
901 void LPTMR_DRV_ClearCompareFlag(const uint32_t instance)
902 {
903  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
904 
905  LPTMR_Type* const base = g_lptmrBase[instance];
906 
907  LPTMR_ClearCompareFlag(base);
908 }
909 
910 
911 /*FUNCTION**********************************************************************
912  *
913  * Function Name : LPTMR_DRV_IsRunning
914  * Description : Get the running state of a LPTMR instance.
915  * Possible return values:
916  * - true: Timer/Counter started
917  * - false: Timer/Counter stopped
918  *
919  * Implements : LPTMR_DRV_IsRunning_Activity
920  *END**************************************************************************/
921 bool LPTMR_DRV_IsRunning(const uint32_t instance)
922 {
923  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
924 
925  const LPTMR_Type* const base = g_lptmrBase[instance];
926 
927  bool runningState = LPTMR_GetEnable(base);
928 
929  return runningState;
930 }
931 
932 
933 /*FUNCTION**********************************************************************
934  *
935  * Function Name : LPTMR_DRV_SetInterrupt
936  * Description : Enable/disable the LPTMR interrupt.
937  *
938  * Implements : LPTMR_DRV_SetInterrupt_Activity
939  *END**************************************************************************/
940 void LPTMR_DRV_SetInterrupt(const uint32_t instance,
941  const bool enableInterrupt)
942 {
943  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
944 
945  LPTMR_Type* const base = g_lptmrBase[instance];
946 
947  /* The interrupt enable flag can only be changed, if the LPTMR instance is disabled. */
948  DEV_ASSERT(LPTMR_GetEnable(base) == false);
949 
950  LPTMR_SetInterrupt(base, enableInterrupt);
951 }
952 
953 
954 /*FUNCTION**********************************************************************
955  *
956  * Function Name : LPTMR_DRV_GetCounterValueTicks
957  * Description : Get the current Counter Value in timer ticks representation.
958  * Return:
959  * - the counter value.
960  *
961  * Implements : LPTMR_DRV_GetCounterValueByCount_Activity
962  *END**************************************************************************/
963 uint16_t LPTMR_DRV_GetCounterValueByCount(const uint32_t instance)
964 {
965  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
966 
967  LPTMR_Type* const base = g_lptmrBase[instance];
968 
969  uint16_t counterVal = LPTMR_GetCounterValue(base);
970 
971  return counterVal;
972 }
973 
974 
975 /*FUNCTION**********************************************************************
976  *
977  * Function Name : LPTMR_DRV_StartCounter
978  * Description : Enable (start) the counter.
979  *
980  * Implements : LPTMR_DRV_StartCounter_Activity
981  *END**************************************************************************/
982 void LPTMR_DRV_StartCounter(const uint32_t instance)
983 {
984  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
985 
986  LPTMR_Type* const base = g_lptmrBase[instance];
987 
988  /* Check if a valid clock is selected for the timer/glitch filter */
989 #if (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT))
990  bool bypass = LPTMR_GetBypass(base);
991  lptmr_workmode_t workMode = LPTMR_GetWorkMode(base);
992  (void) bypass;
993  (void) workMode;
994 #endif /* (defined (DEV_ERROR_DETECT) || defined (CUSTOM_DEVASSERT)) */
995  DEV_ASSERT((lptmr_GetClkFreq(LPTMR_GetClockSelect(base), instance) != 0u) || \
996  (bypass && (workMode == LPTMR_WORKMODE_PULSECOUNTER)));
997 
998  LPTMR_Enable(base);
999 }
1000 
1001 
1002 /*FUNCTION**********************************************************************
1003  *
1004  * Function Name : LPTMR_DRV_StopCounter
1005  * Description : Disable (stop) the counter.
1006  *
1007  * Implements : LPTMR_DRV_StopCounter_Activity
1008  *END**************************************************************************/
1009 void LPTMR_DRV_StopCounter(const uint32_t instance)
1010 {
1011  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
1012 
1013  LPTMR_Type* const base = g_lptmrBase[instance];
1014 
1015  LPTMR_Disable(base);
1016 }
1017 
1018 
1019 /*FUNCTION**********************************************************************
1020  *
1021  * Function Name : LPTMR_DRV_SetPinConfiguration
1022  * Description : Set the Input Pin configuration for Pulse Counter mode.
1023  *
1024  * Implements : LPTMR_DRV_SetPinConfiguration_Activity
1025  *END**************************************************************************/
1026 void LPTMR_DRV_SetPinConfiguration(const uint32_t instance,
1027  const lptmr_pinselect_t pinSelect,
1028  const lptmr_pinpolarity_t pinPolarity)
1029 {
1030  DEV_ASSERT(instance < LPTMR_INSTANCE_COUNT);
1031 
1032  LPTMR_Type* const base = g_lptmrBase[instance];
1033 
1034  LPTMR_SetPinSelect(base, pinSelect);
1035  LPTMR_SetPinPolarity(base, pinPolarity);
1036 }
1037 
1038 /*******************************************************************************
1039  * EOF
1040  ******************************************************************************/
void LPTMR_DRV_InitConfigStruct(lptmr_config_t *const config)
Initialize a configuration structure with default values.
lptmr_workmode_t workMode
Definition: lptmr_driver.h:117
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:126
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:119
Defines the configuration structure for LPTMR.
Definition: lptmr_driver.h:111
void LPTMR_DRV_ClearCompareFlag(const uint32_t instance)
Clear the Compare Flag of a LPTMR instance.
lptmr_prescaler_t prescaler
Definition: lptmr_driver.h:120
lptmr_clocksource_t
Clock Source selection Implements : lptmr_clocksource_t_Class.
Definition: lptmr_driver.h:88
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:58
#define LPTMR_CMR_COMPARE_MASK
Definition: S32K142.h:6566
lptmr_counter_units_t counterUnits
Definition: lptmr_driver.h:123
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:100
lptmr_pinselect_t pinSelect
Definition: lptmr_driver.h:125
#define LPTMR_INSTANCE_COUNT
Definition: S32K142.h:6491
#define DEV_ASSERT(x)
Definition: devassert.h:77
lptmr_prescaler_t
Prescaler Selection Implements : lptmr_prescaler_t_Class.
Definition: lptmr_driver.h:66
uint32_t compareValue
Definition: lptmr_driver.h:122
void LPTMR_DRV_GetCompareValueByCount(const uint32_t instance, uint16_t *const compareValueByCount)
Get the compare value in counter tick units, of a LPTMR instance.
clock_names_t
Clock names.
lptmr_pinpolarity_t
Pulse Counter input polarity Implements : lptmr_pinpolarity_t_Class.
Definition: lptmr_driver.h:50
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.
#define SIM_LPO_1K_CLOCK
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: S32K142.h:6502
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.