summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/mcux-sdk/drivers/smartcard
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/imxrt/mcux-sdk/drivers/smartcard')
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard.h274
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.c1143
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.h182
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy.h127
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy_emvsim.c227
5 files changed, 1953 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard.h b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard.h
new file mode 100644
index 0000000000..2c7f81609b
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_SMARTCARD_H_
+#define _FSL_SMARTCARD_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup smartcard
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief Smart card driver version 2.2.2.
+ */
+#define FSL_SMARTCARD_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
+/*@}*/
+
+/*! @brief Smart card global define which specify number of clock cycles until initial 'TS' character has to be received
+ */
+#define SMARTCARD_INIT_DELAY_CLOCK_CYCLES (42000u)
+
+/*! @brief Smart card global define which specify number of clock cycles during which ATR string has to be received */
+#define SMARTCARD_EMV_ATR_DURATION_ETU (20150u)
+
+/*! @brief Smart card specification initial TS character definition of direct convention */
+#define SMARTCARD_TS_DIRECT_CONVENTION (0x3Bu)
+
+/*! @brief Smart card specification initial TS character definition of inverse convention */
+#define SMARTCARD_TS_INVERSE_CONVENTION (0x3Fu)
+
+/*! @brief Smart card Error codes. */
+enum
+{
+ kStatus_SMARTCARD_Success = MAKE_STATUS(kStatusGroup_SMARTCARD, 0), /*!< Transfer ends successfully */
+ kStatus_SMARTCARD_TxBusy = MAKE_STATUS(kStatusGroup_SMARTCARD, 1), /*!< Transmit in progress */
+ kStatus_SMARTCARD_RxBusy = MAKE_STATUS(kStatusGroup_SMARTCARD, 2), /*!< Receiving in progress */
+ kStatus_SMARTCARD_NoTransferInProgress = MAKE_STATUS(kStatusGroup_SMARTCARD, 3), /*!< No transfer in progress */
+ kStatus_SMARTCARD_Timeout = MAKE_STATUS(kStatusGroup_SMARTCARD, 4), /*!< Transfer ends with time-out */
+ kStatus_SMARTCARD_Initialized =
+ MAKE_STATUS(kStatusGroup_SMARTCARD, 5), /*!< Smart card driver is already initialized */
+ kStatus_SMARTCARD_PhyInitialized =
+ MAKE_STATUS(kStatusGroup_SMARTCARD, 6), /*!< Smart card PHY drive is already initialized */
+ kStatus_SMARTCARD_CardNotActivated = MAKE_STATUS(kStatusGroup_SMARTCARD, 7), /*!< Smart card is not activated */
+ kStatus_SMARTCARD_InvalidInput =
+ MAKE_STATUS(kStatusGroup_SMARTCARD, 8), /*!< Function called with invalid input arguments */
+ kStatus_SMARTCARD_OtherError = MAKE_STATUS(kStatusGroup_SMARTCARD, 9) /*!< Some other error occur */
+};
+
+/*! @brief Control codes for the Smart card protocol timers and misc. */
+typedef enum _smartcard_control
+{
+ kSMARTCARD_EnableADT = 0x0u,
+ kSMARTCARD_DisableADT = 0x1u,
+ kSMARTCARD_EnableGTV = 0x2u,
+ kSMARTCARD_DisableGTV = 0x3u,
+ kSMARTCARD_ResetWWT = 0x4u,
+ kSMARTCARD_EnableWWT = 0x5u,
+ kSMARTCARD_DisableWWT = 0x6u,
+ kSMARTCARD_ResetCWT = 0x7u,
+ kSMARTCARD_EnableCWT = 0x8u,
+ kSMARTCARD_DisableCWT = 0x9u,
+ kSMARTCARD_ResetBWT = 0xAu,
+ kSMARTCARD_EnableBWT = 0xBu,
+ kSMARTCARD_DisableBWT = 0xCu,
+ kSMARTCARD_EnableInitDetect = 0xDu,
+ kSMARTCARD_EnableAnack = 0xEu,
+ kSMARTCARD_DisableAnack = 0xFu,
+ kSMARTCARD_ConfigureBaudrate = 0x10u,
+ kSMARTCARD_SetupATRMode = 0x11u,
+ kSMARTCARD_SetupT0Mode = 0x12u,
+ kSMARTCARD_SetupT1Mode = 0x13u,
+ kSMARTCARD_EnableReceiverMode = 0x14u,
+ kSMARTCARD_DisableReceiverMode = 0x15u,
+ kSMARTCARD_EnableTransmitterMode = 0x16u,
+ kSMARTCARD_DisableTransmitterMode = 0x17u,
+ kSMARTCARD_ResetWaitTimeMultiplier = 0x18u,
+} smartcard_control_t;
+
+/*! @brief Defines Smart card interface voltage class values */
+typedef enum _smartcard_card_voltage_class
+{
+ kSMARTCARD_VoltageClassUnknown = 0x0u,
+ kSMARTCARD_VoltageClassA5_0V = 0x1u,
+ kSMARTCARD_VoltageClassB3_3V = 0x2u,
+ kSMARTCARD_VoltageClassC1_8V = 0x3u
+} smartcard_card_voltage_class_t;
+
+/*! @brief Defines Smart card I/O transfer states */
+typedef enum _smartcard_transfer_state
+{
+ kSMARTCARD_IdleState = 0x0u,
+ kSMARTCARD_WaitingForTSState = 0x1u,
+ kSMARTCARD_InvalidTSDetecetedState = 0x2u,
+ kSMARTCARD_ReceivingState = 0x3u,
+ kSMARTCARD_TransmittingState = 0x4u,
+} smartcard_transfer_state_t;
+
+/*! @brief Defines Smart card reset types */
+typedef enum _smartcard_reset_type
+{
+ kSMARTCARD_ColdReset = 0x0u,
+ kSMARTCARD_WarmReset = 0x1u,
+ kSMARTCARD_NoColdReset = 0x2u,
+ kSMARTCARD_NoWarmReset = 0x3u,
+} smartcard_reset_type_t;
+
+/*! @brief Defines Smart card transport protocol types */
+typedef enum _smartcard_transport_type
+{
+ kSMARTCARD_T0Transport = 0x0u,
+ kSMARTCARD_T1Transport = 0x1u
+} smartcard_transport_type_t;
+
+/*! @brief Defines Smart card data parity types */
+typedef enum _smartcard_parity_type
+{
+ kSMARTCARD_EvenParity = 0x0u,
+ kSMARTCARD_OddParity = 0x1u
+} smartcard_parity_type_t;
+
+/*! @brief Defines data Convention format */
+typedef enum _smartcard_card_convention
+{
+ kSMARTCARD_DirectConvention = 0x0u,
+ kSMARTCARD_InverseConvention = 0x1u
+} smartcard_card_convention_t;
+
+/*! @brief Defines Smart card interface IC control types */
+typedef enum _smartcard_interface_control
+{
+ kSMARTCARD_InterfaceSetVcc = 0x00u,
+ kSMARTCARD_InterfaceSetClockToResetDelay = 0x01u,
+ kSMARTCARD_InterfaceReadStatus = 0x02u
+} smartcard_interface_control_t;
+
+/*! @brief Defines transfer direction.*/
+typedef enum _smartcard_direction
+{
+ kSMARTCARD_Receive = 0u,
+ kSMARTCARD_Transmit = 1u
+} smartcard_direction_t;
+
+/*! @brief Smart card interface interrupt callback function type */
+typedef void (*smartcard_interface_callback_t)(void *smartcardContext, void *param);
+/*! @brief Smart card transfer interrupt callback function type */
+typedef void (*smartcard_transfer_callback_t)(void *smartcardContext, void *param);
+
+/*! @brief Time Delay function used to passive waiting using RTOS [us] */
+typedef void (*smartcard_time_delay_t)(uint32_t us);
+
+/*! @brief Defines card-specific parameters for Smart card driver */
+typedef struct _smartcard_card_params
+{
+ /* ISO7816/EMV4.3 specification variables */
+ uint16_t Fi; /*!< 4 bits Fi - clock rate conversion integer */
+ uint8_t fMax; /*!< Maximum Smart card frequency in MHz */
+ uint8_t WI; /*!< 8 bits WI - work wait time integer */
+ uint8_t Di; /*!< 4 bits DI - baud rate divisor */
+ uint8_t BWI; /*!< 4 bits BWI - block wait time integer */
+ uint8_t CWI; /*!< 4 bits CWI - character wait time integer */
+ uint8_t BGI; /*!< 4 bits BGI - block guard time integer */
+ uint8_t GTN; /*!< 8 bits GTN - extended guard time integer */
+ uint8_t IFSC; /*!< Indicates IFSC value of the card */
+ uint8_t modeNegotiable; /*!< Indicates if the card acts in negotiable or a specific mode. */
+ uint8_t currentD; /*!< 4 bits DI - current baud rate divisor*/
+ /* Driver-specific variables */
+ uint8_t status; /*!< Indicates smart card status */
+ bool t0Indicated; /*!< Indicates ff T=0 indicated in TD1 byte */
+ bool t1Indicated; /*!< Indicates if T=1 indicated in TD2 byte */
+ bool atrComplete; /*!< Indicates whether the ATR received from the card was complete or not */
+ bool atrValid; /*!< Indicates whether the ATR received from the card was valid or not */
+ bool present; /*!< Indicates if a smart card is present */
+ bool active; /*!< Indicates if the smart card is activated */
+ bool faulty; /*!< Indicates whether smart card/interface is faulty */
+ smartcard_card_convention_t convention; /*!< Card convention, kSMARTCARD_DirectConvention for direct convention,
+ kSMARTCARD_InverseConvention for inverse convention */
+} smartcard_card_params_t;
+
+/*! @brief Smart card defines the state of the EMV timers in the Smart card driver */
+typedef struct _smartcard_timers_state
+{
+ volatile bool adtExpired; /*!< Indicates whether ADT timer expired */
+ volatile bool wwtExpired; /*!< Indicates whether WWT timer expired */
+ volatile bool cwtExpired; /*!< Indicates whether CWT timer expired */
+ volatile bool bwtExpired; /*!< Indicates whether BWT timer expired */
+ volatile bool initCharTimerExpired; /*!< Indicates whether reception timer
+ for initialization character (TS) after the RST has expired */
+} smartcard_timers_state_t;
+
+/*! @brief Defines user specified configuration of Smart card interface */
+typedef struct _smartcard_interface_config
+{
+ uint32_t smartCardClock; /*!< Smart card interface clock [Hz] */
+ uint32_t clockToResetDelay; /*!< Indicates clock to RST apply delay [smart card clock cycles] */
+ uint8_t clockModule; /*!< Smart card clock module number */
+ uint8_t clockModuleChannel; /*!< Smart card clock module channel number */
+ uint8_t clockModuleSourceClock; /*!< Smart card clock module source clock [e.g., BusClk] */
+ smartcard_card_voltage_class_t vcc; /*!< Smart card voltage class */
+ uint8_t controlPort; /*!< Smart card PHY control port instance */
+ uint8_t controlPin; /*!< Smart card PHY control pin instance */
+ uint8_t irqPort; /*!< Smart card PHY Interrupt port instance */
+ uint8_t irqPin; /*!< Smart card PHY Interrupt pin instance */
+ uint8_t resetPort; /*!< Smart card reset port instance */
+ uint8_t resetPin; /*!< Smart card reset pin instance */
+ uint8_t vsel0Port; /*!< Smart card PHY Vsel0 control port instance */
+ uint8_t vsel0Pin; /*!< Smart card PHY Vsel0 control pin instance */
+ uint8_t vsel1Port; /*!< Smart card PHY Vsel1 control port instance */
+ uint8_t vsel1Pin; /*!< Smart card PHY Vsel1 control pin instance */
+ uint8_t dataPort; /*!< Smart card PHY data port instance */
+ uint8_t dataPin; /*!< Smart card PHY data pin instance */
+ uint8_t dataPinMux; /*!< Smart card PHY data pin mux option */
+ uint8_t tsTimerId; /*!< Numerical identifier of the External HW timer for Initial character detection */
+} smartcard_interface_config_t;
+
+/*! @brief Defines user transfer structure used to initialize transfer */
+typedef struct _smartcard_xfer
+{
+ smartcard_direction_t direction; /*!< Direction of communication. (RX/TX) */
+ uint8_t *buff; /*!< The buffer of data. */
+ size_t size; /*!< The number of transferred units. */
+} smartcard_xfer_t;
+
+/*!
+ * @brief Runtime state of the Smart card driver.
+ */
+typedef struct _smartcard_context
+{
+ /* Xfer part */
+ void *base; /*!< Smart card module base address */
+ smartcard_direction_t direction; /*!< Direction of communication. (RX/TX) */
+ uint8_t *xBuff; /*!< The buffer of data being transferred.*/
+ volatile size_t xSize; /*!< The number of bytes to be transferred. */
+ volatile bool xIsBusy; /*!< True if there is an active transfer. */
+ uint8_t txFifoEntryCount; /*!< Number of data word entries in transmit FIFO. */
+ uint8_t rxFifoThreshold; /*!< The max value of the receiver FIFO threshold. */
+ /* Smart card Interface part */
+ smartcard_interface_callback_t interfaceCallback; /*!< Callback to invoke after interface IC raised interrupt.*/
+ smartcard_transfer_callback_t transferCallback; /*!< Callback to invoke after transfer event occur.*/
+ void *interfaceCallbackParam; /*!< Interface callback parameter pointer.*/
+ void *transferCallbackParam; /*!< Transfer callback parameter pointer.*/
+ smartcard_time_delay_t timeDelay; /*!< Function which handles time delay defined by user or RTOS. */
+ smartcard_reset_type_t resetType; /*!< Indicates whether a Cold reset or Warm reset was requested. */
+ smartcard_transport_type_t tType; /*!< Indicates current transfer protocol (T0 or T1) */
+ /* Smart card State part */
+ volatile smartcard_transfer_state_t transferState; /*!< Indicates the current transfer state */
+ smartcard_timers_state_t timersState; /*!< Indicates the state of different protocol timers used in driver */
+ smartcard_card_params_t
+ cardParams; /*!< Smart card parameters(ATR and current) and interface slots states(ATR and current) */
+ uint8_t IFSD; /*!< Indicates the terminal IFSD */
+ smartcard_parity_type_t parity; /*!< Indicates current parity even/odd */
+ volatile bool rxtCrossed; /*!< Indicates whether RXT thresholds has been crossed */
+ volatile bool txtCrossed; /*!< Indicates whether TXT thresholds has been crossed */
+ volatile bool wtxRequested; /*!< Indicates whether WTX has been requested or not*/
+ volatile bool parityError; /*!< Indicates whether a parity error has been detected */
+ uint8_t statusBytes[2]; /*!< Used to store Status bytes SW1, SW2 of the last executed card command response */
+ /* Configuration part */
+ smartcard_interface_config_t interfaceConfig; /*!< Smart card interface configuration structure */
+ bool abortTransfer; /*!< Used to abort transfer. */
+} smartcard_context_t;
+
+/*! @}*/
+#endif /* _FSL_SMARTCARD_H_*/
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.c b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.c
new file mode 100644
index 0000000000..61bca20b49
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.c
@@ -0,0 +1,1143 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2019 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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) != 0u) && ((context->xSize) > 0u))
+ {
+ /* 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) == 0u)
+ {
+ }
+ /* 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)
+ {
+ uint32_t rx_thd;
+ rx_thd = (base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK);
+ rx_thd |= context->xSize;
+ base->RX_THD = rx_thd;
+ }
+ 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 = (((uint32_t)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 = (uint8_t)(((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1u);
+ 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 = (uint8_t)(((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1u);
+ 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 = 11u + ((((uint32_t)1u << context->cardParams.BWI) + 1u) * 960u * context->cardParams.currentD);
+#ifdef CARDSIM_EXTRADELAY_USED
+ base->BWT_VAL = bwiVal + 100u;
+#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 = ((uint16_t)1u << context->cardParams.CWI) + 16u;
+#else
+ temp16 = ((uint16_t)1u << context->cardParams.CWI) + 15u;
+#endif
+ }
+ else
+ {
+#ifdef CARDSIM_EXTRADELAY_USED
+ temp16 = ((uint16_t)1u << context->cardParams.CWI) + 20u + SMARTCARD_CWT_ADJUSTMENT;
+#else
+ temp16 = ((uint16_t)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 = (uint8_t)(((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1u);
+ 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;
+ }
+}
+
+/*!
+ * brief Fills in the smartcard_card_params structure with default values according to the EMV 4.3 specification.
+ *
+ * param cardParams The configuration structure of type smartcard_interface_config_t.
+ * Function fill in members:
+ * Fi = 372;
+ * Di = 1;
+ * currentD = 1;
+ * WI = 0x0A;
+ * GTN = 0x00;
+ * with default values.
+ */
+void SMARTCARD_EMVSIM_GetDefaultConfig(smartcard_card_params_t *cardParams)
+{
+ /* Initializes the configure structure to zero. */
+ (void)memset(cardParams, 0, sizeof(*cardParams));
+
+ /* EMV default values */
+ cardParams->Fi = 372u;
+ cardParams->Di = 1u;
+ cardParams->currentD = 1u;
+ cardParams->WI = 0x0Au;
+ cardParams->GTN = 0x00u;
+}
+
+/*!
+ * brief Initializes an EMVSIM peripheral for the Smart card/ISO-7816 operation.
+ *
+ * This function un-gates the EMVSIM clock, initializes the module to EMV default settings,
+ * configures the IRQ, enables the module-level interrupt to the core and, initializes the driver context.
+ *
+ * param base The EMVSIM peripheral base address.
+ * param context A pointer to the smart card driver context structure.
+ * param srcClock_Hz Smart card clock generation module source clock.
+ *
+ * return An error code or kStatus_SMARTCARD_Success.
+ */
+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 =
+ (uint8_t)((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT);
+ /* Compute max value of rx fifo threshold */
+ context->rxFifoThreshold =
+ (uint8_t)((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 ((uint32_t)s_emvsimIRQ[instance] < (uint32_t)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;
+}
+
+/*!
+ * brief This function disables the EMVSIM interrupts, disables the transmitter and receiver,
+ * flushes the FIFOs, and gates EMVSIM clock in SIM.
+ *
+ * param base The EMVSIM module base address.
+ */
+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) != 0u)
+ {
+ while ((base->TX_STATUS & EMVSIM_TX_STATUS_ETCF_MASK) == 0u)
+ {
+ }
+ }
+ 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 ((uint32_t)s_emvsimIRQ[instance] < (uint32_t)FSL_FEATURE_INTMUX_IRQ_START_INDEX)
+ {
+ NVIC_DisableIRQ(s_emvsimIRQ[instance]);
+ }
+#else
+ NVIC_DisableIRQ(s_emvsimIRQ[instance]);
+#endif
+}
+
+/*!
+ * brief Transfer data using interrupts.
+ *
+ * A non-blocking (also known as asynchronous) function means that the function returns
+ * immediately after initiating the transfer function. The application has to get the
+ * transfer status to see when the transfer is complete. In other words, after calling the non-blocking
+ * (asynchronous) transfer function, the application must get the transfer status to check if the transmit
+ * is completed or not.
+ *
+ * param base The EMVSIM peripheral base address.
+ * param context A pointer to a smart card driver context structure.
+ * param xfer A pointer to the smart card transfer structure where the linked buffers and sizes are stored.
+ *
+ * return An error code or kStatus_SMARTCARD_Success.
+ */
+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 (0 != 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;
+}
+
+/*!
+ * brief Returns whether the previous EMVSIM transfer has finished.
+ *
+ * When performing an async transfer, call this function to ascertain the context of the
+ * current transfer: in progress (or busy) or complete (success). If the
+ * transfer is still in progress, the user can obtain the number of words that have not been
+ * transferred.
+ *
+ * param base The EMVSIM module base address.
+ * param context A pointer to a smart card driver context structure.
+ *
+ * return The number of bytes not transferred.
+ */
+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 */
+ uint32_t count;
+ count = context->xSize;
+ count += ((base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK) >> EMVSIM_TX_STATUS_TX_CNT_SHIFT);
+ return (int32_t)count;
+ }
+ return (int32_t)context->xSize;
+ }
+
+ return 0;
+}
+
+/*!
+ * brief Terminates an asynchronous EMVSIM transfer early.
+ *
+ * During an async EMVSIM transfer, the user can terminate the transfer early
+ * if the transfer is still in progress.
+ *
+ * param base The EMVSIM peripheral address.
+ * param context A pointer to a smart card driver context structure.
+ * retval kStatus_SMARTCARD_Success The transmit abort was successful.
+ * retval kStatus_SMARTCARD_NoTransmitInProgress No transmission is currently in progress.
+ */
+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;
+}
+
+/*!
+ * brief Handles EMVSIM module interrupts.
+ *
+ * param base The EMVSIM peripheral base address.
+ * param context A pointer to a smart card driver context structure.
+ */
+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) == 0u) && ((base->PCSR & EMVSIM_PCSR_SPDIF_MASK) != 0u))
+ {
+ /* Clear card presence interrupt status */
+ base->PCSR |= EMVSIM_PCSR_SPDIF_MASK;
+ /* Set PD signal edge behaviour */
+ if (((emvsim_presence_detect_edge_t)(uint32_t)((base->PCSR & EMVSIM_PCSR_SPDES_MASK) >>
+ EMVSIM_PCSR_SPDES_SHIFT) == kEMVSIM_DetectOnFallingEdge) &&
+ ((emvsim_presence_detect_status_t)(uint32_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)(uint32_t)((base->PCSR & EMVSIM_PCSR_SPDES_MASK) >>
+ EMVSIM_PCSR_SPDES_SHIFT) == kEMVSIM_DetectOnRisingEdge) &&
+ ((emvsim_presence_detect_status_t)(uint32_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 == 0u) &&
+ ((base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT0_TO_MASK) != 0u))
+ {
+ /* 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) == 0u) &&
+ ((base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT1_TO_MASK) != 0u))
+ { /* 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) != 0u)
+ {
+ 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) != 0u)
+ {
+ 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) != 0u)
+ {
+ 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) == 0u) &&
+ ((base->RX_STATUS & EMVSIM_RX_STATUS_CWT_ERR_MASK) != 0u))
+ { /* 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) == 0u) &&
+ ((base->RX_STATUS & EMVSIM_RX_STATUS_BWT_ERR_MASK) != 0u))
+ { /* 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 */
+ (void)SMARTCARD_EMVSIM_Control(base, context, kSMARTCARD_ResetWaitTimeMultiplier, 1u);
+ }
+ 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) == 0u) &&
+ ((base->RX_STATUS & EMVSIM_RX_STATUS_RX_DATA_MASK) != 0u))
+ {
+ if ((context->tType == kSMARTCARD_T1Transport) && (context->xSize > 0u) &&
+ ((base->INT_MASK & EMVSIM_INT_MASK_BWT_ERR_IM_MASK) == 0u))
+ {
+ 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) == 0u) &&
+ ((base->RX_STATUS & EMVSIM_RX_STATUS_RDTF_MASK) != 0u))
+ {
+ if (kSMARTCARD_WaitingForTSState == context->transferState)
+ {
+ /* Read byte */
+ (void)(base->RX_BUF);
+
+ if ((base->CTRL & EMVSIM_CTRL_ICM_MASK) != 0u)
+ { /* 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)(uint32_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) != 0u) && ((context->xSize) > 0u))
+ {
+ /* 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 == 0u)
+ {
+ 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 */
+ uint32_t rx_thd;
+ rx_thd = (base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK);
+ rx_thd |= context->xSize;
+ base->RX_THD = rx_thd;
+ }
+ }
+ }
+
+ /* ETC IRQ - all data from fifo is transmitted */
+ if (((base->INT_MASK & EMVSIM_INT_MASK_ETC_IM_MASK) == 0u) &&
+ ((base->TX_STATUS & EMVSIM_TX_STATUS_ETCF_MASK) != 0u))
+ {
+ smartcard_emvsim_CompleteSendData(base, context);
+ }
+
+ /* TDT IRQ - tx fifo is empty */
+ if (((base->INT_MASK & EMVSIM_INT_MASK_TDT_IM_MASK) == 0u) &&
+ ((base->TX_STATUS & EMVSIM_TX_STATUS_TDTF_MASK) != 0u))
+ {
+ if (context->xSize == 0u)
+ {
+ smartcard_emvsim_CompleteSendData(base, context);
+ }
+
+ if (context->xSize == 1u)
+ {
+ /* 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 */
+ size_t getu_tail = (size_t)(base->TX_GETU > 0u);
+ while (((context->txFifoEntryCount - (uint8_t)((base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK) >>
+ EMVSIM_TX_STATUS_TX_CNT_SHIFT)) > 0u) &&
+ (context->xSize > getu_tail))
+ {
+ /* Write data to fifo */
+ base->TX_BUF = *(context->xBuff);
+ ++context->xBuff;
+ --context->xSize;
+ }
+
+ if (context->xSize == 0u)
+ {
+ /* 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;
+ }
+ }
+ }
+ SDK_ISR_EXIT_BARRIER;
+}
+
+/*!
+ * brief Controls the EMVSIM module per different user request.
+ *
+ * param base The EMVSIM peripheral base address.
+ * param context A pointer to a smart card driver context structure.
+ * param control Control type.
+ * param param Integer value of specific to control command.
+ *
+ * return kStatus_SMARTCARD_Success in success.
+ * return kStatus_SMARTCARD_OtherError in case of error.
+ */
+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;
+ }
+
+ status_t status = kStatus_SMARTCARD_Success;
+ 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 = (((uint32_t)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) | 1u);
+ /* 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 + ((((uint32_t)1u << 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:
+ status = kStatus_SMARTCARD_InvalidInput;
+ break;
+ }
+ return status;
+}
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.h b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.h
new file mode 100644
index 0000000000..397966bc02
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_emvsim.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_SMARTCARD_EMVSIM_H_
+#define _FSL_SMARTCARD_EMVSIM_H_
+
+#include "fsl_smartcard.h"
+
+/*!
+ * @addtogroup smartcard_emvsim_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief EMV RX NACK interrupt generation threshold */
+#define SMARTCARD_EMV_RX_NACK_THRESHOLD (5u)
+
+/*! @brief EMV TX NACK interrupt generation threshold */
+#define SMARTCARD_EMV_TX_NACK_THRESHOLD (5u)
+
+/*! @brief Smart card Word Wait Timer adjustment value */
+#define SMARTCARD_WWT_ADJUSTMENT (160u)
+
+/*! @brief Smart card Character Wait Timer adjustment value */
+#define SMARTCARD_CWT_ADJUSTMENT (3u)
+
+/*! @brief General Purpose Counter clock selections */
+typedef enum _emvsim_gpc_clock_select
+{
+ kEMVSIM_GPCClockDisable = 0u, /*!< Disabled */
+ kEMVSIM_GPCCardClock = 1u, /*!< Card clock */
+ kEMVSIM_GPCRxClock = 2u, /*!< Receive clock */
+ kEMVSIM_GPCTxClock = 3u, /*!< Transmit ETU clock */
+} emvsim_gpc_clock_select_t;
+
+/*! @brief EMVSIM card presence detection edge control */
+typedef enum _presence_detect_edge
+{
+ kEMVSIM_DetectOnFallingEdge = 0u, /*!< Presence detected on the falling edge */
+ kEMVSIM_DetectOnRisingEdge = 1u, /*!< Presence detected on the rising edge */
+} emvsim_presence_detect_edge_t;
+
+/*! @brief EMVSIM card presence detection status */
+typedef enum _presence_detect_status
+{
+ kEMVSIM_DetectPinIsLow = 0u, /*!< Presence detected pin is logic low */
+ kEMVSIM_DetectPinIsHigh = 1u, /*!< Presence detected pin is logic high */
+} emvsim_presence_detect_status_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name Smart card EMVSIM Driver
+ * @{
+ */
+
+/*!
+ * @brief Fills in the smartcard_card_params structure with default values according to the EMV 4.3 specification.
+ *
+ * @param cardParams The configuration structure of type smartcard_interface_config_t.
+ * Function fill in members:
+ * Fi = 372;
+ * Di = 1;
+ * currentD = 1;
+ * WI = 0x0A;
+ * GTN = 0x00;
+ * with default values.
+ */
+void SMARTCARD_EMVSIM_GetDefaultConfig(smartcard_card_params_t *cardParams);
+
+/*!
+ * @brief Initializes an EMVSIM peripheral for the Smart card/ISO-7816 operation.
+ *
+ * This function un-gates the EMVSIM clock, initializes the module to EMV default settings,
+ * configures the IRQ, enables the module-level interrupt to the core and, initializes the driver context.
+ *
+ * @param base The EMVSIM peripheral base address.
+ * @param context A pointer to the smart card driver context structure.
+ * @param srcClock_Hz Smart card clock generation module source clock.
+ *
+ * @return An error code or kStatus_SMARTCARD_Success.
+ */
+status_t SMARTCARD_EMVSIM_Init(EMVSIM_Type *base, smartcard_context_t *context, uint32_t srcClock_Hz);
+
+/*!
+ * @brief This function disables the EMVSIM interrupts, disables the transmitter and receiver,
+ * flushes the FIFOs, and gates EMVSIM clock in SIM.
+ *
+ * @param base The EMVSIM module base address.
+ */
+void SMARTCARD_EMVSIM_Deinit(EMVSIM_Type *base);
+
+/*!
+ * @brief Returns whether the previous EMVSIM transfer has finished.
+ *
+ * When performing an async transfer, call this function to ascertain the context of the
+ * current transfer: in progress (or busy) or complete (success). If the
+ * transfer is still in progress, the user can obtain the number of words that have not been
+ * transferred.
+ *
+ * @param base The EMVSIM module base address.
+ * @param context A pointer to a smart card driver context structure.
+ *
+ * @return The number of bytes not transferred.
+ */
+int32_t SMARTCARD_EMVSIM_GetTransferRemainingBytes(EMVSIM_Type *base, smartcard_context_t *context);
+
+/*!
+ * @brief Terminates an asynchronous EMVSIM transfer early.
+ *
+ * During an async EMVSIM transfer, the user can terminate the transfer early
+ * if the transfer is still in progress.
+ *
+ * @param base The EMVSIM peripheral address.
+ * @param context A pointer to a smart card driver context structure.
+ * @retval kStatus_SMARTCARD_Success The transmit abort was successful.
+ * @retval kStatus_SMARTCARD_NoTransmitInProgress No transmission is currently in progress.
+ */
+status_t SMARTCARD_EMVSIM_AbortTransfer(EMVSIM_Type *base, smartcard_context_t *context);
+
+/*!
+ * @brief Transfer data using interrupts.
+ *
+ * A non-blocking (also known as asynchronous) function means that the function returns
+ * immediately after initiating the transfer function. The application has to get the
+ * transfer status to see when the transfer is complete. In other words, after calling the non-blocking
+ * (asynchronous) transfer function, the application must get the transfer status to check if the transmit
+ * is completed or not.
+ *
+ * @param base The EMVSIM peripheral base address.
+ * @param context A pointer to a smart card driver context structure.
+ * @param xfer A pointer to the smart card transfer structure where the linked buffers and sizes are stored.
+ *
+ * @return An error code or kStatus_SMARTCARD_Success.
+ */
+status_t SMARTCARD_EMVSIM_TransferNonBlocking(EMVSIM_Type *base, smartcard_context_t *context, smartcard_xfer_t *xfer);
+
+/*!
+ * @brief Controls the EMVSIM module per different user request.
+ *
+ * @param base The EMVSIM peripheral base address.
+ * @param context A pointer to a smart card driver context structure.
+ * @param control Control type.
+ * @param param Integer value of specific to control command.
+ *
+ * return kStatus_SMARTCARD_Success in success.
+ * return kStatus_SMARTCARD_OtherError in case of error.
+ */
+status_t SMARTCARD_EMVSIM_Control(EMVSIM_Type *base,
+ smartcard_context_t *context,
+ smartcard_control_t control,
+ uint32_t param);
+
+/*!
+ * @brief Handles EMVSIM module interrupts.
+ *
+ * @param base The EMVSIM peripheral base address.
+ * @param context A pointer to a smart card driver context structure.
+ */
+void SMARTCARD_EMVSIM_IRQHandler(EMVSIM_Type *base, smartcard_context_t *context);
+/*@}*/
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @}*/
+
+#endif /* _FSL_SMARTCARD_EMVSIM_H_*/
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy.h b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy.h
new file mode 100644
index 0000000000..21408bef76
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_SMARTCARD_PHY_H_
+#define _FSL_SMARTCARD_PHY_H_
+
+#include "fsl_smartcard.h"
+
+/*!
+ * @addtogroup smartcard_phy_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Smart card definition which specifies the adjustment number of clock cycles during which an ATR string has to
+ * be received.
+ */
+#define SMARTCARD_ATR_DURATION_ADJUSTMENT (360u)
+
+/*! @brief Smart card definition which specifies the adjustment number of clock cycles until an initial 'TS' character
+ * has to be
+ * received. */
+#define SMARTCARD_INIT_DELAY_CLOCK_CYCLES_ADJUSTMENT (4200u)
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @brief Fills in the configuration structure with default values.
+ *
+ * @param config The Smart card user configuration structure which contains configuration structure of type
+ * smartcard_interface_config_t.
+ * Function fill in members:
+ * clockToResetDelay = 42000,
+ * vcc = kSmartcardVoltageClassB3_3V,
+ * with default values.
+ */
+void SMARTCARD_PHY_GetDefaultConfig(smartcard_interface_config_t *config);
+
+/*!
+ * @brief Initializes a Smart card interface instance.
+ *
+ * @param base The Smart card peripheral base address.
+ * @param config The user configuration structure of type smartcard_interface_config_t. Call the
+ * function SMARTCARD_PHY_GetDefaultConfig() to fill the configuration structure.
+ * @param srcClock_Hz Smart card clock generation module source clock.
+ *
+ * @retval kStatus_SMARTCARD_Success or kStatus_SMARTCARD_OtherError in case of error.
+ */
+status_t SMARTCARD_PHY_Init(void *base, smartcard_interface_config_t const *config, uint32_t srcClock_Hz);
+
+/*!
+ * @brief De-initializes a Smart card interface, stops the Smart card clock, and disables the VCC.
+ *
+ * @param base The Smart card peripheral module base address.
+ * @param config The user configuration structure of type smartcard_interface_config_t.
+ */
+void SMARTCARD_PHY_Deinit(void *base, smartcard_interface_config_t const *config);
+
+/*!
+ * @brief Activates the Smart card IC.
+ *
+ * @param base The Smart card peripheral module base address.
+ * @param context A pointer to a Smart card driver context structure.
+ * @param resetType type of reset to be performed, possible values
+ * = kSmartcardColdReset, kSmartcardWarmReset
+ *
+ * @retval kStatus_SMARTCARD_Success or kStatus_SMARTCARD_OtherError in case of error.
+ */
+status_t SMARTCARD_PHY_Activate(void *base, smartcard_context_t *context, smartcard_reset_type_t resetType);
+
+/*!
+ * @brief De-activates the Smart card IC.
+ *
+ * @param base The Smart card peripheral module base address.
+ * @param context A pointer to a Smart card driver context structure.
+ *
+ * @retval kStatus_SMARTCARD_Success or kStatus_SMARTCARD_OtherError in case of error.
+ */
+status_t SMARTCARD_PHY_Deactivate(void *base, smartcard_context_t *context);
+
+/*!
+ * @brief Controls the Smart card interface IC.
+ *
+ * @param base The Smart card peripheral module base address.
+ * @param context A pointer to a Smart card driver context structure.
+ * @param control A interface command type.
+ * @param param Integer value specific to control type
+ *
+ * @retval kStatus_SMARTCARD_Success or kStatus_SMARTCARD_OtherError in case of error.
+ */
+status_t SMARTCARD_PHY_Control(void *base,
+ smartcard_context_t *context,
+ smartcard_interface_control_t control,
+ uint32_t param);
+
+/*!
+ * @brief Smart card interface IC IRQ ISR.
+ *
+ * @param base The Smart card peripheral module base address.
+ * @param context The Smart card context pointer.
+ */
+#if defined(USING_PHY_TDA8035)
+void SMARTCARD_PHY_IRQHandler(void *base, smartcard_context_t *context);
+#endif
+/*@}*/
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @}*/
+
+#endif /* _FSL_SMARTCARD_PHY_H_*/
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy_emvsim.c b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy_emvsim.c
new file mode 100644
index 0000000000..1be83f8101
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/smartcard/fsl_smartcard_phy_emvsim.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_smartcard_emvsim.h"
+#include "fsl_smartcard_phy.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.smartcard_phy_emvsim"
+#endif
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Private Functions
+ ******************************************************************************/
+static uint32_t smartcard_phy_emvsim_InterfaceClockInit(EMVSIM_Type *base,
+ const smartcard_interface_config_t *config,
+ uint32_t srcClock_Hz);
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/*!
+ * @brief This function initializes clock module used for card clock generation
+ */
+static uint32_t smartcard_phy_emvsim_InterfaceClockInit(EMVSIM_Type *base,
+ const smartcard_interface_config_t *config,
+ uint32_t srcClock_Hz)
+{
+ assert((NULL != config) && (0u != srcClock_Hz));
+
+ uint32_t emvsimClkMhz = 0u;
+ uint8_t emvsimPRSCValue;
+
+ /* Retrieve EMV SIM clock */
+ emvsimClkMhz = srcClock_Hz / 1000000u;
+ /* Calculate MOD value */
+ emvsimPRSCValue = (uint8_t)((emvsimClkMhz * 1000u) / (config->smartCardClock / 1000u));
+ /* Set clock prescaler */
+ base->CLKCFG = (base->CLKCFG & ~EMVSIM_CLKCFG_CLK_PRSC_MASK) | EMVSIM_CLKCFG_CLK_PRSC(emvsimPRSCValue);
+
+ return config->smartCardClock;
+}
+
+void SMARTCARD_PHY_GetDefaultConfig(smartcard_interface_config_t *config)
+{
+ assert((NULL != config));
+
+ /* Initializes the configure structure to zero. */
+ (void)memset(config, 0, sizeof(*config));
+
+ config->clockToResetDelay = SMARTCARD_INIT_DELAY_CLOCK_CYCLES;
+ config->vcc = kSMARTCARD_VoltageClassB3_3V;
+}
+
+status_t SMARTCARD_PHY_Init(void *base, smartcard_interface_config_t const *config, uint32_t srcClock_Hz)
+{
+ if ((NULL == config) || (0u == srcClock_Hz))
+ {
+ return kStatus_SMARTCARD_InvalidInput;
+ }
+ EMVSIM_Type *emvsimBase = (EMVSIM_Type *)base;
+
+ /* SMARTCARD clock initialization. Clock is still not active after this call */
+ (void)smartcard_phy_emvsim_InterfaceClockInit(emvsimBase, config, srcClock_Hz);
+
+ /* Configure EMVSIM direct interface driver interrupt occur according card presence */
+ if ((emvsimBase->PCSR & EMVSIM_PCSR_SPDP_MASK) != 0u)
+ {
+ emvsimBase->PCSR &= ~EMVSIM_PCSR_SPDES_MASK;
+ }
+ else
+ {
+ emvsimBase->PCSR |= EMVSIM_PCSR_SPDES_MASK;
+ }
+ /* Un-mask presence detect interrupt flag */
+ emvsimBase->PCSR &= ~EMVSIM_PCSR_SPDIM_MASK;
+
+ return kStatus_SMARTCARD_Success;
+}
+
+void SMARTCARD_PHY_Deinit(void *base, smartcard_interface_config_t const *config)
+{
+ assert((NULL != config));
+ /* Deactivate VCC, CLOCK */
+ ((EMVSIM_Type *)base)->PCSR &= ~(EMVSIM_PCSR_SCEN_MASK | EMVSIM_PCSR_SVCC_EN_MASK);
+}
+
+status_t SMARTCARD_PHY_Activate(void *base, smartcard_context_t *context, smartcard_reset_type_t resetType)
+{
+ if ((NULL == context) || (NULL == context->timeDelay))
+ {
+ return kStatus_SMARTCARD_InvalidInput;
+ }
+ assert(context->interfaceConfig.vcc == kSMARTCARD_VoltageClassB3_3V);
+
+ EMVSIM_Type *emvsimBase = (EMVSIM_Type *)base;
+
+ context->timersState.initCharTimerExpired = false;
+ context->resetType = resetType;
+
+ /* Disable receiver to deactivate GPC timers trigger */
+ emvsimBase->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
+ if (resetType == kSMARTCARD_ColdReset)
+ { /* Set polarity of VCC to active high, Enable VCC for SMARTCARD, Enable smart card clock */
+ emvsimBase->PCSR =
+ (emvsimBase->PCSR & ~EMVSIM_PCSR_VCCENP_MASK) | (EMVSIM_PCSR_SVCC_EN_MASK | EMVSIM_PCSR_SCEN_MASK);
+ /* Set transfer inversion to default(direct) value */
+ emvsimBase->CTRL &= ~EMVSIM_CTRL_IC_MASK;
+ }
+ else if (resetType == kSMARTCARD_WarmReset)
+ { /* Ensure that card is already active */
+ if (!context->cardParams.active)
+ { /* Card is not active;hence return */
+ return kStatus_SMARTCARD_CardNotActivated;
+ }
+ }
+ else
+ {
+ return kStatus_SMARTCARD_InvalidInput;
+ }
+ /* Set Reset low */
+ emvsimBase->PCSR &= ~EMVSIM_PCSR_SRST_MASK;
+ /* Calculate time delay needed for reset */
+ uint32_t temp =
+ ((((uint32_t)10000u * context->interfaceConfig.clockToResetDelay) / context->interfaceConfig.smartCardClock) *
+ 100u) +
+ 1u;
+ context->timeDelay(temp);
+ /* Pull reset HIGH Now to mark the end of Activation sequence */
+ emvsimBase->PCSR |= EMVSIM_PCSR_SRST_MASK;
+ /* Disable GPC timers input clock */
+ emvsimBase->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
+ /* Down counter trigger, and clear any pending counter status flag */
+ emvsimBase->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK | EMVSIM_TX_STATUS_GPCNT0_TO_MASK;
+ /* Set counter value for TS detection delay */
+ emvsimBase->GPCNT0_VAL = (SMARTCARD_INIT_DELAY_CLOCK_CYCLES + SMARTCARD_INIT_DELAY_CLOCK_CYCLES_ADJUSTMENT);
+ /* Pre-load counter value for ATR duration delay */
+ emvsimBase->GPCNT1_VAL = (SMARTCARD_EMV_ATR_DURATION_ETU + SMARTCARD_ATR_DURATION_ADJUSTMENT);
+ /* Select the clock for GPCNT for both TS detection and early start of ATR duration counter */
+ emvsimBase->CLKCFG |=
+ (EMVSIM_CLKCFG_GPCNT0_CLK_SEL(kEMVSIM_GPCCardClock) | EMVSIM_CLKCFG_GPCNT1_CLK_SEL(kEMVSIM_GPCTxClock));
+ /* Set receiver to ICM mode, Flush RX FIFO */
+ emvsimBase->CTRL |= (EMVSIM_CTRL_ICM_MASK | EMVSIM_CTRL_FLSH_RX_MASK);
+ /* Enable counter interrupt for TS detection */
+ emvsimBase->INT_MASK &= ~EMVSIM_INT_MASK_GPCNT0_IM_MASK;
+ /* Clear any pending status flags */
+ emvsimBase->RX_STATUS = 0xFFFFFFFFu;
+ /* Enable receiver */
+ emvsimBase->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
+ /* Here the card was activated */
+ context->cardParams.active = true;
+
+ return kStatus_SMARTCARD_Success;
+}
+
+status_t SMARTCARD_PHY_Deactivate(void *base, smartcard_context_t *context)
+{
+ if ((NULL == context))
+ {
+ return kStatus_SMARTCARD_InvalidInput;
+ }
+
+ EMVSIM_Type *emvsimBase = (EMVSIM_Type *)base;
+
+ /* Assert Reset */
+ emvsimBase->PCSR &= ~EMVSIM_PCSR_SRST_MASK;
+ /* Stop SMARTCARD clock generation */
+ emvsimBase->PCSR &= ~EMVSIM_PCSR_SCEN_MASK;
+ /* Deactivate card by disabling VCC */
+ emvsimBase->PCSR &= ~EMVSIM_PCSR_SVCC_EN_MASK;
+ /* According EMV 4.3 specification deactivation sequence should be done within 100ms.
+ * The period is measured from the time that RST is set to state L to the time that Vcc
+ * reaches 0.4 V or less.
+ */
+ context->timeDelay(100 * 1000);
+ /* Here the card was deactivated */
+ context->cardParams.active = false;
+
+ return kStatus_SMARTCARD_Success;
+}
+
+status_t SMARTCARD_PHY_Control(void *base,
+ smartcard_context_t *context,
+ smartcard_interface_control_t control,
+ uint32_t param)
+{
+ if ((NULL == context))
+ {
+ return kStatus_SMARTCARD_InvalidInput;
+ }
+
+ status_t status = kStatus_SMARTCARD_Success;
+
+ switch (control)
+ {
+ case kSMARTCARD_InterfaceSetVcc:
+ /* Only 3.3V interface supported by the direct interface */
+ assert((smartcard_card_voltage_class_t)param == kSMARTCARD_VoltageClassB3_3V);
+ context->interfaceConfig.vcc = (smartcard_card_voltage_class_t)param;
+ break;
+ case kSMARTCARD_InterfaceSetClockToResetDelay:
+ /* Set interface clock to Reset delay set by caller */
+ context->interfaceConfig.clockToResetDelay = param;
+ break;
+ case kSMARTCARD_InterfaceReadStatus:
+ /* Expecting active low present detect */
+ context->cardParams.present = (bool)((emvsim_presence_detect_status_t)(uint32_t)(
+ (((EMVSIM_Type *)base)->PCSR & EMVSIM_PCSR_SPDP_MASK) >>
+ EMVSIM_PCSR_SPDP_SHIFT) == kEMVSIM_DetectPinIsLow);
+ break;
+ default:
+ status = kStatus_SMARTCARD_InvalidInput;
+ break;
+ }
+
+ return status;
+}