示例#1
0
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;
}
示例#2
0
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 & ~(TPM_CnSC_CHF_MASK);

    /* 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)))
    {
    }
}
示例#3
0
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));

    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_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
    }
#endif
}
示例#4
0
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
    /* 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)))
    {
    }
}
示例#5
0
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
    /* 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
    /* Clear the combine bit for chnlNumber */
    base->COMBINE &= ~(1U << TPM_COMBINE_COMBINE1_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)))
    {
    }
}
示例#6
0
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);

    uint32_t reg;
    /* Clear quadrature Decoder mode for channel 0 or 1*/
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
    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)))
    {
    }
}
示例#7
0
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);

    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
    /* 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;
}
/*FUNCTION**********************************************************************
 *
 * Function Name : SMARTCARD_DRV_InterfaceClockInit
 * Description   : This function initializes clock module used for card clock generation
 *
 *END**************************************************************************/
static uint16_t SMARTCARD_DRV_InterfaceClockInit(uint8_t clockModuleInstance,  uint8_t clockModuleChannel, uint32_t cardClk)
{
#if defined(EMVSIM_INSTANCE_COUNT)
    assert(clockModuleInstance < EMVSIM_INSTANCE_COUNT);
    
    EMVSIM_Type * base = g_emvsimBase[clockModuleInstance];
    uint32_t emvsimClkMhz = 0;
    uint8_t emvsimPRSCValue;
    
    /* Retrieve EMV SIM clock */
    emvsimClkMhz = CLOCK_SYS_GetEmvsimFreq(clockModuleInstance)/1000000;
    
    /* Calculate MOD value */
    emvsimPRSCValue = (emvsimClkMhz*1000)/(cardClk/1000);
    
    /* Set clock prescaler */
    EMVSIM_HAL_SetClockPrescaler(base, emvsimPRSCValue);
    
    /* Enable smart card clock */
    EMVSIM_HAL_EnableCardClock(base);
    
    return cardClk;
	
#elif defined(FTM_INSTANCE_COUNT)
    assert(clockModuleInstance < FTM_INSTANCE_COUNT);
    
    
    ftm_user_config_t ftmInfo;    
    uint32_t periph_clk_mhz = 0;
    uint16_t ftmModValue;
    FTM_Type * ftmBase = g_ftmBase[clockModuleInstance];
    uint32_t chnlPairnum = FTM_HAL_GetChnPairIndex(clockModuleChannel);
    
    /* Retrieve FTM system clock */
    periph_clk_mhz = CLOCK_SYS_GetBusClockFreq()/1000000;
    
    /* Calculate MOD value */
    ftmModValue = ((periph_clk_mhz*1000/2)/(cardClk/1000)) -1;
    
    /* Clear FTM driver user configuration */
    memset(&ftmInfo, 0, sizeof(ftmInfo));
    
    ftmInfo.BDMMode = kFtmBdmMode_11;
    ftmInfo.syncMethod = kFtmUseSoftwareTrig;
    
    /* Initialize FTM driver */
    FTM_DRV_Init(clockModuleInstance, &ftmInfo);
    
    /* Reset FTM prescaler to 'Divide by 1', i.e., to be same clock as peripheral clock  */
    FTM_HAL_SetClockPs(ftmBase, kFtmDividedBy1);
    
    /* Disable FTM counter firstly */
    FTM_HAL_SetClockSource(ftmBase, kClock_source_FTM_None);

    /* Set initial counter value */
    FTM_HAL_SetCounterInitVal(ftmBase, 0);
    
    /* Set MOD value */
    FTM_HAL_SetMod(ftmBase, ftmModValue);
    
    /*  Other initializations to defaults */
    FTM_HAL_SetCpwms(ftmBase, 0);
    FTM_HAL_SetDualChnCombineCmd(ftmBase, chnlPairnum, false);
    FTM_HAL_SetDualEdgeCaptureCmd(ftmBase, chnlPairnum, false);
    
    /* Configure mode to output compare, tougle output on match */
    FTM_HAL_SetChnEdgeLevel(ftmBase, clockModuleChannel, kFtmToggleOnMatch);
    FTM_HAL_SetChnMSnBAMode(ftmBase, clockModuleChannel, 1);
    
    /* Configure a match value to toggle output at */
    FTM_HAL_SetChnCountVal(ftmBase, clockModuleChannel, 1);

    /* Set clock source to start the counter */
    FTM_HAL_SetClockSource(ftmBase, kClock_source_FTM_SystemClk);
    
    /* Re-calculate the actually configured smartcard clock and return to caller */
    return (uint32_t)(((periph_clk_mhz*1000/2)/(FTM_HAL_GetMod(ftmBase)+1))*1000);
#elif defined(TPM_INSTANCE_COUNT)
    assert(clockModuleInstance < TPM_INSTANCE_COUNT);
    assert(clockModuleChannel < FSL_FEATURE_TPM_CHANNEL_COUNTn(clockModuleInstance));
    
    /* Initialize TPM driver parameter */
    tpm_pwm_param_t param = {
        kTpmCenterAlignedPWM,   /* mode */
        kTpmHighTrue,           /* edgeMode */
        cardClk,                /* uFrequencyHZ */
        50                      /* uDutyCyclePercent */
    };
    
    /* Initialize TPM driver */
    tpm_general_config_t driverInfo;
    memset(&driverInfo, 0, sizeof(driverInfo));
    
    driverInfo.isDBGMode = true;
    TPM_DRV_Init(clockModuleInstance, &driverInfo);
    
    /* Set TPM clock source, the user will have to call the Clocking API's to set the 
     * TPM module clock before calling this function */
    TPM_DRV_SetClock(clockModuleInstance, kTpmClockSourceModuleClk, kTpmDividedBy1);
    
    /* Start TPM in PWM mode to generate smart card clock */
    TPM_DRV_PwmStart(clockModuleInstance, &param, clockModuleChannel);
    
    return cardClk;
#else
    return 0;
#endif
}