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