]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_MPU_M23_Nuvoton_NuMaker_PFM_M2351_IAR_GCC/Nuvoton_Code/StdDriver/src/sc.c
Add Cortex M23 GCC and IAR ports. Add demo projects for Nuvoton NuMaker-PFM-2351.
[freertos] / FreeRTOS / Demo / CORTEX_MPU_M23_Nuvoton_NuMaker_PFM_M2351_IAR_GCC / Nuvoton_Code / StdDriver / src / sc.c
1 /**************************************************************************//**\r
2  * @file     sc.c\r
3  * @version  V3.00\r
4  * @brief    Smartcard(SC) driver source file\r
5  *\r
6  * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.\r
7  *****************************************************************************/\r
8 #include "NuMicro.h"\r
9 \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
13 \r
14 /** @endcond HIDDEN_SYMBOLS */\r
15 \r
16 /** @addtogroup Standard_Driver Standard Driver\r
17   @{\r
18 */\r
19 \r
20 /** @addtogroup SC_Driver SC Driver\r
21   @{\r
22 */\r
23 \r
24 /** @addtogroup SC_EXPORTED_FUNCTIONS SC Exported Functions\r
25   @{\r
26 */\r
27 \r
28 /**\r
29   * @brief      Indicates specified smartcard slot status\r
30   *\r
31   * @param[in]  sc      The pointer of smartcard module.\r
32   *\r
33   * @return     Card insert status\r
34   * @retval     TRUE    Card insert\r
35   * @retval     FALSE   Card remove\r
36   *\r
37   * @details    This function is used to check if specified smartcard slot is presented.\r
38   */\r
39 uint32_t SC_IsCardInserted(SC_T *sc)\r
40 {\r
41     uint32_t u32Ret;\r
42 \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
46 \r
47     if(((sc == SC0) || (sc == SC0_NS)) && (g_u32CardStateIgnore[0] == 1UL))\r
48     {\r
49         u32Ret = (uint32_t)TRUE;\r
50     }\r
51     else if(((sc == SC1) || (sc == SC1_NS)) && (g_u32CardStateIgnore[1] == 1UL))\r
52     {\r
53         u32Ret = (uint32_t)TRUE;\r
54     }\r
55     else if(((sc == SC2) || (sc == SC2_NS)) && (g_u32CardStateIgnore[2] == 1UL))\r
56     {\r
57         u32Ret = (uint32_t)TRUE;\r
58     }\r
59     else if(cond1 != cond2)\r
60     {\r
61         u32Ret = (uint32_t)FALSE;\r
62     }\r
63     else\r
64     {\r
65         u32Ret = (uint32_t)TRUE;\r
66     }\r
67 \r
68     return u32Ret;\r
69 }\r
70 \r
71 /*\r
72   * @brief      Reset the Tx and Rx FIFO of smartcard module\r
73   *\r
74   * @param[in]  sc      The pointer of smartcard module.\r
75   *\r
76   * @return     None\r
77   *\r
78   * @details    This function reset both transmit and receive FIFO of specified smartcard module.\r
79   */\r
80 void SC_ClearFIFO(SC_T *sc)\r
81 {\r
82     while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)\r
83     {\r
84         ;\r
85     }\r
86     sc->ALTCTL |= (SC_ALTCTL_TXRST_Msk | SC_ALTCTL_RXRST_Msk);\r
87 }\r
88 \r
89 /**\r
90   * @brief      Disable specified smartcard module\r
91   *\r
92   * @param[in]  sc      The pointer of smartcard module.\r
93   *\r
94   * @return     None\r
95   *\r
96   * @details    This function disable specified smartcard module, and force all transition to IDLE state.\r
97   */\r
98 void SC_Close(SC_T *sc)\r
99 {\r
100     sc->INTEN = 0UL;\r
101     while(sc->PINCTL & SC_PINCTL_SYNC_Msk)\r
102     {\r
103         ;\r
104     }\r
105     sc->PINCTL = 0UL;\r
106     sc->ALTCTL = 0UL;\r
107     while(sc->CTL & SC_CTL_SYNC_Msk)\r
108     {\r
109         ;\r
110     }\r
111     sc->CTL = 0UL;\r
112 }\r
113 \r
114 /**\r
115   * @brief      Initialized smartcard module\r
116   *\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
125   *\r
126   * @return     None\r
127   *\r
128   * @details    This function initialized smartcard module.\r
129   */\r
130 void SC_Open(SC_T *sc, uint32_t u32CardDet, uint32_t u32PWR)\r
131 {\r
132     uint32_t u32Reg = 0UL, u32Intf;\r
133 \r
134     if((sc == SC0) || (sc == SC0_NS))\r
135     {\r
136         u32Intf = 0UL;\r
137     }\r
138     else if((sc == SC1) || (sc == SC1_NS))\r
139     {\r
140         u32Intf = 1UL;\r
141     }\r
142     else\r
143     {\r
144         u32Intf = 2UL;\r
145     }\r
146 \r
147     if(u32CardDet != SC_PIN_STATE_IGNORE)\r
148     {\r
149         u32Reg = u32CardDet ? 0UL : SC_CTL_CDLV_Msk;\r
150         g_u32CardStateIgnore[u32Intf] = 0UL;\r
151     }\r
152     else\r
153     {\r
154         g_u32CardStateIgnore[u32Intf] = 1UL;\r
155     }\r
156     sc->PINCTL = u32PWR ? 0UL : SC_PINCTL_PWRINV_Msk;\r
157     while(sc->CTL & SC_CTL_SYNC_Msk)\r
158     {\r
159         ;\r
160     }\r
161     sc->CTL = SC_CTL_SCEN_Msk | SC_CTL_TMRSEL_Msk | u32Reg;\r
162 }\r
163 \r
164 /**\r
165   * @brief      Reset specified smartcard module\r
166   *\r
167   * @param[in]  sc      The pointer of smartcard module.\r
168   *\r
169   * @return     None\r
170   *\r
171   * @details    This function reset specified smartcard module to its default state for activate smartcard.\r
172   */\r
173 void SC_ResetReader(SC_T *sc)\r
174 {\r
175     uint32_t u32Intf;\r
176 \r
177     if((sc == SC0) || (sc == SC0_NS))\r
178     {\r
179         u32Intf = 0UL;\r
180     }\r
181     else if((sc == SC1) || (sc == SC1_NS))\r
182     {\r
183         u32Intf = 1UL;\r
184     }\r
185     else\r
186     {\r
187         u32Intf = 2UL;\r
188     }\r
189 \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
194     {\r
195         ;\r
196     }\r
197     sc->CTL &= ~(SC_CTL_RXTRGLV_Msk |\r
198                  SC_CTL_CDDBSEL_Msk |\r
199                  SC_CTL_TXRTY_Msk |\r
200                  SC_CTL_TXRTYEN_Msk |\r
201                  SC_CTL_RXRTY_Msk |\r
202                  SC_CTL_RXRTYEN_Msk);\r
203     while(sc->CTL & SC_CTL_SYNC_Msk)\r
204     {\r
205         ;\r
206     }\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
210     sc->RXTOUT = 0UL;\r
211     /* 372 clocks per ETU by default */\r
212     sc->ETUCTL = 371UL;\r
213 \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
216     {\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
224     }\r
225     else\r
226     {\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
235     }\r
236 \r
237     return;\r
238 }\r
239 \r
240 /**\r
241   * @brief      Set Block Guard Time (BGT)\r
242   *\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
245   *\r
246   * @return     None\r
247   *\r
248   * @details    This function is used to configure block guard time (BGT) of specified smartcard module.\r
249   */\r
250 void SC_SetBlockGuardTime(SC_T *sc, uint32_t u32BGT)\r
251 {\r
252     sc->CTL = (sc->CTL & ~SC_CTL_BGT_Msk) | ((u32BGT - 1UL) << SC_CTL_BGT_Pos);\r
253 }\r
254 \r
255 /**\r
256   * @brief      Set Character Guard Time (CGT)\r
257   *\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
260   *\r
261   * @return     None\r
262   *\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
265   */\r
266 void SC_SetCharGuardTime(SC_T *sc, uint32_t u32CGT)\r
267 {\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
270     sc->EGT = u32CGT;\r
271 }\r
272 \r
273 /**\r
274   * @brief      Stop all smartcard timer\r
275   *\r
276   * @param[in]  sc      The pointer of smartcard module.\r
277   *\r
278   * @return     None\r
279   *\r
280   * @note       This function stop the timers within specified smartcard module, \b not timer module.\r
281   */\r
282 void SC_StopAllTimer(SC_T *sc)\r
283 {\r
284     while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)\r
285     {\r
286         ;\r
287     }\r
288     sc->ALTCTL &= ~(SC_ALTCTL_CNTEN0_Msk | SC_ALTCTL_CNTEN1_Msk | SC_ALTCTL_CNTEN2_Msk);\r
289 }\r
290 \r
291 /**\r
292   * @brief      Configure and start smartcard timer\r
293   *\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
309   *\r
310   * @return     None\r
311   *\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
314   */\r
315 void SC_StartTimer(SC_T *sc, uint32_t u32TimerNum, uint32_t u32Mode, uint32_t u32ETUCount)\r
316 {\r
317     uint32_t u32Reg = u32Mode | (SC_TMRCTL0_CNT_Msk & (u32ETUCount - 1UL));\r
318     while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk)\r
319     {\r
320         ;\r
321     }\r
322     if(u32TimerNum == 0UL)\r
323     {\r
324         while(sc->TMRCTL0 & SC_TMRCTL0_SYNC_Msk)\r
325         {\r
326             ;\r
327         }\r
328         sc->TMRCTL0 = u32Reg;\r
329         sc->ALTCTL |= SC_ALTCTL_CNTEN0_Msk;\r
330     }\r
331     else if(u32TimerNum == 1UL)\r
332     {\r
333         while(sc->TMRCTL1 & SC_TMRCTL1_SYNC_Msk)\r
334         {\r
335             ;\r
336         }\r
337         sc->TMRCTL1 = u32Reg;\r
338         sc->ALTCTL |= SC_ALTCTL_CNTEN1_Msk;\r
339     }\r
340     else       /* timer 2 */\r
341     {\r
342         while(sc->TMRCTL2 & SC_TMRCTL2_SYNC_Msk)\r
343         {\r
344             ;\r
345         }\r
346         sc->TMRCTL2 = u32Reg;\r
347         sc->ALTCTL |= SC_ALTCTL_CNTEN2_Msk;\r
348     }\r
349 }\r
350 \r
351 /**\r
352   * @brief      Stop a smartcard timer\r
353   *\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
356   *\r
357   * @return     None\r
358   *\r
359   * @note       This function stop the timer within specified smartcard module, \b not timer module.\r
360   */\r
361 void SC_StopTimer(SC_T *sc, uint32_t u32TimerNum)\r
362 {\r
363     while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk) {}\r
364 \r
365     if(u32TimerNum == 0UL)      /* timer 0 */\r
366     {\r
367         sc->ALTCTL &= ~SC_ALTCTL_CNTEN0_Msk;\r
368     }\r
369     else if(u32TimerNum == 1UL) /* timer 1 */\r
370     {\r
371         sc->ALTCTL &= ~SC_ALTCTL_CNTEN1_Msk;\r
372     }\r
373     else                        /* timer 2 */\r
374     {\r
375         sc->ALTCTL &= ~SC_ALTCTL_CNTEN2_Msk;\r
376     }\r
377 }\r
378 \r
379 /**\r
380   * @brief      Get smartcard clock frequency\r
381   *\r
382   * @param[in]  sc      The pointer of smartcard module.\r
383   *\r
384   * @return     Smartcard frequency in kHZ\r
385   *\r
386   * @details    This function is used to get specified smartcard module clock frequency in kHz.\r
387   */\r
388 uint32_t SC_GetInterfaceClock(SC_T *sc)\r
389 {\r
390     uint32_t u32ClkSrc, u32Num, u32Clk = __HIRC, u32Div;\r
391 \r
392     /* Get smartcard module clock source and divider */\r
393     if((sc == SC0) || (sc == SC0_NS))\r
394     {\r
395         u32Num = 0UL;\r
396         u32ClkSrc = CLK_GetModuleClockSource(SC0_MODULE);\r
397         u32Div = CLK_GetModuleClockDivider(SC0_MODULE);\r
398     }\r
399     else if((sc == SC1) || (sc == SC1_NS))\r
400     {\r
401         u32Num = 1UL;\r
402         u32ClkSrc = CLK_GetModuleClockSource(SC1_MODULE);\r
403         u32Div = CLK_GetModuleClockDivider(SC1_MODULE);\r
404     }\r
405     else if((sc == SC2) || (sc == SC2_NS))\r
406     {\r
407         u32Num = 2UL;\r
408         u32ClkSrc = CLK_GetModuleClockSource(SC2_MODULE);\r
409         u32Div = CLK_GetModuleClockDivider(SC2_MODULE);\r
410     }\r
411     else\r
412     {\r
413         u32Clk = 0UL;\r
414     }\r
415 \r
416     if(u32Clk == 0UL)\r
417     {\r
418         ; /* Invalid sc port */\r
419     }\r
420     else\r
421     {\r
422         /* Get smartcard module clock */\r
423         if(u32ClkSrc == 0UL)\r
424         {\r
425             u32Clk = __HXT;\r
426         }\r
427         else if(u32ClkSrc == 1UL)\r
428         {\r
429             u32Clk = CLK_GetPLLClockFreq();\r
430         }\r
431         else if(u32ClkSrc == 2UL)\r
432         {\r
433             if(u32Num == 1UL)\r
434             {\r
435                 u32Clk = CLK_GetPCLK1Freq();\r
436             }\r
437             else\r
438             {\r
439                 u32Clk = CLK_GetPCLK0Freq();\r
440             }\r
441         }\r
442         else\r
443         {\r
444             u32Clk = __HIRC;\r
445         }\r
446 \r
447         u32Clk /= (u32Div + 1UL) * 1000UL;\r
448     }\r
449 \r
450     return u32Clk;\r
451 }\r
452 \r
453 /*@}*/ /* end of group SC_EXPORTED_FUNCTIONS */\r
454 \r
455 /*@}*/ /* end of group SC_Driver */\r
456 \r
457 /*@}*/ /* end of group Standard_Driver */\r
458 \r
459 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/\r