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