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 /** \cond usb_massstorage 00030 * \page usb_massstorage USB Device Mass Storage Example 00031 * 00032 * \section Purpose 00033 * 00034 * The USB Mass storage Example will help you to get familiar with the 00035 * USB Device Port(UDP) on Samv7 Microcontrollers. Also 00036 * it can help you to be familiar with the USB Framework that is used for 00037 * rapid development of USB-compliant class drivers such as USB Mass 00038 * Storage class (MSD). 00039 * 00040 * \section Requirements 00041 * 00042 * This package can be used with all Atmel Xplained board that have USB interface 00043 * 00044 * \section Description 00045 * 00046 * The demo simulates a SD/MMC USB disk. 00047 * 00048 * When the board running this program connected to a host (PC for example), with 00049 * USB cable, the board appears as a USB Disk for the host. Then the host can 00050 * format/read/write on the disk. 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 the terminal window, the following text should appear: 00065 * \code 00066 * -- USB Device Mass Storage Example xxx -- 00067 * -- SAMxxxxx-xx 00068 * -- Compiled: xxx xx xxxx xx:xx:xx -- 00069 * \endcode 00070 * -# When connecting USB cable to windows, the host 00071 * reports a new USB %device attachment and Disk installation. 00072 * . Then new "USB Mass Storage Device" and 00073 * "ATMEL Mass Storage MSD USB Device" and "Generic volume" appear in 00074 * hardware %device list. 00075 * -# You can find the new disk on host, and to create/write file to it. 00076 * 00077 * \section References 00078 * - usb_massstorage/main.c 00079 * - pio.h 00080 * - pio_it.h 00081 * - memories: Storage Media interface for MSD 00082 * - usb: USB Framework, USB MSD driver and UDP interface driver 00083 * - \ref usbd_framework 00084 * - \ref usbd_api 00085 * - \ref usbd_msd 00086 * - \ref usbd_msd_drv 00087 */ 00088 00089 /** 00090 * \file 00091 * 00092 * This file contains all the specific code for the 00093 * usb_massstorage. 00094 */ 00095 00096 /*---------------------------------------------------------------------------- 00097 * Headers 00098 *----------------------------------------------------------------------------*/ 00099 00100 #include "board.h" 00101 00102 #include "libstoragemedia.h" 00103 #include "libsdmmc.h" 00104 00105 #include "MSDDriver.h" 00106 #include "MSDLun.h" 00107 00108 #include <stdbool.h> 00109 #include <stdint.h> 00110 #include <stdio.h> 00111 00112 /*---------------------------------------------------------------------------- 00113 * Compiling Options 00114 *----------------------------------------------------------------------------*/ 00115 00116 /* No transfer speed dump */ 00117 #define DBG_SPEED_OFF 00118 #define USBHS_PRI 3 00119 #define HSMCI_PRI 2 00120 #define XDMAC_PRI 1 00121 /*---------------------------------------------------------------------------- 00122 * Local definitions 00123 *----------------------------------------------------------------------------*/ 00124 00125 /** Maximum number of LUNs which can be defined. */ 00126 #define MAX_LUNS 2 00127 00128 /** Media index for different disks */ 00129 00130 #define DRV_RAMDISK 0 /**< RAM disk */ 00131 #define DRV_SDMMC 1 /**< SD card */ 00132 #define DRV_NAND 2 /**< Nand flash */ 00133 00134 /** RamDisk size (in bytes) */ 00135 /** RamDisk size: 20K (WinXP can not format the disk if lower than 20K) */ 00136 #define RAMDISK_SIZE 128*1024 00137 00138 COMPILER_SECTION("ramdisk_region") static uint8_t ramdisk_reserved[RAMDISK_SIZE]; 00139 #define RAMDISK_BASE_ADDR ((uint32_t)ramdisk_reserved) 00140 00141 /** Size of one block in bytes. */ 00142 #define BLOCK_SIZE 512 00143 00144 /** Size of the MSD IO buffer in bytes (150K, more the better). */ 00145 #define MSD_BUFFER_SIZE ( 32 * BLOCK_SIZE ) 00146 00147 00148 /*---------------------------------------------------------------------------- 00149 * Global variables 00150 *----------------------------------------------------------------------------*/ 00151 00152 /** MSD Driver Descriptors List */ 00153 extern const USBDDriverDescriptors msdDriverDescriptors; 00154 00155 /** SD card pins instance. */ 00156 static const Pin pinsSd[] = {BOARD_MCI_PINS_SLOTA, BOARD_MCI_PIN_CK}; 00157 00158 /** SD card detection pin instance. */ 00159 static const Pin pinsCd[] = {BOARD_MCI_PIN_CD}; 00160 00161 /** Available media. */ 00162 sMedia medias[MAX_LUNS]; 00163 00164 /*---------------------------------------------------------------------------- 00165 * Local variables 00166 *----------------------------------------------------------------------------*/ 00167 /** DMA driver instance */ 00168 static sXdmad dmaDrv; 00169 00170 /** Device LUNs. */ 00171 static MSDLun luns[MAX_LUNS]; 00172 00173 /** SDCard driver instance. */ 00174 static sSdCard sdDrv[BOARD_NUM_MCI]; 00175 00176 /** MCI driver instance. */ 00177 /** SDCard driver instance. */ 00178 static sMcid mciDrv[BOARD_NUM_MCI]; 00179 00180 /** LUN read/write buffer. */ 00181 static uint8_t mSdBuffer[MSD_BUFFER_SIZE]; 00182 static uint8_t mRamBuffer[MSD_BUFFER_SIZE]; 00183 00184 /** Total data write to disk */ 00185 uint32_t msdWriteTotal = 0; 00186 00187 /** Delay TO event */ 00188 uint8_t msdRefresh = 0; 00189 00190 00191 /** 00192 * XDMA0 interrupt handler. 00193 */ 00194 void XDMAC_Handler(void) 00195 { 00196 XDMAD_Handler(&dmaDrv); 00197 } 00198 00199 /** 00200 * MCI interrupt handler. Forwards the event to the MCI driver handlers. 00201 */ 00202 void HSMCI_Handler(void) 00203 { 00204 uint32_t i; 00205 for (i = 0; i < BOARD_NUM_MCI; i ++) { 00206 MCID_Handler(&mciDrv[i]); 00207 } 00208 } 00209 00210 /*----------------------------------------------------------------------------- 00211 * Callback re-implementation 00212 *-----------------------------------------------------------------------------*/ 00213 00214 /** 00215 * Invoked when a new SETUP request is received from the host. Forwards the 00216 * request to the Mass Storage device driver handler function. 00217 * \param request Pointer to a USBGenericRequest instance. 00218 */ 00219 void USBDCallbacks_RequestReceived(const USBGenericRequest *request) 00220 { 00221 MSDDriver_RequestHandler(request); 00222 } 00223 00224 /** 00225 * Invoked when the configuration of the device changes. Resets the mass 00226 * storage driver. 00227 * \param cfgnum New configuration number. 00228 */ 00229 void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum) 00230 { 00231 MSDDriver_ConfigurationChangeHandler(cfgnum); 00232 } 00233 00234 /*---------------------------------------------------------------------------- 00235 * Callbacks 00236 *----------------------------------------------------------------------------*/ 00237 /** 00238 * Invoked when the MSD finish a READ/WRITE. 00239 * \param flowDirection 1 - device to host (READ10) 00240 * 0 - host to device (WRITE10) 00241 * \param dataLength Length of data transferred in bytes. 00242 * \param fifoNullCount Times that FIFO is NULL to wait 00243 * \param fifoFullCount Times that FIFO is filled to wait 00244 */ 00245 static void MSDCallbacks_Data(uint8_t flowDirection, 00246 uint32_t dataLength, 00247 uint32_t fifoNullCount, 00248 uint32_t fifoFullCount) 00249 { 00250 fifoNullCount = fifoNullCount; /* dummy */ 00251 fifoFullCount = fifoFullCount; /*dummy */ 00252 if (!flowDirection) { 00253 msdWriteTotal += dataLength; 00254 } 00255 } 00256 /*---------------------------------------------------------------------------- 00257 * Local functions 00258 *----------------------------------------------------------------------------*/ 00259 /** 00260 * Configure for SD detect pin 00261 */ 00262 static void CardDetectConfigure(void) 00263 { 00264 PIO_Configure(pinsCd, PIO_LISTSIZE(pinsCd)); 00265 /* No protection detect pin */ 00266 } 00267 00268 /** 00269 * Check if the card is connected. 00270 * \param iMci Controller number. 00271 * Return 1 if card is inserted. 00272 */ 00273 static uint8_t CardIsConnected(uint8_t iMci) 00274 { 00275 return PIO_Get(&pinsCd[iMci]) ? 0 : 1; 00276 } 00277 00278 /** 00279 * Run init on the inserted card 00280 * \param iMci Controller number. 00281 */ 00282 static void CardInit(sSdCard *pSd) 00283 { 00284 uint8_t error; 00285 uint8_t retry = 2; 00286 while(retry --) { 00287 error = SD_Init(pSd); 00288 if (error == SDMMC_OK) break; 00289 } 00290 if (error) { 00291 TRACE_ERROR("SD/MMC card initialization failed: %d\n\r", error); 00292 return; 00293 } 00294 TRACE_INFO(" SD/MMC card initialization successful\n\r"); 00295 if (SD_GetCardType(pSd) & CARD_TYPE_bmSDMMC) { 00296 TRACE_INFO(" MEM Card OK, size: %d MB", (int)SD_GetTotalSizeKB(pSd)/1000); 00297 TRACE_INFO(", %d * %dB\n\r", (int)SD_GetNumberBlocks(pSd), (int)SD_GetBlockSize(pSd)); 00298 } 00299 if (SD_GetCardType(pSd) & CARD_TYPE_bmSDIO) { 00300 TRACE_ERROR("-E- IO Card Detected \n\r"); 00301 } 00302 } 00303 00304 /** 00305 * Initialize PIOs 00306 */ 00307 static void _ConfigurePIOs(void) 00308 { 00309 /* Configure SDcard pins */ 00310 PIO_Configure(pinsSd, PIO_LISTSIZE(pinsSd)); 00311 /* Configure SD card detection */ 00312 CardDetectConfigure(); 00313 } 00314 00315 /** 00316 * Initialize driver instances. 00317 */ 00318 static void _ConfigureDrivers(void) 00319 { 00320 uint32_t i; 00321 /* Initialize the DMA driver */ 00322 XDMAD_Initialize(&dmaDrv,0); 00323 00324 /* Enable XDMA interrupt and give it priority over any other peripheral 00325 interrupt */ 00326 NVIC_ClearPendingIRQ(XDMAC_IRQn); 00327 NVIC_SetPriority(XDMAC_IRQn, XDMAC_PRI); 00328 NVIC_EnableIRQ( XDMAC_IRQn ); 00329 00330 /* Initialize the HSMCI driver */ 00331 MCID_Init(&mciDrv[0], HSMCI, ID_HSMCI, BOARD_MCK, &dmaDrv, 0 ) ; 00332 00333 /* Enable MCI interrupt and give it priority lower than DMA*/ 00334 NVIC_ClearPendingIRQ(HSMCI_IRQn); 00335 NVIC_SetPriority(HSMCI_IRQn, HSMCI_PRI); 00336 NVIC_EnableIRQ( HSMCI_IRQn ); 00337 00338 /* Initialize SD driver */ 00339 for (i = 0; i < BOARD_NUM_MCI; i ++) { 00340 SDD_InitializeSdmmcMode(&sdDrv[i], &mciDrv[i], 0); 00341 } 00342 } 00343 00344 /*---------------------------------------------------------------------------- 00345 * Internal functions 00346 *----------------------------------------------------------------------------*/ 00347 static void SDDiskInit(sSdCard *pSd) 00348 { 00349 uint8_t sdConnected; 00350 pSd = &sdDrv[0]; 00351 /* Infinite loop */ 00352 sdConnected=0; 00353 if (CardIsConnected(0)) { 00354 if (sdConnected == 0) { 00355 sdConnected = 1; 00356 printf("-I- connect to solt n\r"); 00357 CardInit(pSd); 00358 00359 SD_DumpCID(pSd->CID); 00360 SD_DumpCSD(pSd->CSD); 00361 SD_DumpExtCSD(pSd->EXT); 00362 MEDSdusb_Initialize(&medias[DRV_SDMMC], pSd); 00363 } 00364 } else if (sdConnected) { 00365 sdConnected = 0; 00366 printf("** Card Disconnected\n\r"); 00367 } 00368 LUN_Init(&(luns[DRV_SDMMC]), 00369 &(medias[DRV_SDMMC]), 00370 mSdBuffer, MSD_BUFFER_SIZE, 00371 0, 0, 0, 0, 00372 MSDCallbacks_Data); 00373 } 00374 00375 /** 00376 * Initialize SDRAM to assign RamDisk block 00377 */ 00378 static void RamDiskInit(void) 00379 { 00380 TRACE_INFO("RamDisk @ %x, size %d\n\r", (RAMDISK_BASE_ADDR ), RAMDISK_SIZE); 00381 00382 MEDRamDisk_Initialize(&(medias[DRV_RAMDISK]), 00383 BLOCK_SIZE, 00384 (RAMDISK_BASE_ADDR ) / BLOCK_SIZE, 00385 RAMDISK_SIZE / BLOCK_SIZE, 00386 1); 00387 LUN_Init(&(luns[DRV_RAMDISK]), 00388 &(medias[DRV_RAMDISK]), 00389 mRamBuffer, MSD_BUFFER_SIZE, 00390 0, 0, 0, 0, 00391 MSDCallbacks_Data); 00392 } 00393 00394 /** 00395 * Initialize MSD Media & LUNs 00396 */ 00397 static void _MemoriesInitialize(sSdCard *pSd) 00398 { 00399 uint32_t i ; 00400 00401 /* Reset all LUNs */ 00402 for (i = 0; i < MAX_LUNS; i ++) 00403 LUN_Init(&luns[i], 0, 0, 0, 0, 0, 0, 0, 0); 00404 00405 BOARD_ConfigureSdram(); 00406 /*Initialize SD Card */ 00407 SDDiskInit(pSd); 00408 00409 /*Initialize RAM disk */ 00410 RamDiskInit(); 00411 00412 gNbMedias = 2; 00413 } 00414 /** 00415 * Configure USBHS settings for USB device 00416 */ 00417 static void _ConfigureUotghs(void) 00418 { 00419 /* UTMI parallel mode, High/Full/Low Speed */ 00420 /* UUSBCK not used in this configuration (High Speed) */ 00421 PMC->PMC_SCDR = PMC_SCDR_USBCLK; 00422 /* USB clock register: USB Clock Input is UTMI PLL */ 00423 PMC->PMC_USB = PMC_USB_USBS; 00424 /* Enable peripheral clock for USBHS */ 00425 PMC_EnablePeripheral(ID_USBHS); 00426 USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE; 00427 /* Enable PLL 480 MHz */ 00428 PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF); 00429 /* Wait that PLL is considered locked by the PMC */ 00430 while( !(PMC->PMC_SR & PMC_SR_LOCKU) ); 00431 00432 /* IRQ */ 00433 NVIC_SetPriority(USBHS_IRQn, USBHS_PRI); 00434 NVIC_EnableIRQ(USBHS_IRQn) ; 00435 } 00436 /*---------------------------------------------------------------------------- 00437 * Exported functions 00438 *----------------------------------------------------------------------------*/ 00439 00440 /** 00441 * \brief usb_massstorage Application entry point. 00442 * 00443 * Configures UART, 00444 * Configures TC0, USB MSD Driver and run it. 00445 * 00446 * \return Unused (ANSI-C compatibility). 00447 */ 00448 int main( void ) 00449 { 00450 sSdCard *pSd = 0; 00451 00452 /* Disable watchdog */ 00453 WDT_Disable( WDT ) ; 00454 00455 SCB_EnableICache(); 00456 SCB_EnableDCache(); 00457 00458 printf("-- USB Device Mass Storage Example %s --\n\r", SOFTPACK_VERSION); 00459 printf("-- %s\n\r", BOARD_NAME); 00460 printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ; 00461 00462 /* If they are present, configure Vbus & Wake-up pins */ 00463 PIO_InitializeInterrupts(0); 00464 00465 /* Initialize all USB power (off) */ 00466 _ConfigureUotghs(); 00467 /* Initialize PIO pins */ 00468 _ConfigurePIOs(); 00469 00470 /* Initialize drivers */ 00471 _ConfigureDrivers(); 00472 00473 _MemoriesInitialize(pSd); 00474 00475 /* BOT driver initialization */ 00476 MSDDriver_Initialize(&msdDriverDescriptors, luns, MAX_LUNS); 00477 00478 /* connect if needed */ 00479 USBD_Connect(); 00480 while (1) { 00481 /* Mass storage state machine */ 00482 if (USBD_GetState() < USBD_STATE_CONFIGURED){} 00483 else { 00484 MSDDriver_StateMachine(); 00485 if (msdRefresh) { 00486 msdRefresh = 0; 00487 if (msdWriteTotal < 50 * 1000) { 00488 /* Flush Disk Media */ 00489 } 00490 msdWriteTotal = 0; 00491 } 00492 } 00493 } 00494 } 00495 /** \endcond */