1 /**************************************************************************//**
\r
4 * @brief Smartcard(SC) driver source file
\r
6 * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
\r
7 *****************************************************************************/
\r
10 /* Below are variables used locally by SC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */
\r
11 /** @cond HIDDEN_SYMBOLS */
\r
12 static uint32_t g_u32CardStateIgnore[SC_INTERFACE_NUM] = {0UL, 0UL, 0UL};
\r
14 /** @endcond HIDDEN_SYMBOLS */
\r
16 /** @addtogroup Standard_Driver Standard Driver
\r
20 /** @addtogroup SC_Driver SC Driver
\r
24 /** @addtogroup SC_EXPORTED_FUNCTIONS SC Exported Functions
\r
29 * @brief Indicates specified smartcard slot status
\r
31 * @param[in] sc The pointer of smartcard module.
\r
33 * @return Card insert status
\r
34 * @retval TRUE Card insert
\r
35 * @retval FALSE Card remove
\r
37 * @details This function is used to check if specified smartcard slot is presented.
\r
39 uint32_t SC_IsCardInserted(SC_T *sc)
\r
43 /* put conditions into two variable to remove IAR compilation warning */
\r
44 uint32_t cond1 = ((sc->STATUS & SC_STATUS_CDPINSTS_Msk) >> SC_STATUS_CDPINSTS_Pos);
\r
45 uint32_t cond2 = ((sc->CTL & SC_CTL_CDLV_Msk) >> SC_CTL_CDLV_Pos);
\r
47 if(((sc == SC0) || (sc == SC0_NS)) && (g_u32CardStateIgnore[0] == 1UL))
\r
49 u32Ret = (uint32_t)TRUE;
\r
51 else if(((sc == SC1) || (sc == SC1_NS)) && (g_u32CardStateIgnore[1] == 1UL))
\r
53 u32Ret = (uint32_t)TRUE;
\r
55 else if(((sc == SC2) || (sc == SC2_NS)) && (g_u32CardStateIgnore[2] == 1UL))
\r
57 u32Ret = (uint32_t)TRUE;
\r
59 else if(cond1 != cond2)
\r
61 u32Ret = (uint32_t)FALSE;
\r
65 u32Ret = (uint32_t)TRUE;
\r
72 * @brief Reset the Tx and Rx FIFO of smartcard module
\r
74 * @param[in] sc The pointer of smartcard module.
\r
78 * @details This function reset both transmit and receive FIFO of specified smartcard module.
\r
80 void SC_ClearFIFO(SC_T *sc)
\r
82 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)
\r
86 sc->ALTCTL |= (SC_ALTCTL_TXRST_Msk | SC_ALTCTL_RXRST_Msk);
\r
90 * @brief Disable specified smartcard module
\r
92 * @param[in] sc The pointer of smartcard module.
\r
96 * @details This function disable specified smartcard module, and force all transition to IDLE state.
\r
98 void SC_Close(SC_T *sc)
\r
101 while(sc->PINCTL & SC_PINCTL_SYNC_Msk)
\r
107 while(sc->CTL & SC_CTL_SYNC_Msk)
\r
115 * @brief Initialized smartcard module
\r
117 * @param[in] sc The pointer of smartcard module.
\r
118 * @param[in] u32CardDet Card detect polarity, select the SC_CD pin state which indicates card absent. Could be:
\r
119 * -\ref SC_PIN_STATE_HIGH
\r
120 * -\ref SC_PIN_STATE_LOW
\r
121 * -\ref SC_PIN_STATE_IGNORE, no card detect pin, always assumes card present.
\r
122 * @param[in] u32PWR Power off polarity, select the SC_PWR pin state which could set smartcard VCC to high level. Could be:
\r
123 * -\ref SC_PIN_STATE_HIGH
\r
124 * -\ref SC_PIN_STATE_LOW
\r
128 * @details This function initialized smartcard module.
\r
130 void SC_Open(SC_T *sc, uint32_t u32CardDet, uint32_t u32PWR)
\r
132 uint32_t u32Reg = 0UL, u32Intf;
\r
134 if((sc == SC0) || (sc == SC0_NS))
\r
138 else if((sc == SC1) || (sc == SC1_NS))
\r
147 if(u32CardDet != SC_PIN_STATE_IGNORE)
\r
149 u32Reg = u32CardDet ? 0UL : SC_CTL_CDLV_Msk;
\r
150 g_u32CardStateIgnore[u32Intf] = 0UL;
\r
154 g_u32CardStateIgnore[u32Intf] = 1UL;
\r
156 sc->PINCTL = u32PWR ? 0UL : SC_PINCTL_PWRINV_Msk;
\r
157 while(sc->CTL & SC_CTL_SYNC_Msk)
\r
161 sc->CTL = SC_CTL_SCEN_Msk | SC_CTL_TMRSEL_Msk | u32Reg;
\r
165 * @brief Reset specified smartcard module
\r
167 * @param[in] sc The pointer of smartcard module.
\r
171 * @details This function reset specified smartcard module to its default state for activate smartcard.
\r
173 void SC_ResetReader(SC_T *sc)
\r
177 if((sc == SC0) || (sc == SC0_NS))
\r
181 else if((sc == SC1) || (sc == SC1_NS))
\r
190 /* Reset FIFO, enable auto de-activation while card removal */
\r
191 sc->ALTCTL |= (SC_ALTCTL_TXRST_Msk | SC_ALTCTL_RXRST_Msk | SC_ALTCTL_ADACEN_Msk);
\r
192 /* Set Rx trigger level to 1 character, longest card detect debounce period, disable error retry (EMV ATR does not use error retry) */
\r
193 while(sc->CTL & SC_CTL_SYNC_Msk)
\r
197 sc->CTL &= ~(SC_CTL_RXTRGLV_Msk |
\r
198 SC_CTL_CDDBSEL_Msk |
\r
200 SC_CTL_TXRTYEN_Msk |
\r
202 SC_CTL_RXRTYEN_Msk);
\r
203 while(sc->CTL & SC_CTL_SYNC_Msk)
\r
207 /* Enable auto convention, and all three smartcard internal timers */
\r
208 sc->CTL |= SC_CTL_AUTOCEN_Msk | SC_CTL_TMRSEL_Msk;
\r
209 /* Disable Rx timeout */
\r
211 /* 372 clocks per ETU by default */
\r
212 sc->ETUCTL = 371UL;
\r
214 /* Enable necessary interrupt for smartcard operation */
\r
215 if(g_u32CardStateIgnore[u32Intf]) /* Do not enable card detect interrupt if card present state ignore */
\r
217 sc->INTEN = (SC_INTEN_RDAIEN_Msk |
\r
218 SC_INTEN_TERRIEN_Msk |
\r
219 SC_INTEN_TMR0IEN_Msk |
\r
220 SC_INTEN_TMR1IEN_Msk |
\r
221 SC_INTEN_TMR2IEN_Msk |
\r
222 SC_INTEN_BGTIEN_Msk |
\r
223 SC_INTEN_ACERRIEN_Msk);
\r
227 sc->INTEN = (SC_INTEN_RDAIEN_Msk |
\r
228 SC_INTEN_TERRIEN_Msk |
\r
229 SC_INTEN_TMR0IEN_Msk |
\r
230 SC_INTEN_TMR1IEN_Msk |
\r
231 SC_INTEN_TMR2IEN_Msk |
\r
232 SC_INTEN_BGTIEN_Msk |
\r
233 SC_INTEN_ACERRIEN_Msk |
\r
234 SC_INTEN_CDIEN_Msk);
\r
241 * @brief Set Block Guard Time (BGT)
\r
243 * @param[in] sc The pointer of smartcard module.
\r
244 * @param[in] u32BGT Block guard time using ETU as unit, valid range are between 1 ~ 32.
\r
248 * @details This function is used to configure block guard time (BGT) of specified smartcard module.
\r
250 void SC_SetBlockGuardTime(SC_T *sc, uint32_t u32BGT)
\r
252 sc->CTL = (sc->CTL & ~SC_CTL_BGT_Msk) | ((u32BGT - 1UL) << SC_CTL_BGT_Pos);
\r
256 * @brief Set Character Guard Time (CGT)
\r
258 * @param[in] sc The pointer of smartcard module.
\r
259 * @param[in] u32CGT Character guard time using ETU as unit, valid range are between 11 ~ 267.
\r
263 * @details This function is used to configure character guard time (CGT) of specified smartcard module.
\r
264 * @note Before using this API, user should set the correct stop bit length first.
\r
266 void SC_SetCharGuardTime(SC_T *sc, uint32_t u32CGT)
\r
268 /* CGT is "START bit" + "8-bits" + "Parity bit" + "STOP bit(s)" + "EGT counts" */
\r
269 u32CGT -= sc->CTL & SC_CTL_NSB_Msk ? 11UL : 12UL;
\r
274 * @brief Stop all smartcard timer
\r
276 * @param[in] sc The pointer of smartcard module.
\r
280 * @note This function stop the timers within specified smartcard module, \b not timer module.
\r
282 void SC_StopAllTimer(SC_T *sc)
\r
284 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)
\r
288 sc->ALTCTL &= ~(SC_ALTCTL_CNTEN0_Msk | SC_ALTCTL_CNTEN1_Msk | SC_ALTCTL_CNTEN2_Msk);
\r
292 * @brief Configure and start smartcard timer
\r
294 * @param[in] sc The pointer of smartcard module.
\r
295 * @param[in] u32TimerNum Timer to start. Valid values are 0, 1, 2.
\r
296 * @param[in] u32Mode Timer operating mode, valid values are:
\r
297 * - \ref SC_TMR_MODE_0
\r
298 * - \ref SC_TMR_MODE_1
\r
299 * - \ref SC_TMR_MODE_2
\r
300 * - \ref SC_TMR_MODE_3
\r
301 * - \ref SC_TMR_MODE_4
\r
302 * - \ref SC_TMR_MODE_5
\r
303 * - \ref SC_TMR_MODE_6
\r
304 * - \ref SC_TMR_MODE_7
\r
305 * - \ref SC_TMR_MODE_8
\r
306 * - \ref SC_TMR_MODE_F
\r
307 * @param[in] u32ETUCount Timer timeout duration, ETU based. For timer 0, valid range are between 1 ~ 0x1000000 ETUs.
\r
308 * For timer 1 and timer 2, valid range are between 1 ~ 0x100 ETUs.
\r
312 * @note This function start the timer within specified smartcard module, \b not timer module.
\r
313 * @note Depend on the timer operating mode, timer may not start counting immediately and starts when condition match.
\r
315 void SC_StartTimer(SC_T *sc, uint32_t u32TimerNum, uint32_t u32Mode, uint32_t u32ETUCount)
\r
317 uint32_t u32Reg = u32Mode | (SC_TMRCTL0_CNT_Msk & (u32ETUCount - 1UL));
\r
318 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)
\r
322 if(u32TimerNum == 0UL)
\r
324 while(sc->TMRCTL0 & SC_TMRCTL0_SYNC_Msk)
\r
328 sc->TMRCTL0 = u32Reg;
\r
329 sc->ALTCTL |= SC_ALTCTL_CNTEN0_Msk;
\r
331 else if(u32TimerNum == 1UL)
\r
333 while(sc->TMRCTL1 & SC_TMRCTL1_SYNC_Msk)
\r
337 sc->TMRCTL1 = u32Reg;
\r
338 sc->ALTCTL |= SC_ALTCTL_CNTEN1_Msk;
\r
342 while(sc->TMRCTL2 & SC_TMRCTL2_SYNC_Msk)
\r
346 sc->TMRCTL2 = u32Reg;
\r
347 sc->ALTCTL |= SC_ALTCTL_CNTEN2_Msk;
\r
352 * @brief Stop a smartcard timer
\r
354 * @param[in] sc The pointer of smartcard module.
\r
355 * @param[in] u32TimerNum Timer to stop. Valid values are 0, 1, 2.
\r
359 * @note This function stop the timer within specified smartcard module, \b not timer module.
\r
361 void SC_StopTimer(SC_T *sc, uint32_t u32TimerNum)
\r
363 while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk) {}
\r
365 if(u32TimerNum == 0UL) /* timer 0 */
\r
367 sc->ALTCTL &= ~SC_ALTCTL_CNTEN0_Msk;
\r
369 else if(u32TimerNum == 1UL) /* timer 1 */
\r
371 sc->ALTCTL &= ~SC_ALTCTL_CNTEN1_Msk;
\r
375 sc->ALTCTL &= ~SC_ALTCTL_CNTEN2_Msk;
\r
380 * @brief Get smartcard clock frequency
\r
382 * @param[in] sc The pointer of smartcard module.
\r
384 * @return Smartcard frequency in kHZ
\r
386 * @details This function is used to get specified smartcard module clock frequency in kHz.
\r
388 uint32_t SC_GetInterfaceClock(SC_T *sc)
\r
390 uint32_t u32ClkSrc, u32Num, u32Clk = __HIRC, u32Div;
\r
392 /* Get smartcard module clock source and divider */
\r
393 if((sc == SC0) || (sc == SC0_NS))
\r
396 u32ClkSrc = CLK_GetModuleClockSource(SC0_MODULE);
\r
397 u32Div = CLK_GetModuleClockDivider(SC0_MODULE);
\r
399 else if((sc == SC1) || (sc == SC1_NS))
\r
402 u32ClkSrc = CLK_GetModuleClockSource(SC1_MODULE);
\r
403 u32Div = CLK_GetModuleClockDivider(SC1_MODULE);
\r
405 else if((sc == SC2) || (sc == SC2_NS))
\r
408 u32ClkSrc = CLK_GetModuleClockSource(SC2_MODULE);
\r
409 u32Div = CLK_GetModuleClockDivider(SC2_MODULE);
\r
418 ; /* Invalid sc port */
\r
422 /* Get smartcard module clock */
\r
423 if(u32ClkSrc == 0UL)
\r
427 else if(u32ClkSrc == 1UL)
\r
429 u32Clk = CLK_GetPLLClockFreq();
\r
431 else if(u32ClkSrc == 2UL)
\r
435 u32Clk = CLK_GetPCLK1Freq();
\r
439 u32Clk = CLK_GetPCLK0Freq();
\r
447 u32Clk /= (u32Div + 1UL) * 1000UL;
\r
453 /*@}*/ /* end of group SC_EXPORTED_FUNCTIONS */
\r
455 /*@}*/ /* end of group SC_Driver */
\r
457 /*@}*/ /* end of group Standard_Driver */
\r
459 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
\r