1239 lines
45 KiB
C
1239 lines
45 KiB
C
/***************************************************************************//**
|
|
* @file
|
|
* @brief Timer/counter (TIMER) peripheral API
|
|
*******************************************************************************
|
|
* # License
|
|
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
|
|
*******************************************************************************
|
|
*
|
|
* SPDX-License-Identifier: Zlib
|
|
*
|
|
* The licensor of this software is Silicon Laboratories Inc.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty. In no event will the authors be held liable for any damages
|
|
* arising from the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software
|
|
* in a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifndef EM_TIMER_H
|
|
#define EM_TIMER_H
|
|
|
|
#include "em_device.h"
|
|
#if defined(TIMER_COUNT) && (TIMER_COUNT > 0)
|
|
|
|
#include <stdbool.h>
|
|
#include "sl_assert.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/***************************************************************************//**
|
|
* @addtogroup timer
|
|
* @{
|
|
******************************************************************************
|
|
* @deprecated
|
|
* Deprecated macro TIMER_CH_VALID for SDID 80, new code should use TIMER_REF_CH_VALID.*/
|
|
|
|
/*******************************************************************************
|
|
******************************* DEFINES ***********************************
|
|
******************************************************************************/
|
|
|
|
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
|
|
|
/** Validation of TIMER register block pointer reference for assert statements. */
|
|
#define TIMER_REF_VALID(ref) TIMER_Valid(ref)
|
|
|
|
/** Validation of TIMER compare/capture channel number. */
|
|
#if defined(_SILICON_LABS_32B_SERIES_0)
|
|
#define TIMER_CH_VALID(ch) ((ch) < 3)
|
|
#elif defined(_SILICON_LABS_32B_SERIES_1)
|
|
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
|
|
#define TIMER_CH_VALID(ch) _Pragma("GCC warning \"'TIMER_CH_VALID' macro is deprecated for EFR32xG1, Use TIMER_REF_CH_VALID instead\"") ((ch) < 4)
|
|
#else
|
|
#define TIMER_CH_VALID(ch) ((ch) < 4)
|
|
#endif
|
|
#else
|
|
#define TIMER_CH_VALID(ch) ((ch) < 3)
|
|
#endif
|
|
|
|
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
|
|
#define TIMER_REF_CH_VALID(ref, ch) ((ref == TIMER0) ? ((ch) < 3) : ((ch) < 4))
|
|
#define TIMER_REF_CH_VALIDATE(ref, ch) TIMER_REF_CH_VALID(ref, ch)
|
|
#else
|
|
#define TIMER_REF_CH_VALIDATE(ref, ch) TIMER_CH_VALID(ch)
|
|
#endif
|
|
|
|
/** @endcond */
|
|
|
|
/*******************************************************************************
|
|
******************************** ENUMS ************************************
|
|
******************************************************************************/
|
|
|
|
/** Timer compare/capture mode. */
|
|
typedef enum {
|
|
#if defined (_TIMER_CC_CTRL_MODE_MASK)
|
|
timerCCModeOff = _TIMER_CC_CTRL_MODE_OFF, /**< Channel turned off. */
|
|
timerCCModeCapture = _TIMER_CC_CTRL_MODE_INPUTCAPTURE, /**< Input capture. */
|
|
timerCCModeCompare = _TIMER_CC_CTRL_MODE_OUTPUTCOMPARE, /**< Output compare. */
|
|
timerCCModePWM = _TIMER_CC_CTRL_MODE_PWM /**< Pulse-Width modulation. */
|
|
#endif
|
|
#if defined (_TIMER_CC_CFG_MODE_MASK)
|
|
timerCCModeOff = _TIMER_CC_CFG_MODE_OFF, /**< Channel turned off. */
|
|
timerCCModeCapture = _TIMER_CC_CFG_MODE_INPUTCAPTURE, /**< Input capture. */
|
|
timerCCModeCompare = _TIMER_CC_CFG_MODE_OUTPUTCOMPARE, /**< Output compare. */
|
|
timerCCModePWM = _TIMER_CC_CFG_MODE_PWM /**< Pulse-Width modulation. */
|
|
#endif
|
|
} TIMER_CCMode_TypeDef;
|
|
|
|
/** Clock select. */
|
|
typedef enum {
|
|
#if defined (_TIMER_CTRL_CLKSEL_MASK)
|
|
timerClkSelHFPerClk = _TIMER_CTRL_CLKSEL_PRESCHFPERCLK, /**< Prescaled HFPER / HFPERB clock. */
|
|
timerClkSelCC1 = _TIMER_CTRL_CLKSEL_CC1, /**< Compare/Capture Channel 1 Input. */
|
|
timerClkSelCascade = _TIMER_CTRL_CLKSEL_TIMEROUF /**< Cascaded clocked by underflow or overflow by lower numbered timer. */
|
|
#endif
|
|
#if defined (_TIMER_CFG_CLKSEL_MASK)
|
|
timerClkSelHFPerClk = _TIMER_CFG_CLKSEL_PRESCEM01GRPACLK, /**< Prescaled EM01GRPA clock. */
|
|
timerClkSelCC1 = _TIMER_CFG_CLKSEL_CC1, /**< Compare/Capture Channel 1 Input. */
|
|
timerClkSelCascade = _TIMER_CFG_CLKSEL_TIMEROUF /**< Cascaded clocked by underflow or overflow by lower numbered timer. */
|
|
#endif
|
|
} TIMER_ClkSel_TypeDef;
|
|
|
|
/** Input capture edge select. */
|
|
typedef enum {
|
|
/** Rising edges detected. */
|
|
timerEdgeRising = _TIMER_CC_CTRL_ICEDGE_RISING,
|
|
|
|
/** Falling edges detected. */
|
|
timerEdgeFalling = _TIMER_CC_CTRL_ICEDGE_FALLING,
|
|
|
|
/** Both edges detected. */
|
|
timerEdgeBoth = _TIMER_CC_CTRL_ICEDGE_BOTH,
|
|
|
|
/** No edge detection, leave signal as is. */
|
|
timerEdgeNone = _TIMER_CC_CTRL_ICEDGE_NONE
|
|
} TIMER_Edge_TypeDef;
|
|
|
|
/** Input capture event control. */
|
|
typedef enum {
|
|
/** PRS output pulse, interrupt flag, and DMA request set on every capture. */
|
|
timerEventEveryEdge = _TIMER_CC_CTRL_ICEVCTRL_EVERYEDGE,
|
|
/** PRS output pulse, interrupt flag, and DMA request set on every second capture. */
|
|
timerEventEvery2ndEdge = _TIMER_CC_CTRL_ICEVCTRL_EVERYSECONDEDGE,
|
|
/**
|
|
* PRS output pulse, interrupt flag, and DMA request set on rising edge (if
|
|
* input capture edge = BOTH).
|
|
*/
|
|
timerEventRising = _TIMER_CC_CTRL_ICEVCTRL_RISING,
|
|
/**
|
|
* PRS output pulse, interrupt flag, and DMA request set on falling edge (if
|
|
* input capture edge = BOTH).
|
|
*/
|
|
timerEventFalling = _TIMER_CC_CTRL_ICEVCTRL_FALLING
|
|
} TIMER_Event_TypeDef;
|
|
|
|
/** Input edge action. */
|
|
typedef enum {
|
|
/** No action taken. */
|
|
timerInputActionNone = _TIMER_CTRL_FALLA_NONE,
|
|
|
|
/** Start counter without reload. */
|
|
timerInputActionStart = _TIMER_CTRL_FALLA_START,
|
|
|
|
/** Stop counter without reload. */
|
|
timerInputActionStop = _TIMER_CTRL_FALLA_STOP,
|
|
|
|
/** Reload and start counter. */
|
|
timerInputActionReloadStart = _TIMER_CTRL_FALLA_RELOADSTART
|
|
} TIMER_InputAction_TypeDef;
|
|
|
|
/** Timer mode. */
|
|
typedef enum {
|
|
#if defined (_TIMER_CTRL_MODE_MASK)
|
|
timerModeUp = _TIMER_CTRL_MODE_UP, /**< Up-counting. */
|
|
timerModeDown = _TIMER_CTRL_MODE_DOWN, /**< Down-counting. */
|
|
timerModeUpDown = _TIMER_CTRL_MODE_UPDOWN, /**< Up/down-counting. */
|
|
timerModeQDec = _TIMER_CTRL_MODE_QDEC /**< Quadrature decoder. */
|
|
#endif
|
|
#if defined (_TIMER_CFG_MODE_MASK)
|
|
timerModeUp = _TIMER_CFG_MODE_UP, /**< Up-counting. */
|
|
timerModeDown = _TIMER_CFG_MODE_DOWN, /**< Down-counting. */
|
|
timerModeUpDown = _TIMER_CFG_MODE_UPDOWN, /**< Up/down-counting. */
|
|
timerModeQDec = _TIMER_CFG_MODE_QDEC /**< Quadrature decoder. */
|
|
#endif
|
|
} TIMER_Mode_TypeDef;
|
|
|
|
/** Compare/capture output action. */
|
|
typedef enum {
|
|
/** No action. */
|
|
timerOutputActionNone = _TIMER_CC_CTRL_CUFOA_NONE,
|
|
|
|
/** Toggle on event. */
|
|
timerOutputActionToggle = _TIMER_CC_CTRL_CUFOA_TOGGLE,
|
|
|
|
/** Clear on event. */
|
|
timerOutputActionClear = _TIMER_CC_CTRL_CUFOA_CLEAR,
|
|
|
|
/** Set on event. */
|
|
timerOutputActionSet = _TIMER_CC_CTRL_CUFOA_SET
|
|
} TIMER_OutputAction_TypeDef;
|
|
|
|
/** Prescaler. */
|
|
typedef enum {
|
|
#if defined (_TIMER_CTRL_PRESC_MASK)
|
|
timerPrescale1 = _TIMER_CTRL_PRESC_DIV1, /**< Divide by 1. */
|
|
timerPrescale2 = _TIMER_CTRL_PRESC_DIV2, /**< Divide by 2. */
|
|
timerPrescale4 = _TIMER_CTRL_PRESC_DIV4, /**< Divide by 4. */
|
|
timerPrescale8 = _TIMER_CTRL_PRESC_DIV8, /**< Divide by 8. */
|
|
timerPrescale16 = _TIMER_CTRL_PRESC_DIV16, /**< Divide by 16. */
|
|
timerPrescale32 = _TIMER_CTRL_PRESC_DIV32, /**< Divide by 32. */
|
|
timerPrescale64 = _TIMER_CTRL_PRESC_DIV64, /**< Divide by 64. */
|
|
timerPrescale128 = _TIMER_CTRL_PRESC_DIV128, /**< Divide by 128. */
|
|
timerPrescale256 = _TIMER_CTRL_PRESC_DIV256, /**< Divide by 256. */
|
|
timerPrescale512 = _TIMER_CTRL_PRESC_DIV512, /**< Divide by 512. */
|
|
timerPrescale1024 = _TIMER_CTRL_PRESC_DIV1024 /**< Divide by 1024. */
|
|
#endif
|
|
#if defined (_TIMER_CFG_PRESC_MASK)
|
|
timerPrescale1 = _TIMER_CFG_PRESC_DIV1, /**< Divide by 1. */
|
|
timerPrescale2 = _TIMER_CFG_PRESC_DIV2, /**< Divide by 2. */
|
|
timerPrescale4 = _TIMER_CFG_PRESC_DIV4, /**< Divide by 4. */
|
|
timerPrescale8 = _TIMER_CFG_PRESC_DIV8, /**< Divide by 8. */
|
|
timerPrescale16 = _TIMER_CFG_PRESC_DIV16, /**< Divide by 16. */
|
|
timerPrescale32 = _TIMER_CFG_PRESC_DIV32, /**< Divide by 32. */
|
|
timerPrescale64 = _TIMER_CFG_PRESC_DIV64, /**< Divide by 64. */
|
|
timerPrescale128 = _TIMER_CFG_PRESC_DIV128, /**< Divide by 128. */
|
|
timerPrescale256 = _TIMER_CFG_PRESC_DIV256, /**< Divide by 256. */
|
|
timerPrescale512 = _TIMER_CFG_PRESC_DIV512, /**< Divide by 512. */
|
|
timerPrescale1024 = _TIMER_CFG_PRESC_DIV1024 /**< Divide by 1024. */
|
|
#endif
|
|
} TIMER_Prescale_TypeDef;
|
|
|
|
/** Peripheral Reflex System signal. */
|
|
typedef uint8_t TIMER_PRSSEL_TypeDef;
|
|
|
|
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
|
/** Deprecated PRS channel selector. New code should use an integer instead of
|
|
* using these deprecated enum values. */
|
|
#define timerPRSSELCh0 0UL
|
|
#define timerPRSSELCh1 1UL
|
|
#define timerPRSSELCh2 2UL
|
|
#define timerPRSSELCh3 3UL
|
|
#define timerPRSSELCh4 4UL
|
|
#define timerPRSSELCh5 5UL
|
|
#define timerPRSSELCh6 6UL
|
|
#define timerPRSSELCh7 7UL
|
|
#define timerPRSSELCh8 8UL
|
|
#define timerPRSSELCh9 9UL
|
|
#define timerPRSSELCh10 10UL
|
|
#define timerPRSSELCh11 11UL
|
|
/** @endcond */
|
|
|
|
#if defined (_TIMER_CC_CFG_INSEL_MASK)
|
|
/** PRS input type */
|
|
typedef enum {
|
|
timerPrsInputNone = 0x0, /**< No PRS input. */
|
|
timerPrsInputSync = _TIMER_CC_CFG_INSEL_PRSSYNC, /**< Synchronous PRS selected. */
|
|
timerPrsInputAsyncLevel = _TIMER_CC_CFG_INSEL_PRSASYNCLEVEL, /**< Asynchronous level PRS selected. */
|
|
timerPrsInputAsyncPulse = _TIMER_CC_CFG_INSEL_PRSASYNCPULSE, /**< Asynchronous pulse PRS selected. */
|
|
} TIMER_PrsInput_TypeDef;
|
|
#endif
|
|
|
|
#if defined(_TIMER_DTFC_DTFA_MASK) || defined(_TIMER_DTFCFG_DTFA_MASK)
|
|
/** DT (Dead Time) Fault Actions. */
|
|
typedef enum {
|
|
#if defined(_TIMER_DTFC_DTFA_MASK)
|
|
timerDtiFaultActionNone = _TIMER_DTFC_DTFA_NONE, /**< No action on fault. */
|
|
timerDtiFaultActionInactive = _TIMER_DTFC_DTFA_INACTIVE, /**< Set outputs inactive. */
|
|
timerDtiFaultActionClear = _TIMER_DTFC_DTFA_CLEAR, /**< Clear outputs. */
|
|
timerDtiFaultActionTristate = _TIMER_DTFC_DTFA_TRISTATE /**< Tristate outputs. */
|
|
#endif
|
|
#if defined(_TIMER_DTFCFG_DTFA_MASK)
|
|
timerDtiFaultActionNone = _TIMER_DTFCFG_DTFA_NONE, /**< No action on fault. */
|
|
timerDtiFaultActionInactive = _TIMER_DTFCFG_DTFA_INACTIVE, /**< Set outputs inactive. */
|
|
timerDtiFaultActionClear = _TIMER_DTFCFG_DTFA_CLEAR, /**< Clear outputs. */
|
|
timerDtiFaultActionTristate = _TIMER_DTFCFG_DTFA_TRISTATE /**< Tristate outputs. */
|
|
#endif
|
|
} TIMER_DtiFaultAction_TypeDef;
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
******************************* STRUCTS ***********************************
|
|
******************************************************************************/
|
|
|
|
/** TIMER initialization structure. */
|
|
typedef struct {
|
|
/** Start counting when initialization completed. */
|
|
bool enable;
|
|
|
|
/** Counter shall keep running during debug halt. */
|
|
bool debugRun;
|
|
|
|
/** Prescaling factor, if HFPER / HFPERB clock used. */
|
|
TIMER_Prescale_TypeDef prescale;
|
|
|
|
/** Clock selection. */
|
|
TIMER_ClkSel_TypeDef clkSel;
|
|
|
|
#if defined(TIMER_CTRL_X2CNT) && (defined(TIMER_CTRL_ATI) || defined(TIMER_CFG_ATI)) \
|
|
&& (defined(TIMER_CTRL_RSSCOIST) || defined(TIMER_CFG_RSSCOIST))
|
|
/** 2x Count mode, counter increments/decrements by 2, meant for PWM mode. */
|
|
bool count2x;
|
|
|
|
/** ATI (Always Track Inputs) makes CCPOL always track
|
|
* the polarity of the inputs. */
|
|
bool ati;
|
|
|
|
/** Reload-Start Sets COIST
|
|
* When enabled, compare output is set to COIST value on a Reload-Start event. */
|
|
bool rssCoist;
|
|
#endif
|
|
|
|
/** Action on falling input edge. */
|
|
TIMER_InputAction_TypeDef fallAction;
|
|
|
|
/** Action on rising input edge. */
|
|
TIMER_InputAction_TypeDef riseAction;
|
|
|
|
/** Counting mode. */
|
|
TIMER_Mode_TypeDef mode;
|
|
|
|
/** DMA request clear on active. */
|
|
bool dmaClrAct;
|
|
|
|
/** Select X2 or X4 quadrature decode mode (if used). */
|
|
bool quadModeX4;
|
|
|
|
/** Determines if only counting up or down once. */
|
|
bool oneShot;
|
|
|
|
/** Timer can be start/stop/reload by other timers. */
|
|
bool sync;
|
|
|
|
#if defined(TIMER_CTRL_DISSYNCOUT) || defined(TIMER_CFG_DISSYNCOUT)
|
|
/** Disable ability of timer to start/stop/reload other timers that have their SYNC bit set. */
|
|
bool disSyncOut;
|
|
#endif
|
|
} TIMER_Init_TypeDef;
|
|
|
|
/** Default configuration for TIMER initialization structure. */
|
|
#if defined(TIMER_CTRL_X2CNT) && (defined(TIMER_CTRL_ATI) || defined(TIMER_CFG_ATI)) \
|
|
&& (defined(TIMER_CTRL_RSSCOIST) || defined(TIMER_CFG_RSSCOIST))
|
|
#if (defined(TIMER_CTRL_DISSYNCOUT) || defined(TIMER_CFG_DISSYNCOUT))
|
|
#define TIMER_INIT_DEFAULT \
|
|
{ \
|
|
true, /* Enable timer when initialization completes. */ \
|
|
false, /* Stop counter during debug halt. */ \
|
|
timerPrescale1, /* No prescaling. */ \
|
|
timerClkSelHFPerClk, /* Select HFPER / HFPERB clock. */ \
|
|
false, /* Not 2x count mode. */ \
|
|
false, /* No ATI. */ \
|
|
false, /* No RSSCOIST. */ \
|
|
timerInputActionNone, /* No action on falling input edge. */ \
|
|
timerInputActionNone, /* No action on rising input edge. */ \
|
|
timerModeUp, /* Up-counting. */ \
|
|
false, /* Do not clear DMA requests when DMA channel is active. */ \
|
|
false, /* Select X2 quadrature decode mode (if used). */ \
|
|
false, /* Disable one shot. */ \
|
|
false, /* Not started/stopped/reloaded by other timers. */ \
|
|
false /* Disable ability to start/stop/reload other timers. */ \
|
|
}
|
|
#else
|
|
#define TIMER_INIT_DEFAULT \
|
|
{ \
|
|
true, /* Enable timer when initialization completes. */ \
|
|
false, /* Stop counter during debug halt. */ \
|
|
timerPrescale1, /* No prescaling. */ \
|
|
timerClkSelHFPerClk, /* Select HFPER / HFPERB clock. */ \
|
|
false, /* Not 2x count mode. */ \
|
|
false, /* No ATI. */ \
|
|
false, /* No RSSCOIST. */ \
|
|
timerInputActionNone, /* No action on falling input edge. */ \
|
|
timerInputActionNone, /* No action on rising input edge. */ \
|
|
timerModeUp, /* Up-counting. */ \
|
|
false, /* Do not clear DMA requests when DMA channel is active. */ \
|
|
false, /* Select X2 quadrature decode mode (if used). */ \
|
|
false, /* Disable one shot. */ \
|
|
false /* Not started/stopped/reloaded by other timers. */ \
|
|
}
|
|
#endif
|
|
#else
|
|
#define TIMER_INIT_DEFAULT \
|
|
{ \
|
|
true, /* Enable timer when initialization completes. */ \
|
|
false, /* Stop counter during debug halt. */ \
|
|
timerPrescale1, /* No prescaling. */ \
|
|
timerClkSelHFPerClk, /* Select HFPER / HFPERB clock. */ \
|
|
timerInputActionNone, /* No action on falling input edge. */ \
|
|
timerInputActionNone, /* No action on rising input edge. */ \
|
|
timerModeUp, /* Up-counting. */ \
|
|
false, /* Do not clear DMA requests when DMA channel is active. */ \
|
|
false, /* Select X2 quadrature decode mode (if used). */ \
|
|
false, /* Disable one shot. */ \
|
|
false /* Not started/stopped/reloaded by other timers. */ \
|
|
}
|
|
#endif
|
|
|
|
/** PRS Output configuration. */
|
|
typedef enum {
|
|
timerPrsOutputPulse = 0, /**< Pulse PRS output from a channel. */
|
|
timerPrsOutputLevel = 1, /**< PRS output follows CC out level. */
|
|
timerPrsOutputDefault = timerPrsOutputPulse, /**< Default PRS output behavior. */
|
|
} TIMER_PrsOutput_t;
|
|
|
|
/** TIMER compare/capture initialization structure. */
|
|
typedef struct {
|
|
/** Input capture event control. */
|
|
TIMER_Event_TypeDef eventCtrl;
|
|
|
|
/** Input capture edge select. */
|
|
TIMER_Edge_TypeDef edge;
|
|
|
|
/**
|
|
* Peripheral reflex system trigger selection. Only applicable if @p prsInput
|
|
* is enabled.
|
|
*/
|
|
TIMER_PRSSEL_TypeDef prsSel;
|
|
|
|
/** Counter underflow output action. */
|
|
TIMER_OutputAction_TypeDef cufoa;
|
|
|
|
/** Counter overflow output action. */
|
|
TIMER_OutputAction_TypeDef cofoa;
|
|
|
|
/** Counter match output action. */
|
|
TIMER_OutputAction_TypeDef cmoa;
|
|
|
|
/** Compare/capture channel mode. */
|
|
TIMER_CCMode_TypeDef mode;
|
|
|
|
/** Enable digital filter. */
|
|
bool filter;
|
|
|
|
/** Select TIMERnCCx (false) or PRS input (true). */
|
|
bool prsInput;
|
|
|
|
/**
|
|
* Compare output initial state. Only used in Output Compare and PWM mode.
|
|
* When true, the compare/PWM output is set high when the counter is
|
|
* disabled. When counting resumes, this value will represent the initial
|
|
* value for the compare/PWM output. If the bit is cleared, the output
|
|
* will be cleared when the counter is disabled.
|
|
*/
|
|
bool coist;
|
|
|
|
/** Invert output from compare/capture channel. */
|
|
bool outInvert;
|
|
|
|
/**
|
|
* PRS output configuration. PRS output from a timer can either be a
|
|
* pulse output or a level output that follows the CC out value.
|
|
*/
|
|
TIMER_PrsOutput_t prsOutput;
|
|
|
|
#if defined(_TIMER_CC_CFG_INSEL_MASK)
|
|
/** When PRS input is used this field is used to configure the type of
|
|
* PRS input. */
|
|
TIMER_PrsInput_TypeDef prsInputType;
|
|
#endif
|
|
} TIMER_InitCC_TypeDef;
|
|
|
|
/** Default configuration for TIMER compare/capture initialization structure. */
|
|
#if defined(_TIMER_CC_CFG_INSEL_MASK)
|
|
#define TIMER_INITCC_DEFAULT \
|
|
{ \
|
|
timerEventEveryEdge, /* Event on every capture. */ \
|
|
timerEdgeRising, /* Input capture edge on rising edge. */ \
|
|
0, /* Not used by default, select PRS channel 0. */ \
|
|
timerOutputActionNone, /* No action on underflow. */ \
|
|
timerOutputActionNone, /* No action on overflow. */ \
|
|
timerOutputActionNone, /* No action on match. */ \
|
|
timerCCModeOff, /* Disable compare/capture channel. */ \
|
|
false, /* Disable filter. */ \
|
|
false, /* No PRS input. */ \
|
|
false, /* Clear output when counter disabled. */ \
|
|
false, /* Do not invert output. */ \
|
|
timerPrsOutputDefault, /* Use default PRS output configuration. */ \
|
|
timerPrsInputNone /* No PRS input, so input type is none. */ \
|
|
}
|
|
#else
|
|
#define TIMER_INITCC_DEFAULT \
|
|
{ \
|
|
timerEventEveryEdge, /* Event on every capture. */ \
|
|
timerEdgeRising, /* Input capture edge on rising edge. */ \
|
|
0, /* Not used by default, select PRS channel 0. */ \
|
|
timerOutputActionNone, /* No action on underflow. */ \
|
|
timerOutputActionNone, /* No action on overflow. */ \
|
|
timerOutputActionNone, /* No action on match. */ \
|
|
timerCCModeOff, /* Disable compare/capture channel. */ \
|
|
false, /* Disable filter. */ \
|
|
false, /* No PRS input. */ \
|
|
false, /* Clear output when counter disabled. */ \
|
|
false, /* Do not invert output. */ \
|
|
timerPrsOutputDefault, /* Use default PRS output configuration. */ \
|
|
}
|
|
#endif
|
|
|
|
#if defined(_TIMER_DTCTRL_MASK)
|
|
/** TIMER Dead Time Insertion (DTI) initialization structure. */
|
|
typedef struct {
|
|
/** Enable DTI or leave it disabled until @ref TIMER_EnableDTI() is called. */
|
|
bool enable;
|
|
|
|
/** DTI Output Polarity. */
|
|
bool activeLowOut;
|
|
|
|
/** DTI Complementary Output Invert. */
|
|
bool invertComplementaryOut;
|
|
|
|
/** Enable Automatic Start-up functionality (when debugger exits). */
|
|
bool autoRestart;
|
|
|
|
/** Enable/disable PRS as DTI input. */
|
|
bool enablePrsSource;
|
|
|
|
/** Select which PRS channel as DTI input. Only valid if @p enablePrsSource
|
|
is enabled. */
|
|
TIMER_PRSSEL_TypeDef prsSel;
|
|
|
|
/** DTI prescaling factor, if HFPER / HFPERB clock used. */
|
|
TIMER_Prescale_TypeDef prescale;
|
|
|
|
/** DTI Rise Time */
|
|
unsigned int riseTime;
|
|
|
|
/** DTI Fall Time */
|
|
unsigned int fallTime;
|
|
|
|
/** DTI outputs enable bit mask, consisting of one bit per DTI
|
|
output signal, i.e., CC0, CC1, CC2, CDTI0, CDTI1, and CDTI2.
|
|
This value should consist of one or more TIMER_DTOGEN_DTOGnnnEN flags
|
|
(defined in \<part_name\>_timer.h) OR'ed together. */
|
|
uint32_t outputsEnableMask;
|
|
|
|
/** Enable core lockup as a fault source. */
|
|
bool enableFaultSourceCoreLockup;
|
|
|
|
/** Enable debugger as a fault source. */
|
|
bool enableFaultSourceDebugger;
|
|
|
|
/** Enable PRS fault source 0 (@p faultSourcePrsSel0). */
|
|
bool enableFaultSourcePrsSel0;
|
|
|
|
/** Select which PRS signal to be PRS fault source 0. */
|
|
TIMER_PRSSEL_TypeDef faultSourcePrsSel0;
|
|
|
|
/** Enable PRS fault source 1 (@p faultSourcePrsSel1). */
|
|
bool enableFaultSourcePrsSel1;
|
|
|
|
/** Select which PRS signal to be PRS fault source 1. */
|
|
TIMER_PRSSEL_TypeDef faultSourcePrsSel1;
|
|
|
|
/** Fault Action */
|
|
TIMER_DtiFaultAction_TypeDef faultAction;
|
|
} TIMER_InitDTI_TypeDef;
|
|
|
|
/** Default configuration for TIMER DTI initialization structure. */
|
|
#define TIMER_INITDTI_DEFAULT \
|
|
{ \
|
|
true, /* Enable the DTI. */ \
|
|
false, /* CC[0|1|2] outputs are active high. */ \
|
|
false, /* CDTI[0|1|2] outputs are not inverted. */ \
|
|
false, /* No auto restart when debugger exits. */ \
|
|
false, /* No PRS source selected. */ \
|
|
0, /* Not used by default, select PRS channel 0. */ \
|
|
timerPrescale1, /* No prescaling. */ \
|
|
0, /* No rise time. */ \
|
|
0, /* No fall time. */ \
|
|
TIMER_DTOGEN_DTOGCC0EN | TIMER_DTOGEN_DTOGCDTI0EN, /* Enable CC0 and CDTI0. */ \
|
|
true, /* Enable core lockup as fault source. */ \
|
|
true, /* Enable debugger as fault source. */ \
|
|
false, /* Disable PRS fault source 0. */ \
|
|
0, /* Not used by default, select PRS channel 0. */ \
|
|
false, /* Disable PRS fault source 1. */ \
|
|
0, /* Not used by default, select PRS channel 0. */ \
|
|
timerDtiFaultActionInactive, /* No fault action. */ \
|
|
}
|
|
#endif /* _TIMER_DTCTRL_MASK */
|
|
|
|
/*******************************************************************************
|
|
***************************** PROTOTYPES **********************************
|
|
******************************************************************************/
|
|
|
|
#if defined(TIMER_STATUS_SYNCBUSY)
|
|
void TIMER_SyncWait(TIMER_TypeDef * timer);
|
|
#endif
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Validate the TIMER register block pointer.
|
|
*
|
|
* @param[in] ref
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @return
|
|
* True if ref points to a valid timer, false otherwise.
|
|
******************************************************************************/
|
|
__STATIC_INLINE bool TIMER_Valid(const TIMER_TypeDef *ref)
|
|
{
|
|
return (ref == TIMER0)
|
|
#if defined(TIMER1)
|
|
|| (ref == TIMER1)
|
|
#endif
|
|
#if defined(TIMER2)
|
|
|| (ref == TIMER2)
|
|
#endif
|
|
#if defined(TIMER3)
|
|
|| (ref == TIMER3)
|
|
#endif
|
|
#if defined(TIMER4)
|
|
|| (ref == TIMER4)
|
|
#endif
|
|
#if defined(TIMER5)
|
|
|| (ref == TIMER5)
|
|
#endif
|
|
#if defined(TIMER6)
|
|
|| (ref == TIMER6)
|
|
#endif
|
|
#if defined(TIMER7)
|
|
|| (ref == TIMER7)
|
|
#endif
|
|
#if defined(TIMER8)
|
|
|| (ref == TIMER8)
|
|
#endif
|
|
#if defined(TIMER9)
|
|
|| (ref == TIMER9)
|
|
#endif
|
|
#if defined(WTIMER0)
|
|
|| (ref == WTIMER0)
|
|
#endif
|
|
#if defined(WTIMER1)
|
|
|| (ref == WTIMER1)
|
|
#endif
|
|
#if defined(WTIMER2)
|
|
|| (ref == WTIMER2)
|
|
#endif
|
|
#if defined(WTIMER3)
|
|
|| (ref == WTIMER3)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Check whether the TIMER is valid and supports Dead Timer Insertion (DTI).
|
|
*
|
|
* @param[in] ref
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @return
|
|
* True if ref points to a valid timer that supports DTI, false otherwise.
|
|
******************************************************************************/
|
|
__STATIC_INLINE bool TIMER_SupportsDTI(const TIMER_TypeDef *ref)
|
|
{
|
|
(void) ref;
|
|
|
|
return 0
|
|
#if defined(TIMER0_DTI)
|
|
#if (TIMER0_DTI == 1)
|
|
|| (ref == TIMER0)
|
|
#endif
|
|
#elif defined(_TIMER_DTCTRL_MASK)
|
|
|| (ref == TIMER0)
|
|
#endif
|
|
#if defined(TIMER1_DTI) && (TIMER1_DTI == 1)
|
|
|| (ref == TIMER1)
|
|
#endif
|
|
#if defined(TIMER2_DTI) && (TIMER2_DTI == 1)
|
|
|| (ref == TIMER2)
|
|
#endif
|
|
#if defined(TIMER3_DTI) && (TIMER3_DTI == 1)
|
|
|| (ref == TIMER3)
|
|
#endif
|
|
#if defined(TIMER4_DTI) && (TIMER4_DTI == 1)
|
|
|| (ref == TIMER4)
|
|
#endif
|
|
#if defined(TIMER5_DTI) && (TIMER5_DTI == 1)
|
|
|| (ref == TIMER5)
|
|
#endif
|
|
#if defined(TIMER6_DTI) && (TIMER6_DTI == 1)
|
|
|| (ref == TIMER6)
|
|
#endif
|
|
#if defined(TIMER7_DTI) && (TIMER7_DTI == 1)
|
|
|| (ref == TIMER7)
|
|
#endif
|
|
#if defined(TIMER8_DTI) && (TIMER8_DTI == 1)
|
|
|| (ref == TIMER8)
|
|
#endif
|
|
#if defined(TIMER9_DTI) && (TIMER9_DTI == 1)
|
|
|| (ref == TIMER9)
|
|
#endif
|
|
#if defined(WTIMER0)
|
|
|| (ref == WTIMER0)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get the Max count of the timer.
|
|
*
|
|
* @param[in] ref
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @return
|
|
* The max count value of the timer. This is 0xFFFF for 16 bit timers
|
|
* and 0xFFFFFFFF for 32 bit timers.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_MaxCount(const TIMER_TypeDef *ref)
|
|
{
|
|
(void) ref;
|
|
|
|
#if defined(WTIMER_PRESENT)
|
|
if ((ref == WTIMER0)
|
|
#if defined(WTIMER1)
|
|
|| (ref == WTIMER1)
|
|
#endif
|
|
#if defined(WTIMER2)
|
|
|| (ref == WTIMER2)
|
|
#endif
|
|
#if defined(WTIMER3)
|
|
|| (ref == WTIMER3)
|
|
#endif
|
|
) {
|
|
return 0xFFFFFFFFUL;
|
|
}
|
|
#endif /* defined(WTIMER_PRESENT) */
|
|
|
|
#if defined(_SILICON_LABS_32B_SERIES_2)
|
|
EFM_ASSERT(TIMER_NUM(ref) != -1);
|
|
|
|
return (uint32_t)((1ULL << TIMER_CNTWIDTH(TIMER_NUM(ref))) - 1);
|
|
#else
|
|
return 0xFFFFUL;
|
|
#endif /* defined(_SILICON_LABS_32B_SERIES_2) */
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get compare/capture value for the compare/capture channel.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] ch
|
|
* Compare/capture channel to access.
|
|
*
|
|
* @return
|
|
* Current capture value.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_CaptureGet(TIMER_TypeDef *timer, unsigned int ch)
|
|
{
|
|
#if defined (_TIMER_CC_CFG_MASK)
|
|
if ((timer->CC[ch].CFG & _TIMER_CC_CFG_MODE_MASK) == TIMER_CC_CFG_MODE_INPUTCAPTURE) {
|
|
return timer->CC[ch].ICF;
|
|
} else {
|
|
return timer->CC[ch].OC;
|
|
}
|
|
#else
|
|
return timer->CC[ch].CCV;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get the buffered compare/capture value for compare/capture channel.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] ch
|
|
* Compare/capture channel to access.
|
|
*
|
|
* @return
|
|
* Current buffered capture value.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_CaptureBufGet(TIMER_TypeDef *timer, unsigned int ch)
|
|
{
|
|
#if defined (_TIMER_CC_CFG_MASK)
|
|
if ((timer->CC[ch].CFG & _TIMER_CC_CFG_MODE_MASK) == TIMER_CC_CFG_MODE_INPUTCAPTURE) {
|
|
return timer->CC[ch].ICOF;
|
|
} else {
|
|
return timer->CC[ch].OCB;
|
|
}
|
|
#else
|
|
return timer->CC[ch].CCVB;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set the compare value buffer for the compare/capture channel when operating in
|
|
* compare or PWM mode.
|
|
*
|
|
* @details
|
|
* The compare value buffer holds the value which will be written to
|
|
* TIMERn_CCx_CCV on an update event if the buffer has been updated since
|
|
* the last event.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] ch
|
|
* Compare/capture channel to access.
|
|
*
|
|
* @param[in] val
|
|
* Value to set in compare value buffer register.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_CompareBufSet(TIMER_TypeDef *timer,
|
|
unsigned int ch,
|
|
uint32_t val)
|
|
{
|
|
EFM_ASSERT(val <= TIMER_MaxCount(timer));
|
|
#if defined (_TIMER_CC_CFG_MASK)
|
|
EFM_ASSERT(timer->EN & TIMER_EN_EN);
|
|
timer->CC[ch].OCB = val;
|
|
#else
|
|
timer->CC[ch].CCVB = val;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set the compare value for compare/capture channel when operating in compare
|
|
* or PWM mode.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] ch
|
|
* Compare/capture channel to access.
|
|
*
|
|
* @param[in] val
|
|
* Value to set in compare value register.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_CompareSet(TIMER_TypeDef *timer,
|
|
unsigned int ch,
|
|
uint32_t val)
|
|
{
|
|
EFM_ASSERT(val <= TIMER_MaxCount(timer));
|
|
#if defined (_TIMER_CC_CFG_MASK)
|
|
EFM_ASSERT(timer->EN & TIMER_EN_EN);
|
|
timer->CC[ch].OC = val;
|
|
#else
|
|
timer->CC[ch].CCV = val;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get the TIMER counter value.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to TIMER peripheral register block.
|
|
*
|
|
* @return
|
|
* Current TIMER counter value.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_CounterGet(TIMER_TypeDef *timer)
|
|
{
|
|
return timer->CNT;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set the TIMER counter value.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] val
|
|
* Value to set counter to.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_CounterSet(TIMER_TypeDef *timer, uint32_t val)
|
|
{
|
|
EFM_ASSERT(val <= TIMER_MaxCount(timer));
|
|
#if defined(TIMER_HAS_SET_CLEAR)
|
|
bool enabled = (timer->EN & TIMER_EN_EN) != 0UL;
|
|
timer->EN_SET = TIMER_EN_EN;
|
|
#endif
|
|
timer->CNT = val;
|
|
#if defined(TIMER_HAS_SET_CLEAR)
|
|
if (!enabled) {
|
|
TIMER_SyncWait(timer);
|
|
timer->EN_CLR = TIMER_EN_EN;
|
|
#if defined(_TIMER_EN_DISABLING_MASK)
|
|
while (timer->EN & _TIMER_EN_DISABLING_MASK) {
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Start/stop TIMER.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] enable
|
|
* Set to true to enable counting; set to false otherwise.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_Enable(TIMER_TypeDef *timer, bool enable)
|
|
{
|
|
EFM_ASSERT(TIMER_REF_VALID(timer));
|
|
|
|
if (enable) {
|
|
timer->CMD = TIMER_CMD_START;
|
|
} else {
|
|
timer->CMD = TIMER_CMD_STOP;
|
|
}
|
|
}
|
|
|
|
void TIMER_Init(TIMER_TypeDef *timer, const TIMER_Init_TypeDef *init);
|
|
void TIMER_InitCC(TIMER_TypeDef *timer,
|
|
unsigned int ch,
|
|
const TIMER_InitCC_TypeDef *init);
|
|
|
|
#if defined(_TIMER_DTCTRL_MASK)
|
|
void TIMER_InitDTI(TIMER_TypeDef *timer, const TIMER_InitDTI_TypeDef *init);
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Enable or disable DTI unit.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] enable
|
|
* Set to true to enable DTI unit; set to false otherwise.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_EnableDTI(TIMER_TypeDef *timer, bool enable)
|
|
{
|
|
#if defined(TIMER_HAS_SET_CLEAR)
|
|
uint32_t timerEn = timer->EN & TIMER_EN_EN;
|
|
TIMER_SyncWait(timer);
|
|
timer->EN_CLR = TIMER_EN_EN;
|
|
#if defined(_TIMER_EN_DISABLING_MASK)
|
|
while (timer->EN & _TIMER_EN_DISABLING_MASK) {
|
|
}
|
|
#endif
|
|
if (enable) {
|
|
timer->DTCFG_SET = TIMER_DTCFG_DTEN;
|
|
} else {
|
|
timer->DTCFG_CLR = TIMER_DTCFG_DTEN;
|
|
}
|
|
timer->EN_SET = timerEn;
|
|
#else
|
|
EFM_ASSERT(TIMER_SupportsDTI(timer));
|
|
|
|
if (enable) {
|
|
timer->DTCTRL |= TIMER_DTCTRL_DTEN;
|
|
} else {
|
|
timer->DTCTRL &= ~TIMER_DTCTRL_DTEN;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get DTI fault source flags status.
|
|
*
|
|
* @note
|
|
* Event bits are not cleared by this function.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @return
|
|
* Status of the DTI fault source flags. Returns one or more valid
|
|
* DTI fault source flags (TIMER_DTFAULT_nnn) OR'ed together.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_GetDTIFault(TIMER_TypeDef *timer)
|
|
{
|
|
EFM_ASSERT(TIMER_SupportsDTI(timer));
|
|
return timer->DTFAULT;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Clear DTI fault source flags.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* DTI fault source(s) to clear. Use one or more valid DTI fault
|
|
* source flags (TIMER_DTFAULT_nnn) OR'ed together.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_ClearDTIFault(TIMER_TypeDef *timer, uint32_t flags)
|
|
|
|
{
|
|
EFM_ASSERT(TIMER_SupportsDTI(timer));
|
|
#if defined (TIMER_EN_EN)
|
|
EFM_ASSERT(timer->EN & TIMER_EN_EN);
|
|
#endif
|
|
|
|
timer->DTFAULTC = flags;
|
|
}
|
|
#endif /* _TIMER_DTCTRL_MASK */
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Clear one or more pending TIMER interrupts.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* Pending TIMER interrupt source(s) to clear. Use one or more valid
|
|
* interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_IntClear(TIMER_TypeDef *timer, uint32_t flags)
|
|
{
|
|
#if defined (TIMER_HAS_SET_CLEAR)
|
|
timer->IF_CLR = flags;
|
|
#else
|
|
timer->IFC = flags;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Disable one or more TIMER interrupts.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* TIMER interrupt source(s) to disable. Use one or more valid
|
|
* interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_IntDisable(TIMER_TypeDef *timer, uint32_t flags)
|
|
{
|
|
timer->IEN &= ~flags;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Enable one or more TIMER interrupts.
|
|
*
|
|
* @note
|
|
* Depending on the use, a pending interrupt may already be set prior to
|
|
* enabling the interrupt. To ignore a pending interrupt, consider using
|
|
* TIMER_IntClear() prior to enabling the interrupt.
|
|
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* TIMER interrupt source(s) to enable. Use one or more valid
|
|
* interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_IntEnable(TIMER_TypeDef *timer, uint32_t flags)
|
|
{
|
|
timer->IEN |= flags;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get pending TIMER interrupt flags.
|
|
*
|
|
* @note
|
|
* Event bits are not cleared by this function.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @return
|
|
* TIMER interrupt source(s) pending. Returns one or more valid
|
|
* interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_IntGet(TIMER_TypeDef *timer)
|
|
{
|
|
return timer->IF;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get enabled and pending TIMER interrupt flags.
|
|
* Useful for handling more interrupt sources in the same interrupt handler.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @note
|
|
* Interrupt flags are not cleared by this function.
|
|
*
|
|
* @return
|
|
* Pending and enabled TIMER interrupt sources.
|
|
* The return value is the bitwise AND combination of
|
|
* - the OR combination of enabled interrupt sources in TIMERx_IEN_nnn
|
|
* register (TIMERx_IEN_nnn) and
|
|
* - the OR combination of valid interrupt flags of the TIMER module
|
|
* (TIMERx_IF_nnn).
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_IntGetEnabled(TIMER_TypeDef *timer)
|
|
{
|
|
uint32_t ien;
|
|
|
|
/* Store TIMER->IEN in temporary variable in order to define explicit order
|
|
* of volatile accesses. */
|
|
ien = timer->IEN;
|
|
|
|
/* Bitwise AND of pending and enabled interrupts */
|
|
return timer->IF & ien;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set one or more pending TIMER interrupts from SW.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* TIMER interrupt source(s) to set to pending. Use one or more valid
|
|
* interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_IntSet(TIMER_TypeDef *timer, uint32_t flags)
|
|
{
|
|
#if defined (TIMER_HAS_SET_CLEAR)
|
|
timer->IF_SET = flags;
|
|
#else
|
|
timer->IFS = flags;
|
|
#endif
|
|
}
|
|
|
|
#if defined(_TIMER_DTLOCK_LOCKKEY_LOCK)
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Lock some TIMER registers to protect them from being
|
|
* modified.
|
|
*
|
|
* @details
|
|
* Refer to the reference manual for TIMER registers that will be locked.
|
|
*
|
|
* @note
|
|
* If locking the TIMER registers, they must be unlocked prior to using any
|
|
* TIMER API function that modifies TIMER registers protected by the lock.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to TIMER peripheral register block.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_Lock(TIMER_TypeDef *timer)
|
|
{
|
|
EFM_ASSERT(TIMER0 == timer);
|
|
#if defined (TIMER_EN_EN)
|
|
EFM_ASSERT(timer->EN & TIMER_EN_EN);
|
|
#endif
|
|
|
|
timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_LOCK;
|
|
}
|
|
#endif
|
|
|
|
void TIMER_Reset(TIMER_TypeDef *timer);
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set the top value buffer for the timer.
|
|
*
|
|
* @details
|
|
* When top value buffer register is updated, value is loaded into
|
|
* top value register at the next wrap around. This feature is useful
|
|
* in order to update top value safely when timer is running.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] val
|
|
* Value to set in top value buffer register.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_TopBufSet(TIMER_TypeDef *timer, uint32_t val)
|
|
{
|
|
EFM_ASSERT(val <= TIMER_MaxCount(timer));
|
|
#if defined (TIMER_EN_EN)
|
|
EFM_ASSERT(timer->EN & TIMER_EN_EN);
|
|
#endif
|
|
|
|
timer->TOPB = val;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get the top value setting for the timer.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @return
|
|
* Current top value.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t TIMER_TopGet(TIMER_TypeDef *timer)
|
|
{
|
|
return timer->TOP;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set the top value for timer.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
*
|
|
* @param[in] val
|
|
* Value to set in top value register.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_TopSet(TIMER_TypeDef *timer, uint32_t val)
|
|
{
|
|
EFM_ASSERT(val <= TIMER_MaxCount(timer));
|
|
#if defined (TIMER_EN_EN)
|
|
EFM_ASSERT(timer->EN & TIMER_EN_EN);
|
|
#endif
|
|
|
|
timer->TOP = val;
|
|
}
|
|
|
|
#if defined(TIMER_DTLOCK_LOCKKEY_UNLOCK)
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Unlock TIMER to enable writing to locked registers again.
|
|
*
|
|
* @param[in] timer
|
|
* Pointer to the TIMER peripheral register block.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void TIMER_Unlock(TIMER_TypeDef *timer)
|
|
{
|
|
EFM_ASSERT(TIMER0 == timer);
|
|
#if defined (TIMER_EN_EN)
|
|
EFM_ASSERT(timer->EN & TIMER_EN_EN);
|
|
#endif
|
|
|
|
timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_UNLOCK;
|
|
}
|
|
#endif
|
|
|
|
/** @} (end addtogroup timer) */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* defined(TIMER_COUNT) && (TIMER_COUNT > 0) */
|
|
#endif /* EM_TIMER_H */
|