1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066 |
- /*
- * The Clear BSD License
- * Copyright (c) 2015-2016, 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_smartcard_emvsim.h"
- /* Component ID definition, used by tools. */
- #ifndef FSL_COMPONENT_ID
- #define FSL_COMPONENT_ID "platform.drivers.smartcard_emvsim"
- #endif
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*! @brief Pointers to emvsim bases for each instance. */
- static EMVSIM_Type *const s_emvsimBases[] = EMVSIM_BASE_PTRS;
- /*! @brief Pointers to emvsim IRQ number for each instance. */
- static const IRQn_Type s_emvsimIRQ[] = EMVSIM_IRQS;
- #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /*! @brief Pointers to emvsim clocks for each instance. */
- static const clock_ip_name_t s_emvsimClock[] = EMVSIM_CLOCKS;
- #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
- /* #define CARDSIM_EXTRADELAY_USED */
- /*******************************************************************************
- * Private Functions
- ******************************************************************************/
- static void smartcard_emvsim_CompleteSendData(EMVSIM_Type *base, smartcard_context_t *context);
- static void smartcard_emvsim_StartSendData(EMVSIM_Type *base, smartcard_context_t *context);
- static void smartcard_emvsim_CompleteReceiveData(EMVSIM_Type *base, smartcard_context_t *context);
- static void smartcard_emvsim_StartReceiveData(EMVSIM_Type *base, smartcard_context_t *context);
- static void smartcard_emvsim_SetTransferType(EMVSIM_Type *base,
- smartcard_context_t *context,
- smartcard_control_t control);
- static uint32_t smartcard_emvsim_GetInstance(EMVSIM_Type *base);
- /*******************************************************************************
- * Code
- ******************************************************************************/
- /*!
- * @brief Get the UART instance from peripheral base address.
- *
- * @param base UART peripheral base address.
- * @return UART instance.
- */
- static uint32_t smartcard_emvsim_GetInstance(EMVSIM_Type *base)
- {
- uint8_t instance = 0;
- uint32_t emvsimArrayCount = (sizeof(s_emvsimBases) / sizeof(s_emvsimBases[0]));
- /* Find the instance index from base address mappings. */
- for (instance = 0; instance < emvsimArrayCount; instance++)
- {
- if (s_emvsimBases[instance] == base)
- {
- break;
- }
- }
- assert(instance < emvsimArrayCount);
- return instance;
- }
- /*!
- * @brief Finish up a transmit by completing the process of sending data and disabling the interrupt.
- *
- * @param base The EMVSIM peripheral base address.
- * @param context A pointer to a SMARTCARD driver context structure.
- */
- static void smartcard_emvsim_CompleteSendData(EMVSIM_Type *base, smartcard_context_t *context)
- {
- assert((NULL != context));
- /* Disable ETC and TDT interrupt */
- base->INT_MASK |= (EMVSIM_INT_MASK_ETC_IM_MASK | EMVSIM_INT_MASK_TDT_IM_MASK);
- /* Disable transmitter */
- base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK;
- /* Clear receive status flag */
- base->RX_STATUS = EMVSIM_RX_STATUS_RX_DATA_MASK;
- /* Enable Receiver */
- base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
- /* Update the information of the module driver context */
- context->xIsBusy = false;
- context->transferState = kSMARTCARD_IdleState;
- /* Clear txSize to avoid any spurious transmit from ISR */
- context->xSize = 0u;
- /* Invoke user call-back */
- if (NULL != context->transferCallback)
- {
- context->transferCallback(context, context->transferCallbackParam);
- }
- }
- /*!
- * @brief Finish up a receive by completing the process of receiving data and disabling the interrupt.
- *
- * @param base The EMVSIM peripheral base address.
- * @param context A pointer to a SMARTCARD driver context structure.
- */
- static void smartcard_emvsim_CompleteReceiveData(EMVSIM_Type *base, smartcard_context_t *context)
- {
- assert((NULL != context));
- /* Disable RDT and RX_DATA interrupt */
- base->INT_MASK |= (EMVSIM_INT_MASK_RDT_IM_MASK | EMVSIM_INT_MASK_RX_DATA_IM_MASK);
- /* Read data from fifo */
- while ((base->RX_STATUS & EMVSIM_RX_STATUS_RX_CNT_MASK) && (context->xSize))
- {
- /* Get data and put into receive buffer */
- *context->xBuff = (uint8_t)(base->RX_BUF);
- ++context->xBuff;
- --context->xSize;
- }
- /* Update the information of the module driver context */
- context->xIsBusy = false;
- /* Invoke user call-back */
- if (NULL != context->transferCallback)
- {
- context->transferCallback(context, context->transferCallbackParam);
- }
- }
- /*!
- * @brief Initiate (start) a transmit by beginning the process of sending data and enabling the interrupt.
- *
- * @param base The EMVSIM peripheral base address.
- * @param context A pointer to a SMARTCARD driver context structure.
- */
- static void smartcard_emvsim_StartSendData(EMVSIM_Type *base, smartcard_context_t *context)
- {
- assert((NULL != context));
- uint32_t delay = 0u;
- uint32_t control = 0u;
- /* Block guard time */
- /* 22 etus (16 Receiver Clocks == 1 etu) */
- delay = 22u * 16u;
- /* Disable all functionality like protocol timers, NACK generation */
- control = base->CTRL;
- base->CTRL = 0u;
- base->TX_GETU = context->cardParams.GTN;
- /* Clear Global counter time-out flag */
- base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
- /* Disable counter interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_GPCNT1_IM_MASK;
- /* Set counter value */
- base->GPCNT1_VAL = delay;
- /* Select the clock for GPCNT */
- base->CLKCFG =
- (base->CLKCFG & ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK) | EMVSIM_CLKCFG_GPCNT1_CLK_SEL(kEMVSIM_GPCRxClock);
- /* Trigger the counter */
- base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
- /* Wait until counter overflow event occur */
- while ((!(base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT1_TO_MASK)))
- {
- }
- /* Clear status flag and disable GPCNT1 clock */
- base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
- base->CLKCFG &= ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK;
- /* Restore Control register */
- base->CTRL = control & ~(EMVSIM_CTRL_XMT_EN_MASK | EMVSIM_CTRL_RCV_EN_MASK);
- /* Update transferState */
- context->transferState = kSMARTCARD_TransmittingState;
- context->xIsBusy = true;
- /* Flush transmitter */
- base->CTRL |= EMVSIM_CTRL_FLSH_TX_MASK;
- /* Enable transmitter */
- base->CTRL |= EMVSIM_CTRL_XMT_EN_MASK;
- /* Set transmitter data threshold value to 0 - TDTF is set when the fifo is empty */
- base->TX_THD &= ~EMVSIM_TX_THD_TDT_MASK;
- /* Enable TDT interrupt */
- base->INT_MASK &= ~EMVSIM_INT_MASK_TDT_IM_MASK;
- }
- /*!
- * @brief Initiate (start) a receive by beginning the process of receiving data and enabling the interrupt.
- *
- * @param base The EMVSIM peripheral base address.
- * @param context A pointer to a SMARTCARD driver context structure.
- */
- static void smartcard_emvsim_StartReceiveData(EMVSIM_Type *base, smartcard_context_t *context)
- {
- assert((NULL != context));
- /* Initialize the module driver context structure to indicate transfer in progress */
- context->xIsBusy = true;
- /* Enable BWT Timer interrupt to occur */
- base->INT_MASK &= ~EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
- /* Disable transmitter */
- base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK;
- /* Enable receiver and switch to receive direction */
- base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
- /* Set rx threshold value - number of bytes that must exist in the Receive FIFO to trigger the receive data
- * threshold interrupt flag (RDTF).*/
- if (context->xSize < context->rxFifoThreshold)
- {
- base->RX_THD = ((base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK) | context->xSize);
- }
- else
- {
- base->RX_THD = ((base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK) | context->rxFifoThreshold);
- }
- /* Enable RDT interrupt - count of bytes in rx fifo is equal or greater than threshold RX_THD[RDT] */
- base->INT_MASK &= ~EMVSIM_INT_MASK_RDT_IM_MASK;
- if (context->tType == kSMARTCARD_T1Transport)
- {
- /* Enable interrupt when new byte is received - in T=1 is necessary to disable BWT interrupt and enable CWT
- * interrupt after receiving the first byte */
- base->INT_MASK &= ~EMVSIM_INT_MASK_RX_DATA_IM_MASK;
- }
- }
- /*!
- * @brief Sets up the EMVSIM hardware for T=0 or T=1 protocol data exchange and initialize timer values.
- *
- * @param base The EMVSIM peripheral base address.
- * @param context A pointer to a SMARTCARD driver context structure.
- */
- static void smartcard_emvsim_SetTransferType(EMVSIM_Type *base,
- smartcard_context_t *context,
- smartcard_control_t control)
- {
- assert((NULL != context));
- assert((control == kSMARTCARD_SetupATRMode) || (control == kSMARTCARD_SetupT0Mode) ||
- (control == kSMARTCARD_SetupT1Mode));
- uint16_t temp16 = 0u;
- uint32_t bwiVal = 0u;
- uint8_t tdt = 0u;
- if (control == kSMARTCARD_SetupATRMode)
- {
- /* Disable all functionality at first */
- base->CTRL &= ~(EMVSIM_CTRL_RCVR_11_MASK | EMVSIM_CTRL_XMT_CRC_LRC_MASK | EMVSIM_CTRL_LRC_EN_MASK |
- EMVSIM_CTRL_ANACK_MASK | EMVSIM_CTRL_ONACK_MASK | EMVSIM_CTRL_RCV_EN_MASK);
- /* Set default values as per EMV specification */
- context->cardParams.Fi = 372u;
- context->cardParams.Di = 1u;
- context->cardParams.currentD = 1u;
- context->cardParams.WI = 0x0Au;
- context->cardParams.GTN = 0x00u;
- /* Set default baudrate/ETU time based on EMV parameters and card clock */
- base->DIVISOR = ((context->cardParams.Fi / context->cardParams.currentD) & 0x1FFu);
- /* EMV expectation: WWT = (960 x D x WI) + (D x 480)
- * EMVSIM formula: BWT_VAL[15:0] = CWT_VAL[15:0] */
- temp16 = (960u * context->cardParams.currentD * context->cardParams.WI) +
- (context->cardParams.currentD * 480u) + SMARTCARD_WWT_ADJUSTMENT;
- base->CWT_VAL = temp16;
- base->BWT_VAL = temp16;
- /* Set Extended Guard Timer value
- * EMV expectation: GT = GTN not equal to 255 -> 12 + GTN = GTN equal to 255 -> 12
- * EMVSIM formula: same as above */
- base->TX_GETU = context->cardParams.GTN;
- /* Setting Rx threshold so that an interrupt is generated when a NACK is
- sent either due to parity error or wrong INIT char*/
- base->RX_THD = EMVSIM_RX_THD_RDT(1);
- /* Setting up Tx NACK threshold */
- tdt = ((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1;
- base->TX_THD = (EMVSIM_TX_THD_TNCK_THD(SMARTCARD_EMV_TX_NACK_THRESHOLD) | EMVSIM_TX_THD_TDT(tdt));
- /* Clear all pending interrupts */
- base->RX_STATUS = 0xFFFFFFFFu;
- /* Enable Tx NACK threshold interrupt to occur */
- base->INT_MASK &= ~EMVSIM_INT_MASK_TNACK_IM_MASK;
- /* Set transport type to T=0 in SMARTCARD context structure */
- context->tType = kSMARTCARD_T0Transport;
- }
- else if (control == kSMARTCARD_SetupT0Mode)
- {
- /* Disable receiver at first if it's not, Disable T=0 mode counters 1st,
- * Setup for single wire ISO7816 mode (setup 12 etu mode).
- * Set transport protocol type to T=0, Disable initial character detection.*/
- base->CTRL &=
- ~(EMVSIM_CTRL_RCV_EN_MASK | EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK | EMVSIM_CTRL_RCVR_11_MASK |
- EMVSIM_CTRL_XMT_CRC_LRC_MASK | EMVSIM_CTRL_LRC_EN_MASK | EMVSIM_CTRL_ICM_MASK);
- /* EMV expectation: WWT = (960 x D x WI) + (D x 480)
- * EMVSIM formula: BWT_VAL[15:0] = CWT_VAL[15:0] */
- temp16 = (960u * context->cardParams.currentD * context->cardParams.WI) +
- (context->cardParams.currentD * 480u) + SMARTCARD_WWT_ADJUSTMENT;
- base->CWT_VAL = temp16;
- base->BWT_VAL = temp16;
- /* Set Extended Guard Timer value
- * EMV expectation: GT = GTN not equal to 255 -> 12 + GTN = GTN equal to 255 -> 12
- * EMVSIM formula: same as above for range [0:254]
- * Fix for EMV. If TX_GETU == 0 in T0 mode, 3 stop bits are inserted. */
- context->cardParams.GTN = (context->cardParams.GTN == 0xFFu) ? 0x00u : context->cardParams.GTN;
- base->TX_GETU = context->cardParams.GTN;
- /* Setting Rx threshold so that an interrupt is generated when a NACK is
- sent either due to parity error or wrong INIT char */
- base->RX_THD = (EMVSIM_RX_THD_RNCK_THD(SMARTCARD_EMV_RX_NACK_THRESHOLD) | EMVSIM_RX_THD_RDT(1));
- /* Setting up Tx NACK threshold */
- tdt = ((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1;
- base->TX_THD = (EMVSIM_TX_THD_TNCK_THD(SMARTCARD_EMV_TX_NACK_THRESHOLD) | EMVSIM_TX_THD_TDT(tdt));
- /* Enable Tx NACK threshold interrupt to occur */
- base->INT_MASK &= ~EMVSIM_INT_MASK_TNACK_IM_MASK;
- /* Enable T=0 mode counters, Enable NACK on error interrupt and NACK on overflow interrupt */
- base->CTRL |=
- (EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK | EMVSIM_CTRL_ANACK_MASK | EMVSIM_CTRL_ONACK_MASK);
- /* Set transport type to T=0 in SMARTCARD context structure */
- context->tType = kSMARTCARD_T0Transport;
- }
- else
- { /* Disable T=1 mode counters 1st, Disable NACK on error interrupt, Disable NACK on overflow interrupt */
- base->CTRL &= ~(EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK | EMVSIM_CTRL_ANACK_MASK |
- EMVSIM_CTRL_ONACK_MASK | EMVSIM_CTRL_XMT_CRC_LRC_MASK | EMVSIM_CTRL_LRC_EN_MASK);
- /* Calculate and set Block Wait Timer (BWT) value
- * EMV expectation: BWT = 11 + (2^BWI x 960 x D) + (D x 960) = 11 + (2^BWI + 1) x 960 x D
- * EMVSIM formula: BWT = Same */
- bwiVal = 11 + (((1 << context->cardParams.BWI) + 1u) * 960u * context->cardParams.currentD);
- #ifdef CARDSIM_EXTRADELAY_USED
- base->BWT_VAL = bwiVal + 100;
- #else
- base->BWT_VAL = bwiVal;
- #endif
- /* Calculate and set Character Wait Timer (CWT) value
- * EMV expectation: CWT = ((2^CWI + 11) + 4)
- * EMVSIM formula: CWT = Same */
- if (context->cardParams.currentD == 1u)
- {
- #ifdef CARDSIM_EXTRADELAY_USED
- temp16 = (1u << context->cardParams.CWI) + 16u;
- #else
- temp16 = (1u << context->cardParams.CWI) + 15u;
- #endif
- }
- else
- {
- #ifdef CARDSIM_EXTRADELAY_USED
- temp16 = (1u << context->cardParams.CWI) + 20u + SMARTCARD_CWT_ADJUSTMENT;
- #else
- temp16 = (1u << context->cardParams.CWI) + 15u + SMARTCARD_CWT_ADJUSTMENT;
- #endif
- }
- /* EMV = 15, ISO = 11,
- * EMV expectation: BGT = 22
- * EMVSIM formula: BGT = Same */
- base->CWT_VAL = temp16;
- context->cardParams.BGI = 22u;
- base->BGT_VAL = context->cardParams.BGI;
- /* Set Extended Guard Timer value
- * EMV expectation: GT = GTN not equal to 255 -> 12 + GTN = GTN equal to 255 -> 11
- * EMVSIM formula: same as above */
- base->TX_GETU = context->cardParams.GTN;
- /* Setup for single wire ISO7816 mode,
- * Set transport protocol type to T=1, Enable T=0 mode counters */
- base->CTRL |= (EMVSIM_CTRL_RCVR_11_MASK | EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK);
- /* Setting Rx threshold */
- base->RX_THD = (EMVSIM_RX_THD_RNCK_THD(SMARTCARD_EMV_RX_NACK_THRESHOLD) | EMVSIM_RX_THD_RDT(1));
- /* Setting up Tx threshold */
- tdt = ((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1;
- base->TX_THD = (EMVSIM_TX_THD_TDT(tdt) | EMVSIM_TX_THD_TNCK_THD(SMARTCARD_EMV_TX_NACK_THRESHOLD));
- /* Set transport type to T=1 in SMARTCARD context structure */
- context->tType = kSMARTCARD_T1Transport;
- }
- }
- void SMARTCARD_EMVSIM_GetDefaultConfig(smartcard_card_params_t *cardParams)
- {
- /* EMV default values */
- cardParams->Fi = 372u;
- cardParams->Di = 1u;
- cardParams->currentD = 1u;
- cardParams->WI = 0x0Au;
- cardParams->GTN = 0x00u;
- }
- status_t SMARTCARD_EMVSIM_Init(EMVSIM_Type *base, smartcard_context_t *context, uint32_t srcClock_Hz)
- {
- assert((NULL != base));
- if ((NULL == context) || (srcClock_Hz == 0u))
- {
- return kStatus_SMARTCARD_InvalidInput;
- }
- uint32_t instance = smartcard_emvsim_GetInstance(base);
- /* Set source clock for EMVSIM MCGPLLCLK */
- #if (defined(FSL_FEATURE_SOC_MCG_COUNT) && FSL_FEATURE_SOC_MCG_COUNT)
- CLOCK_SetEmvsimClock(1u);
- #endif
- #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /* Enable emvsim clock */
- CLOCK_EnableClock(s_emvsimClock[instance]);
- #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
- context->base = base;
- /* Initialize EMVSIM to a known context. */
- base->CLKCFG = 0u;
- base->DIVISOR = 372u;
- base->CTRL = 0x300u;
- base->INT_MASK = 0x7FFFu;
- base->RX_THD = 1u;
- base->TX_THD = 0u;
- base->PCSR = 0x1000000u;
- base->TX_GETU = 0u;
- base->CWT_VAL = 0xFFFFu;
- base->BWT_VAL = 0xFFFFFFFFu;
- base->BGT_VAL = 0u;
- base->GPCNT0_VAL = 0xFFFFu;
- base->GPCNT1_VAL = 0xFFFFu;
- /* Initialize EMVSIM module for SMARTCARD mode of default operation */
- smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupATRMode);
- /* Store information about tx fifo depth */
- context->txFifoEntryCount = (base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT;
- /* Compute max value of rx fifo threshold */
- context->rxFifoThreshold = (base->PARAM & EMVSIM_PARAM_RX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_RX_FIFO_DEPTH_SHIFT;
- if ((EMVSIM_RX_THD_RDT_MASK >> EMVSIM_RX_THD_RDT_SHIFT) < context->rxFifoThreshold)
- {
- context->rxFifoThreshold = (EMVSIM_RX_THD_RDT_MASK >> EMVSIM_RX_THD_RDT_SHIFT);
- }
- /* Enable EMVSIM interrupt on NVIC level. */
- #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && FSL_FEATURE_SOC_INTMUX_COUNT
- if (s_emvsimIRQ[instance] < FSL_FEATURE_INTMUX_IRQ_START_INDEX)
- {
- NVIC_EnableIRQ(s_emvsimIRQ[instance]);
- }
- #else
- NVIC_EnableIRQ(s_emvsimIRQ[instance]);
- #endif
- /* Finally, disable the EMVSIM receiver and transmitter */
- base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK & ~EMVSIM_CTRL_RCV_EN_MASK;
- return kStatus_SMARTCARD_Success;
- }
- void SMARTCARD_EMVSIM_Deinit(EMVSIM_Type *base)
- {
- uint32_t instance = 0u;
- /* In case there is still data in the TX FIFO or shift register that is
- * being transmitted wait till transmit is complete.
- * Wait until the data is completely shifted out of shift register */
- if (base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK)
- {
- while ((!(base->TX_STATUS & EMVSIM_TX_STATUS_ETCF_MASK)))
- {
- }
- }
- instance = smartcard_emvsim_GetInstance(base);
- /* Disable TX and RX */
- base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK & ~EMVSIM_CTRL_RCV_EN_MASK;
- #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /* Gate EMVSIM module clock */
- CLOCK_DisableClock(s_emvsimClock[instance]);
- #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
- /* Disable emvsim interrupt in NVIC */
- #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && FSL_FEATURE_SOC_INTMUX_COUNT
- if (s_emvsimIRQ[instance] < FSL_FEATURE_INTMUX_IRQ_START_INDEX)
- {
- NVIC_DisableIRQ(s_emvsimIRQ[instance]);
- }
- #else
- NVIC_DisableIRQ(s_emvsimIRQ[instance]);
- #endif
- }
- status_t SMARTCARD_EMVSIM_TransferNonBlocking(EMVSIM_Type *base, smartcard_context_t *context, smartcard_xfer_t *xfer)
- {
- if ((NULL == context) || (NULL == xfer) || (xfer->buff == NULL))
- {
- return kStatus_SMARTCARD_InvalidInput;
- }
- /* Check input parameters */
- if ((0u == xfer->size))
- {
- return kStatus_SMARTCARD_Success;
- }
- /* Check if some transfer is in progress */
- if (0u != SMARTCARD_EMVSIM_GetTransferRemainingBytes(base, context))
- {
- if (kSMARTCARD_Receive == context->direction)
- {
- return kStatus_SMARTCARD_RxBusy;
- }
- else
- {
- return kStatus_SMARTCARD_TxBusy;
- }
- }
- /* Initialize error check flags */
- context->rxtCrossed = false;
- context->txtCrossed = false;
- context->parityError = false;
- /* Initialize SMARTCARD context structure to start transfer */
- context->xBuff = xfer->buff;
- context->xSize = xfer->size;
- if (kSMARTCARD_Receive == xfer->direction)
- {
- context->direction = xfer->direction;
- context->transferState = kSMARTCARD_ReceivingState;
- /* Start transfer */
- smartcard_emvsim_StartReceiveData(base, context);
- }
- else if (kSMARTCARD_Transmit == xfer->direction)
- {
- context->direction = xfer->direction;
- context->transferState = kSMARTCARD_TransmittingState;
- /* Start transfer */
- smartcard_emvsim_StartSendData(base, context);
- }
- else
- {
- return kStatus_SMARTCARD_InvalidInput;
- }
- return kStatus_SMARTCARD_Success;
- }
- int32_t SMARTCARD_EMVSIM_GetTransferRemainingBytes(EMVSIM_Type *base, smartcard_context_t *context)
- {
- if ((NULL == context))
- {
- return -1;
- }
- if (context->xIsBusy)
- {
- if (context->direction == kSMARTCARD_Transmit)
- {
- /* Count of bytes in buffer + data in fifo */
- return (context->xSize +
- ((base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK) >> EMVSIM_TX_STATUS_TX_CNT_SHIFT));
- }
- return context->xSize;
- }
- return 0;
- }
- status_t SMARTCARD_EMVSIM_AbortTransfer(EMVSIM_Type *base, smartcard_context_t *context)
- {
- if ((NULL == context))
- {
- return kStatus_SMARTCARD_InvalidInput;
- }
- context->abortTransfer = true;
- /* Check if a transfer is running. */
- if ((!context->xIsBusy))
- {
- return kStatus_SMARTCARD_NoTransferInProgress;
- }
- /* Call transfer complete to abort transfer */
- if (kSMARTCARD_Receive == context->direction)
- { /* Stop the running transfer. */
- smartcard_emvsim_CompleteReceiveData(base, context);
- }
- else if (kSMARTCARD_Transmit == context->direction)
- { /* Stop the running transfer. */
- smartcard_emvsim_CompleteSendData(base, context);
- }
- else
- {
- return kStatus_SMARTCARD_InvalidInput;
- }
- return kStatus_SMARTCARD_Success;
- }
- void SMARTCARD_EMVSIM_IRQHandler(EMVSIM_Type *base, smartcard_context_t *context)
- {
- if (NULL == context)
- {
- return;
- }
- /* Check card insertion/removal interrupt occurs, only EMVSIM DIRECT interface driver using enables this interrupt
- * to occur */
- if ((!(base->PCSR & EMVSIM_PCSR_SPDIM_MASK)) && (base->PCSR & EMVSIM_PCSR_SPDIF_MASK))
- {
- /* Clear card presence interrupt status */
- base->PCSR |= EMVSIM_PCSR_SPDIF_MASK;
- /* Set PD signal edge behaviour */
- if (((emvsim_presence_detect_edge_t)((base->PCSR & EMVSIM_PCSR_SPDES_MASK) >> EMVSIM_PCSR_SPDES_SHIFT) ==
- kEMVSIM_DetectOnFallingEdge) &&
- ((emvsim_presence_detect_status_t)((base->PCSR & EMVSIM_PCSR_SPDP_MASK) >> EMVSIM_PCSR_SPDP_SHIFT) ==
- kEMVSIM_DetectPinIsLow))
- { /* Set rising edge interrupt */
- base->PCSR |= EMVSIM_PCSR_SPDES_MASK;
- }
- if (((emvsim_presence_detect_edge_t)((base->PCSR & EMVSIM_PCSR_SPDES_MASK) >> EMVSIM_PCSR_SPDES_SHIFT) ==
- kEMVSIM_DetectOnRisingEdge) &&
- ((emvsim_presence_detect_status_t)((base->PCSR & EMVSIM_PCSR_SPDP_MASK) >> EMVSIM_PCSR_SPDP_SHIFT) ==
- kEMVSIM_DetectPinIsHigh))
- { /* Set falling edge interrupt */
- base->PCSR &= ~EMVSIM_PCSR_SPDES_MASK;
- }
- /* Card presence(insertion)/removal detected */
- /* Invoke callback if there is one */
- if (NULL != context->interfaceCallback)
- {
- context->interfaceCallback(context, context->interfaceCallbackParam);
- }
- return;
- }
- /* Check if timer for initial character (TS) detection has expired */
- if (((base->INT_MASK & EMVSIM_INT_MASK_GPCNT0_IM_MASK) >> EMVSIM_INT_MASK_GPCNT0_IM_SHIFT == 0) &&
- (base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT0_TO_MASK))
- {
- /* Disable TS and ADT timers by clearing source clock to 0 */
- base->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
- context->timersState.initCharTimerExpired = true;
- /* Disable and clear GPCNT interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_GPCNT0_IM_MASK;
- base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT0_TO_MASK;
- /* Down counter trigger, and clear any pending counter status flag */
- base->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
- base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
- context->transferState = kSMARTCARD_IdleState;
- /* Unblock the caller */
- smartcard_emvsim_CompleteReceiveData(base, context);
- return;
- }
- /* Check if timer for ATR duration timer has expired */
- if ((!(base->INT_MASK & EMVSIM_INT_MASK_GPCNT1_IM_MASK)) && (base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT1_TO_MASK))
- { /* Disable clock counter by clearing source clock to 0 */
- base->CLKCFG &= ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK;
- /* Disable and clear GPCNT interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_GPCNT1_IM_MASK;
- base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
- context->timersState.adtExpired = true;
- /* Unblock the caller */
- smartcard_emvsim_CompleteReceiveData(base, context);
- return;
- }
- /*
- * Check if a parity error was indicated.
- * A parity error will cause transmission of NACK if ANACK bit is set in
- * CTRL register and PEF bit will not be asserted. When ANACK is not set,
- * PEF will be asserted.
- */
- if ((base->RX_STATUS & EMVSIM_RX_STATUS_PEF_MASK))
- {
- context->parityError = true;
- /* Clear parity error indication */
- base->RX_STATUS = EMVSIM_RX_STATUS_PEF_MASK;
- }
- /* Check if transmit NACK generation threshold was reached */
- if ((base->TX_STATUS & EMVSIM_TX_STATUS_TNTE_MASK))
- {
- context->txtCrossed = true;
- /* Disable transmit NACK threshold interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_TNACK_IM_MASK;
- /* Clear transmit NACK threshold error flag */
- base->TX_STATUS = EMVSIM_TX_STATUS_TNTE_MASK;
- /* Unblock the caller */
- smartcard_emvsim_CompleteSendData(base, context);
- return;
- }
- /* Check if receive NACK generation threshold was reached */
- if (base->RX_STATUS & EMVSIM_RX_STATUS_RTE_MASK)
- {
- context->rxtCrossed = true;
- /* Clear receiver NACK threshold interrupt status */
- base->RX_STATUS = EMVSIM_RX_STATUS_RTE_MASK;
- if (context->xIsBusy)
- { /* Unblock the caller */
- smartcard_emvsim_CompleteReceiveData(base, context);
- }
- }
- /* Check if a Character Wait Timer expired */
- if ((!(base->INT_MASK & EMVSIM_INT_MASK_CWT_ERR_IM_MASK)) && (base->RX_STATUS & EMVSIM_RX_STATUS_CWT_ERR_MASK))
- { /* Disable Character Wait Timer interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_CWT_ERR_IM_MASK;
- /* Reset the counter */
- base->CTRL &= ~EMVSIM_CTRL_CWT_EN_MASK;
- /* Clear interrupt status */
- base->RX_STATUS = EMVSIM_RX_STATUS_CWT_ERR_MASK;
- /* Enable CWT timer */
- base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
- context->transferState = kSMARTCARD_IdleState;
- if (kSMARTCARD_T0Transport == context->tType)
- { /* Indicate WWT expired */
- context->timersState.wwtExpired = true;
- }
- else
- { /* Indicate CWT expired */
- context->timersState.cwtExpired = true;
- }
- if (context->xIsBusy)
- { /* Terminate and unblock any caller */
- smartcard_emvsim_CompleteReceiveData(base, context);
- }
- }
- /* Check if a Block Wait Timer expired */
- if ((!(base->INT_MASK & EMVSIM_INT_MASK_BWT_ERR_IM_MASK)) && (base->RX_STATUS & EMVSIM_RX_STATUS_BWT_ERR_MASK))
- { /* Disable Block Wait Timer interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
- /* Clear interrupt status flag */
- base->CTRL &= ~EMVSIM_CTRL_BWT_EN_MASK;
- /* Clear error */
- base->RX_STATUS = EMVSIM_RX_STATUS_BWT_ERR_MASK;
- /* Enable BWT timer */
- base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
- if (kSMARTCARD_T0Transport == context->tType)
- { /* Indicate WWT expired */
- context->timersState.wwtExpired = true;
- }
- else
- { /* Indicate BWT expired */
- context->timersState.bwtExpired = true;
- }
- /* Check if Wait Time Extension(WTX) was requested */
- if (context->wtxRequested)
- { /* Reset WTX to default */
- SMARTCARD_EMVSIM_Control(base, context, kSMARTCARD_ResetWaitTimeMultiplier, 1);
- }
- if (context->xIsBusy)
- { /* Terminate and unblock any caller */
- smartcard_emvsim_CompleteReceiveData(base, context);
- }
- }
- /* RX_DATA IRQ */
- /* Used in T=1 after receive 1st byte - disable BWT and enable CWT interrupt */
- if ((!(base->INT_MASK & EMVSIM_INT_MASK_RX_DATA_IM_MASK)) && (base->RX_STATUS & EMVSIM_RX_STATUS_RX_DATA_MASK))
- {
- if ((context->tType == kSMARTCARD_T1Transport) && (context->xSize > 0u) &&
- (!(base->INT_MASK & EMVSIM_INT_MASK_BWT_ERR_IM_MASK)))
- {
- context->timersState.cwtExpired = false;
- /* Clear CWT error flag */
- base->RX_STATUS = EMVSIM_RX_STATUS_CWT_ERR_MASK;
- /* Enable CWT */
- base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
- /* Only the 1st byte has been received, now time to disable BWT interrupt and enable CWT interrupt */
- base->INT_MASK = (base->INT_MASK & ~EMVSIM_INT_MASK_CWT_ERR_IM_MASK) | EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
- }
- /* Disable interrupt when is received new byte */
- base->INT_MASK |= EMVSIM_INT_MASK_RX_DATA_IM_MASK;
- }
- /* RDT IRQ - count of bytes in rx fifo reached the rx threshold value RX_THD[RDT] */
- if ((!(base->INT_MASK & EMVSIM_INT_MASK_RDT_IM_MASK)) && (base->RX_STATUS & EMVSIM_RX_STATUS_RDTF_MASK))
- {
- if (kSMARTCARD_WaitingForTSState == context->transferState)
- {
- /* Read byte */
- (void)(base->RX_BUF);
- if (base->CTRL & EMVSIM_CTRL_ICM_MASK)
- { /* ICM mode still enabled, this is due to parity error */
- context->transferState = kSMARTCARD_InvalidTSDetecetedState;
- }
- else
- { /* Received valid TS */
- context->transferState = kSMARTCARD_ReceivingState;
- /* Get Data Convention form by reading IC bit of EMVSIM_CTRL register */
- context->cardParams.convention =
- (smartcard_card_convention_t)((base->CTRL & EMVSIM_CTRL_IC_MASK) >> EMVSIM_CTRL_IC_SHIFT);
- }
- if (kSMARTCARD_InvalidTSDetecetedState == context->transferState)
- { /* Stop initial character (TS) detection timer, ADT timer and it's interrupt to occur */
- base->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
- base->INT_MASK |= EMVSIM_INT_MASK_GPCNT0_IM_MASK;
- smartcard_emvsim_CompleteReceiveData(base, context);
- }
- if (kSMARTCARD_ReceivingState == context->transferState)
- { /* Stop initial character (TS) detection timer and disable ATR duration timer to reset it */
- base->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
- /* Start ATR duration counter (restart GPCNT) */
- base->CLKCFG |= EMVSIM_CLKCFG_GPCNT1_CLK_SEL(kEMVSIM_GPCTxClock);
- /* Start ATR duration counter, Disable counter 0 interrupt and Enable counter 1 interrupt */
- base->INT_MASK = (base->INT_MASK & ~EMVSIM_INT_MASK_GPCNT1_IM_MASK) | EMVSIM_INT_MASK_GPCNT0_IM_MASK;
- /* Complete receive transfer */
- smartcard_emvsim_CompleteReceiveData(base, context);
- }
- /* Return anyway */
- return;
- }
- while ((base->RX_STATUS & EMVSIM_RX_STATUS_RX_CNT_MASK) && (context->xSize))
- {
- /* Get data and put into receive buffer */
- *context->xBuff = (uint8_t)(base->RX_BUF);
- ++context->xBuff;
- --context->xSize;
- }
- /* Check if the last byte was received */
- if (context->xSize == 0)
- {
- smartcard_emvsim_CompleteReceiveData(base, context);
- }
- else
- {
- /* If the count of remaining bytes to receive is less than depth of fifo, update the value of the receiver
- * data threshold */
- if (context->xSize < context->rxFifoThreshold)
- {
- /* Set receiver data threshold value to count of remaining bytes */
- base->RX_THD = ((base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK) | context->xSize);
- }
- }
- }
- /* ETC IRQ - all data from fifo is transmitted */
- if ((!(base->INT_MASK & EMVSIM_INT_MASK_ETC_IM_MASK)) && (base->TX_STATUS & EMVSIM_TX_STATUS_ETCF_MASK))
- {
- smartcard_emvsim_CompleteSendData(base, context);
- }
- /* TDT IRQ - tx fifo is empty */
- if ((!(base->INT_MASK & EMVSIM_INT_MASK_TDT_IM_MASK)) && (base->TX_STATUS & EMVSIM_TX_STATUS_TDTF_MASK))
- {
- if (context->xSize == 0)
- {
- smartcard_emvsim_CompleteSendData(base, context);
- }
- if (context->xSize == 1)
- {
- /* Disable TDT interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_TDT_IM_MASK;
- /* When the TX_GETU is not zero while sending last byte, the transmitter sends one byte more */
- base->TX_GETU = 0;
- /* Write data to fifo */
- base->TX_BUF = *(context->xBuff);
- ++context->xBuff;
- --context->xSize;
- /* Last byte was written to fifo - wait for ETC interrupt */
- /* Clear ETC flag and enable ETC interrupt */
- base->TX_STATUS |= EMVSIM_TX_STATUS_ETCF_MASK;
- base->INT_MASK &= ~EMVSIM_INT_MASK_ETC_IM_MASK;
- }
- else
- {
- /* To fifo will be written 2 or more bytes */
- int getu_tail = (base->TX_GETU > 0);
- while ((context->txFifoEntryCount -
- ((base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK) >> EMVSIM_TX_STATUS_TX_CNT_SHIFT)) &&
- (context->xSize > getu_tail))
- {
- /* Write data to fifo */
- base->TX_BUF = *(context->xBuff);
- ++context->xBuff;
- --context->xSize;
- }
- if (context->xSize == 0)
- {
- /* Disable TDT interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_TDT_IM_MASK;
- /* Clear ETC flag and enable ETC interrupt */
- base->TX_STATUS |= EMVSIM_TX_STATUS_ETCF_MASK;
- base->INT_MASK &= ~EMVSIM_INT_MASK_ETC_IM_MASK;
- }
- }
- }
- /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
- exception return operation might vector to incorrect interrupt */
- #if defined __CORTEX_M && (__CORTEX_M == 4U)
- __DSB();
- #endif
- }
- status_t SMARTCARD_EMVSIM_Control(EMVSIM_Type *base,
- smartcard_context_t *context,
- smartcard_control_t control,
- uint32_t param)
- {
- if ((NULL == context))
- {
- return kStatus_SMARTCARD_InvalidInput;
- }
- uint32_t temp32 = 0u;
- switch (control)
- {
- case kSMARTCARD_EnableADT:
- /* Do nothing, ADT counter has been loaded and started after reset
- * and during starting TS delay counter only. This is because, once
- * TS counter has been triggered with RCV_EN down-up, we should not
- * trigger again after TS is received(to avoid missing next character to
- * TS. Rather, after TS is received, the ATR duration counter should just
- * be restarted w/o re-triggering the counter. */
- break;
- case kSMARTCARD_DisableADT:
- base->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
- /* Stop ADT specific counter and it's interrupt to occur */
- base->CLKCFG &= ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK;
- base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
- base->INT_MASK |= EMVSIM_INT_MASK_GPCNT1_IM_MASK;
- break;
- case kSMARTCARD_EnableGTV:
- /* Enable GTV specific interrupt */
- base->INT_MASK &= ~EMVSIM_INT_MASK_BGT_ERR_IM_MASK;
- break;
- case kSMARTCARD_DisableGTV:
- /* Disable GTV specific interrupt */
- base->INT_MASK |= EMVSIM_INT_MASK_BGT_ERR_IM_MASK;
- break;
- case kSMARTCARD_ResetWWT:
- /* Reset WWT Timer */
- base->CTRL &= ~(EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK);
- base->CTRL |= (EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK);
- break;
- case kSMARTCARD_EnableWWT:
- /* BGT must be masked */
- base->INT_MASK |= EMVSIM_INT_MASK_BGT_ERR_IM_MASK;
- /* Enable WWT Timer interrupt to occur */
- base->INT_MASK &= (~EMVSIM_INT_MASK_CWT_ERR_IM_MASK & ~EMVSIM_INT_MASK_BWT_ERR_IM_MASK);
- break;
- case kSMARTCARD_DisableWWT:
- /* Disable WWT Timer interrupt to occur */
- base->INT_MASK |= (EMVSIM_INT_MASK_CWT_ERR_IM_MASK | EMVSIM_INT_MASK_BWT_ERR_IM_MASK);
- break;
- case kSMARTCARD_ResetCWT:
- /* Reset CWT Timer */
- base->CTRL &= ~EMVSIM_CTRL_CWT_EN_MASK;
- base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
- break;
- case kSMARTCARD_EnableCWT:
- base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
- /* Enable CWT Timer interrupt to occur */
- base->INT_MASK &= ~EMVSIM_INT_MASK_CWT_ERR_IM_MASK;
- break;
- case kSMARTCARD_DisableCWT:
- /* CWT counter is for receive mode only */
- base->CTRL &= ~EMVSIM_CTRL_CWT_EN_MASK;
- /* Disable CWT Timer interrupt to occur */
- base->INT_MASK |= EMVSIM_INT_MASK_CWT_ERR_IM_MASK;
- break;
- case kSMARTCARD_ResetBWT:
- /* Reset BWT Timer */
- base->CTRL &= ~EMVSIM_CTRL_BWT_EN_MASK;
- base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
- break;
- case kSMARTCARD_EnableBWT:
- base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
- /* Enable BWT Timer interrupt to occur */
- base->INT_MASK &= ~EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
- break;
- case kSMARTCARD_DisableBWT:
- /* Disable BWT Timer interrupt to occur */
- base->INT_MASK |= EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
- break;
- case kSMARTCARD_EnableInitDetect:
- /* Clear all ISO7816 interrupt flags */
- base->RX_STATUS = 0xFFFFFFFFu;
- /* Enable initial character detection : hardware method */
- context->transferState = kSMARTCARD_WaitingForTSState;
- /* Enable initial character detection */
- base->CTRL |= EMVSIM_CTRL_ICM_MASK;
- base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
- break;
- case kSMARTCARD_EnableAnack:
- /* Enable NACK-on-error interrupt to occur */
- base->CTRL |= EMVSIM_CTRL_ANACK_MASK;
- break;
- case kSMARTCARD_DisableAnack:
- /* Disable NACK-on-error interrupt to occur */
- base->CTRL &= ~EMVSIM_CTRL_ANACK_MASK;
- break;
- case kSMARTCARD_ConfigureBaudrate:
- /* Set default baudrate/ETU time based on EMV parameters and card clock */
- base->DIVISOR = ((context->cardParams.Fi / context->cardParams.currentD) & 0x1FFu);
- break;
- case kSMARTCARD_SetupATRMode:
- /* Set in default ATR mode */
- smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupATRMode);
- break;
- case kSMARTCARD_SetupT0Mode:
- /* Set transport protocol type to T=0 */
- smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupT0Mode);
- break;
- case kSMARTCARD_SetupT1Mode:
- /* Set transport protocol type to T=1 */
- smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupT1Mode);
- break;
- case kSMARTCARD_EnableReceiverMode:
- /* Enable receiver mode and switch to receive direction */
- base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
- /* Set receiver threshold value to 1 */
- base->RX_THD = ((base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK) | 1);
- /* Enable RDT interrupt */
- base->INT_MASK &= ~EMVSIM_INT_MASK_RDT_IM_MASK;
- break;
- case kSMARTCARD_DisableReceiverMode:
- /* Disable receiver */
- base->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
- break;
- case kSMARTCARD_EnableTransmitterMode:
- /* Enable transmitter mode and switch to transmit direction */
- base->CTRL |= EMVSIM_CTRL_XMT_EN_MASK;
- break;
- case kSMARTCARD_DisableTransmitterMode:
- /* Disable transmitter */
- base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK;
- break;
- case kSMARTCARD_ResetWaitTimeMultiplier:
- base->CTRL &= ~EMVSIM_CTRL_BWT_EN_MASK;
- /* Reset Wait Timer Multiplier
- * EMV Formula : WTX x (11 + ((2^BWI + 1) x 960 x D)) */
- temp32 = ((uint8_t)param) *
- (11u + (((1 << context->cardParams.BWI) + 1u) * 960u * context->cardParams.currentD));
- #ifdef CARDSIM_EXTRADELAY_USED
- temp32 += context->cardParams.currentD * 50;
- #endif
- base->BWT_VAL = temp32;
- /* Set flag to SMARTCARD context accordingly */
- if (param > 1u)
- {
- context->wtxRequested = true;
- }
- else
- {
- context->wtxRequested = false;
- }
- base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
- break;
- default:
- return kStatus_SMARTCARD_InvalidInput;
- }
- return kStatus_SMARTCARD_Success;
- }
|