SAMV71 Xplained Ultra Software Package 1.4

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 /** \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     ( 128 * 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 */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines