SAM3S8/SD8 Software Package: libraries/libboard_sam3s-ek2/source/iso7816_4.c Source File

SAM3S8/SD8 Software Package 1.2

# iso7816_4.c

Go to the documentation of this file.

    00001 /* ----------------------------------------------------------------------------
    00002  *         ATMEL Microcontroller Software Support
    00003  * ----------------------------------------------------------------------------
    00004  * Copyright (c) 2009, Atmel Corporation
    00005  *
    00006  * All rights reserved.
    00007  *
    00008  * Redistribution and use in source and binary forms, with or without
    00009  * modification, are permitted provided that the following conditions are met:
    00010  *
    00011  * - Redistributions of source code must retain the above copyright notice,
    00012  * this list of conditions and the disclaimer below.
    00013  *
    00014  * Atmel's name may not be used to endorse or promote products derived from
    00015  * this software without specific prior written permission.
    00016  *
    00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
    00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
    00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
    00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00027  * ----------------------------------------------------------------------------
    00028  */
    00029
    00030 /**
    00031  * \file
    00032  *
    00033  * \section Purpose
    00034  *
    00035  * ISO 7816 driver
    00036  *
    00037  * \section Usage
    00038  *
    00039  * Explanation on the usage of the code made available through the header file.
    00040  */
    00041
    00042 /*------------------------------------------------------------------------------
    00043  *         Headers
    00044  *------------------------------------------------------------------------------*/
    00045
    00046 #include "board.h"
    00047
    00048 /*------------------------------------------------------------------------------
    00049  *         Definitions
    00050  *------------------------------------------------------------------------------*/
    00051 /** Case for APDU commands*/
    00052 #define CASE1  1
    00053 #define CASE2  2
    00054 #define CASE3  3
    00055
    00056 /** Flip flop for send and receive char */
    00057 #define USART_SEND 0
    00058 #define USART_RCV  1
    00059
    00060 #if !defined(BOARD_ISO7816_BASE_USART)
    00061   #define BOARD_ISO7816_BASE_USART USART1
    00062   #define BOARD_ISO7816_ID_USART   ID_USART1
    00063 #endif
    00064
    00065 /*-----------------------------------------------------------------------------
    00066  *          Internal variables
    00067  *-----------------------------------------------------------------------------*/
    00068 /** Variable for state of send and receive froom USART */
    00069 static uint8_t StateUsartGlobal = USART_RCV;
    00070 /** Pin reset master card */
    00071 static Pin st_pinIso7816RstMC;
    00072
    00073 /*----------------------------------------------------------------------------
    00074  *          Internal functions
    00075  *----------------------------------------------------------------------------*/
    00076
    00077 /**
    00078  * Get a character from ISO7816
    00079  * \param pCharToReceive Pointer for store the received char
    00080  * \return 0: if timeout else status of US_CSR
    00081  */
    00082 static uint32_t ISO7816_GetChar( uint8_t *pCharToReceive )
    00083 {
    00084     uint32_t status;
    00085     uint32_t timeout=0;
    00086
    00087     if( StateUsartGlobal == USART_SEND ) {
    00088         while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXEMPTY) == 0) {}
    00089         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
    00090         StateUsartGlobal = USART_RCV;
    00091     }
    00092
    00093     /* Wait USART ready for reception */
    00094     while( ((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_RXRDY) == 0) ) {
    00095         if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
    00096             TRACE_DEBUG("TimeOut\n\r");
    00097             return( 0 );
    00098         }
    00099     }
    00100
    00101     TRACE_DEBUG("T: %u\n\r", timeout);
    00102
    00103
    00104     /* At least one complete character has been received and US_RHR has not yet been read. */
    00105
    00106     /* Get a char */
    00107     *pCharToReceive = ((BOARD_ISO7816_BASE_USART->US_RHR) & 0xFF);
    00108
    00109     status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
    00110                                       US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
    00111                                       (1<<10)));
    00112
    00113     if (status != 0 ) {
    00114        /* TRACE_DEBUG("R:0x%X\n\r", status); */
    00115         TRACE_DEBUG("R:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR);
    00116         TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER );
    00117         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;
    00118     }
    00119
    00120     /* Return status */
    00121     return( status );
    00122 }
    00123
    00124
    00125 /**
    00126  * Send a char to ISO7816
    00127  * \param CharToSend char to be send
    00128  * \return status of US_CSR
    00129  */
    00130 static uint32_t ISO7816_SendChar( uint8_t CharToSend )
    00131 {
    00132     uint32_t status;
    00133
    00134     if( StateUsartGlobal == USART_RCV ) {
    00135         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
    00136         StateUsartGlobal = USART_SEND;
    00137     }
    00138
    00139     /* Wait USART ready for transmit */
    00140     while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXRDY) == 0)  {}
    00141     /* There is no character in the US_THR */
    00142
    00143     /* Transmit a char */
    00144     BOARD_ISO7816_BASE_USART->US_THR = CharToSend;
    00145
    00146     status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
    00147                                       US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
    00148                                       (1<<10)));
    00149
    00150     if (status != 0 ) {
    00151         TRACE_DEBUG("E:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR);
    00152         TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER );
    00153         BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA;
    00154     }
    00155
    00156     /* Return status */
    00157     return( status );
    00158 }
    00159
    00160
    00161 /**
    00162  *  Iso 7816 ICC power on
    00163  */
    00164 static void ISO7816_IccPowerOn( void )
    00165 {
    00166     /* Set RESET Master Card */
    00167     PIO_Set(&st_pinIso7816RstMC);
    00168 }
    00169
    00170 /*----------------------------------------------------------------------------
    00171  *          Exported functions
    00172  *----------------------------------------------------------------------------*/
    00173
    00174 /**
    00175  *  Iso 7816 ICC power off
    00176  */
    00177 void ISO7816_IccPowerOff( void )
    00178 {
    00179     /* Clear RESET Master Card */
    00180     PIO_Clear(&st_pinIso7816RstMC);
    00181 }
    00182
    00183 /**
    00184  * Transfert Block TPDU T=0
    00185  * \param pAPDU    APDU buffer
    00186  * \param pMessage Message buffer
    00187  * \param wLength  Block length
    00188  * \return         Message index
    00189  */
    00190 uint16_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
    00191                                         uint8_t *pMessage,
    00192                                         uint16_t wLength )
    00193 {
    00194     uint16_t NeNc;
    00195     uint16_t indexApdu = 4;
    00196     uint16_t indexMessage = 0;
    00197     uint8_t SW1 = 0;
    00198     uint8_t procByte;
    00199     uint8_t cmdCase;
    00200
    00201     TRACE_DEBUG("pAPDU[0]=0x%X\n\r",pAPDU[0]);
    00202     TRACE_DEBUG("pAPDU[1]=0x%X\n\r",pAPDU[1]);
    00203     TRACE_DEBUG("pAPDU[2]=0x%X\n\r",pAPDU[2]);
    00204     TRACE_DEBUG("pAPDU[3]=0x%X\n\r",pAPDU[3]);
    00205     TRACE_DEBUG("pAPDU[4]=0x%X\n\r",pAPDU[4]);
    00206     TRACE_DEBUG("pAPDU[5]=0x%X\n\r",pAPDU[5]);
    00207     TRACE_DEBUG("wlength=%d\n\r",wLength);
    00208
    00209     ISO7816_SendChar( pAPDU[0] ); /* CLA */
    00210     ISO7816_SendChar( pAPDU[1] ); /* INS */
    00211     ISO7816_SendChar( pAPDU[2] ); /* P1 */
    00212     ISO7816_SendChar( pAPDU[3] ); /* P2 */
    00213     ISO7816_SendChar( pAPDU[4] ); /* P3 */
    00214
    00215     /* Handle the four structures of command APDU */
    00216     indexApdu = 4;
    00217
    00218     if( wLength == 4 ) {
    00219         cmdCase = CASE1;
    00220         NeNc = 0;
    00221     }
    00222     else if( wLength == 5) {
    00223         cmdCase = CASE2;
    00224         NeNc = pAPDU[4]; /* C5 */
    00225         if (NeNc == 0) {
    00226             NeNc = 256;
    00227         }
    00228     }
    00229     else if( wLength == 6) {
    00230         NeNc = pAPDU[4]; /* C5 */
    00231         cmdCase = CASE3;
    00232     }
    00233     else if( wLength == 7) {
    00234         NeNc = pAPDU[4]; /* C5 */
    00235         if( NeNc == 0 ) {
    00236             cmdCase = CASE2;
    00237             NeNc = (pAPDU[5]<<8)+pAPDU[6];
    00238         }
    00239         else {
    00240             cmdCase = CASE3;
    00241         }
    00242     }
    00243     else {
    00244         NeNc = pAPDU[4]; /* C5 */
    00245         if( NeNc == 0 ) {
    00246             cmdCase = CASE3;
    00247             NeNc = (pAPDU[5]<<8)+pAPDU[6];
    00248         }
    00249         else {
    00250             cmdCase = CASE3;
    00251         }
    00252     }
    00253
    00254     TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
    00255
    00256     /* Handle Procedure Bytes */
    00257     do {
    00258         ISO7816_GetChar(&procByte);
    00259         /* Handle NULL */
    00260         if ( procByte == ISO_NULL_VAL ) {
    00261             TRACE_DEBUG("INS\n\r");
    00262             continue;
    00263         }
    00264         /* Handle SW1 */
    00265         else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
    00266             TRACE_DEBUG("SW1\n\r");
    00267             SW1 = 1;
    00268         }
    00269         /* Handle INS */
    00270         else if ( pAPDU[1] == procByte) {
    00271             TRACE_DEBUG("HdlINS\n\r");
    00272             if (cmdCase == CASE2) {
    00273                 /* receive data from card */
    00274                 do {
    00275                     ISO7816_GetChar(&pMessage[indexMessage++]);
    00276                 } while( 0 != --NeNc );
    00277             }
    00278             else {
    00279                  /* Send data */
    00280                 do {
    00281                     ISO7816_SendChar(pAPDU[indexApdu++]);
    00282                 } while( 0 != --NeNc );
    00283             }
    00284         }
    00285         /* Handle INS ^ 0xff */
    00286         else if ( pAPDU[1] == (procByte ^ 0xff)) {
    00287             TRACE_DEBUG("HdlINS+\n\r");
    00288             if (cmdCase == CASE2) {
    00289                 /* receive data from card */
    00290                 ISO7816_GetChar(&pMessage[indexMessage++]);
    00291             }
    00292             else {
    00293                 ISO7816_SendChar(pAPDU[indexApdu++]);
    00294             }
    00295             NeNc--;
    00296         }
    00297         else {
    00298             /* ?? */
    00299             TRACE_DEBUG("procByte=0x%X\n\r", procByte);
    00300             break;
    00301         }
    00302     } while (NeNc != 0);
    00303
    00304     /* Status Bytes */
    00305     if (SW1 == 0) {
    00306         ISO7816_GetChar(&pMessage[indexMessage++]); /* SW1 */
    00307     }
    00308     else {
    00309         pMessage[indexMessage++] = procByte;
    00310     }
    00311     ISO7816_GetChar(&pMessage[indexMessage++]); /* SW2 */
    00312
    00313     return( indexMessage );
    00314
    00315 }
    00316
    00317 /**
    00318  *  Escape ISO7816
    00319  */
    00320 void ISO7816_Escape( void )
    00321 {
    00322     TRACE_DEBUG("For user, if needed\n\r");
    00323 }
    00324
    00325 /**
    00326  *  Restart clock ISO7816
    00327  */
    00328 void ISO7816_RestartClock( void )
    00329 {
    00330     TRACE_DEBUG("ISO7816_RestartClock\n\r");
    00331     BOARD_ISO7816_BASE_USART->US_BRGR = 13;
    00332 }
    00333
    00334 /**
    00335  *  Stop clock ISO7816
    00336  */
    00337 void ISO7816_StopClock( void )
    00338 {
    00339     TRACE_DEBUG("ISO7816_StopClock\n\r");
    00340     BOARD_ISO7816_BASE_USART->US_BRGR = 0;
    00341 }
    00342
    00343 /**
    00344  *  T0 APDU
    00345  */
    00346 void ISO7816_toAPDU( void )
    00347 {
    00348     TRACE_DEBUG("ISO7816_toAPDU\n\r");
    00349     TRACE_DEBUG("Not supported at this time\n\r");
    00350 }
    00351
    00352 /**
    00353  * Answer To Reset (ATR)
    00354  * \param pAtr    ATR buffer
    00355  * \param pLength Pointer for store the ATR length
    00356  */
    00357 void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
    00358 {
    00359     uint32_t i;
    00360     uint32_t j;
    00361     uint32_t y;
    00362
    00363     *pLength = 0;
    00364
    00365     /* Read ATR TS */
    00366     ISO7816_GetChar(&pAtr[0]);
    00367     /* Read ATR T0 */
    00368     ISO7816_GetChar(&pAtr[1]);
    00369     y = pAtr[1] & 0xF0;
    00370     i = 2;
    00371
    00372     /* Read ATR Ti */
    00373     while (y) {
    00374
    00375         if (y & 0x10) {  /* TA[i] */
    00376             ISO7816_GetChar(&pAtr[i++]);
    00377         }
    00378         if (y & 0x20) {  /* TB[i] */
    00379             ISO7816_GetChar(&pAtr[i++]);
    00380         }
    00381         if (y & 0x40) {  /* TC[i] */
    00382             ISO7816_GetChar(&pAtr[i++]);
    00383         }
    00384         if (y & 0x80) {  /* TD[i] */
    00385             ISO7816_GetChar(&pAtr[i]);
    00386             y =  pAtr[i++] & 0xF0;
    00387         }
    00388         else {
    00389             y = 0;
    00390         }
    00391     }
    00392
    00393     /* Historical Bytes */
    00394     y = pAtr[1] & 0x0F;
    00395     for( j=0; j < y; j++ ) {
    00396         ISO7816_GetChar(&pAtr[i++]);
    00397     }
    00398
    00399     *pLength = i;
    00400
    00401 }
    00402
    00403 /**
    00404  * Set data rate and clock frequency
    00405  * \param dwClockFrequency ICC clock frequency in KHz.
    00406  * \param dwDataRate       ICC data rate in bpd
    00407  */
    00408 void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate )
    00409 {
    00410     uint8_t ClockFrequency;
    00411
    00412     /* Define the baud rate divisor register */
    00413     /* CD  = MCK / SCK */
    00414     /* SCK = FIDI x BAUD = 372 x 9600 */
    00415     /* BOARD_MCK */
    00416     /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
    00417     BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
    00418
    00419     ClockFrequency = BOARD_MCK / BOARD_ISO7816_BASE_USART->US_BRGR;
    00420
    00421     BOARD_ISO7816_BASE_USART->US_FIDI = (ClockFrequency)/dwDataRate;
    00422
    00423 }
    00424
    00425 /**
    00426  * Pin status for ISO7816 RESET
    00427  * \return 1 if the Pin RstMC is high; otherwise 0.
    00428  */
    00429 uint8_t ISO7816_StatusReset( void )
    00430 {
    00431     return PIO_Get(&st_pinIso7816RstMC);
    00432 }
    00433
    00434 /**
    00435  *  cold reset
    00436  */
    00437 void ISO7816_cold_reset( void )
    00438 {
    00439     volatile uint32_t i;
    00440
    00441     /* tb: wait 400 cycles*/
    00442     for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
    00443     }
    00444
    00445     BOARD_ISO7816_BASE_USART->US_RHR;
    00446     BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
    00447
    00448     ISO7816_IccPowerOn();
    00449 }
    00450
    00451 /**
    00452  *  Warm reset
    00453  */
    00454 void ISO7816_warm_reset( void )
    00455 {
    00456     volatile uint32_t i;
    00457
    00458     ISO7816_IccPowerOff();
    00459
    00460     /* tb: wait 400 cycles */
    00461     for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) {
    00462     }
    00463
    00464     BOARD_ISO7816_BASE_USART->US_RHR;
    00465     BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
    00466
    00467     ISO7816_IccPowerOn();
    00468 }
    00469
    00470 /**
    00471  * Decode ATR trace
    00472  * \param pAtr pointer on ATR buffer
    00473  */
    00474 void ISO7816_Decode_ATR( uint8_t* pAtr )
    00475 {
    00476     uint32_t i;
    00477     uint32_t j;
    00478     uint32_t y;
    00479     uint8_t offset;
    00480
    00481     printf("\n\r");
    00482     printf("ATR: Answer To Reset:\n\r");
    00483     printf("TS = 0x%X Initial character ",pAtr[0]);
    00484     if( pAtr[0] == 0x3B ) {
    00485
    00486         printf("Direct Convention\n\r");
    00487     }
    00488     else {
    00489         if( pAtr[0] == 0x3F ) {
    00490
    00491             printf("Inverse Convention\n\r");
    00492         }
    00493         else {
    00494             printf("BAD Convention\n\r");
    00495         }
    00496     }
    00497
    00498     printf("T0 = 0x%X Format caracter\n\r",pAtr[1]);
    00499     printf("    Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
    00500     printf("    Presence further interface byte:\n\r");
    00501     if( pAtr[1]&0x80 ) {
    00502         printf("TA ");
    00503     }
    00504     if( pAtr[1]&0x40 ) {
    00505         printf("TB ");
    00506     }
    00507     if( pAtr[1]&0x20 ) {
    00508         printf("TC ");
    00509     }
    00510     if( pAtr[1]&0x10 ) {
    00511         printf("TD ");
    00512     }
    00513     if( pAtr[1] != 0 ) {
    00514         printf(" present\n\r");
    00515     }
    00516
    00517     i = 2;
    00518     y = pAtr[1] & 0xF0;
    00519
    00520     /* Read ATR Ti */
    00521     offset = 1;
    00522     while (y) {
    00523
    00524         if (y & 0x10) {  /* TA[i] */
    00525             printf("TA[%d] = 0x%X ", offset, pAtr[i]);
    00526             if( offset == 1 ) {
    00527                 printf("FI = %d ", (pAtr[i]>>8));
    00528                 printf("DI = %d", (pAtr[i]&0x0F));
    00529             }
    00530             printf("\n\r");
    00531             i++;
    00532         }
    00533         if (y & 0x20) {  /* TB[i] */
    00534             printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
    00535             i++;
    00536         }
    00537         if (y & 0x40) {  /* TC[i] */
    00538             printf("TC[%d] = 0x%X ", offset, pAtr[i]);
    00539             if( offset == 1 ) {
    00540                 printf("Extra Guard Time: N = %d", pAtr[i]);
    00541             }
    00542             printf("\n\r");
    00543             i++;
    00544         }
    00545         if (y & 0x80) {  /* TD[i] */
    00546             printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
    00547             y =  pAtr[i++] & 0xF0;
    00548         }
    00549         else {
    00550             y = 0;
    00551         }
    00552         offset++;
    00553     }
    00554
    00555     /* Historical Bytes */
    00556     printf("Historical bytes:\n\r");
    00557     y = pAtr[1] & 0x0F;
    00558     for( j=0; j < y; j++ ) {
    00559
    00560         printf(" 0x%X", pAtr[i]);
    00561         if( (pAtr[i] > 0x21) && (pAtr[i] < 0x7D) ) {  /* ASCII */
    00562             printf("(%c) ", pAtr[i]);
    00563         }
    00564         i++;
    00565     }
    00566     printf("\n\r\n\r");
    00567
    00568 }
    00569
    00570 /** Initializes a ISO driver
    00571  *  \param pPinIso7816RstMC Pin ISO 7816 Rst MC
    00572  */
    00573 void ISO7816_Init( const Pin pPinIso7816RstMC )
    00574 {
    00575     TRACE_DEBUG("ISO_Init\n\r");
    00576
    00577     /* Pin ISO7816 initialize */
    00578     st_pinIso7816RstMC  = pPinIso7816RstMC;
    00579
    00580     USART_Configure( BOARD_ISO7816_BASE_USART,
    00581                      US_MR_USART_MODE_IS07816_T_0
    00582                      | US_MR_USCLKS_MCK
    00583                      | US_MR_NBSTOP_1_BIT
    00584                      | US_MR_PAR_EVEN
    00585                      | US_MR_CHRL_8_BIT
    00586                      | US_MR_CLKO
    00587                      | (3<<24), /* MAX_ITERATION */
    00588                      1,
    00589                      0);
    00590
    00591     /* Configure USART */
    00592     PMC_EnablePeripheral(BOARD_ISO7816_ID_USART);
    00593     /* Disable interrupts */
    00594     BOARD_ISO7816_BASE_USART->US_IDR = (uint32_t) -1;
    00595
    00596     BOARD_ISO7816_BASE_USART->US_FIDI = 372;  /* by default */
    00597     /* Define the baud rate divisor register */
    00598     /* CD  = MCK / SCK */
    00599     /* SCK = FIDI x BAUD = 372 x 9600 */
    00600     /* BOARD_MCK */
    00601     /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
    00602     BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (372*9600);
    00603
    00604     /* Write the Timeguard Register */
    00605     BOARD_ISO7816_BASE_USART->US_TTGR = 5;
    00606
    00607     USART_SetTransmitterEnabled(BOARD_ISO7816_BASE_USART, 1);
    00608     USART_SetReceiverEnabled(BOARD_ISO7816_BASE_USART, 1);
    00609
    00610 }
    00611

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines