123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794 |
- /*
- * The Clear BSD License
- * Copyright (c) 2015, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted (subject to the limitations in the disclaimer below) provided
- * that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "fsl_tpm.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /* Component ID definition, used by tools. */
- #ifndef FSL_COMPONENT_ID
- #define FSL_COMPONENT_ID "platform.drivers.tpm"
- #endif
- #define TPM_COMBINE_SHIFT (8U)
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*!
- * @brief Gets the instance from the base address
- *
- * @param base TPM peripheral base address
- *
- * @return The TPM instance
- */
- static uint32_t TPM_GetInstance(TPM_Type *base);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*! @brief Pointers to TPM bases for each instance. */
- static TPM_Type *const s_tpmBases[] = TPM_BASE_PTRS;
- #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /*! @brief Pointers to TPM clocks for each instance. */
- static const clock_ip_name_t s_tpmClocks[] = TPM_CLOCKS;
- #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
- /*******************************************************************************
- * Code
- ******************************************************************************/
- static uint32_t TPM_GetInstance(TPM_Type *base)
- {
- uint32_t instance;
- uint32_t tpmArrayCount = (sizeof(s_tpmBases) / sizeof(s_tpmBases[0]));
- /* Find the instance index from base address mappings. */
- for (instance = 0; instance < tpmArrayCount; instance++)
- {
- if (s_tpmBases[instance] == base)
- {
- break;
- }
- }
- assert(instance < tpmArrayCount);
- return instance;
- }
- void TPM_Init(TPM_Type *base, const tpm_config_t *config)
- {
- assert(config);
- #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /* Enable the module clock */
- CLOCK_EnableClock(s_tpmClocks[TPM_GetInstance(base)]);
- #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
- #if defined(FSL_FEATURE_TPM_HAS_GLOBAL) && FSL_FEATURE_TPM_HAS_GLOBAL
- /* TPM reset is available on certain SoC's */
- TPM_Reset(base);
- #endif
- /* Set the clock prescale factor */
- base->SC = TPM_SC_PS(config->prescale);
- #if !(defined(FSL_FEATURE_TPM_HAS_NO_CONF) && FSL_FEATURE_TPM_HAS_NO_CONF)
- /* Setup the counter operation */
- base->CONF = TPM_CONF_DOZEEN(config->enableDoze) | TPM_CONF_GTBEEN(config->useGlobalTimeBase) |
- TPM_CONF_CROT(config->enableReloadOnTrigger) | TPM_CONF_CSOT(config->enableStartOnTrigger) |
- TPM_CONF_CSOO(config->enableStopOnOverflow) |
- #if defined(FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER) && FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
- TPM_CONF_CPOT(config->enablePauseOnTrigger) |
- #endif
- #if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
- TPM_CONF_TRGSRC(config->triggerSource) |
- #endif
- TPM_CONF_TRGSEL(config->triggerSelect);
- if (config->enableDebugMode)
- {
- base->CONF |= TPM_CONF_DBGMODE_MASK;
- }
- else
- {
- base->CONF &= ~TPM_CONF_DBGMODE_MASK;
- }
- #endif
- }
- void TPM_Deinit(TPM_Type *base)
- {
- #if defined(FSL_FEATURE_TPM_HAS_SC_CLKS) && FSL_FEATURE_TPM_HAS_SC_CLKS
- /* Stop the counter */
- base->SC &= ~TPM_SC_CLKS_MASK;
- #else
- /* Stop the counter */
- base->SC &= ~TPM_SC_CMOD_MASK;
- #endif
- #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /* Gate the TPM clock */
- CLOCK_DisableClock(s_tpmClocks[TPM_GetInstance(base)]);
- #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
- }
- void TPM_GetDefaultConfig(tpm_config_t *config)
- {
- assert(config);
- /* TPM clock divide by 1 */
- config->prescale = kTPM_Prescale_Divide_1;
- #if !(defined(FSL_FEATURE_TPM_HAS_NO_CONF) && FSL_FEATURE_TPM_HAS_NO_CONF)
- /* Use internal TPM counter as timebase */
- config->useGlobalTimeBase = false;
- /* TPM counter continues in doze mode */
- config->enableDoze = false;
- /* TPM counter pauses when in debug mode */
- config->enableDebugMode = false;
- /* TPM counter will not be reloaded on input trigger */
- config->enableReloadOnTrigger = false;
- /* TPM counter continues running after overflow */
- config->enableStopOnOverflow = false;
- /* TPM counter starts immediately once it is enabled */
- config->enableStartOnTrigger = false;
- #if defined(FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER) && FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
- config->enablePauseOnTrigger = false;
- #endif
- /* Choose trigger select 0 as input trigger for controlling counter operation */
- config->triggerSelect = kTPM_Trigger_Select_0;
- #if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
- /* Choose external trigger source to control counter operation */
- config->triggerSource = kTPM_TriggerSource_External;
- #endif
- #endif
- }
- status_t TPM_SetupPwm(TPM_Type *base,
- const tpm_chnl_pwm_signal_param_t *chnlParams,
- uint8_t numOfChnls,
- tpm_pwm_mode_t mode,
- uint32_t pwmFreq_Hz,
- uint32_t srcClock_Hz)
- {
- assert(chnlParams);
- assert(pwmFreq_Hz);
- assert(numOfChnls);
- assert(srcClock_Hz);
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- if(mode == kTPM_CombinedPwm)
- {
- assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base));
- }
- #endif
- uint32_t mod;
- uint32_t tpmClock = (srcClock_Hz / (1U << (base->SC & TPM_SC_PS_MASK)));
- uint16_t cnv;
- uint8_t i;
- #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
- /* The TPM's QDCTRL register required to be effective */
- if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
- {
- /* Clear quadrature Decoder mode because in quadrature Decoder mode PWM doesn't operate*/
- base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
- }
- #endif
- switch (mode)
- {
- case kTPM_EdgeAlignedPwm:
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- case kTPM_CombinedPwm:
- #endif
- base->SC &= ~TPM_SC_CPWMS_MASK;
- mod = (tpmClock / pwmFreq_Hz) - 1;
- break;
- case kTPM_CenterAlignedPwm:
- base->SC |= TPM_SC_CPWMS_MASK;
- mod = tpmClock / (pwmFreq_Hz * 2);
- break;
- default:
- return kStatus_Fail;
- }
- /* Return an error in case we overflow the registers, probably would require changing
- * clock source to get the desired frequency */
- if (mod > 65535U)
- {
- return kStatus_Fail;
- }
- /* Set the PWM period */
- base->MOD = mod;
- /* Setup each TPM channel */
- for (i = 0; i < numOfChnls; i++)
- {
- /* Return error if requested dutycycle is greater than the max allowed */
- if (chnlParams->dutyCyclePercent > 100)
- {
- return kStatus_Fail;
- }
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- if (mode == kTPM_CombinedPwm)
- {
- uint16_t cnvFirstEdge;
- /* This check is added for combined mode as the channel number should be the pair number */
- if (chnlParams->chnlNumber >= (FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2))
- {
- return kStatus_Fail;
- }
- /* Return error if requested value is greater than the max allowed */
- if (chnlParams->firstEdgeDelayPercent > 100)
- {
- return kStatus_Fail;
- }
- /* Configure delay of the first edge */
- if (chnlParams->firstEdgeDelayPercent == 0)
- {
- /* No delay for the first edge */
- cnvFirstEdge = 0;
- }
- else
- {
- cnvFirstEdge = (mod * chnlParams->firstEdgeDelayPercent) / 100;
- }
- /* Configure dutycycle */
- if (chnlParams->dutyCyclePercent == 0)
- {
- /* Signal stays low */
- cnv = 0;
- cnvFirstEdge = 0;
- }
- else
- {
- cnv = (mod * chnlParams->dutyCyclePercent) / 100;
- /* For 100% duty cycle */
- if (cnv >= mod)
- {
- cnv = mod + 1;
- }
- }
- /* Set the combine bit for the channel pair */
- base->COMBINE |= (1U << (TPM_COMBINE_COMBINE0_SHIFT + (TPM_COMBINE_SHIFT * chnlParams->chnlNumber)));
- /* When switching mode, disable channel n first */
- base->CONTROLS[chnlParams->chnlNumber * 2].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[chnlParams->chnlNumber * 2].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Set the requested PWM mode for channel n, PWM output requires mode select to be set to 2 */
- base->CONTROLS[chnlParams->chnlNumber * 2].CnSC |=
- ((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT));
- /* Wait till mode change is acknowledged */
- while (!(base->CONTROLS[chnlParams->chnlNumber * 2].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Set the channel pair values */
- base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge;
- /* When switching mode, disable channel n + 1 first */
- base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Set the requested PWM mode for channel n + 1, PWM output requires mode select to be set to 2 */
- base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC |=
- ((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT));
- /* Wait till mode change is acknowledged */
- while (!(base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Set the channel pair values */
- base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv;
- }
- else
- {
- #endif
- if (chnlParams->dutyCyclePercent == 0)
- {
- /* Signal stays low */
- cnv = 0;
- }
- else
- {
- cnv = (mod * chnlParams->dutyCyclePercent) / 100;
- /* For 100% duty cycle */
- if (cnv >= mod)
- {
- cnv = mod + 1;
- }
- }
- /* When switching mode, disable channel first */
- base->CONTROLS[chnlParams->chnlNumber].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[chnlParams->chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Set the requested PWM mode, PWM output requires mode select to be set to 2 */
- base->CONTROLS[chnlParams->chnlNumber].CnSC |=
- ((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT));
- /* Wait till mode change is acknowledged */
- while (!(base->CONTROLS[chnlParams->chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- base->CONTROLS[chnlParams->chnlNumber].CnV = cnv;
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- }
- #endif
- chnlParams++;
- }
- return kStatus_Success;
- }
- void TPM_UpdatePwmDutycycle(TPM_Type *base,
- tpm_chnl_t chnlNumber,
- tpm_pwm_mode_t currentPwmMode,
- uint8_t dutyCyclePercent)
- {
- assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- if(currentPwmMode == kTPM_CombinedPwm)
- {
- assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base));
- }
- #endif
- uint16_t cnv, mod;
- mod = base->MOD;
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- if (currentPwmMode == kTPM_CombinedPwm)
- {
- uint16_t cnvFirstEdge;
- /* This check is added for combined mode as the channel number should be the pair number */
- if (chnlNumber >= (FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2))
- {
- return;
- }
- cnv = (mod * dutyCyclePercent) / 100;
- cnvFirstEdge = base->CONTROLS[chnlNumber * 2].CnV;
- /* For 100% duty cycle */
- if (cnv >= mod)
- {
- cnv = mod + 1;
- }
- base->CONTROLS[(chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv;
- }
- else
- {
- #endif
- cnv = (mod * dutyCyclePercent) / 100;
- /* For 100% duty cycle */
- if (cnv >= mod)
- {
- cnv = mod + 1;
- }
- base->CONTROLS[chnlNumber].CnV = cnv;
- #if defined(FSL_FEATURE_TPM_WAIT_CnV_REGISTER_UPDATE) && FSL_FEATURE_TPM_WAIT_CnV_REGISTER_UPDATE
- while(!(cnv == base->CONTROLS[chnlNumber].CnV))
- {
- }
- #endif
-
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- }
- #endif
- }
- void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_t level)
- {
- assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
- uint32_t reg = base->CONTROLS[chnlNumber].CnSC
- #if !(defined(FSL_FEATURE_TPM_CnSC_CHF_WRITE_0_CLEAR) && FSL_FEATURE_TPM_CnSC_CHF_WRITE_0_CLEAR)
- & ~(TPM_CnSC_CHF_MASK)
- #endif
- ;
- /* When switching mode, disable channel first */
- base->CONTROLS[chnlNumber].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Clear the field and write the new level value */
- reg &= ~(TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- reg |= ((uint32_t)level << TPM_CnSC_ELSA_SHIFT) & (TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
-
- base->CONTROLS[chnlNumber].CnSC = reg;
- /* Wait till mode change is acknowledged */
- reg &= (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- while (reg != (base->CONTROLS[chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- }
- void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capture_edge_t captureMode)
- {
- assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
- #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
- /* The TPM's QDCTRL register required to be effective */
- if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
- {
- /* Clear quadrature Decoder mode for channel 0 or 1*/
- if ((chnlNumber == 0) || (chnlNumber == 1))
- {
- base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
- }
- }
- #endif
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- /* The TPM's COMBINE register required to be effective */
- if( FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base) )
- {
- /* Clear the combine bit for chnlNumber */
- base->COMBINE &= ~(1U << TPM_COMBINE_SHIFT * (chnlNumber / 2));
- }
- #endif
- /* When switching mode, disable channel first */
- base->CONTROLS[chnlNumber].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Set the requested input capture mode */
- base->CONTROLS[chnlNumber].CnSC |= captureMode;
- /* Wait till mode change is acknowledged */
- while (!(base->CONTROLS[chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- }
- void TPM_SetupOutputCompare(TPM_Type *base,
- tpm_chnl_t chnlNumber,
- tpm_output_compare_mode_t compareMode,
- uint32_t compareValue)
- {
- assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
- #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
- /* The TPM's QDCTRL register required to be effective */
- if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
- {
- /* Clear quadrature Decoder mode for channel 0 or 1 */
- if ((chnlNumber == 0) || (chnlNumber == 1))
- {
- base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
- }
- }
- #endif
- /* When switching mode, disable channel first */
- base->CONTROLS[chnlNumber].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Setup the channel output behaviour when a match occurs with the compare value */
- base->CONTROLS[chnlNumber].CnSC |= compareMode;
- /* Setup the compare value */
- base->CONTROLS[chnlNumber].CnV = compareValue;
- /* Wait till mode change is acknowledged */
- while (!(base->CONTROLS[chnlNumber].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- }
- #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
- void TPM_SetupDualEdgeCapture(TPM_Type *base,
- tpm_chnl_t chnlPairNumber,
- const tpm_dual_edge_capture_param_t *edgeParam,
- uint32_t filterValue)
- {
- assert(edgeParam);
- assert(chnlPairNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2);
- assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base));
- uint32_t reg;
- #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
- /* The TPM's QDCTRL register required to be effective */
- if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
- {
- /* Clear quadrature Decoder mode for channel 0 or 1*/
- if (chnlPairNumber == 0)
- {
- base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
- }
- }
- #endif
- /* Unlock: When switching mode, disable channel first */
- base->CONTROLS[chnlPairNumber * 2].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[chnlPairNumber * 2].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- base->CONTROLS[chnlPairNumber * 2 + 1].CnSC &=
- ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[chnlPairNumber * 2 + 1].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Now, the registers for input mode can be operated. */
- if (edgeParam->enableSwap)
- {
- /* Set the combine and swap bits for the channel pair */
- base->COMBINE |= (TPM_COMBINE_COMBINE0_MASK | TPM_COMBINE_COMSWAP0_MASK)
- << (TPM_COMBINE_SHIFT * chnlPairNumber);
- /* Input filter setup for channel n+1 input */
- reg = base->FILTER;
- reg &= ~(TPM_FILTER_CH0FVAL_MASK << (TPM_FILTER_CH1FVAL_SHIFT * (chnlPairNumber + 1)));
- reg |= (filterValue << (TPM_FILTER_CH1FVAL_SHIFT * (chnlPairNumber + 1)));
- base->FILTER = reg;
- }
- else
- {
- reg = base->COMBINE;
- /* Clear the swap bit for the channel pair */
- reg &= ~(TPM_COMBINE_COMSWAP0_MASK << (TPM_COMBINE_COMSWAP0_SHIFT * chnlPairNumber));
- /* Set the combine bit for the channel pair */
- reg |= TPM_COMBINE_COMBINE0_MASK << (TPM_COMBINE_SHIFT * chnlPairNumber);
- base->COMBINE = reg;
- /* Input filter setup for channel n input */
- reg = base->FILTER;
- reg &= ~(TPM_FILTER_CH0FVAL_MASK << (TPM_FILTER_CH1FVAL_SHIFT * chnlPairNumber));
- reg |= (filterValue << (TPM_FILTER_CH1FVAL_SHIFT * chnlPairNumber));
- base->FILTER = reg;
- }
- /* Setup the edge detection from channel n */
- base->CONTROLS[chnlPairNumber * 2].CnSC |= edgeParam->currChanEdgeMode;
- /* Wait till mode change is acknowledged */
- while (!(base->CONTROLS[chnlPairNumber * 2].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Setup the edge detection from channel n+1 */
- base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC |= edgeParam->nextChanEdgeMode;
- /* Wait till mode change is acknowledged */
- while (!(base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC &
- (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- }
- #endif
- #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
- void TPM_SetupQuadDecode(TPM_Type *base,
- const tpm_phase_params_t *phaseAParams,
- const tpm_phase_params_t *phaseBParams,
- tpm_quad_decode_mode_t quadMode)
- {
- assert(phaseAParams);
- assert(phaseBParams);
- assert(FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base));
- base->CONTROLS[0].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[0].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- uint32_t reg;
- /* Set Phase A filter value */
- reg = base->FILTER;
- reg &= ~(TPM_FILTER_CH0FVAL_MASK);
- reg |= TPM_FILTER_CH0FVAL(phaseAParams->phaseFilterVal);
- base->FILTER = reg;
- #if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
- /* Set Phase A polarity */
- if (phaseAParams->phasePolarity)
- {
- base->POL |= TPM_POL_POL0_MASK;
- }
- else
- {
- base->POL &= ~TPM_POL_POL0_MASK;
- }
- #endif
- base->CONTROLS[1].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
- /* Wait till mode change to disable channel is acknowledged */
- while ((base->CONTROLS[1].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
- {
- }
- /* Set Phase B filter value */
- reg = base->FILTER;
- reg &= ~(TPM_FILTER_CH1FVAL_MASK);
- reg |= TPM_FILTER_CH1FVAL(phaseBParams->phaseFilterVal);
- base->FILTER = reg;
- #if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
- /* Set Phase B polarity */
- if (phaseBParams->phasePolarity)
- {
- base->POL |= TPM_POL_POL1_MASK;
- }
- else
- {
- base->POL &= ~TPM_POL_POL1_MASK;
- }
- #endif
- /* Set Quadrature mode */
- reg = base->QDCTRL;
- reg &= ~(TPM_QDCTRL_QUADMODE_MASK);
- reg |= TPM_QDCTRL_QUADMODE(quadMode);
- base->QDCTRL = reg;
- /* Enable Quad decode */
- base->QDCTRL |= TPM_QDCTRL_QUADEN_MASK;
- }
- #endif
- void TPM_EnableInterrupts(TPM_Type *base, uint32_t mask)
- {
- uint32_t chnlInterrupts = (mask & 0xFF);
- uint8_t chnlNumber = 0;
- /* Enable the timer overflow interrupt */
- if (mask & kTPM_TimeOverflowInterruptEnable)
- {
- base->SC |= TPM_SC_TOIE_MASK;
- }
- /* Enable the channel interrupts */
- while (chnlInterrupts)
- {
- if (chnlInterrupts & 0x1)
- {
- base->CONTROLS[chnlNumber].CnSC |= TPM_CnSC_CHIE_MASK;
- }
- chnlNumber++;
- chnlInterrupts = chnlInterrupts >> 1U;
- }
- }
- void TPM_DisableInterrupts(TPM_Type *base, uint32_t mask)
- {
- uint32_t chnlInterrupts = (mask & 0xFF);
- uint8_t chnlNumber = 0;
- /* Disable the timer overflow interrupt */
- if (mask & kTPM_TimeOverflowInterruptEnable)
- {
- base->SC &= ~TPM_SC_TOIE_MASK;
- }
- /* Disable the channel interrupts */
- while (chnlInterrupts)
- {
- if (chnlInterrupts & 0x1)
- {
- base->CONTROLS[chnlNumber].CnSC &= ~TPM_CnSC_CHIE_MASK;
- }
- chnlNumber++;
- chnlInterrupts = chnlInterrupts >> 1U;
- }
- }
- uint32_t TPM_GetEnabledInterrupts(TPM_Type *base)
- {
- uint32_t enabledInterrupts = 0;
- int8_t chnlCount = FSL_FEATURE_TPM_CHANNEL_COUNTn(base);
- /* The CHANNEL_COUNT macro returns -1 if it cannot match the TPM instance */
- assert(chnlCount != -1);
- /* Check if timer overflow interrupt is enabled */
- if (base->SC & TPM_SC_TOIE_MASK)
- {
- enabledInterrupts |= kTPM_TimeOverflowInterruptEnable;
- }
- /* Check if the channel interrupts are enabled */
- while (chnlCount > 0)
- {
- chnlCount--;
- if (base->CONTROLS[chnlCount].CnSC & TPM_CnSC_CHIE_MASK)
- {
- enabledInterrupts |= (1U << chnlCount);
- }
- }
- return enabledInterrupts;
- }
|