]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/AtmelFiles/libboard_sama5d3x-ek/source/iso7816_4.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS / Demo / CORTEX_A5_SAMA5D3x_Xplained_IAR / AtmelFiles / libboard_sama5d3x-ek / source / iso7816_4.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2012, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /**\r
31  * \file\r
32  *\r
33  * \section Purpose\r
34  *\r
35  * ISO 7816 driver\r
36  *\r
37  * \section Usage\r
38  *\r
39  * Explanation on the usage of the code made available through the header file.\r
40  */\r
41 \r
42 /*------------------------------------------------------------------------------\r
43  *         Headers\r
44  *------------------------------------------------------------------------------*/\r
45 \r
46 #include "board.h"\r
47 \r
48 /*------------------------------------------------------------------------------\r
49  *         Definitions\r
50  *------------------------------------------------------------------------------*/\r
51 /** Case for APDU commands*/\r
52 #define CASE1  1\r
53 #define CASE2  2\r
54 #define CASE3  3\r
55 \r
56 /** Flip flop for send and receive char */\r
57 #define USART_SEND 0\r
58 #define USART_RCV  1\r
59 \r
60 #if !defined(BOARD_ISO7816_BASE_USART)\r
61   #define BOARD_ISO7816_BASE_USART USART1\r
62   #define BOARD_ISO7816_ID_USART   ID_USART1\r
63 #endif\r
64 \r
65 /*-----------------------------------------------------------------------------\r
66  *          Internal variables\r
67  *-----------------------------------------------------------------------------*/\r
68 /** Variable for state of send and receive froom USART */\r
69 static uint8_t StateUsartGlobal = USART_RCV;\r
70 /** Pin reset master card */\r
71 static Pin st_pinIso7816RstMC;\r
72 \r
73 /*----------------------------------------------------------------------------\r
74  *          Internal functions\r
75  *----------------------------------------------------------------------------*/\r
76 \r
77 /**\r
78  * Get a character from ISO7816\r
79  * \param pCharToReceive Pointer for store the received char\r
80  * \return 0: if timeout else status of US_CSR\r
81  */\r
82 static uint32_t ISO7816_GetChar( uint8_t *pCharToReceive )\r
83 {\r
84     uint32_t status;\r
85     uint32_t timeout=0;\r
86 \r
87     if( StateUsartGlobal == USART_SEND ) {\r
88         while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXEMPTY) == 0) {}\r
89         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;\r
90         StateUsartGlobal = USART_RCV;\r
91     }\r
92 \r
93     /* Wait USART ready for reception */\r
94     while( ((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_RXRDY) == 0) ) {\r
95         if(timeout++ > 12000 * (BOARD_MCK/1000000)) {\r
96             TRACE_DEBUG("TimeOut\n\r");\r
97             return( 0 );\r
98         }\r
99     }\r
100 \r
101     TRACE_DEBUG("T: %u\n\r", timeout);\r
102 \r
103 \r
104     /* At least one complete character has been received and US_RHR has not yet been read. */\r
105 \r
106     /* Get a char */\r
107     *pCharToReceive = ((BOARD_ISO7816_BASE_USART->US_RHR) & 0xFF);\r
108 \r
109     status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|\r
110                                       US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|\r
111                                       (1<<10)));\r
112 \r
113     if (status != 0 ) {\r
114        /* TRACE_DEBUG("R:0x%X\n\r", status); */\r
115         TRACE_DEBUG("R:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR);\r
116         TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER );\r
117         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;\r
118     }\r
119 \r
120     /* Return status */\r
121     return( status );\r
122 }\r
123 \r
124 \r
125 /**\r
126  * Send a char to ISO7816\r
127  * \param CharToSend char to be send\r
128  * \return status of US_CSR\r
129  */\r
130 static uint32_t ISO7816_SendChar( uint8_t CharToSend )\r
131 {\r
132     uint32_t status;\r
133 \r
134     if( StateUsartGlobal == USART_RCV ) {\r
135         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;\r
136         StateUsartGlobal = USART_SEND;\r
137     }\r
138 \r
139     /* Wait USART ready for transmit */\r
140     while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXRDY) == 0)  {}\r
141     /* There is no character in the US_THR */\r
142 \r
143     /* Transmit a char */\r
144     BOARD_ISO7816_BASE_USART->US_THR = CharToSend;\r
145 \r
146     status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|\r
147                                       US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|\r
148                                       (1<<10)));\r
149 \r
150     if (status != 0 ) {\r
151         TRACE_DEBUG("E:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR);\r
152         TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER );\r
153         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;\r
154     }\r
155 \r
156     /* Return status */\r
157     return( status );\r
158 }\r
159 \r
160 \r
161 /**\r
162  *  Iso 7816 ICC power on\r
163  */\r
164 static void ISO7816_IccPowerOn( void )\r
165 {\r
166     /* Set RESET Master Card */\r
167     PIO_Set(&st_pinIso7816RstMC);\r
168 }\r
169 \r
170 /*----------------------------------------------------------------------------\r
171  *          Exported functions\r
172  *----------------------------------------------------------------------------*/\r
173 \r
174 /**\r
175  *  Iso 7816 ICC power off\r
176  */\r
177 void ISO7816_IccPowerOff( void )\r
178 {\r
179     /* Clear RESET Master Card */\r
180     PIO_Clear(&st_pinIso7816RstMC);\r
181 }\r
182 \r
183 /**\r
184  * Transfert Block TPDU T=0\r
185  * \param pAPDU    APDU buffer\r
186  * \param pMessage Message buffer\r
187  * \param wLength  Block length\r
188  * \return         Message index\r
189  */\r
190 uint16_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,\r
191                                        uint8_t *pMessage,\r
192                                        uint16_t wLength )\r
193 {\r
194     uint16_t NeNc;\r
195     uint16_t indexApdu = 4;\r
196     uint16_t indexMessage = 0;\r
197     uint8_t SW1 = 0;\r
198     uint8_t procByte;\r
199     uint8_t cmdCase;\r
200     uint8_t ins;\r
201 \r
202     TRACE_DEBUG("pAPDU[0]=0x%X\n\r",pAPDU[0]);\r
203     TRACE_DEBUG("pAPDU[1]=0x%X\n\r",pAPDU[1]);\r
204     TRACE_DEBUG("pAPDU[2]=0x%X\n\r",pAPDU[2]);\r
205     TRACE_DEBUG("pAPDU[3]=0x%X\n\r",pAPDU[3]);\r
206     TRACE_DEBUG("pAPDU[4]=0x%X\n\r",pAPDU[4]);\r
207     TRACE_DEBUG("pAPDU[5]=0x%X\n\r",pAPDU[5]);\r
208     TRACE_DEBUG("wlength=%d\n\r",wLength);\r
209 \r
210     ISO7816_SendChar( pAPDU[0] ); /* CLA */\r
211     ISO7816_SendChar( pAPDU[1] ); /* INS */\r
212     ISO7816_SendChar( pAPDU[2] ); /* P1 */\r
213     ISO7816_SendChar( pAPDU[3] ); /* P2 */\r
214     ISO7816_SendChar( pAPDU[4] ); /* P3 */\r
215 \r
216     /* Handle the four structures of command APDU */\r
217     indexApdu = 4;\r
218 \r
219     if( wLength == 4 ) {\r
220         cmdCase = CASE1;\r
221         NeNc = 0;\r
222     }\r
223     else if( wLength == 5) {\r
224         cmdCase = CASE2;\r
225         NeNc = pAPDU[4]; /* C5 */\r
226         if (NeNc == 0) {\r
227             NeNc = 256;\r
228         }\r
229     }\r
230     else if( wLength == 6) {\r
231         NeNc = pAPDU[4]; /* C5 */\r
232         cmdCase = CASE3;\r
233     }\r
234     else if( wLength == 7) {\r
235         NeNc = pAPDU[4]; /* C5 */\r
236         if( NeNc == 0 ) {\r
237             cmdCase = CASE2;\r
238             NeNc = (pAPDU[5]<<8)+pAPDU[6];\r
239         }\r
240         else {\r
241             cmdCase = CASE3;\r
242         }\r
243     }\r
244     else {\r
245         NeNc = pAPDU[4]; /* C5 */\r
246         if( NeNc == 0 ) {\r
247             cmdCase = CASE3;\r
248             NeNc = (pAPDU[5]<<8)+pAPDU[6];\r
249         }\r
250         else {\r
251             cmdCase = CASE3;\r
252         }\r
253     }\r
254 \r
255     TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);\r
256 \r
257     /* Handle Procedure Bytes */\r
258     do {\r
259         ISO7816_GetChar(&procByte);\r
260         ins = procByte ^ 0xff;\r
261         /* Handle NULL */\r
262         if ( procByte == ISO_NULL_VAL ) {\r
263             TRACE_DEBUG("INS\n\r");\r
264             continue;\r
265         }\r
266         /* Handle SW1 */\r
267         else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {\r
268             TRACE_DEBUG("SW1\n\r");\r
269             SW1 = 1;\r
270         }\r
271         /* Handle INS */\r
272         else if ( pAPDU[1] == procByte) {\r
273             TRACE_DEBUG("HdlINS\n\r");\r
274             if (cmdCase == CASE2) {\r
275                 /* receive data from card */\r
276                 do {\r
277                     ISO7816_GetChar(&pMessage[indexMessage++]);\r
278                 } while( 0 != --NeNc );\r
279             }\r
280             else {\r
281                  /* Send data */\r
282                 do {\r
283                     ISO7816_SendChar(pAPDU[indexApdu++]);\r
284                 } while( 0 != --NeNc );\r
285             }\r
286         }\r
287         /* Handle INS ^ 0xff */\r
288         else if ( pAPDU[1] == ins) {\r
289             TRACE_DEBUG("HdlINS+\n\r");\r
290             if (cmdCase == CASE2) {\r
291                 /* receive data from card */\r
292                 ISO7816_GetChar(&pMessage[indexMessage++]);\r
293             }\r
294             else {\r
295                 ISO7816_SendChar(pAPDU[indexApdu++]);\r
296             }\r
297             NeNc--;\r
298         }\r
299         else {\r
300             /* ?? */\r
301             TRACE_DEBUG("procByte=0x%X\n\r", procByte);\r
302             break;\r
303         }\r
304     } while (NeNc != 0);\r
305 \r
306     /* Status Bytes */\r
307     if (SW1 == 0) {\r
308         ISO7816_GetChar(&pMessage[indexMessage++]); /* SW1 */\r
309     }\r
310     else {\r
311         pMessage[indexMessage++] = procByte;\r
312     }\r
313     ISO7816_GetChar(&pMessage[indexMessage++]); /* SW2 */\r
314 \r
315     return( indexMessage );\r
316 \r
317 }\r
318 \r
319 /**\r
320  *  Escape ISO7816\r
321  */\r
322 void ISO7816_Escape( void )\r
323 {\r
324     TRACE_DEBUG("For user, if needed\n\r");\r
325 }\r
326 \r
327 /**\r
328  *  Restart clock ISO7816\r
329  */\r
330 void ISO7816_RestartClock( void )\r
331 {\r
332     TRACE_DEBUG("ISO7816_RestartClock\n\r");\r
333     BOARD_ISO7816_BASE_USART->US_BRGR = 13;\r
334 }\r
335 \r
336 /**\r
337  *  Stop clock ISO7816\r
338  */\r
339 void ISO7816_StopClock( void )\r
340 {\r
341     TRACE_DEBUG("ISO7816_StopClock\n\r");\r
342     BOARD_ISO7816_BASE_USART->US_BRGR = 0;\r
343 }\r
344 \r
345 /**\r
346  *  T0 APDU\r
347  */\r
348 void ISO7816_toAPDU( void )\r
349 {\r
350     TRACE_DEBUG("ISO7816_toAPDU\n\r");\r
351     TRACE_DEBUG("Not supported at this time\n\r");\r
352 }\r
353 \r
354 /**\r
355  * Answer To Reset (ATR)\r
356  * \param pAtr    ATR buffer\r
357  * \param pLength Pointer for store the ATR length\r
358  */\r
359 void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )\r
360 {\r
361     uint32_t i;\r
362     uint32_t j;\r
363     uint32_t y;\r
364 \r
365     *pLength = 0;\r
366 \r
367     /* Read ATR TS */\r
368     ISO7816_GetChar(&pAtr[0]);\r
369     /* Read ATR T0 */\r
370     ISO7816_GetChar(&pAtr[1]);\r
371     y = pAtr[1] & 0xF0;\r
372     i = 2;\r
373 \r
374     /* Read ATR Ti */\r
375     while (y) {\r
376 \r
377         if (y & 0x10) {  /* TA[i] */\r
378             ISO7816_GetChar(&pAtr[i++]);\r
379         }\r
380         if (y & 0x20) {  /* TB[i] */\r
381             ISO7816_GetChar(&pAtr[i++]);\r
382         }\r
383         if (y & 0x40) {  /* TC[i] */\r
384             ISO7816_GetChar(&pAtr[i++]);\r
385         }\r
386         if (y & 0x80) {  /* TD[i] */\r
387             ISO7816_GetChar(&pAtr[i]);\r
388             y =  pAtr[i++] & 0xF0;\r
389         }\r
390         else {\r
391             y = 0;\r
392         }\r
393     }\r
394 \r
395     /* Historical Bytes */\r
396     y = pAtr[1] & 0x0F;\r
397     for( j=0; j < y; j++ ) {\r
398         ISO7816_GetChar(&pAtr[i++]);\r
399     }\r
400 \r
401     *pLength = i;\r
402 \r
403 }\r
404 \r
405 /**\r
406  * Set data rate and clock frequency\r
407  * \param dwClockFrequency ICC clock frequency in KHz.\r
408  * \param dwDataRate       ICC data rate in bpd\r
409  */\r
410 void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate )\r
411 {\r
412     uint8_t ClockFrequency;\r
413 \r
414     /* Define the baud rate divisor register */\r
415     /* CD  = MCK / SCK */\r
416     /* SCK = FIDI x BAUD = 372 x 9600 */\r
417     /* BOARD_MCK */\r
418     /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */\r
419     BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);\r
420 \r
421     ClockFrequency = BOARD_MCK / BOARD_ISO7816_BASE_USART->US_BRGR;\r
422 \r
423     BOARD_ISO7816_BASE_USART->US_FIDI = (ClockFrequency)/dwDataRate;\r
424 \r
425 }\r
426 \r
427 /**\r
428  * Pin status for ISO7816 RESET\r
429  * \return 1 if the Pin RstMC is high; otherwise 0.\r
430  */\r
431 uint8_t ISO7816_StatusReset( void )\r
432 {\r
433     return PIO_Get(&st_pinIso7816RstMC);\r
434 }\r
435 \r
436 /**\r
437  *  cold reset\r
438  */\r
439 void ISO7816_cold_reset( void )\r
440 {\r
441     volatile uint32_t i;\r
442 \r
443     /* tb: wait 400 cycles*/\r
444     for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {\r
445     }\r
446 \r
447     BOARD_ISO7816_BASE_USART->US_RHR;\r
448     BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;\r
449 \r
450     ISO7816_IccPowerOn();\r
451 }\r
452 \r
453 /**\r
454  *  Warm reset\r
455  */\r
456 void ISO7816_warm_reset( void )\r
457 {\r
458     volatile uint32_t i;\r
459 \r
460     ISO7816_IccPowerOff();\r
461 \r
462     /* tb: wait 400 cycles */\r
463     for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {\r
464     }\r
465 \r
466     BOARD_ISO7816_BASE_USART->US_RHR;\r
467     BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;\r
468 \r
469     ISO7816_IccPowerOn();\r
470 }\r
471 \r
472 /**\r
473  * Decode ATR trace\r
474  * \param pAtr pointer on ATR buffer\r
475  */\r
476 void ISO7816_Decode_ATR( uint8_t* pAtr )\r
477 {\r
478     uint32_t i;\r
479     uint32_t j;\r
480     uint32_t y;\r
481     uint8_t offset;\r
482 \r
483     printf("\n\r");\r
484     printf("ATR: Answer To Reset:\n\r");\r
485     printf("TS = 0x%X Initial character ",pAtr[0]);\r
486     if( pAtr[0] == 0x3B ) {\r
487 \r
488         printf("Direct Convention\n\r");\r
489     }\r
490     else {\r
491         if( pAtr[0] == 0x3F ) {\r
492 \r
493             printf("Inverse Convention\n\r");\r
494         }\r
495         else {\r
496             printf("BAD Convention\n\r");\r
497         }\r
498     }\r
499 \r
500     printf("T0 = 0x%X Format caracter\n\r",pAtr[1]);\r
501     printf("    Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);\r
502     printf("    Presence further interface byte:\n\r");\r
503     if( pAtr[1]&0x80 ) {\r
504         printf("TA ");\r
505     }\r
506     if( pAtr[1]&0x40 ) {\r
507         printf("TB ");\r
508     }\r
509     if( pAtr[1]&0x20 ) {\r
510         printf("TC ");\r
511     }\r
512     if( pAtr[1]&0x10 ) {\r
513         printf("TD ");\r
514     }\r
515     if( pAtr[1] != 0 ) {\r
516         printf(" present\n\r");\r
517     }\r
518 \r
519     i = 2;\r
520     y = pAtr[1] & 0xF0;\r
521 \r
522     /* Read ATR Ti */\r
523     offset = 1;\r
524     while (y) {\r
525 \r
526         if (y & 0x10) {  /* TA[i] */\r
527             printf("TA[%d] = 0x%X ", offset, pAtr[i]);\r
528             if( offset == 1 ) {\r
529                 printf("FI = %d ", (pAtr[i]>>8));\r
530                 printf("DI = %d", (pAtr[i]&0x0F));\r
531             }\r
532             printf("\n\r");\r
533             i++;\r
534         }\r
535         if (y & 0x20) {  /* TB[i] */\r
536             printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);\r
537             i++;\r
538         }\r
539         if (y & 0x40) {  /* TC[i] */\r
540             printf("TC[%d] = 0x%X ", offset, pAtr[i]);\r
541             if( offset == 1 ) {\r
542                 printf("Extra Guard Time: N = %d", pAtr[i]);\r
543             }\r
544             printf("\n\r");\r
545             i++;\r
546         }\r
547         if (y & 0x80) {  /* TD[i] */\r
548             printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);\r
549             y =  pAtr[i++] & 0xF0;\r
550         }\r
551         else {\r
552             y = 0;\r
553         }\r
554         offset++;\r
555     }\r
556 \r
557     /* Historical Bytes */\r
558     printf("Historical bytes:\n\r");\r
559     y = pAtr[1] & 0x0F;\r
560     for( j=0; j < y; j++ ) {\r
561 \r
562         printf(" 0x%X", pAtr[i]);\r
563         if( (pAtr[i] > 0x21) && (pAtr[i] < 0x7D) ) {  /* ASCII */\r
564             printf("(%c) ", pAtr[i]);\r
565         }\r
566         i++;\r
567     }\r
568     printf("\n\r\n\r");\r
569 \r
570 }\r
571 \r
572 /** Initializes a ISO driver\r
573  *  \param pPinIso7816RstMC Pin ISO 7816 Rst MC\r
574  */\r
575 void ISO7816_Init( const Pin pPinIso7816RstMC )\r
576 {\r
577     TRACE_DEBUG("ISO_Init\n\r");\r
578 \r
579     /* Pin ISO7816 initialize */\r
580     st_pinIso7816RstMC  = pPinIso7816RstMC;\r
581 \r
582     USART_Configure( BOARD_ISO7816_BASE_USART,\r
583                      US_MR_USART_MODE_IS07816_T_0\r
584                      | US_MR_USCLKS_MCK\r
585                      | US_MR_NBSTOP_1_BIT\r
586                      | US_MR_PAR_EVEN\r
587                      | US_MR_CHRL_8_BIT\r
588                      | US_MR_CLKO\r
589                      | (3<<24), /* MAX_ITERATION */\r
590                      1,\r
591                      0);\r
592 \r
593     /* Configure USART */\r
594     PMC_EnablePeripheral(BOARD_ISO7816_ID_USART);\r
595     /* Disable interrupts */\r
596     BOARD_ISO7816_BASE_USART->US_IDR = (uint32_t) -1;\r
597 \r
598     BOARD_ISO7816_BASE_USART->US_FIDI = 372;  /* by default */\r
599     /* Define the baud rate divisor register */\r
600     /* CD  = MCK / SCK */\r
601     /* SCK = FIDI x BAUD = 372 x 9600 */\r
602     /* BOARD_MCK */\r
603     /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */\r
604     BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (372*9600);\r
605 \r
606     /* Write the Timeguard Register */\r
607     BOARD_ISO7816_BASE_USART->US_TTGR = 5;\r
608 \r
609     USART_SetTransmitterEnabled(BOARD_ISO7816_BASE_USART, 1);\r
610     USART_SetReceiverEnabled(BOARD_ISO7816_BASE_USART, 1);\r
611 \r
612 }\r
613 \r