SAMV71 Xplained Ultra Software Package 1.5

main.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /**
00031  *  \page hsmci_multimedia_card Basic MultiMediaCard Example
00032  *
00033  *  \section Purpose
00034  *
00035  *  The Basic MultiMediaCard Example will help you to get familiar with HSMCI
00036  *  interface on SAM Microcontrollers. It can also help you to get familiar
00037  *  with the SD and MMC operation flow which can be used for fast implementation
00038  *  of your own SD/MMC drivers and other applications related.
00039  *
00040  *  \section Requirements
00041  *
00042  *  This package can be used with SAMV71 Xplained Ultra board or SAME70 Xplained board.
00043  *
00044  *  \section Description
00045  *
00046  *  Open HyperTerminal before running this program, the HyperTerminal will
00047  *  give out the test hints, you can run different tests on a inserted card.
00048  *
00049  *  \section Usage
00050  *
00051  * The MultiMedia Card Example offers a set of functions to perform
00052  *  MultiMedia Card tests:
00053  *  -# Dump MultiMedia Card information
00054  *  -# Test all blocks on MultiMedia Card
00055  *  -# Test R/W Speed (performance) of the MultiMedia Card
00056  *  You can find following information depends on your needs:
00057  *  - Usage of auto detection of sdcard insert and sdcard write-protection
00058  *  - (HS)MCI interface initialize sequence and interrupt installation
00059  *  - SD/MMC card driver implementation based on (HS)MCI interface
00060  *  - SD card physical layer initialize sequence implementation
00061  *  - MMC card physical layer initialize sequence implementation
00062  *  - Sample usage of SD/MMC card write and read
00063  *
00064  *  -# Build the program and download it inside the board.
00065  *     Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf
00066  *  -# On the computer, open and configure a terminal application
00067  *     (e.g. HyperTerminal on Microsoft Windows) with these settings:
00068  *    - 115200 bauds
00069  *    - 8 bits of data
00070  *    - No parity
00071  *    - 1 stop bit
00072  *    - No flow control
00073  *  -# Start the application
00074  *  -# In HyperTerminal, it will show something like on start up
00075  *      \code
00076  *      -- MultiMedia Card Example xxx --
00077  *      -- SAMxxxxx-xx
00078  *      -- Compiled: xxx xx xxxx xx:xx:xx --
00079  *      -I- Cannot check if SD card is write-protected
00080  *
00081  *      ==========================================
00082  *      -I- Card Type 1, CSD_STRUCTURE 0
00083  *      -I- SD 4-BITS BUS
00084  *      -I- CMD6(1) arg 0x80FFFF01
00085  *      -I- SD HS Not Supported
00086  *      -I- SD/MMC TRANS SPEED 25000 KBit/s
00087  *      -I- SD/MMC card initialization successful
00088  *      -I- Card size: 483 MB, 990976 * 512B
00089  *      ...
00090  *      \endcode
00091  *  -# Test function menu is like this
00092  *      \code
00093  *      # i,I   : Re-initialize card
00094  *      # t     : Disk R/W/Verify test
00095  *      # T     : Disk performance test
00096  *      # p     : Change number of blocks in one access for test
00097  *      \endcode
00098  *
00099  *  \par See Also
00100  *  - \ref hsmci_sdcard : Another Simple Example for SD/MMC access.
00101  *  - \ref sdmmc_lib : SD/MMC card driver with mci-interface.
00102  *  - \ref hsmci_module : sdcard physical layer driver with hsmci-interface.
00103  *
00104  *  \section References
00105  *  - hsmci_multimedia_card/main.c
00106  *  - hsmci.h
00107  *  - pio.h
00108  */
00109 
00110 /**
00111  *  \file
00112  *
00113  * This file contains all the specific code for the hsmci_multimedia_card example.
00114  *
00115  *  \section Purpose
00116  *
00117  *  \section Contents
00118  *  The hsmci_multimedia_card application can be roughly broken down as follows:
00119  *     - Optional functions for detection (card insert, card protect)
00120  *        - CardDetectConfigure(), CardIsConnected()
00121  *        - CardIsProtected()
00122  *     - Interrupt handlers
00123  *        - MCI_IrqHandler()
00124  *     - The main function, which implements the program behaviour
00125  *        - I/O configuration
00126  *        - SD/MMC card auto-detect write-protected-check (if supported)
00127  *        - Initialize MCI interface and installing an isr relating to MCI
00128  *        - Initialize sdcard, get necessary sdcard's parameters
00129  *        - write/read sdcard
00130  */
00131 
00132 /*----------------------------------------------------------------------------
00133  *         Headers
00134  *----------------------------------------------------------------------------*/
00135 
00136 #include "board.h"
00137 #include "libsdmmc.h"
00138 
00139 #include <stdint.h>
00140 #include <stdio.h>
00141 #include <string.h>
00142 #include <assert.h>
00143 
00144 
00145 /*----------------------------------------------------------------------------
00146  *         Local definitions
00147  *----------------------------------------------------------------------------*/
00148 
00149 /** Maximum number of blocks read once (for performance test) */
00150 #define NB_MULTI_BLOCKS     64//8192
00151 
00152 /** Split R/W to 2, first R/W 4 blocks then remaining */
00153 #define NB_SPLIT_MULTI      4
00154 
00155 /** Test settings: start block address (0) */
00156 #define TEST_BLOCK_START    (0)
00157 
00158 /** Test settings: end block address (total SD/MMC) */
00159 #define TEST_BLOCK_END      SD_GetNumberBlocks(&sdDrv[bMciID])
00160 
00161 /** Test settings: skip size when "skip" key pressed */
00162 #define TEST_BLOCK_SKIP     (100 * 1024 * 2)    // 100M
00163 
00164 /** Test settings: Number of bytes to test performance */
00165 #define TEST_PERFORMENCT_SIZE   (4*1024*1024)
00166 
00167 /** Test settings: The value used to generate test data */
00168 #define TEST_FILL_VALUE_U32     (0x5A6C1439)
00169 
00170 /** Number of errors displayed */
00171 #define NB_ERRORS       3
00172 
00173 /** Number of bad blocks displayed */
00174 #define NB_BAD_BLOCK    200
00175 
00176 /*----------------------------------------------------------------------------
00177  *         Local variables
00178  *----------------------------------------------------------------------------*/
00179 
00180 /** DMA driver instance */
00181 static sXdmad dmaDrv;
00182 
00183 /** MCI driver instance. */
00184 static sMcid mciDrv[2];
00185 
00186 COMPILER_ALIGNED(32) static sSdCard sdDrv[2];
00187 
00188 /** Current selected MCI interface */
00189 static uint8_t bMciID = 0;
00190 
00191 /** SD card pins instance. */
00192 static const Pin pinsSd[] = {BOARD_MCI_PINS_SLOTA, BOARD_MCI_PIN_CK};
00193 
00194 /** SD card detection pin instance. */
00195 static const Pin pinsCd[] = {BOARD_MCI_PIN_CD};
00196 
00197 COMPILER_ALIGNED(32) static uint8_t pBuffer[SDMMC_BLOCK_SIZE * NB_MULTI_BLOCKS];
00198 
00199 /** Number or errors detected */
00200 static uint32_t nbErrors;
00201 
00202 /** Number of block r/w once to test performance */
00203 static uint32_t performanceMultiBlock = NB_MULTI_BLOCKS;
00204 
00205 /*----------------------------------------------------------------------------
00206  *         Local macros
00207  *----------------------------------------------------------------------------*/
00208 
00209 /* Defined to test Multi-Block functions */
00210 
00211 /** \def READ_MULTI
00212  *  \brief Define to test multi-read (SD_Read())
00213  *         or
00214  *         single-read is used (SD_ReadBlocks()) */
00215 #define READ_MULTI
00216 /** \def WRITE_MULTI
00217  *  \brief Define to test multi-write (SD_Write())
00218  *         or
00219  *         single-write is used (SD_WriteBlocks()) */
00220 #define WRITE_MULTI
00221 
00222 /** \macro SDT_ReadFun
00223  * Function used for SD card test reading.
00224  * \param pSd  Pointer to a SD card driver instance.
00225  * \param address  Address of the block to read.
00226  * \param nbBlocks Number of blocks to be read.
00227  * \param pData    Data buffer whose size is at least the block size.
00228  */
00229 #ifdef  READ_MULTI
00230 #define MMCT_ReadFun(pSd, blk, nbBlk, pData) \
00231     SD_Read(pSd, blk, pData, nbBlk, NULL, NULL)
00232 #else
00233 #define MMCT_ReadFun(pSd, blk, nbBlk, pData) \
00234     SD_ReadBlocks(pSd, blk, pData, nbBlk)
00235 #endif
00236 
00237 /** \macro SDT_WriteFun
00238  * Function used for SD card test writing.
00239  * \param pSd  Pointer to a SD card driver instance.
00240  * \param address  Address of the block to read.
00241  * \param nbBlocks Number of blocks to be read.
00242  * \param pData    Data buffer whose size is at least the block size.
00243  */
00244 #ifdef  WRITE_MULTI
00245 #define MMCT_WriteFun(pSd, blk, nbBlk, pData) \
00246     SD_Write(pSd, blk, pData, nbBlk, NULL, NULL)
00247 #else
00248 #define MMCT_WriteFun(pSd, blk, nbBlk, pData) \
00249     SD_WriteBlocks(pSd, blk, pData, nbBlk)
00250 #endif
00251 
00252 /*----------------------------------------------------------------------------
00253  *         Local functions
00254  *----------------------------------------------------------------------------*/
00255 
00256 /**
00257  * DMA interrupt handler.
00258  */
00259 void XDMAC_Handler(void)
00260 {
00261     XDMAD_Handler(&dmaDrv);
00262 }
00263 
00264 
00265 /**
00266  * MCI interrupt handler. Forwards the event to the MCI driver handlers.
00267  */
00268 void HSMCI_Handler(void)
00269 {
00270     uint32_t i;
00271 
00272     for (i = 0; i < BOARD_NUM_MCI; i ++)
00273         MCID_Handler(&mciDrv[i]);
00274 }
00275 
00276 /*----------------------------------------------------------------------------
00277  *         Optional: SD card detection (connection, protection)
00278  *----------------------------------------------------------------------------*/
00279 
00280 /**
00281  * Configure for SD detect pin
00282  */
00283 static void CardDetectConfigure(void)
00284 {
00285     PIO_Configure(pinsCd, PIO_LISTSIZE(pinsCd));
00286     /* No protection detect pin */
00287 }
00288 
00289 /**
00290  * Check if the card is connected.
00291  * \param iMci Controller number.
00292  * Return 1 if card is inserted.
00293  */
00294 static uint8_t CardIsConnected(uint8_t iMci)
00295 {
00296     return PIO_Get(&pinsCd[iMci]) ? 0 : 1;
00297 }
00298 
00299 /**
00300  * Check if the card is write protected.
00301  * \param iMci Controller number.
00302  * Return 1 if card is protected.
00303  */
00304 static uint8_t CardIsProtected(void)
00305 {
00306     printf("-I- Cannot check if SD card is write-protected\n\r");
00307     return 0;
00308 }
00309 
00310 /**
00311  * Get Dec Input
00312  * \param numChar Number of character to wait.
00313  * \param pInt    Pointer to uint32_t for input result.
00314  * \return 0 if valid data input.
00315  */
00316 static uint8_t GetDecInput(uint8_t numChar, uint32_t *pInt)
00317 {
00318     uint8_t key;
00319     uint32_t  i;
00320     uint32_t  result = 0;
00321 
00322     for (i = 0; i < numChar;) {
00323         key = DBG_GetChar();
00324 
00325         if (key == 27) {
00326             printf(" Canceled\n\r");
00327             return key;
00328         }
00329 
00330         if (key > '9' || key < '0') continue;
00331 
00332         DBG_PutChar(key);
00333         result = result * 10 + (key - '0');
00334         i ++;
00335     }
00336 
00337     if (pInt) *pInt = result;
00338 
00339     return 0;
00340 }
00341 
00342 /**
00343  * \brief Max Error Break
00344  * Check if max number of error achieved.
00345  * \param halt Whether halt the device if error number achieved.
00346  */
00347 static uint8_t MaxErrorBreak(uint8_t halt)
00348 {
00349     if (NB_ERRORS) {
00350         if (nbErrors ++ > NB_ERRORS) {
00351             while (halt);
00352 
00353             nbErrors = 0;
00354             return 1;
00355         }
00356     }
00357 
00358     return 0;
00359 }
00360 
00361 /**
00362  * Display: Dump Splitting row
00363  */
00364 static void DumpSeperator(void)
00365 {
00366     printf("\n\r==========================================\n\r");
00367 }
00368 
00369 /**
00370  * Display: Dump main menu
00371  */
00372 static void DumpMenu(void)
00373 {
00374     DumpSeperator();
00375     printf("-!- MCK is %uMHz\n\r", (unsigned)BOARD_MCK / 1000000);
00376     printf("-!- Buffer@%x,size 0x%x\n\r", (unsigned int)pBuffer, sizeof(pBuffer));
00377     printf("# C     : Change number of blocks in one access for test\n\r");
00378     printf("# D     : Dump block contents\n\r");
00379     printf("# I     : Re-initialize card\n\r");
00380     printf("# T     : Disk R/W/Verify test\n\r");
00381     printf("# P     : Disk performance test\n\r");
00382     printf("# R     : Read verify only test\n\r");
00383     printf("# V     : Read verify with performance test\n\r");
00384 }
00385 
00386 /**
00387  * Dump buffer
00388  * \param pData Pointer to data buffer.
00389  * \param len   Buffer length.
00390  */
00391 static void DumpBuffer(unsigned char *pData, unsigned int len)
00392 {
00393     uint32_t i;
00394     printf("-I- buffer %u: %c .. %c .. %c .. %c..",
00395            len, pData[0], pData[3], pData[8], pData[8 + 5]);
00396 
00397     for (i = 0; i < len; i ++) {
00398         if ((i % 16) == 0) printf("\n\r%3x:", (unsigned int)i);
00399 
00400         printf(" %02X", pData[i]);
00401     }
00402 
00403     printf("\n\r");
00404 }
00405 
00406 /**
00407  * Dump block & information
00408  * \param pData Pointer to data block.
00409  * \param block Block number.
00410  */
00411 static void DumpBlock(uint8_t *pData, uint32_t block)
00412 {
00413     uint32_t i;
00414     printf("-I- Block %d: %c .. %c .. %c .. %c..",
00415            (int)block, pData[0], pData[3], pData[8], pData[8 + 5]);
00416 
00417     for (i = 0; i < 512; i ++) {
00418         if ((i % 16) == 0) printf("\n\r%3x:", (unsigned int)i);
00419 
00420         printf(" %02X", pData[i]);
00421     }
00422 
00423     printf("\n\r");
00424 }
00425 
00426 /**
00427  * Dump card registers
00428  * \param iMci Controller number.
00429  */
00430 static void DumpCardInfo(uint8_t iMci)
00431 {
00432     sSdCard *pSd = &sdDrv[iMci];
00433 
00434     if (SD_GetCardType(pSd) & CARD_TYPE_bmSDIO)
00435         SDIO_DumpCardInformation(pSd);
00436 
00437     if (SD_GetCardType(pSd) & CARD_TYPE_bmSDMMC) {
00438         SD_DumpCID(pSd->CID);
00439         SD_DumpCSD(pSd->CSD);
00440 
00441         if (SD_GetCardType(pSd) & CARD_TYPE_bmSD)
00442             SD_DumpSdStatus(pSd->SSR);
00443     }
00444 }
00445 
00446 /**
00447  * Run tests on the inserted card
00448  * \param iMci Controller number.
00449  */
00450 static void CardInit(uint8_t iMci)
00451 {
00452     sSdCard *pSd = &sdDrv[iMci];
00453     uint8_t error;
00454     uint8_t retry = 2;
00455 
00456     DumpSeperator();
00457 
00458     while (retry --) {
00459         error = SD_Init(pSd);
00460 
00461         if (error == SDMMC_OK) break;
00462     }
00463 
00464     if (error) {
00465         printf("-E- SD/MMC card initialization failed: %d\n\r", error);
00466         return;
00467     }
00468 
00469     printf("-I- SD/MMC card initialization successful\n\r");
00470 
00471     if (SD_GetCardType(pSd) & CARD_TYPE_bmSDMMC) {
00472         printf("-I- MEM Card OK, size: %d MB", (int)SD_GetTotalSizeKB(pSd) / 1000);
00473         printf(", %d * %dB\n\r", (int)SD_GetNumberBlocks(pSd),
00474                (int)SD_GetBlockSize(pSd));
00475     }
00476 
00477     if (SD_GetCardType(pSd) & CARD_TYPE_bmSDIO)
00478         printf("-I- IO Card Detected OK\n\r");
00479 
00480     DumpCardInfo(iMci);
00481 }
00482 
00483 /**
00484  * Block Dump (read)
00485  * \param iMci Controller number.
00486  */
00487 static void BlockDump(uint8_t iMci)
00488 {
00489     sSdCard *pSd = &sdDrv[iMci];
00490     uint32_t block;
00491     DumpSeperator();
00492     printf("-!- Input block:");
00493 
00494     if (GetDecInput(5, &block))
00495         return;
00496 
00497     printf("\n\r-I- Dump Block %d: %d\n\r",
00498            (int)block, MMCT_ReadFun(pSd, block, 1, pBuffer));
00499     DumpBlock(pBuffer, block);
00500 }
00501 
00502 /**
00503  * Sdio test
00504  * \param iMci Controller number.
00505  */
00506 static void SdioTest(uint8_t iMci)
00507 {
00508     sSdCard *pSd = &sdDrv[iMci];
00509     uint32_t i;
00510 
00511     DumpSeperator();
00512 
00513     /* SDIO always has FN1(IEN.1) and Mem(IEN.0), test with these bits */
00514     printf("R/W Direct test:\n\r");
00515 
00516     printf("CIA:\n\r");
00517     SDIO_ReadDirect(pSd, SDIO_CIA, 0, &pBuffer[0], 0x14);
00518     DumpBuffer(pBuffer, 0x14);
00519     printf("Write 0x03 to IEN(CIA.4): rc %d\n\r",
00520            SDIO_WriteDirect(pSd, SDIO_CIA, SDIO_IEN_REG, 0x03));
00521     printf("IEN After Write:");
00522     SDIO_ReadDirect(pSd, SDIO_CIA, SDIO_IEN_REG, &pBuffer[1], 1);
00523     printf("0x%02X\n\r", pBuffer[1]);
00524 
00525     if (0x03 == pBuffer[1])
00526         printf("-- test OK\n\r");
00527     else
00528         printf("-- test FAIL\n\r");
00529 
00530     SDIO_WriteDirect(pSd, SDIO_CIA, SDIO_IEN_REG, pBuffer[SDIO_IEN_REG]);
00531 
00532     printf("R/W Extended test:\n\r");
00533     printf("Dump CIA:\n\r");
00534 
00535     for (i = 0; i < 0x40; i ++) pBuffer[i] = 0xFF; /* Clear Buffer */
00536 
00537     SDIO_ReadBytes(pSd, SDIO_CIA, 0, 0, pBuffer, 0x39, 0, 0);
00538     DumpBuffer(pBuffer, 0x14);
00539 
00540     printf("Modify Some R/W bytes (2,4) for FN0 and write:\n\r");
00541     pBuffer[0x2] = 0x2; /* IOE */
00542     pBuffer[0x4] = 0x2; /* IEN */
00543     /* Dont write to CIA.0x7, CIA.0xD or operation pause transfer */
00544     SDIO_WriteBytes(pSd, SDIO_CIA, 2, 0, &pBuffer[2], 5/*(0xC-2)*/, 0, 0);
00545     printf("CIA after write:\n\r");
00546     //SDIO_ReadDirect(pSd, SDIO_CIA, 0, pBuffer, 0x14);
00547     SDIO_ReadBytes(pSd, SDIO_CIA, 0, 0, pBuffer, 0x14, 0, 0);
00548     DumpBuffer(pBuffer, 0x14);
00549 
00550     if (pBuffer[0x2] != 0x2)
00551         printf("-- CIA.2 Fail\n\r");
00552     else if (pBuffer[0x4] != 0x2)
00553         printf("-- CIA.4 Fail\n\r");
00554     else
00555         printf("-- test OK\n\r");
00556 
00557     /* Restore data to 0 */
00558     SDIO_WriteDirect(pSd, SDIO_CIA, SDIO_IOE_REG, 0);
00559     SDIO_WriteDirect(pSd, SDIO_CIA, SDIO_IEN_REG, 0);
00560 }
00561 
00562 /**
00563  * Sdio performance test
00564  * \param iMci Controller number.
00565  */
00566 static void SdioPerformanceTest(uint8_t iMci)
00567 {
00568     sSdCard *pSd = &sdDrv[iMci];
00569     uint32_t i, blkSize = 1, totalNb = 0;
00570     uint32_t tickStart, tickEnd, ticks, rwSpeed;
00571 
00572     DumpSeperator();
00573     printf("-I- IO Performance test, size %dK, MCK %dMHz\n\r",
00574            TEST_PERFORMENCT_SIZE / 1024,
00575            (int)(BOARD_MCK / 1000000));
00576     printf("Read Direct  speed: ");
00577     tickStart = GetTicks();
00578 
00579     for (totalNb = 0;;) {
00580         if (SDIO_ReadDirect(pSd, SDIO_CIA, 0, &pBuffer[0], 0x14))
00581             return;
00582 
00583         totalNb += 0x14;
00584         tickEnd = GetTicks();
00585         ticks = GetDelayInTicks(tickStart, tickEnd);
00586 
00587         if (ticks > 800) break;
00588     }
00589 
00590     rwSpeed = totalNb / ticks;
00591     printf("%uK\n\r", (unsigned int)rwSpeed);
00592     printf("Write Direct speed: ");
00593     tickStart = GetTicks();
00594 
00595     for (totalNb = 0;;) {
00596         for (i = 0; i < 0x14; i ++) {
00597             if (SDIO_WriteDirect(pSd,
00598                                  SDIO_CIA,
00599                                  SDIO_IEN_REG,
00600                                  pBuffer[SDIO_IEN_REG]))
00601                 return;
00602         }
00603 
00604         totalNb += 0x14;
00605         tickEnd = GetTicks();
00606         ticks = GetDelayInTicks(tickStart, tickEnd);
00607 
00608         if (ticks > 800) break;
00609     }
00610 
00611     rwSpeed = totalNb / ticks;
00612     printf("%uK\n\r", (unsigned int)rwSpeed);
00613 
00614     printf("R/W Extended test:\n\r");
00615 
00616     for (blkSize = 4; blkSize <= 512; blkSize <<= 1) {
00617         printf("- Cnt %3u: ", (unsigned int)blkSize);
00618         tickStart = GetTicks();
00619 
00620         for (totalNb = 0;;) {
00621             if (SDIO_ReadBytes(pSd,
00622                                SDIO_CIA, 0,
00623                                0,
00624                                pBuffer, blkSize,
00625                                0, 0))
00626                 return;
00627 
00628             totalNb += blkSize;
00629             tickEnd = GetTicks();
00630             ticks = GetDelayInTicks(tickStart, tickEnd);
00631 
00632             if (ticks > 800) break;
00633         }
00634 
00635         rwSpeed = totalNb / ticks;
00636         printf("R %5uK, ", (unsigned int)rwSpeed);
00637 
00638         for (i = 0; i < blkSize; i ++)
00639             pBuffer[i] = pBuffer[SDIO_IEN_REG];
00640 
00641         tickStart = GetTicks();
00642 
00643         for (totalNb = 0; ;) {
00644             if (SDIO_WriteBytes(pSd,
00645                                 SDIO_CIA, SDIO_IEN_REG,
00646                                 1,
00647                                 pBuffer, blkSize,
00648                                 0, 0))
00649                 return;
00650 
00651             totalNb += blkSize;
00652             tickEnd = GetTicks();
00653             ticks = GetDelayInTicks(tickStart, tickEnd);
00654 
00655             if (ticks > 800) break;
00656         }
00657 
00658         rwSpeed = totalNb / ticks;
00659         printf("W %5uK", (unsigned int)rwSpeed);
00660         printf("\n\r");
00661     }
00662 }
00663 
00664 /**
00665  * Disk test
00666  * \param iMci Controller number.
00667  * \param clr  Do block clear.
00668  * \param wr   Do block write.
00669  * \param rd   Do block read.
00670  */
00671 static void DiskTest(uint8_t iMci,
00672                      uint8_t clr,
00673                      uint8_t wr,
00674                      uint8_t rd)
00675 {
00676     sSdCard *pSd = &sdDrv[iMci];
00677     uint8_t error = 0;
00678     uint32_t i, errcnt = 0;
00679     uint32_t multiBlock, block, splitMulti;
00680 
00681     DumpSeperator();
00682     printf("-!- Test code: 1.clr, 2.wr, 3.rd\n\r");
00683 
00684     /* Perform tests on each block */
00685     multiBlock = 0;
00686 
00687     for (block = TEST_BLOCK_START;
00688          block < TEST_BLOCK_END;
00689          block += multiBlock) {
00690 
00691         /* Perform different single or multiple bloc operations */
00692         if (multiBlock >= 16)   multiBlock <<= 1;
00693         else                    multiBlock ++;
00694 
00695         if (multiBlock > NB_MULTI_BLOCKS)
00696             multiBlock = 1;
00697 
00698         /* Multi-block adjustment */
00699         if (block + multiBlock > TEST_BLOCK_END)
00700             multiBlock = TEST_BLOCK_END - block;
00701 
00702         /* ** Perform single block or multi block transfer */
00703         printf("\r-I- Testing block [%6u - %6u] ...",
00704                (unsigned int)block, (unsigned int)(block + multiBlock - 1));
00705 
00706         if (clr) {
00707             /* - Clear the block */
00708             memset(pBuffer, 0, SDMMC_BLOCK_SIZE * multiBlock);
00709 
00710             for (i = 0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00711                 if (pBuffer[i] != 0) {
00712                     /* Fatal error */
00713                     printf("\n\r-F- Data @ %u for write : 0x00 <> 0x%02x\n\r",
00714                            (unsigned int)i, pBuffer[i]);
00715                     return;
00716                 }
00717             }
00718 
00719             error = MMCT_WriteFun(pSd, block, multiBlock, pBuffer);
00720 
00721             if (error) {
00722                 printf("\n\r-E- 1. Write block (%d) #%u\n\r", error,
00723                        (unsigned int)block);
00724 
00725                 if (MaxErrorBreak(0)) return;
00726 
00727                 /* Skip following test */
00728                 continue;
00729             }
00730 
00731             /* - Read back the data to check the write operation */
00732             memset(pBuffer, 0xFF, SDMMC_BLOCK_SIZE * multiBlock);
00733             SCB_CleanDCache_by_Addr((uint32_t *)pBuffer, SDMMC_BLOCK_SIZE * multiBlock);
00734             error = MMCT_ReadFun(pSd, block, multiBlock, pBuffer);
00735 
00736             if (error) {
00737                 printf("\n\r-E- 1. Read block (%d) #%u\n\r", error,
00738                        (unsigned int)block);
00739 
00740                 if (MaxErrorBreak(0)) return;
00741 
00742                 /* Skip following test */
00743                 continue;
00744             }
00745 
00746             for (i = 0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00747                 if (pBuffer[i] != 0) {
00748                     printf("\n\r-E- 1. B%u.D[%u] : 0 <> 0x%02X\n\r",
00749                            (unsigned int)block, (unsigned int)i, (int)pBuffer[i]);
00750 
00751                     if (MaxErrorBreak(0)) return;
00752 
00753                     /* Only find first verify error. */
00754                     break;
00755                 }
00756             }
00757         }
00758 
00759         if (wr) {
00760             /* - Write a checker board pattern on the block */
00761             for (i = 0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00762                 if ((i & 1) == 0)  pBuffer[i] = (i & 0x55);
00763                 else               pBuffer[i] = (i & 0xAA);
00764             }
00765 
00766             for (i = 0; i < multiBlock; ) {
00767                 splitMulti = ((multiBlock - i) > NB_SPLIT_MULTI) ?
00768                              NB_SPLIT_MULTI : (multiBlock - i);
00769                 error = MMCT_WriteFun(pSd,
00770                                       block + i,
00771                                       splitMulti,
00772                                       &pBuffer[i * SDMMC_BLOCK_SIZE]);
00773 
00774                 if (error) break;
00775 
00776                 i += splitMulti;
00777             }
00778 
00779             if (error) {
00780                 printf("\n\r-E- 2. Write block #%u(%u+%u): %d\n\r",
00781                        (unsigned int)(block + i),
00782                        (unsigned int)block,
00783                        (unsigned int)i, error);
00784 
00785                 if (MaxErrorBreak(0)) return;
00786 
00787                 /* Skip Following Test */
00788                 continue;
00789             }
00790         }
00791 
00792         if (rd) {
00793             /* - Read back the data to check the write operation */
00794             memset(pBuffer, 0, SDMMC_BLOCK_SIZE * multiBlock);
00795             SCB_CleanDCache_by_Addr((uint32_t *)pBuffer, SDMMC_BLOCK_SIZE * multiBlock);
00796 
00797             for (i = 0; i < multiBlock; ) {
00798                 splitMulti = ((multiBlock - i) > NB_SPLIT_MULTI) ?
00799                              NB_SPLIT_MULTI : (multiBlock - i);
00800                 error = MMCT_ReadFun(pSd,
00801                                      block + i,
00802                                      splitMulti,
00803                                      &pBuffer[i * SDMMC_BLOCK_SIZE]);
00804 
00805                 if (error) break;
00806 
00807                 i += splitMulti;
00808             }
00809 
00810             if (error) {
00811                 printf("\n\r-E- 2. Read block #%u(%u+%u): %d\n\r",
00812                        (unsigned int)(block + i),
00813                        (unsigned int)block,
00814                        (unsigned int)i, error);
00815 
00816                 if (MaxErrorBreak(0)) return;
00817 
00818                 /* Skip Following Test */
00819                 continue;
00820             }
00821 
00822             errcnt = 0;
00823 
00824             for (i = 0; i < SDMMC_BLOCK_SIZE * multiBlock; i++) {
00825 
00826                 if (!(((i & 1) == 0) && (pBuffer[i] == (i & 0x55))) &&
00827                     !(((i & 1) != 0) && (pBuffer[i] == (i & 0xAA))) ) {
00828                     uint32_t j, js;
00829                     printf("\n\r-E- 2.0x%x. Data @ %u (0x%x)\n\r",
00830                            (unsigned int)errcnt, (unsigned int)i, (unsigned int)i);
00831                     printf("  -Src:");
00832                     js = (i > 8) ? (i - 8) : 0;
00833 
00834                     for (j = js; j < i + 8; j ++)
00835                         printf(" %02x",
00836                                (unsigned int)(((j & 1) != 0) ? (j & 0xAA) : (j & 0x55)));
00837 
00838                     printf("\n\r  -Dat:");
00839 
00840                     for (j = js; j < i + 8; j ++)
00841                         printf("%c%02x", (i == j) ? '!' : ' ', pBuffer[j]);
00842 
00843                     printf("\n\r");
00844 
00845                     if (MaxErrorBreak(0)) return;
00846 
00847                     // Only find first 3 verify error.
00848                     if (errcnt ++ >= 3)
00849                         break;
00850                 }
00851             }
00852         }
00853 
00854         if (DBG_IsRxReady()) {
00855             switch (DBG_GetChar()) {
00856             /* Skip 100M */
00857             case 'k':
00858                 block += TEST_BLOCK_SKIP;
00859 
00860                 if (block > TEST_BLOCK_END)
00861                     block -= 5 + multiBlock;
00862 
00863                 printf("\n\r");
00864                 break;
00865 
00866             /* Cancel */
00867             case 'c':
00868                 return;
00869             }
00870         }
00871     }
00872 
00873     printf("All block tested!\n\r");
00874 }
00875 
00876 /**
00877  * Run disk performance test
00878  * R/W test can be masked to verify previous written data only
00879  * \param iMci Controller number.
00880  * \param wr   Do block write.
00881  * \param rd   Do block read.
00882  * \param errDetail Dump detailed error information.
00883  */
00884 static void DiskPerformanceTest(uint8_t iMci,
00885                                 uint8_t wr,
00886                                 uint8_t rd,
00887                                 uint8_t errDetail)
00888 {
00889     sSdCard *pSd = &sdDrv[iMci];
00890     uint8_t error = 0;
00891     uint32_t  block, i, nBadBlock = 0, nErrors;
00892     uint32_t  tickStart, tickEnd, ticks, rwSpeed;
00893     uint32_t *pBuf;
00894     DumpSeperator();
00895     printf("-I- Performance test, size %dK, Multi %d, MCK %dMHz\n\r",
00896            TEST_PERFORMENCT_SIZE / 1024,
00897            (int)performanceMultiBlock,
00898            (int)(BOARD_MCK / 1000000));
00899 #ifdef READ_MULTI
00900     printf("-I- Read by Multi block, size %d\n\r", (int)SDMMC_BLOCK_SIZE);
00901 #else
00902     printf("-I- Read block by block, size %d\n\r", (int)SDMMC_BLOCK_SIZE);
00903 #endif
00904 #ifdef WRITE_MULTI
00905     printf("-I- Write by Multi block, size %d\n\r", (int)SDMMC_BLOCK_SIZE);
00906 #else
00907     printf("-I- Write block by block, size %d\n\r", (int)SDMMC_BLOCK_SIZE);
00908 #endif
00909 
00910     if (wr) {
00911         printf("--- Write test .. ");
00912 
00913         for (i = 0; i < SDMMC_BLOCK_SIZE * performanceMultiBlock; i += 4) {
00914             pBuf = (uint32_t *)(void *)(&pBuffer[i]);
00915             *pBuf = TEST_FILL_VALUE_U32;
00916         }
00917 
00918         nBadBlock = 0;
00919         tickStart = GetTicks();
00920 
00921         for (block = TEST_BLOCK_START;
00922              block < (TEST_PERFORMENCT_SIZE / SDMMC_BLOCK_SIZE)
00923              + TEST_BLOCK_START;
00924              block += performanceMultiBlock) {
00925             pBuf = (uint32_t *)(void *)pBuffer;
00926             *pBuf = block;
00927             error = MMCT_WriteFun(pSd,
00928                                   block, performanceMultiBlock,
00929                                   pBuffer);
00930 
00931             if (error) {
00932                 if (nBadBlock ++ >= NB_BAD_BLOCK) {
00933                     printf("-E- WR_B(%u)\n\r", (unsigned int)block);
00934                     break;
00935                 } else error = 0;
00936             }
00937         }
00938 
00939         tickEnd = GetTicks();
00940         ticks = GetDelayInTicks(tickStart, tickEnd);
00941         rwSpeed = (TEST_PERFORMENCT_SIZE
00942                    - nBadBlock * performanceMultiBlock * SDMMC_BLOCK_SIZE)
00943                   / ticks;
00944         printf("Done, Bad %u, Speed %uK\n\r",
00945                (unsigned int)nBadBlock, (unsigned int)rwSpeed);
00946     }
00947 
00948     if (rd) {
00949         printf("--- Read test .. ");
00950         nBadBlock = 0;
00951         tickStart = GetTicks();
00952 
00953         for (block = TEST_BLOCK_START;
00954              block < (TEST_PERFORMENCT_SIZE / SDMMC_BLOCK_SIZE)
00955              + TEST_BLOCK_START;
00956              block += performanceMultiBlock) {
00957 
00958             error = MMCT_ReadFun(pSd,
00959                                  block, performanceMultiBlock,
00960                                  pBuffer);
00961 
00962             if (error) {
00963                 if (nBadBlock ++ >= NB_BAD_BLOCK) {
00964                     printf("-E- RD_B(%u)\n\r", (unsigned int)block);
00965                     break;
00966                 } else error = 0;
00967             }
00968 
00969             if (error) break;
00970         }
00971 
00972         tickEnd = GetTicks();
00973         ticks = GetDelayInTicks(tickStart, tickEnd);
00974         rwSpeed = (TEST_PERFORMENCT_SIZE
00975                    - nBadBlock * performanceMultiBlock * SDMMC_BLOCK_SIZE)
00976                   / ticks;
00977         printf("Done, read  %u, Speed %uK\n\r",
00978                (unsigned int)(TEST_PERFORMENCT_SIZE -
00979                               nBadBlock * performanceMultiBlock * SDMMC_BLOCK_SIZE) / SDMMC_BLOCK_SIZE,
00980                (unsigned int)rwSpeed);
00981     }
00982 
00983     printf("--- Data verify .. ");
00984     nErrors = 0;
00985 
00986     for (block = TEST_BLOCK_START;
00987          block < (TEST_PERFORMENCT_SIZE / SDMMC_BLOCK_SIZE) + TEST_BLOCK_START;
00988          block += performanceMultiBlock) {
00989 
00990         memset(pBuffer, 0x00, SDMMC_BLOCK_SIZE * performanceMultiBlock);
00991         SCB_CleanDCache_by_Addr((uint32_t *)pBuffer,
00992                                 SDMMC_BLOCK_SIZE * performanceMultiBlock);
00993         error = MMCT_ReadFun(pSd,
00994                              block, performanceMultiBlock,
00995                              pBuffer);
00996 
00997         if (error) {
00998             printf("-E- RD_B(%u)\n\r", (unsigned int)block);
00999             break;
01000         }
01001 
01002         pBuf = (uint32_t *)(void *)pBuffer;
01003 
01004         if (*pBuf != block) {
01005             if (errDetail) {
01006                 if (nErrors ++ < NB_ERRORS) {
01007                     printf("-E- Blk(%u)[0](%08x<>%08x)\n\r",
01008                            (unsigned int)block,
01009                            (unsigned int)block,
01010                            (unsigned int)(*pBuf));
01011                 }
01012             } else {
01013                 printf("-E- BlkN(%x<>%x)\n\r",
01014                        (unsigned int)block, (unsigned int)(*pBuf));
01015                 error = 1;
01016                 break;
01017             }
01018         }
01019 
01020         for (i = 4; i < SDMMC_BLOCK_SIZE * performanceMultiBlock; i += 4) {
01021             pBuf = (uint32_t *)(void *)(&pBuffer[i]);
01022 
01023             if ((*pBuf != TEST_FILL_VALUE_U32)) {
01024                 if (errDetail) {
01025                     /* Dump 10 errors only */
01026                     if (nErrors ++ < NB_ERRORS) {
01027                         uint32_t j;
01028                         printf("-E- Blk(%u)[%u](%08x.. <>",
01029                                (unsigned int)block,
01030                                (unsigned int)i,
01031                                (unsigned int)TEST_FILL_VALUE_U32);
01032 
01033                         for (j = (i > 4) ? (i - 4) : i;
01034                              j <= i + 4;
01035                              j += 4) {
01036                             printf("%c%08X",
01037                                    (i == j) ? '!' : ' ',
01038                                    (unsigned int)(*pBuf));
01039                         }
01040 
01041                         printf(")\n\r");
01042                     }
01043                 } else {
01044                     printf("-E- Blk(%u)[%u](%x<>%x)\n\r",
01045                            (unsigned int)block,
01046                            (unsigned int)i,
01047                            (unsigned int)TEST_FILL_VALUE_U32,
01048                            (unsigned int)(*pBuf));
01049                     error = 1;
01050                     break;
01051                 }
01052             }
01053         }
01054 
01055         if (error) break;
01056     }
01057 
01058     if (errDetail && nErrors)
01059         printf("-I- %u u32 ERRORS found!\n\r", (unsigned int)nErrors);
01060 
01061     if (error)
01062         return;
01063 
01064     printf("OK\n\r");
01065 }
01066 
01067 
01068 /**
01069  * Initialize PIOs
01070  */
01071 static void _ConfigurePIOs(void)
01072 {
01073     /* Configure SDcard pins */
01074     PIO_Configure(pinsSd, PIO_LISTSIZE(pinsSd));
01075     /* Configure SD card detection */
01076     CardDetectConfigure();
01077     CardIsProtected();
01078 }
01079 
01080 /**
01081  * Initialize driver instances.
01082  */
01083 static void _ConfigureDrivers(void)
01084 {
01085     uint32_t i;
01086     /* Initialize the DMA driver */
01087     XDMAD_Initialize(&dmaDrv, 0);
01088 
01089     NVIC_ClearPendingIRQ(XDMAC_IRQn);
01090     NVIC_SetPriority(XDMAC_IRQn, 1);
01091     NVIC_EnableIRQ(XDMAC_IRQn);
01092 
01093     /* Initialize the HSMCI driver */
01094     MCID_Init(&mciDrv[0], HSMCI, ID_HSMCI, BOARD_MCK, &dmaDrv, 0);
01095 
01096     NVIC_ClearPendingIRQ(HSMCI_IRQn);
01097     NVIC_SetPriority(HSMCI_IRQn, 3);
01098     NVIC_EnableIRQ(HSMCI_IRQn);
01099 
01100     /* Initialize SD driver */
01101     for (i = 0; i < BOARD_NUM_MCI; i++)
01102         SDD_InitializeSdmmcMode(&sdDrv[i], &mciDrv[i], 0);
01103 }
01104 
01105 /*----------------------------------------------------------------------------
01106  *         Global functions
01107  *----------------------------------------------------------------------------*/
01108 
01109 /**
01110  *  \brief hsmci_multimedia_card Application entry point.
01111  *
01112  *  \return Unused (ANSI-C compatibility).
01113  */
01114 int main(void)
01115 {
01116     uint8_t connected = 0;
01117 
01118     /* Disable watchdog */
01119     WDT_Disable(WDT);
01120 
01121     SCB_EnableICache();
01122     SCB_EnableDCache();
01123     TimeTick_Configure();
01124 
01125     /* Output example information*/
01126     printf("-- MultiMedia Card Example %s --\n\r", SOFTPACK_VERSION);
01127     printf("-- %s\n\r", BOARD_NAME);
01128     printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME);
01129     bMciID = 0;
01130     /* Initialize PIO pins */
01131     _ConfigurePIOs();
01132 
01133     /* Initialize drivers */
01134     _ConfigureDrivers();
01135 
01136 
01137     /* Card insert detection loop */
01138     for (; ;) {
01139         if (CardIsConnected(bMciID)) {
01140             if (connected == 0) {
01141                 connected = 1;
01142                 /* Delay before card initialize */
01143                 Wait(300);
01144                 /* Do card test */
01145                 CardInit(bMciID);
01146                 DumpMenu();
01147             }
01148         } else if (connected) {
01149             connected = 0;
01150             printf("** Card Disconnected\n\r");
01151         }
01152 
01153         if (DBG_IsRxReady()) {
01154             uint8_t key = DBG_GetChar();
01155 
01156             switch (key) {
01157             /* Change performance test block size */
01158             case 'c':
01159             case 'C': {
01160                 if (performanceMultiBlock >= NB_MULTI_BLOCKS)
01161                     performanceMultiBlock = 1;
01162                 else
01163                     performanceMultiBlock <<= 1;
01164 
01165                 printf("-!- Performance Multi set to %d\n\r", (int)performanceMultiBlock);
01166             }
01167             break;
01168 
01169             /* Show help information */
01170             default:
01171                 if (!connected)
01172                     DumpMenu();
01173                 else {
01174                     switch (key) {
01175                     /* Dump block contents */
01176                     case 'd':
01177                     case 'D':
01178                         BlockDump(bMciID);
01179                         break;
01180 
01181                     /* Initialize the card again */
01182                     case 'I':
01183                     case 'i':
01184                         CardInit(bMciID);
01185                         break;
01186 
01187                     /* Run test on whole disk */
01188                     case 't':
01189                     case 'T':
01190                         if (SD_GetCardType(&sdDrv[bMciID]) & CARD_TYPE_bmSDIO)
01191                             SdioTest(bMciID);
01192 
01193                         if (SD_GetCardType(&sdDrv[bMciID]) & CARD_TYPE_bmSDMMC)
01194                             DiskTest(bMciID, 1, 1, 1);
01195 
01196                         printf("\n\r");
01197                         break;
01198 
01199                     /* Run performance test */
01200                     case 'P':
01201                     case 'p':
01202                         if (SD_GetCardType(&sdDrv[bMciID]) & CARD_TYPE_bmSDIO)
01203                             SdioPerformanceTest(bMciID);
01204 
01205                         if (SD_GetCardType(&sdDrv[bMciID]) & CARD_TYPE_bmSDMMC)
01206                             DiskPerformanceTest(bMciID, 1, 1, 0);
01207 
01208                         printf("\n\r");
01209                         break;
01210 
01211                     /* Read/Verify ONLY test */
01212                     case 'r':
01213                     case 'R':
01214                         DiskTest(bMciID, 0, 0, 1);
01215                         printf("\n\r");
01216                         break;
01217 
01218                     /* Read/Verify ONLY performance test */
01219                     case 'V':
01220                     case 'v':
01221                         DiskPerformanceTest(bMciID, 0, 1, 1);
01222                         printf("\n\r");
01223                         break;
01224 
01225                     /* Show help information */
01226                     default:
01227                         DumpMenu();
01228                     }
01229                 }
01230 
01231                 break;
01232             }
01233         }
01234     }
01235 }
01236 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines