Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smartcard_phy_emvsim.c@167:356ef919c855, 2017-06-20 (annotated)
- Committer:
- kkado
- Date:
- Tue Jun 20 11:06:37 2017 +0000
- Revision:
- 167:356ef919c855
- Parent:
- 154:37f96f9d4de2
Build 137 with reduced HSE timeout
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 154:37f96f9d4de2 | 1 | /* |
<> | 154:37f96f9d4de2 | 2 | * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. |
<> | 154:37f96f9d4de2 | 3 | * All rights reserved. |
<> | 154:37f96f9d4de2 | 4 | * |
<> | 154:37f96f9d4de2 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
<> | 154:37f96f9d4de2 | 6 | * are permitted provided that the following conditions are met: |
<> | 154:37f96f9d4de2 | 7 | * |
<> | 154:37f96f9d4de2 | 8 | * o Redistributions of source code must retain the above copyright notice, this list |
<> | 154:37f96f9d4de2 | 9 | * of conditions and the following disclaimer. |
<> | 154:37f96f9d4de2 | 10 | * |
<> | 154:37f96f9d4de2 | 11 | * o Redistributions in binary form must reproduce the above copyright notice, this |
<> | 154:37f96f9d4de2 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
<> | 154:37f96f9d4de2 | 13 | * other materials provided with the distribution. |
<> | 154:37f96f9d4de2 | 14 | * |
<> | 154:37f96f9d4de2 | 15 | * o Neither the name of Freescale Semiconductor, Inc. nor the names of its |
<> | 154:37f96f9d4de2 | 16 | * contributors may be used to endorse or promote products derived from this |
<> | 154:37f96f9d4de2 | 17 | * software without specific prior written permission. |
<> | 154:37f96f9d4de2 | 18 | * |
<> | 154:37f96f9d4de2 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
<> | 154:37f96f9d4de2 | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
<> | 154:37f96f9d4de2 | 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
<> | 154:37f96f9d4de2 | 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
<> | 154:37f96f9d4de2 | 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
<> | 154:37f96f9d4de2 | 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
<> | 154:37f96f9d4de2 | 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
<> | 154:37f96f9d4de2 | 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
<> | 154:37f96f9d4de2 | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
<> | 154:37f96f9d4de2 | 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
<> | 154:37f96f9d4de2 | 29 | */ |
<> | 154:37f96f9d4de2 | 30 | |
<> | 154:37f96f9d4de2 | 31 | #include "fsl_smartcard_emvsim.h" |
<> | 154:37f96f9d4de2 | 32 | #include "fsl_smartcard_phy_emvsim.h" |
<> | 154:37f96f9d4de2 | 33 | |
<> | 154:37f96f9d4de2 | 34 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 35 | * Variables |
<> | 154:37f96f9d4de2 | 36 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 37 | |
<> | 154:37f96f9d4de2 | 38 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 39 | * Private Functions |
<> | 154:37f96f9d4de2 | 40 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 41 | static uint32_t smartcard_phy_emvsim_InterfaceClockInit(EMVSIM_Type *base, |
<> | 154:37f96f9d4de2 | 42 | const smartcard_interface_config_t *config, |
<> | 154:37f96f9d4de2 | 43 | uint32_t srcClock_Hz); |
<> | 154:37f96f9d4de2 | 44 | |
<> | 154:37f96f9d4de2 | 45 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 46 | * Code |
<> | 154:37f96f9d4de2 | 47 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 48 | |
<> | 154:37f96f9d4de2 | 49 | /*! |
<> | 154:37f96f9d4de2 | 50 | * @brief This function initializes clock module used for card clock generation |
<> | 154:37f96f9d4de2 | 51 | */ |
<> | 154:37f96f9d4de2 | 52 | static uint32_t smartcard_phy_emvsim_InterfaceClockInit(EMVSIM_Type *base, |
<> | 154:37f96f9d4de2 | 53 | const smartcard_interface_config_t *config, |
<> | 154:37f96f9d4de2 | 54 | uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 55 | { |
<> | 154:37f96f9d4de2 | 56 | assert((NULL != config) && (0u != srcClock_Hz)); |
<> | 154:37f96f9d4de2 | 57 | |
<> | 154:37f96f9d4de2 | 58 | uint32_t emvsimClkMhz = 0u; |
<> | 154:37f96f9d4de2 | 59 | uint8_t emvsimPRSCValue; |
<> | 154:37f96f9d4de2 | 60 | |
<> | 154:37f96f9d4de2 | 61 | /* Retrieve EMV SIM clock */ |
<> | 154:37f96f9d4de2 | 62 | emvsimClkMhz = srcClock_Hz / 1000000u; |
<> | 154:37f96f9d4de2 | 63 | /* Calculate MOD value */ |
<> | 154:37f96f9d4de2 | 64 | emvsimPRSCValue = (emvsimClkMhz * 1000u) / (config->smartCardClock / 1000u); |
<> | 154:37f96f9d4de2 | 65 | /* Set clock prescaler */ |
<> | 154:37f96f9d4de2 | 66 | base->CLKCFG = (base->CLKCFG & ~EMVSIM_CLKCFG_CLK_PRSC_MASK) | EMVSIM_CLKCFG_CLK_PRSC(emvsimPRSCValue); |
<> | 154:37f96f9d4de2 | 67 | |
<> | 154:37f96f9d4de2 | 68 | return config->smartCardClock; |
<> | 154:37f96f9d4de2 | 69 | } |
<> | 154:37f96f9d4de2 | 70 | |
<> | 154:37f96f9d4de2 | 71 | void SMARTCARD_PHY_EMVSIM_GetDefaultConfig(smartcard_interface_config_t *config) |
<> | 154:37f96f9d4de2 | 72 | { |
<> | 154:37f96f9d4de2 | 73 | assert((NULL != config)); |
<> | 154:37f96f9d4de2 | 74 | |
<> | 154:37f96f9d4de2 | 75 | config->clockToResetDelay = SMARTCARD_INIT_DELAY_CLOCK_CYCLES; |
<> | 154:37f96f9d4de2 | 76 | config->vcc = kSMARTCARD_VoltageClassB3_3V; |
<> | 154:37f96f9d4de2 | 77 | } |
<> | 154:37f96f9d4de2 | 78 | |
<> | 154:37f96f9d4de2 | 79 | status_t SMARTCARD_PHY_EMVSIM_Init(EMVSIM_Type *base, smartcard_interface_config_t const *config, uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 80 | { |
<> | 154:37f96f9d4de2 | 81 | if ((NULL == config) || (0u == srcClock_Hz)) |
<> | 154:37f96f9d4de2 | 82 | { |
<> | 154:37f96f9d4de2 | 83 | return kStatus_SMARTCARD_InvalidInput; |
<> | 154:37f96f9d4de2 | 84 | } |
<> | 154:37f96f9d4de2 | 85 | |
<> | 154:37f96f9d4de2 | 86 | /* SMARTCARD clock initialization. Clock is still not active after this call */ |
<> | 154:37f96f9d4de2 | 87 | if (config->smartCardClock != smartcard_phy_emvsim_InterfaceClockInit(base, config, srcClock_Hz)) |
<> | 154:37f96f9d4de2 | 88 | { |
<> | 154:37f96f9d4de2 | 89 | return kStatus_SMARTCARD_OtherError; |
<> | 154:37f96f9d4de2 | 90 | } |
<> | 154:37f96f9d4de2 | 91 | /* Configure EMVSIM direct interface driver interrupt occur according card presence */ |
<> | 154:37f96f9d4de2 | 92 | if (base->PCSR & EMVSIM_PCSR_SPDP_MASK) |
<> | 154:37f96f9d4de2 | 93 | { |
<> | 154:37f96f9d4de2 | 94 | base->PCSR &= ~EMVSIM_PCSR_SPDES_MASK; |
<> | 154:37f96f9d4de2 | 95 | } |
<> | 154:37f96f9d4de2 | 96 | else |
<> | 154:37f96f9d4de2 | 97 | { |
<> | 154:37f96f9d4de2 | 98 | base->PCSR |= EMVSIM_PCSR_SPDES_MASK; |
<> | 154:37f96f9d4de2 | 99 | } |
<> | 154:37f96f9d4de2 | 100 | /* Un-mask presence detect interrupt flag */ |
<> | 154:37f96f9d4de2 | 101 | base->PCSR &= ~EMVSIM_PCSR_SPDIM_MASK; |
<> | 154:37f96f9d4de2 | 102 | |
<> | 154:37f96f9d4de2 | 103 | return kStatus_SMARTCARD_Success; |
<> | 154:37f96f9d4de2 | 104 | } |
<> | 154:37f96f9d4de2 | 105 | |
<> | 154:37f96f9d4de2 | 106 | void SMARTCARD_PHY_EMVSIM_Deinit(EMVSIM_Type *base, const smartcard_interface_config_t *config) |
<> | 154:37f96f9d4de2 | 107 | { |
<> | 154:37f96f9d4de2 | 108 | assert((NULL != config)); |
<> | 154:37f96f9d4de2 | 109 | /* Deactivate VCC, CLOCK */ |
<> | 154:37f96f9d4de2 | 110 | base->PCSR &= ~(EMVSIM_PCSR_SCEN_MASK | EMVSIM_PCSR_SVCC_EN_MASK); |
<> | 154:37f96f9d4de2 | 111 | } |
<> | 154:37f96f9d4de2 | 112 | |
<> | 154:37f96f9d4de2 | 113 | status_t SMARTCARD_PHY_EMVSIM_Activate(EMVSIM_Type *base, |
<> | 154:37f96f9d4de2 | 114 | smartcard_context_t *context, |
<> | 154:37f96f9d4de2 | 115 | smartcard_reset_type_t resetType) |
<> | 154:37f96f9d4de2 | 116 | { |
<> | 154:37f96f9d4de2 | 117 | if ((NULL == context) || (NULL == context->timeDelay)) |
<> | 154:37f96f9d4de2 | 118 | { |
<> | 154:37f96f9d4de2 | 119 | return kStatus_SMARTCARD_InvalidInput; |
<> | 154:37f96f9d4de2 | 120 | } |
<> | 154:37f96f9d4de2 | 121 | assert(context->interfaceConfig.vcc == kSMARTCARD_VoltageClassB3_3V); |
<> | 154:37f96f9d4de2 | 122 | |
<> | 154:37f96f9d4de2 | 123 | context->timersState.initCharTimerExpired = false; |
<> | 154:37f96f9d4de2 | 124 | context->resetType = resetType; |
<> | 154:37f96f9d4de2 | 125 | |
<> | 154:37f96f9d4de2 | 126 | /* Disable receiver to deactivate GPC timers trigger */ |
<> | 154:37f96f9d4de2 | 127 | base->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK; |
<> | 154:37f96f9d4de2 | 128 | if (resetType == kSMARTCARD_ColdReset) |
<> | 154:37f96f9d4de2 | 129 | { /* Set polarity of VCC to active high, Enable VCC for SMARTCARD, Enable smart card clock */ |
<> | 154:37f96f9d4de2 | 130 | base->PCSR = (base->PCSR & ~EMVSIM_PCSR_VCCENP_MASK) | (EMVSIM_PCSR_SVCC_EN_MASK | EMVSIM_PCSR_SCEN_MASK); |
<> | 154:37f96f9d4de2 | 131 | /* Set transfer inversion to default(direct) value */ |
<> | 154:37f96f9d4de2 | 132 | base->CTRL &= ~EMVSIM_CTRL_IC_MASK; |
<> | 154:37f96f9d4de2 | 133 | } |
<> | 154:37f96f9d4de2 | 134 | else if (resetType == kSMARTCARD_WarmReset) |
<> | 154:37f96f9d4de2 | 135 | { /* Ensure that card is already active */ |
<> | 154:37f96f9d4de2 | 136 | if (!context->cardParams.active) |
<> | 154:37f96f9d4de2 | 137 | { /* Card is not active;hence return */ |
<> | 154:37f96f9d4de2 | 138 | return kStatus_SMARTCARD_CardNotActivated; |
<> | 154:37f96f9d4de2 | 139 | } |
<> | 154:37f96f9d4de2 | 140 | } |
<> | 154:37f96f9d4de2 | 141 | else |
<> | 154:37f96f9d4de2 | 142 | { |
<> | 154:37f96f9d4de2 | 143 | return kStatus_SMARTCARD_InvalidInput; |
<> | 154:37f96f9d4de2 | 144 | } |
<> | 154:37f96f9d4de2 | 145 | /* Set Reset low */ |
<> | 154:37f96f9d4de2 | 146 | base->PCSR &= ~EMVSIM_PCSR_SRST_MASK; |
<> | 154:37f96f9d4de2 | 147 | /* Calculate time delay needed for reset */ |
<> | 154:37f96f9d4de2 | 148 | uint32_t temp = (uint32_t)((float)(1 + (float)(((float)(1000u * context->interfaceConfig.clockToResetDelay)) / |
<> | 154:37f96f9d4de2 | 149 | ((float)context->interfaceConfig.smartCardClock / 1000)))); |
<> | 154:37f96f9d4de2 | 150 | context->timeDelay(temp); |
<> | 154:37f96f9d4de2 | 151 | /* Pull reset HIGH Now to mark the end of Activation sequence */ |
<> | 154:37f96f9d4de2 | 152 | base->PCSR |= EMVSIM_PCSR_SRST_MASK; |
<> | 154:37f96f9d4de2 | 153 | /* Disable GPC timers input clock */ |
<> | 154:37f96f9d4de2 | 154 | base->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK); |
<> | 154:37f96f9d4de2 | 155 | /* Down counter trigger, and clear any pending counter status flag */ |
<> | 154:37f96f9d4de2 | 156 | base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK | EMVSIM_TX_STATUS_GPCNT0_TO_MASK; |
<> | 154:37f96f9d4de2 | 157 | /* Set counter value for TS detection delay */ |
<> | 154:37f96f9d4de2 | 158 | base->GPCNT0_VAL = (SMARTCARD_INIT_DELAY_CLOCK_CYCLES + SMARTCARD_INIT_DELAY_CLOCK_CYCLES_ADJUSTMENT); |
<> | 154:37f96f9d4de2 | 159 | /* Pre-load counter value for ATR duration delay */ |
<> | 154:37f96f9d4de2 | 160 | base->GPCNT1_VAL = (SMARTCARD_EMV_ATR_DURATION_ETU + SMARTCARD_ATR_DURATION_ADJUSTMENT); |
<> | 154:37f96f9d4de2 | 161 | /* Select the clock for GPCNT for both TS detection and early start of ATR duration counter */ |
<> | 154:37f96f9d4de2 | 162 | base->CLKCFG |= |
<> | 154:37f96f9d4de2 | 163 | (EMVSIM_CLKCFG_GPCNT0_CLK_SEL(kEMVSIM_GPCCardClock) | EMVSIM_CLKCFG_GPCNT1_CLK_SEL(kEMVSIM_GPCTxClock)); |
<> | 154:37f96f9d4de2 | 164 | /* Set receiver to ICM mode, Flush RX FIFO */ |
<> | 154:37f96f9d4de2 | 165 | base->CTRL |= (EMVSIM_CTRL_ICM_MASK | EMVSIM_CTRL_FLSH_RX_MASK); |
<> | 154:37f96f9d4de2 | 166 | /* Enable counter interrupt for TS detection */ |
<> | 154:37f96f9d4de2 | 167 | base->INT_MASK &= ~EMVSIM_INT_MASK_GPCNT0_IM_MASK; |
<> | 154:37f96f9d4de2 | 168 | /* Clear any pending status flags */ |
<> | 154:37f96f9d4de2 | 169 | base->RX_STATUS = 0xFFFFFFFFu; |
<> | 154:37f96f9d4de2 | 170 | /* Enable receiver */ |
<> | 154:37f96f9d4de2 | 171 | base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK; |
<> | 154:37f96f9d4de2 | 172 | /* Here the card was activated */ |
<> | 154:37f96f9d4de2 | 173 | context->cardParams.active = true; |
<> | 154:37f96f9d4de2 | 174 | |
<> | 154:37f96f9d4de2 | 175 | return kStatus_SMARTCARD_Success; |
<> | 154:37f96f9d4de2 | 176 | } |
<> | 154:37f96f9d4de2 | 177 | |
<> | 154:37f96f9d4de2 | 178 | status_t SMARTCARD_PHY_EMVSIM_Deactivate(EMVSIM_Type *base, smartcard_context_t *context) |
<> | 154:37f96f9d4de2 | 179 | { |
<> | 154:37f96f9d4de2 | 180 | if ((NULL == context)) |
<> | 154:37f96f9d4de2 | 181 | { |
<> | 154:37f96f9d4de2 | 182 | return kStatus_SMARTCARD_InvalidInput; |
<> | 154:37f96f9d4de2 | 183 | } |
<> | 154:37f96f9d4de2 | 184 | |
<> | 154:37f96f9d4de2 | 185 | /* Assert Reset */ |
<> | 154:37f96f9d4de2 | 186 | base->PCSR &= ~EMVSIM_PCSR_SRST_MASK; |
<> | 154:37f96f9d4de2 | 187 | /* Stop SMARTCARD clock generation */ |
<> | 154:37f96f9d4de2 | 188 | base->PCSR &= ~EMVSIM_PCSR_SCEN_MASK; |
<> | 154:37f96f9d4de2 | 189 | /* Deactivate card by disabling VCC */ |
<> | 154:37f96f9d4de2 | 190 | base->PCSR &= ~EMVSIM_PCSR_SVCC_EN_MASK; |
<> | 154:37f96f9d4de2 | 191 | /* According EMV 4.3 specification deactivation sequence should be done within 100ms. |
<> | 154:37f96f9d4de2 | 192 | * The period is measured from the time that RST is set to state L to the time that Vcc |
<> | 154:37f96f9d4de2 | 193 | * reaches 0.4 V or less. |
<> | 154:37f96f9d4de2 | 194 | */ |
<> | 154:37f96f9d4de2 | 195 | context->timeDelay(100 * 1000); |
<> | 154:37f96f9d4de2 | 196 | /* Here the card was deactivated */ |
<> | 154:37f96f9d4de2 | 197 | context->cardParams.active = false; |
<> | 154:37f96f9d4de2 | 198 | |
<> | 154:37f96f9d4de2 | 199 | return kStatus_SMARTCARD_Success; |
<> | 154:37f96f9d4de2 | 200 | } |
<> | 154:37f96f9d4de2 | 201 | |
<> | 154:37f96f9d4de2 | 202 | status_t SMARTCARD_PHY_EMVSIM_Control(EMVSIM_Type *base, |
<> | 154:37f96f9d4de2 | 203 | smartcard_context_t *context, |
<> | 154:37f96f9d4de2 | 204 | smartcard_interface_control_t control, |
<> | 154:37f96f9d4de2 | 205 | uint32_t param) |
<> | 154:37f96f9d4de2 | 206 | { |
<> | 154:37f96f9d4de2 | 207 | if ((NULL == context)) |
<> | 154:37f96f9d4de2 | 208 | { |
<> | 154:37f96f9d4de2 | 209 | return kStatus_SMARTCARD_InvalidInput; |
<> | 154:37f96f9d4de2 | 210 | } |
<> | 154:37f96f9d4de2 | 211 | |
<> | 154:37f96f9d4de2 | 212 | switch (control) |
<> | 154:37f96f9d4de2 | 213 | { |
<> | 154:37f96f9d4de2 | 214 | case kSMARTCARD_InterfaceSetVcc: |
<> | 154:37f96f9d4de2 | 215 | /* Only 3.3V interface supported by the direct interface */ |
<> | 154:37f96f9d4de2 | 216 | assert((smartcard_card_voltage_class_t)param == kSMARTCARD_VoltageClassB3_3V); |
<> | 154:37f96f9d4de2 | 217 | context->interfaceConfig.vcc = (smartcard_card_voltage_class_t)param; |
<> | 154:37f96f9d4de2 | 218 | break; |
<> | 154:37f96f9d4de2 | 219 | case kSMARTCARD_InterfaceSetClockToResetDelay: |
<> | 154:37f96f9d4de2 | 220 | /* Set interface clock to Reset delay set by caller */ |
<> | 154:37f96f9d4de2 | 221 | context->interfaceConfig.clockToResetDelay = param; |
<> | 154:37f96f9d4de2 | 222 | break; |
<> | 154:37f96f9d4de2 | 223 | case kSMARTCARD_InterfaceReadStatus: |
<> | 154:37f96f9d4de2 | 224 | /* Expecting active low present detect */ |
<> | 154:37f96f9d4de2 | 225 | context->cardParams.present = |
<> | 154:37f96f9d4de2 | 226 | (emvsim_presence_detect_status_t)((base->PCSR & EMVSIM_PCSR_SPDP_MASK) >> EMVSIM_PCSR_SPDP_SHIFT) == |
<> | 154:37f96f9d4de2 | 227 | kEMVSIM_DetectPinIsLow; |
<> | 154:37f96f9d4de2 | 228 | break; |
<> | 154:37f96f9d4de2 | 229 | default: |
<> | 154:37f96f9d4de2 | 230 | return kStatus_SMARTCARD_InvalidInput; |
<> | 154:37f96f9d4de2 | 231 | } |
<> | 154:37f96f9d4de2 | 232 | |
<> | 154:37f96f9d4de2 | 233 | return kStatus_SMARTCARD_Success; |
<> | 154:37f96f9d4de2 | 234 | } |