SAMV71 Xplained Ultra Software Package 1.3

main.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, 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  * \page hsmci_sdcard Basic SD/MMC Card Example
00031  *
00032  * \section Purpose
00033  *
00034  *  The hsmci_sdcard will help you to get familiar with HSMCI interface on
00035  *  SAM Microcontrollers. It can also help you to get familiar with the SD
00036  *  operation flow which can be used for fast implementation of your own SD
00037  *  drivers and other applications related.
00038  *
00039  *  \section Requirements
00040  *
00041  *  This package can be used with SAM V71 Xplained Ultra board.
00042  *
00043  *  \section Description
00044  *
00045  *  The demonstration program detects, initialize the SD/MMC memory card
00046  *  inserted, and performs R/W test on it.
00047  *
00048  *  Open HyperTerminal before running this program, use SAM-BA to download
00049  *  this program to SRAM or Flash, make the program run, the HyperTerminal
00050  *  will give out the test results.
00051  *
00052  *  \section Usage
00053  *
00054  *  -# Build the program and download it inside the SAM V71 Xplained Ultra board. 
00055  *     Please refer to the Getting Started with SAM V71 Microcontrollers.pdf
00056  *  -# On the computer, open and configure a terminal application
00057  *     (e.g. HyperTerminal on Microsoft Windows) with these settings:
00058  *    - 115200 bauds
00059  *    - 8 bits of data
00060  *    - No parity
00061  *    - 1 stop bit
00062  *    - No flow control
00063  *  -# Start the application
00064  *  -# In HyperTerminal, it will show something like
00065  *      \code
00066  *      -- HSMCI SD/MMC Example xxx --
00067  *      -- SAMxxxxx-xx
00068  *      -- Compiled: xxx xx xxxx xx:xx:xx --
00069  *      -I- Please connect a SD card ...
00070  *      -I- SD card connection detected
00071  *      -I- Cannot check if SD card is write-protected
00072  *      -I- SD/MMC card initialization successful
00073  *      -I- Card size: *** MB
00074  *      -I- Block size: *** Bytes
00075  *      -I- Testing block [  *** -   ***] ..."
00076  *      \endcode
00077  *
00078  *  \section References
00079  *  - hsmci_sdcard/main.c
00080  *  - hsmci.h
00081  *  - pio.h
00082  *
00083  */
00084 
00085 /**
00086  *  \file
00087  *
00088  *  \section Purpose
00089  *
00090  *  This file contains all the specific code for the hsmci_sdcard example.
00091  *
00092  *  \section Contents
00093  *  The hsmci_sdcard application can be roughly broken down as follows:
00094  *     - Optional functions
00095  *        - CheckProtection
00096  *        - WaitSdConn
00097  *     - Interrupt handlers
00098  *        - ISR_Mci0
00099  *     - The main function, which implements the program behaviour
00100  *        - I/O configuration
00101  *        - SD card auto-detect and check whether SD card is write-protected
00102  *          (if supported)
00103  *        - Initialize MCI interface and installing an isr relating to MCI
00104  *        - Initialize sdcard, get necessary sdcard's parameters
00105  *        - write/read sdcard at max available SD clock
00106  */
00107 /*----------------------------------------------------------------------------
00108  *         Headers
00109  *----------------------------------------------------------------------------*/
00110 
00111 #include "board.h"
00112  
00113 #include "libsdmmc.h"
00114 #include "Media.h"
00115 #include <stdint.h>
00116 #include <stdio.h>
00117 #include <string.h>
00118 #include <assert.h>
00119 
00120 /*----------------------------------------------------------------------------
00121  *         Local definitions
00122  *----------------------------------------------------------------------------*/
00123 
00124 /** Maximum number of blocks read once */
00125 #define NB_MULTI_BLOCKS     5
00126 
00127 /** Split R/W to 2, first R/W 4 blocks then remaining */
00128 #define NB_SPLIT_MULTI      4
00129 
00130 /** Test settings: start block address (0) */
00131 #define TEST_BLOCK_START    (0)
00132 
00133 /** Test settings: end block address (total SD/MMC) */
00134 #define TEST_BLOCK_END      SD_GetNumberBlocks(&sdDrv[bMciID])
00135 
00136 /** Test settings: skip size when "skip" key pressed */
00137 #define TEST_BLOCK_SKIP     (100 * 1024 * 2)    // 100M
00138 
00139 /**  Number of errors displayed */
00140 #define NB_ERRORS           5
00141 
00142 /*----------------------------------------------------------------------------
00143  *         Local variables
00144  *----------------------------------------------------------------------------*/
00145 
00146 /** DMA driver instance */
00147 
00148 static sXdmad dmaDrv;
00149 
00150 /** MCI driver instance. */
00151 static sMcid mciDrv[BOARD_NUM_MCI];
00152 
00153 /** SDCard driver instance. */
00154 
00155 static sSdCard sdDrv[BOARD_NUM_MCI];
00156 
00157 /** Current selected MCI interface */
00158 static uint8_t bMciID = 0;
00159 
00160 /** SD card pins instance. */
00161 static const Pin pinsSd[] = {BOARD_MCI_PINS_SLOTA, BOARD_MCI_PIN_CK};
00162 
00163 /** SD card detection pin instance. */
00164 static const Pin pinsCd[] = {BOARD_MCI_PIN_CD};
00165 
00166 static uint8_t pBuffer[SDMMC_BLOCK_SIZE * NB_MULTI_BLOCKS];
00167 
00168 /** Number of errors found */
00169 static uint32_t nbErrors;
00170 /*----------------------------------------------------------------------------
00171  *         Local macros
00172  *----------------------------------------------------------------------------*/
00173 
00174 /* Defined to test Multi-Block functions */
00175 
00176 /** \def READ_MULTI
00177  *  \brief Define to test multi-read (SD_Read())
00178  *         or
00179  *         single-read is used (SD_ReadBlocks()) */
00180 #define READ_MULTI
00181 /** \def WRITE_MULTI
00182  *  \brief Define to test multi-write (SD_Write())
00183  *         or
00184  *         single-write is used (SD_WriteBlocks()) */
00185 #define WRITE_MULTI
00186 
00187 /** \macro SDT_ReadFun
00188  * Function used for SD card test reading.
00189  * \param pSd  Pointer to a SD card driver instance.
00190  * \param address  Address of the block to read.
00191  * \param nbBlocks Number of blocks to be read.
00192  * \param pData    Data buffer whose size is at least the block size.
00193  */
00194 #ifdef  READ_MULTI
00195 #define MMCT_ReadFun(pSd, blk, nbBlk, pData) \
00196     SD_Read(pSd, blk, pData, nbBlk, NULL, NULL)
00197 #else
00198 #define MMCT_ReadFun(pSd, blk, nbBlk, pData) \
00199     SD_ReadBlocks(pSd, blk, pData, nbBlk)
00200 #endif
00201 
00202 /** \macro SDT_WriteFun
00203  * Function used for SD card test writing.
00204  * \param pSd  Pointer to a SD card driver instance.
00205  * \param address  Address of the block to read.
00206  * \param nbBlocks Number of blocks to be read.
00207  * \param pData    Data buffer whose size is at least the block size.
00208  */
00209 #ifdef  WRITE_MULTI
00210 #define MMCT_WriteFun(pSd, blk, nbBlk, pData) \
00211     SD_Write(pSd, blk, pData, nbBlk, NULL, NULL)
00212 #else
00213 #define MMCT_WriteFun(pSd, blk, nbBlk, pData) \
00214     SD_WriteBlocks(pSd, blk, pData, nbBlk)
00215 #endif
00216 
00217 /*----------------------------------------------------------------------------
00218  *         Local functions
00219  *----------------------------------------------------------------------------*/
00220 
00221 /**
00222  * DMA interrupt handler.
00223  */
00224 void XDMAC_Handler(void)
00225 {
00226     XDMAD_Handler(&dmaDrv);
00227 }
00228 
00229 /**
00230  * MCI interrupt handler. Forwards the event to the MCI driver handlers.
00231  */
00232 void HSMCI_Handler(void)
00233 {
00234     MCID_Handler(&mciDrv[0]);
00235 }
00236 
00237 /*----------------------------------------------------------------------------
00238  *         Optional: SD card detection (connection, protection)
00239  *----------------------------------------------------------------------------*/
00240 
00241 /**
00242  * Configure for SD detect pin
00243  */
00244 static void CardDetectConfigure(void)
00245 {
00246     PIO_Configure(pinsCd, PIO_LISTSIZE(pinsCd));
00247     /* No protection detect pin */
00248 }
00249 
00250 /**
00251  * Return 1 if card is inserted.
00252  */
00253 static uint8_t CardIsConnected(uint8_t iMci)
00254 {
00255     return PIO_Get(&pinsCd[iMci]) ? 0 : 1;
00256 }
00257 
00258 /**
00259  * Return 1 if any card is inserted.
00260  */
00261 static uint8_t AnyCardIsConnected(void)
00262 {
00263     uint32_t i;
00264     for (i = 0; i < BOARD_NUM_MCI; i ++) {
00265         if ( CardIsConnected(i) ) {
00266             return 1;
00267         }
00268     }
00269     return 0;
00270 }
00271 
00272 /**
00273  * Return 1 if card is protected.
00274  */
00275 static uint8_t CardIsProtected(void)
00276 {
00277     printf("-I- Cannot check if SD card is write-protected\n\r");
00278     return 0;
00279 }
00280 
00281 /**
00282  * Delay some loop
00283  */
00284 static void LoopDelay(volatile unsigned int loop)
00285 {
00286     for(; loop > 0; loop --);
00287 }
00288 
00289 /**
00290  * \brief Max Error Break
00291  * Check if max number of error achieved.
00292  * \param halt Whether halt the device if error number achieved.
00293  */
00294 static uint8_t MaxErrorBreak(uint8_t halt)
00295 {
00296     if (NB_ERRORS) {
00297         if (nbErrors ++ > NB_ERRORS) {
00298             while(halt);
00299             nbErrors = 0;
00300             return 1;
00301         }
00302     }
00303     return 0;
00304 }
00305 
00306 /**
00307  * Display: Dump Splitting row
00308  */
00309 static void DumpSeperator(void)
00310 {
00311     printf("\n\r==========================================\n\r");
00312 }
00313 
00314 /**
00315  * Dump card registers
00316  * \param slot Card slot (not used now).
00317  */
00318 static void DumpCardInfo(uint8_t iMci)
00319 {
00320     sSdCard *pSd = &sdDrv[iMci];
00321 
00322     if (SD_GetCardType(pSd) & CARD_TYPE_bmSDIO) {
00323         SDIO_DumpCardInformation(pSd);
00324     }
00325     if (SD_GetCardType(pSd) & CARD_TYPE_bmSDMMC) {
00326         SD_DumpCID(pSd->CID);
00327         SD_DumpCSD(pSd->CSD);
00328     }
00329 }
00330 
00331 /**
00332  * Run tests on the inserted card
00333  * \param slot Card slot (not used now).
00334  */
00335 static uint8_t CardInit(uint8_t iMci)
00336 {
00337     sSdCard *pSd = &sdDrv[iMci];
00338     uint8_t error;
00339     uint8_t retry = 2;
00340 
00341     DumpSeperator();
00342 
00343     while(retry --) {
00344         error = SD_Init(pSd);
00345         if (error == SDMMC_OK) break;
00346     }
00347     if (error) {
00348         printf("-E- SD/MMC card initialization failed: %d\n\r", error);
00349         return 1;
00350     }
00351     printf("-I- SD/MMC card initialization successful\n\r");
00352     printf("-I- Card size: %d MB", (int)SD_GetTotalSizeKB(pSd)/1000);
00353     printf(", %d * %dB\n\r", 
00354         (int)SD_GetNumberBlocks(pSd), (int)SD_GetBlockSize(pSd));
00355     DumpCardInfo(iMci);
00356     return 0;
00357 }
00358 
00359 /**
00360  * Disk test
00361  * \param slot Card slot (not used now).
00362  * \param clr  Do block clear.
00363  * \param wr   Do block write.
00364  * \param rd   Do block read.
00365  */
00366 static void DiskTest(uint8_t iMci,
00367         uint8_t clr,
00368         uint8_t wr,
00369         uint8_t rd)
00370 {
00371     sSdCard *pSd = &sdDrv[iMci];
00372     uint8_t error = 0;
00373     uint32_t i, errcnt = 0;
00374     uint32_t multiBlock, block, splitMulti;
00375 
00376     DumpSeperator();
00377 
00378     if (pSd->bCardType == CARD_SDIO)
00379     {
00380         printf("-!- SDIO only card, please run SDIO example\n\r");
00381         return;
00382     }
00383 
00384     printf("-!- MCI %d, code: 1.clr, 2.wr, 3.rd\n\r", iMci);
00385 
00386     /* Perform tests on each block */
00387     multiBlock = 0;
00388     for (block = TEST_BLOCK_START;
00389             block < TEST_BLOCK_END;
00390             block += multiBlock) {
00391 
00392         /* Perform different single or multiple bloc operations */
00393         if (multiBlock >= 16)   multiBlock <<= 1;
00394         else                    multiBlock ++;
00395         if (multiBlock > NB_MULTI_BLOCKS)
00396             multiBlock = 1;
00397 
00398         /* Multi-block adjustment */
00399         if (block + multiBlock > TEST_BLOCK_END) {
00400             multiBlock = TEST_BLOCK_END - block;
00401         }
00402 
00403         /* ** Perform single block or multi block transfer */
00404         printf("\r-I- Testing block [%6u - %6u] ...", 
00405             (unsigned int)block, (unsigned int)(block + multiBlock -1));
00406 
00407         if (clr) {
00408             /* - Clear the block */
00409             memset(pBuffer, 0, SDMMC_BLOCK_SIZE * multiBlock);
00410             SCB_CleanDCache();
00411             for (i=0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00412                 if (pBuffer[i] != 0) {
00413                     /* Fatal error */
00414                     printf("\n\r-F- Data @ %u for write : 0x00 <> 0x%02x\n\r", 
00415                         (unsigned int)i, pBuffer[i]);
00416                     return;
00417                 }
00418             }
00419             error = MMCT_WriteFun(pSd, block, multiBlock, pBuffer);
00420             if (error) {
00421                 printf("\n\r-E- 1. Write block (%d) #%u\n\r", error, 
00422                     (unsigned int)block);
00423                 if(MaxErrorBreak(0)) return;
00424                 /* Skip following test */
00425                 continue;
00426             }
00427             __DMB();
00428             /* - Read back the data to check the write operation */
00429             memset(pBuffer, 0xFF, SDMMC_BLOCK_SIZE * multiBlock);
00430             SCB_CleanDCache();
00431             error = MMCT_ReadFun(pSd, block, multiBlock, pBuffer);
00432             if (error) {
00433                 printf("\n\r-E- 1. Read block (%d) #%u\n\r", 
00434                     error, (unsigned int)block);
00435                 if(MaxErrorBreak(0)) return;
00436                 /* Skip following test */
00437                 continue;
00438             }
00439             __DMB();
00440             for (i=0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00441                 if (pBuffer[i] != 0) {
00442                     printf("\n\r-E- 1. B%u.D[%u] : 0 <> 0x%02X\n\r", 
00443                         (unsigned int)block, (unsigned int)i, (int)pBuffer[i]);
00444                     if(MaxErrorBreak(0)) return;
00445                     /* Only find first verify error. */
00446                     break;
00447                 }
00448             }
00449         }
00450 
00451         if (wr) {
00452             /* - Write a checkerboard pattern on the block */
00453             for (i=0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00454                 if ((i & 1) == 0)  pBuffer[i] = (i & 0x55);
00455                 else               pBuffer[i] = (i & 0xAA);
00456             }
00457             SCB_CleanDCache();
00458             for (i = 0; i < multiBlock; ) {
00459                 splitMulti = ((multiBlock - i) > NB_SPLIT_MULTI) ?
00460                     NB_SPLIT_MULTI : (multiBlock - i);
00461                 error = MMCT_WriteFun(pSd,
00462                         block + i,
00463                         splitMulti,
00464                         &pBuffer[i * SDMMC_BLOCK_SIZE]);
00465                 if (error) break;
00466                 i += splitMulti;
00467             }
00468             __DMB();
00469             if (error)
00470             {
00471                 printf("\n\r-E- 2. Write block #%u(%u+%u): %d\n\r",
00472                     (unsigned int)(block+i), 
00473                     (unsigned int)block, 
00474                     (unsigned int)i, error);
00475                 if(MaxErrorBreak(0)) return;
00476                 /* Skip Following Test */
00477                 continue;
00478             }
00479         }
00480 
00481         if (rd) {
00482             /* - Read back the data to check the write operation */
00483             memset(pBuffer, 0, SDMMC_BLOCK_SIZE * multiBlock);
00484             SCB_CleanDCache(); 
00485             for (i = 0; i < multiBlock; ) {
00486                 splitMulti = ((multiBlock - i) > NB_SPLIT_MULTI) ?
00487                     NB_SPLIT_MULTI : (multiBlock - i);
00488                 error = MMCT_ReadFun(pSd,
00489                         block + i,
00490                         splitMulti,
00491                         &pBuffer[i * SDMMC_BLOCK_SIZE]);
00492                 if (error) break;
00493                 i += splitMulti;
00494             }
00495             if (error)
00496             {
00497                 printf("\n\r-E- 2. Read block #%u(%u+%u): %d\n\r", 
00498                     (unsigned int)(block + i), 
00499                     (unsigned int)block, 
00500                     (unsigned int)i, error);
00501                 if(MaxErrorBreak(0)) return;
00502                 /* Skip Following Test */
00503                 continue;
00504             }
00505             __DMB();
00506             errcnt = 0;
00507             for (i=0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00508 
00509                 if (!(((i & 1) == 0) && (pBuffer[i] == (i & 0x55))) &&
00510                         !(((i & 1) != 0) && (pBuffer[i] == (i & 0xAA))) ) {
00511                     uint32_t j, js;
00512                     printf("\n\r-E- 2.%d. Data @ %u (0x%x)\n\r", 
00513                         (unsigned int)errcnt, (unsigned int)i, (unsigned int)i);
00514                     printf("  -Src:");
00515                     js = (i > 8) ? (i - 8) : 0;
00516                     for (j = js; j < i + 8; j ++)
00517                         printf(" %02x", 
00518                         (unsigned int)(((j & 1)!= 0) ? (j & 0xAA):(j & 0x55)));
00519                     printf("\n\r  -Dat:");
00520                     for (j = js; j < i + 8; j ++)
00521                         printf("%c%02x", (i == j) ? '!' : ' ', pBuffer[j]);
00522                     printf("\n\r");
00523                     if(MaxErrorBreak(0)) return;
00524                     // Only find first 3 verify error.
00525                     if (errcnt ++ >= 3)
00526                         break;
00527                 }
00528             }
00529         }
00530 
00531         if (DBG_IsRxReady()) {
00532             switch(DBG_GetChar()) {
00533             /* Skip 100M */
00534             case 'k':
00535                 block += TEST_BLOCK_SKIP;
00536                 if (block > TEST_BLOCK_END) {
00537                     block -= 5 + multiBlock;
00538                 }
00539                 printf("\n\r");
00540                 break;
00541                 /* Cancel */
00542             case 'c':
00543                 return;
00544             }
00545         }
00546     }
00547 
00548     printf("All block tested!\n\r");
00549 }
00550 
00551 /**
00552  * Initialize PIOs
00553  */
00554 static void _ConfigurePIOs(void)
00555 {
00556     /* Configure SDcard pins */
00557     PIO_Configure(pinsSd, PIO_LISTSIZE(pinsSd));
00558     /* Configure SD card detection */
00559     CardDetectConfigure();
00560     /* Check if card is write-protected (if supported) */
00561     CardIsProtected();
00562 }
00563 
00564 /**
00565  * Initialize driver instances.
00566  */
00567 static void _ConfigureDrivers(void)
00568 {
00569     uint32_t i;
00570     /* Initialize the DMA driver */
00571     XDMAD_Initialize(&dmaDrv,0);
00572 
00573     /* Enable XDMA interrupt and give it priority over any other peripheral interrupt */
00574     NVIC_ClearPendingIRQ(XDMAC_IRQn);
00575     NVIC_SetPriority(XDMAC_IRQn, 1);
00576     NVIC_EnableIRQ( XDMAC_IRQn );
00577 
00578     /* Initialize the HSMCI driver */
00579     MCID_Init(&mciDrv[0], HSMCI, ID_HSMCI, BOARD_MCK, &dmaDrv, 0 ) ;
00580 
00581     /* Enable MCI interrupt and give it priority lower than DMA*/
00582     NVIC_ClearPendingIRQ(HSMCI_IRQn);
00583     NVIC_SetPriority(HSMCI_IRQn, 3);
00584     NVIC_EnableIRQ( HSMCI_IRQn );
00585 
00586     /* Initialize SD driver */
00587     for (i = 0; i < BOARD_NUM_MCI; i ++) {
00588         SDD_InitializeSdmmcMode(&sdDrv[i], &mciDrv[i], 0);
00589     }
00590 }
00591 
00592 /*----------------------------------------------------------------------------
00593  *         Global functions
00594  *----------------------------------------------------------------------------*/
00595 
00596 /**
00597  *  \brief hsmci_sdcard Application entry point.
00598  *
00599  *  \return Unused (ANSI-C compatibility).
00600  */
00601 int main(void)
00602 {
00603     uint32_t i;
00604     uint8_t connected[BOARD_NUM_MCI];
00605 
00606     /* Disable watchdog */
00607     WDT_Disable( WDT ) ;
00608   
00609     SCB_EnableICache();
00610     SCB_EnableDCache();
00611 
00612     /* Output example information */
00613     printf("-- HSMCI SD/MMC Example %s --\n\r", SOFTPACK_VERSION);
00614     printf("-- %s\n\r", BOARD_NAME);
00615     printf( "-- Compiled: %s %s  With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ;
00616 
00617 
00618     /* Initialize PIO pins */
00619     _ConfigurePIOs();
00620 
00621     /* Initialize drivers */
00622     _ConfigureDrivers();
00623     /* Initialize connections */
00624     for (i = 0; i < BOARD_NUM_MCI; i ++) {
00625         connected[i] = 0;
00626     }
00627 
00628     /* Check if any card is inserted */
00629     if (!AnyCardIsConnected()) {
00630         printf("-- Please insert a card\n\r");
00631         while(!AnyCardIsConnected());
00632     }
00633 
00634     /* Test all cards */
00635     for (i = 0; i < BOARD_NUM_MCI; i ++) {
00636         if (connected[i] == 0 && CardIsConnected(i)) {
00637             connected[i] = 1;
00638             LoopDelay(BOARD_MCK/1000/200);
00639             if(!CardInit(i)) {
00640                 DiskTest(i, 1, 1, 1);
00641             }
00642         }
00643     }
00644     while(1);
00645 }
00646 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines