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_iad_cdc_msd 00030 * \page usb_iad_cdc_msd USB CDC(Serial)+MSD Example 00031 * 00032 * \section Purpose 00033 * 00034 * The USB CDCMSD Project will help you to get familiar with the 00035 * USB Device Port(UDP)interface and also some of the other interfaces in 00036 * SAMv7 Microcontrollers. Also it can help you to be familiar with the USB 00037 * Framework that is used for rapid development of USB-compliant class 00038 * drivers such as USB Communication Device class (CDC), and how to combine 00039 * two USB functions to a single CDCMSD device (such as CDC + MSD). 00040 * 00041 * \section Requirements 00042 * 00043 * This package can be used with some of Atmel Xplained board that have UDP 00044 * interface, depending on the functions included. 00045 * 00046 * \section win_drv_update Windows Driver Update 00047 * 00048 * The composite device is generally supported by Microsoft windows, but some 00049 * patches are needed for muti-interface functions such as CDC & Audio. 00050 * 00051 * \section Description 00052 * 00053 * The demo simulates a USB composite device that integrates USB CDC Serial 00054 * RS232 Converter function and USB Disk function. 00055 * 00056 * When the board running this program connected to a host (PC for example), 00057 * with USB cable, host will notice the attachment of a USB device. No device 00058 * driver offered for the device now. 00059 * 00060 * \section Usage 00061 * 00062 * -# Build the program and download it inside the SAM V71 Xplained Ultra board. 00063 * Please refer to the Getting Started with SAM V71 Microcontrollers.pdf 00064 * -# On the computer, open and configure a terminal application 00065 * (e.g. HyperTerminal on Microsoft Windows) with these settings: 00066 * - 115200 bauds 00067 * - 8 bits of data 00068 * - No parity 00069 * - 1 stop bit 00070 * - No flow control 00071 * -# Start the application. 00072 * -# In the terminal window, the following text should appear: 00073 * \code 00074 * -- USB CDCMSD Device Project xxx -- 00075 * -- SAMxxxxx-xx 00076 * -- Compiled: xxx xx xxxx xx:xx:xx -- 00077 * \endcode 00078 * -# When connecting USB cable to windows, the LED blinks, and the host 00079 * reports a new USB device attachment. 00080 * -# For the windows driver installation and the test functions, please 00081 * refer to "USB CDC serial converter" & 00082 * "USB Device Mass Storage Project". 00083 * -# You can use the inf file 00084 * libraries\\usb\\device\\composite\\drv\\CompositeCDCSerial.inf 00085 * to install the CDC serial port. 00086 * 00087 * \section References 00088 * 00089 * - usb_iad_cdc_msd/main.c 00090 * - pio: Pin configurations and peripheral configure. 00091 * - memories: Storage Media interface for MSD 00092 * - usb: USB Device Framework, USB CDC driver and UDP interface driver 00093 * - \ref usbd_framework 00094 * - \ref usbd_api 00095 * - \ref usbd_composite "composite" 00096 * - \ref usbd_composite_drv 00097 * - \ref usbd_msd "massstorage" 00098 * - \ref usbd_msd_drv 00099 * - \ref usbd_cdc "cdc-serial" 00100 * - \ref usbd_cdc_serial_drv 00101 * - projects: 00102 * - \ref usb_massstorage 00103 * - \ref usb_cdc_serial 00104 */ 00105 00106 /** 00107 * \file 00108 * 00109 * \section Purpose 00110 * 00111 * This file contains all the specific code for the 00112 * usb_iad_cdc_msd project 00113 */ 00114 00115 /*--------------------------------------------------------------------------- 00116 * Headers 00117 *---------------------------------------------------------------------------*/ 00118 00119 #include "board.h" 00120 00121 #include "libstoragemedia.h" 00122 00123 #include <USBD_Config.h> 00124 #include <CDCMSDDriver.h> 00125 #include <CDCDSerial.h> 00126 #include <MSDFunction.h> 00127 00128 #include <stdint.h> 00129 #include <stdio.h> 00130 #include <string.h> 00131 #include <stdbool.h> 00132 00133 /*--------------------------------------------------------------------------- 00134 * Definitions 00135 *---------------------------------------------------------------------------*/ 00136 00137 /** Size in bytes of the packet used for reading data from USB */ 00138 #define DATAPACKETSIZE \ 00139 CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN) 00140 00141 /** Size in bytes of the buffer used for reading data from the USB & USART */ 00142 #define DATABUFFERSIZE (DATAPACKETSIZE+2) 00143 00144 /** Maximum number of LUNs which can be defined. */ 00145 #define MAX_LUNS 1 00146 /** Media index for different disks */ 00147 #define DRV_RAMDISK 0 /**< RAM disk */ 00148 #define DRV_SDMMC 1 /**< SD card */ 00149 00150 /** Size of one block in bytes. */ 00151 #define BLOCK_SIZE 512 00152 00153 /** Size of the MSD IO buffer in bytes (6K, more the better). */ 00154 #define MSD_BUFFER_SIZE (12*BLOCK_SIZE) 00155 00156 /** RamDisk size: (WinXP can not format the disk if lower than 20K) */ 00157 #define RAMDISK_SIZE 128*1024 00158 00159 COMPILER_SECTION("ramdisk_region") static uint8_t ramdisk_reserved[RAMDISK_SIZE]; 00160 #define RAMDISK_BASE_ADDR ((uint32_t)ramdisk_reserved) 00161 00162 /** Delay for MSD refresh (*4ms) */ 00163 #define MSD_REFRESH_DELAY 250 00164 00165 /** Delay for waiting DBGU input (*4ms) */ 00166 #define INPUT_DELAY (2*250) 00167 00168 /*--------------------------------------------------------------------------- 00169 * External variables 00170 *---------------------------------------------------------------------------*/ 00171 00172 /** Descriptor list for the device to bring up */ 00173 extern const USBDDriverDescriptors cdcmsddDriverDescriptors; 00174 00175 /*--------------------------------------------------------------------------- 00176 * Internal variables 00177 *---------------------------------------------------------------------------*/ 00178 /** Buffer for storing incoming USB data. */ 00179 static uint8_t usbSerialBuffer0[DATABUFFERSIZE]; 00180 00181 /** Serial port opened */ 00182 static uint8_t isSerialPortON = 0; 00183 00184 /*- MSD */ 00185 /** Available media. */ 00186 sMedia medias[MAX_LUNS]; 00187 00188 /** Device LUNs. */ 00189 MSDLun luns[MAX_LUNS]; 00190 00191 /** LUN read/write buffer. */ 00192 uint8_t msdBuffer[MSD_BUFFER_SIZE]; 00193 00194 /** Total data write to disk */ 00195 uint32_t msdWriteTotal = 0; 00196 /** Delay for data write refresh */ 00197 uint32_t msdDelay = MSD_REFRESH_DELAY; 00198 /** Delay TO event */ 00199 uint8_t msdRefresh = 0; 00200 00201 00202 /*----------------------------------------------------------------------------- 00203 * Callback re-implementation 00204 *-----------------------------------------------------------------------------*/ 00205 /** 00206 * Invoked when the configuration of the device changes. Parse used endpoints. 00207 * \param cfgnum New configuration number. 00208 */ 00209 void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) 00210 { 00211 CDCMSDDriver_ConfigurationChangedHandler(cfgnum); 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 CDCMSDDriver_RequestHandler(request); 00222 } 00223 00224 /*---------------------------------------------------------------------------- 00225 * Callbacks 00226 *----------------------------------------------------------------------------*/ 00227 00228 /** 00229 * Invoked when the MSD finish a READ/WRITE. 00230 * \param flowDirection 1 - device to host (READ10) 00231 * 0 - host to device (WRITE10) 00232 * \param dataLength Length of data transferred in bytes. 00233 * \param fifoNullCount Times that FIFO is NULL to wait 00234 * \param fifoFullCount Times that FIFO is filled to wait 00235 */ 00236 static void MSDCallbacks_Data(uint8_t flowDirection, 00237 uint32_t dataLength, 00238 uint32_t fifoNullCount, 00239 uint32_t fifoFullCount) 00240 { 00241 fifoNullCount = fifoNullCount; /* dummy */ 00242 fifoFullCount = fifoFullCount; /*dummy */ 00243 if (!flowDirection) { 00244 msdWriteTotal += dataLength; 00245 } 00246 } 00247 00248 /** 00249 * Invoked when the CDC ControlLineState is changed 00250 * \param DTR New DTR value. 00251 * \param RTS New RTS value. 00252 */ 00253 void CDCDSerial_ControlLineStateChanged(uint8_t DTR, 00254 uint8_t RTS) 00255 { 00256 isSerialPortON = DTR; 00257 RTS = RTS; /* dummy */ 00258 } 00259 00260 /** 00261 * Invoked when the CDC LineCoding is requested to changed 00262 * \param pLineCoding Pointer to new LineCoding settings. 00263 * \return USBRC_SUCCESS if ready to receive the line coding. 00264 */ 00265 uint8_t CDCDSerial_LineCodingIsToChange(CDCLineCoding* pLineCoding) 00266 { 00267 pLineCoding = pLineCoding; /*dummy */ 00268 return USBD_STATUS_SUCCESS; 00269 } 00270 00271 /*--------------------------------------------------------------------------- 00272 * Internal functions 00273 *---------------------------------------------------------------------------*/ 00274 /** 00275 * Configure USBHS settings for USB device 00276 */ 00277 static void _ConfigureUotghs(void) 00278 { 00279 00280 /* UTMI parallel mode, High/Full/Low Speed */ 00281 /* UUSBCK not used in this configuration (High Speed) */ 00282 PMC->PMC_SCDR = PMC_SCDR_USBCLK; 00283 /* USB clock register: USB Clock Input is UTMI PLL */ 00284 PMC->PMC_USB = PMC_USB_USBS; 00285 /* Enable peripheral clock for USBHS */ 00286 PMC_EnablePeripheral(ID_USBHS); 00287 USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE; 00288 /* Enable PLL 480 MHz */ 00289 PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF); 00290 /* Wait that PLL is considered locked by the PMC */ 00291 while( !(PMC->PMC_SR & PMC_SR_LOCKU) ); 00292 00293 /* IRQ */ 00294 NVIC_EnableIRQ(USBHS_IRQn) ; 00295 } 00296 00297 /** 00298 * Initialize DDRAM to assign RamDisk block 00299 */ 00300 static void RamDiskInit(void) 00301 { 00302 BOARD_ConfigureSdram(); 00303 00304 printf("RamDisk @ %x, size %d\n\r", RAMDISK_BASE_ADDR, RAMDISK_SIZE); 00305 00306 MEDRamDisk_Initialize(&(medias[DRV_RAMDISK]), 00307 BLOCK_SIZE, 00308 (RAMDISK_BASE_ADDR ) / BLOCK_SIZE, 00309 RAMDISK_SIZE / BLOCK_SIZE, 00310 1); 00311 LUN_Init(&(luns[DRV_RAMDISK]), 00312 &(medias[DRV_RAMDISK]), 00313 msdBuffer, MSD_BUFFER_SIZE, 00314 0, 0, 0, 0, 00315 MSDCallbacks_Data); 00316 00317 gNbMedias = 1; 00318 } 00319 00320 /** 00321 * Initialize MSD Media & LUNs 00322 */ 00323 static void _MemoriesInitialize(void) 00324 { 00325 uint32_t i ; 00326 00327 /* Reset all LUNs */ 00328 for (i = 0; i < MAX_LUNS; i ++) 00329 LUN_Init(&luns[i], 0, 0, 0, 0, 0, 0, 0, 0); 00330 00331 /* TODO: Add LUN Init here */ 00332 00333 /* RAM disk initialize */ 00334 RamDiskInit(); 00335 /* Nand Flash Init */ 00336 /* SD Card Init */ 00337 } 00338 00339 /*--------------------------------------------------------------------------- 00340 * Exported function 00341 *---------------------------------------------------------------------------*/ 00342 00343 /*--------------------------------------------------------------------------- 00344 * Main 00345 *---------------------------------------------------------------------------*/ 00346 00347 /** 00348 * Initializes drivers and start the USB CDCMSD device. 00349 */ 00350 int main(void) 00351 { 00352 uint8_t usbConnected = 0, serialON = 0; 00353 00354 /* Disable watchdog */ 00355 WDT_Disable( WDT ); 00356 00357 SCB_EnableICache(); 00358 SCB_EnableDCache(); 00359 00360 printf("-- USB CDCMSD Device Project %s --\n\r", SOFTPACK_VERSION); 00361 printf("-- %s\n\r", BOARD_NAME); 00362 printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ; 00363 00364 /* If they are present, configure Vbus & Wake-up pins */ 00365 PIO_InitializeInterrupts(0); 00366 00367 /* If there is on board power, switch it off */ 00368 _ConfigureUotghs(); 00369 00370 /* ----- MSD Function Initialize */ 00371 /* Configure memories */ 00372 _MemoriesInitialize(); 00373 00374 /* USB CDCMSD driver initialization */ 00375 CDCMSDDriver_Initialize(&cdcmsddDriverDescriptors, luns, MAX_LUNS); 00376 00377 /* connect if needed */ 00378 USBD_Connect(); 00379 00380 /* Driver loop */ 00381 while (1) 00382 { 00383 /* Device is not configured */ 00384 if (USBD_GetState() < USBD_STATE_CONFIGURED) { 00385 if (usbConnected) { 00386 printf("-I- USB Disconnect/Suspend\n\r"); 00387 usbConnected = 0; 00388 00389 /* Serial port closed */ 00390 isSerialPortON = 0; 00391 } 00392 } else { 00393 if (usbConnected == 0) { 00394 printf("-I- USB Connect\n\r"); 00395 usbConnected = 1; 00396 } 00397 if (!serialON && isSerialPortON) { 00398 printf("-I- SerialPort ON\n\r"); 00399 /* Start receiving data on the USART */ 00400 /* Start receiving data on the USB */ 00401 CDCDSerial_Read(usbSerialBuffer0, DATAPACKETSIZE, 0, 0); 00402 serialON = 1; 00403 } else if (serialON && !isSerialPortON) { 00404 printf("-I- SeriaoPort OFF\n\r"); 00405 serialON = 0; 00406 } 00407 MSDFunction_StateMachine(); 00408 00409 if (msdRefresh) { 00410 msdRefresh = 0; 00411 if (msdWriteTotal < 50 * 1000) { 00412 /* Flush Disk Media */ 00413 } 00414 msdWriteTotal = 0; 00415 } 00416 } 00417 } 00418 } 00419 /** \endcond */