.. include:: ../../../../lib_xud/doc/rst/version.rst

.. include:: ../../README.rst

|newpage|

Overview
--------

Introduction
............

The Universal Serial Bus (USB) is a communication architecture that gives a PC the ability to interconnect a variety of devices via a simple four-wire cable. One such device is the mass storage. Traditionally, mass storage device class provides adaptability for devices like
 
  - USB flash drive
  - memory card reader
  - digital audio player
  - digital camera
  - external hard drive

The USB specification provides as standard device class for the implementation of USB mass storage.

(http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf)

Block diagram
.............

.. figure:: images/block_diagram.*

   Block diagram of USB Mass storage application example

Features
........

This section describes the features that are supported by the demo application. The application uses an on-board flash with a user memory partition of 2 MB. The application does the following

 * Enumerates as Mass Storage device
 * On Windows host, the display appears as `` drive labelled as unformatted **Removable Disk** ``
 * On Mac, it displays as `` **XMOSLTD Flash Disk Media** `` 

As there is no file system supported by the application, formatting the drive, read and write operations on the drive is not featured.      

USB Mass Storage Device Class application note
----------------------------------------------

The demo in this note uses the XMOS USB device library and shows a simple program that receives data from and sends data to the host.

For the USB Mass storage device class application example, the system comprises three tasks running in separate logical cores of a xCORE multicore microcontroller.

The tasks perform the following operations.
  
  * A task containing the USB library functionality to communicate over USB
  * A task implementing Endpoint0 responding both standard and mass storage class USB requests
  * A task implementing the application code for receiving and sending mass storage data into the device

These tasks communicate via the use of xCONNECT channels which allow data to be passed between application code running on separate logical cores.

The following diagram shows the task and communication structure for this USB mass storage device class application example.

.. figure:: images/task_diagram.*
   :align: center

   Task diagram of USB mass storage application example

Makefile additions for this application
........................................
To start using the USB library, you need to add **lib_xud** to your makefile::

	USED_MODULES = lib_xud

You can then access the USB functions on your source code via the **xud_device.h** header file::

	#include <xud_device.h>

Declaring resource and setting up the USB components
....................................................

**main.xc** contains the application implementation for a device based on the USB mass storage device class. There are some defines in it that are used to configure the XMOS USB device library. These are displayed below.

.. literalinclude:: main.xc
   :start-on: USB Endpoint Defines
   :end-before: /* xSCOPE

These describe the endpoint configuration for this device. This example has bi-directional communication with the host machine via the standard endpoint0, an endpoint for receiving the bulk data from the host into our device and an endpoint for sending the bulk data to host from our device.

The application main() function
...............................

Below is the source code for the main function of this application, which is taken from the source file **main.xc**

.. literalinclude:: main.xc
   :start-on: int main

Looking at this in a more detail you can see the following:

 - The `par` statement starts three separate tasks in parallel
 - There is a task to configure and execute the USB library: `XUD_Main()`
 - There is a task to startup and run the Endpoint0 code: `Endpoint0()`
 - There is a task to deal with USB mass storage requests arriving from the host: `massStorageClass()`
 - The define `USB_TILE` describes the tile on which the individual tasks will run
 - In this example all tasks run on the same tile as the USB PHY although this is only a requirement of XUD_Main()
 - The xCONNECT communication channels used by the application are set up at the beginning of main()
 - The USB defines discussed earlier are passed into the function XUD_Main()

Configuring the USB Device ID
.............................

The USB ID values used for vendor id, product id and device version number are defined in the file **endpoint0.xc**. These are used by the host machine to determine the vendor of the device (in this case XMOS) and the product plus the firmware version.

.. literalinclude:: endpoint0.xc
   :start-on: /* USB Device ID Defines */
   :end-before: /* USB Mass Storage

USB Mass storage Class specific defines
.......................................

The USB Mass storage Class is configured in the file **endpoint0.xc**. Below there are a set of standard defines which are used to configure the USB device descriptors to setup a USB mass storage device running on an xCORE microcontroller.

.. literalinclude:: endpoint0.xc
   :start-on: /* USB Mass Storage
   :end-before: /* USB Device Descriptor */

USB Device Descriptor
.....................

**endpoint0.xc** is where the standard USB device descriptor is declared for the mass storage device. Below is the structure which contains this descriptor. This will be requested by the host when the device is enumerated on the USB bus.

.. literalinclude:: endpoint0.xc
   :start-on: devDesc 
   :end-on: }

From this descriptor you can see that product, vendor and device firmware revision are all coded into this structure. This will allow the host machine to recognise the mass storage device when it is connected to the USB bus.

USB Configuration Descriptor
............................

The USB configuration descriptor is used to configure the device in terms of the device class and the endpoint setup. For the USB mass storage device the configuration descriptor which is read by the host is as follows.

.. literalinclude:: endpoint0.xc
   :start-on: cfgDesc
   :end-on: }

From this you can see that the USB mass storage class defines described earlier are encoded into the configuration descriptor along with the bulk USB endpoint description for receiving storage data into the application code. These endpoint allows us to process the storage data request from the host and to the host inside the main mass storage application task.

USB string descriptor
.....................
There is one more descriptor within this file relating to the configuration of the USB Mass storage Class. This section should also be modified to match the capabilities of the mass storage device.

.. literalinclude:: endpoint0.xc
   :start-on: String table
   :end-on: }

USB Mass storage Class requests
...............................

Inside **endpoint0.xc** there is some code for handling the USB Mass storage device class specific requests. These are shown in the following code:

.. literalinclude:: endpoint0.xc
   :start-on: Mass Storage Class Request
   :end-before: Endpoint 0 

These mass storage specific request are implemented by the application as they do not form part of the standard requests which have to be accepted by all device classes via endpoint0.

USB Mass storage Class Endpoint0
.................................

The function `Endpoint0()` contains the code for dealing with device requests made from the host to the standard endpoint0 which is present in all USB devices. In addition to requests required for all devices, the code handles the requests specific to the mass storage device class.

.. literalinclude:: endpoint0.xc
   :start-on: result == XUD_RES_OKAY
   :end-before: If we

Receiving storage data from the host
.....................................
The application endpoint for Command Transport, Data-In, Data-Out and Status Transport are implemented in the file **mass_storage.xc** as per the flow shown in below figure. This is contained within the function `massStorageClass()` which is shown in next page.

.. figure:: images/command_data_status_flow.*
   :scale: 51%
   :align: center

   Command/Data/Status Flow

.. literalinclude:: mass_storage.xc
   :start-on: void massStorageClass
   :end-on: } // END of massStorageClass

From this you can see the following.

* Two buffers are declared, one to receive the Command transport CBW (Command Block Wrapper) data which is streamed into the application from the host and the other to send Status transport CSW (Command Status Wrapper) to the host.
* This task operates inside a while (1) loop which waits for data to arrive and then processes it.
* It checks for the CBW Signature and packet size that get received from the host. 
* Based on the Operation code available on the CBWCB (CBW Command Block) field, SCSI commands corresponding to flash drive are executed.

  - Operation code received may correspond to SCSI commands like `Inquiry, Test Unit Ready, Request Sense, Read Capacity, Mode Sense, Read/Write,` etc.
* Once the execution (Command transport, Data-In or Data-Out) is completed, the device shall echo the contents of CBWTag field sent by the host back along with the CSWStatus and CSW Signature as Status transport.
  This ensures that the `Status` send to host is associated with the `Command` received from host.

SCSI Command Implementation
............................

Some of the SCSI command definitions and the reponse from the device are mentioned below.

 * **INQUIRY:** command requests that information regarding parameters of the Device be sent to the Host. 
 
   - The response to this command provides standard INQUIRY data of (36 bytes) PDT, RMB (Removable Medium Bit), Vendor Identification, Product Identification and Product Revison Level, etc.
 * **TEST UNIT READY:** command provides a means to check if the Device is ready. This command is useful in that it allows a Host to poll a Device until it is ready without the need to allocate space for returned data.
   
   - The response to this command returns GOOD, if the device accepts an appropriate medium access command or CHECK CONDITION status with a sense key of NOT READY.
 * **REQUEST SENSE:** command requests the device to transfer sense data to the host whenever an error is reported. The sense data  describes what caused the error condition.
 
   - The response to this command is a sense key, Additional Sense Code (ASC) or ASC Qualifier (ASCQ) depending on which error occured [#]_. 
 * **READ CAPACITY:** command requests the device to transfer 8 bytes of parameter data describing the capacity of the installed medium of the device. 
   
   - The response to this command returns Logical Block Address (LBA) and block length in bytes of the memory device. 
 * **MODE SENSE:** command requests the device to transfer parameter data describing the medium type, block descriptor length, read/write error recovery mode.
 
   - The response to this command returns PDT type as medium type, error recovery mode, descriptor length.
 * **READ/WRITE:** command requests the device to read/write data onto the medium.
 
   - The response to `READ` transfers the most recent data value written in the addressed logical block of the medium to host.
   - The response to `WRITE` writes the data transferred by the host to the medium.  
    
.. [#] http://www.t10.org/lists/asc-num.htm
     
|newpage|

Serial Flash Functions
......................

For accessing the on-board serial flash, you need to add the flash library **lflash** in `Makefile` as one of the `XCC_FLAGS` and use **flashlib.h** to access the flash library functions.
`Note: No separate core is required to handle the SPI read/write`
 
The below implementation does write/read operation onto the on-board serial flash M25P16.

.. literalinclude:: mass_storage.xc
   :start-after: //Flash_Functions_start
   :end-before: //Flash_Functions_end
      
|newpage|

|appendix|

Demo Hardware Setup
-------------------

To run the demo, connect the xCORE EXPLORER and xTAG USB recepticals to separate USB connectors on your development PC.

Note, the application makes use use of xSCOPE (rather than JTAG) such that the print message that are generated on the device as part of the demo do not interfere with the real-time behavior of the USB device. 

.. figure:: images/explorerkit-200.*
  
   XMOS xCORE-200 EXPLORER Board

The hardware should be configured as displayed above for this demo:
 
  - The XTAG debug adapter should be connected to the XSYS connector and the XTAG USB cable should be connected to the host machine
  - The xCORE EXPLORER board should have a USB cable connecting the device to the host machine

|newpage|

Launching the demo device
--------------------------

Once the demo example has been built either from the command line using xmake or via the build mechanism of xTIMEcomposer studio the application can be executed on the xCORE-200 or xCORE.AI
EXPLORER board.

Once built there will be a bin directory within the project which contains the binary for the xCORE device. The xCORE binary has a XMOS standard .xe extension.

Launching from the command line
...............................

From the command line the xrun tool is used to download code to both the xCORE devices. Changing into the bin directory of the project we can execute the code on the xCORE microcontroller as follows::

	> xrun --xscope AN00125.xe 	                     <-- Download and execute the xCORE code

Once this command has executed the mass storage USB device should have enumerated on your machine

Launching from xTIMEcomposer Studio
...................................

From xTIMEcomposer Studio the run mechanism is used to download code to xCORE device. Select the xCORE binary from the bin directory, right click and then follow the instructions below.

* Select **Run As**.
* Select **Run Configurations**.
* Double click on xCORE application**.
* Enable xSCOPE in Target I/O options:

  .. figure:: images/xtime-run-xscope.*

     xTIMEcomposer xSCOPE configuration

* Click **Apply** and then **Run**.

Once this command has executed the mass storage USB device should have enumerated on your machine and the below message should get displayed on your xTIMEcomposer console window

.. figure:: images/demo_start.*

   xTIMEcomposer Console Window

|newpage|

Detecting the Mass Storage
--------------------------

Windows Host
............

 * There is no specific driver installtion is required. Windows will automatically install a driver for the mass storage class. You should be able to get the below message screen once enumeration is complete.
   
   .. figure:: images/DriverSw_Installation.*
      :scale: 80%
   
      Driver Software Installation Screen (On Windows 7)
       
 * You can also verify the device using **Device Manager** Menu
 
   - `Click` on **Start Menu** goto **My Computer** - `Right click` and navigate to **Manage** option.
   - On **Computer Management** screen `double click` **Device Manager** on left and navigate to **Universal Serial Bus controllers** option on right.
   - `Double click` on **Universal Serial Bus controllers** and you should be able to see **USB Mass Storage Device**
   
   .. figure:: images/device_detection.*
      :scale: 80%
      
      USB Mass Storage Device detection on Device Manager (On Windows 7)  
      
  * The Mass Storage Device should be seen as an **Removable Disk** (Drive ID may vary depending upon the number of drives available on your machine). 
  
    .. figure:: images/removable_disk.*
       :scale: 78%
       
       USB Mass Storage Device detecting as Removable Disk(I:) (On Windows 7)

 * You could see the successful installation of driver after enumeration is done.
 
   .. figure:: images/installation.*
      :scale: 80%
      
      XMOS LTD Flash Disk - Device Driver software installated successfully

|newpage|
      
OSX Host
........

 * There is no specific driver installtion is required. Mac will automatically detect and you should be able to get the below message screen once enumeration is complete.
   
   .. figure:: images/device_detection_mac.*
      :scale: 80%
   
      USB Mass Storage Device detection (On Mac)

|newpage|

References
----------

.. nopoints::

  * XMOS Tools User Guide

    http://www.xmos.com/published/xtimecomposer-user-guide

  * XMOS xCORE Programming Guide

    http://www.xmos.com/published/xmos-programming-guide
  
  * XMOS xCORE-USB Device Library: 

    http://www.xmos.com/published/xuddg

  * XMOS USB Device Design Guide: 

    http://www.xmos.com/published/xmos-usb-device-design-guide

  * USB Mass Storage Class Bulk-Only Transport

    http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf

  * USB 2.0 Specification

    http://www.usb.org/developers/docs/usb20_docs/usb_20_081114.zip
  
  * USB Mass Storage Specification For Bootability
  
    http://www.usb.org/developers/docs/devclass_docs/usb_msc_boot_1.0.pdf
    
  * SCSI Command
  
    http://en.wikipedia.org/wiki/SCSI_command
    
  * SCSI Commands Reference Manual (Seagate)
  
    http://www.seagate.com/staticfiles/support/disc/manuals/Interface%20manuals/100293068c.pdf
    
  * USB Mass Storage Device Specification Overview [#]_.  
    
.. [#] http://www.usb.org/developers/docs/devclass_docs/Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf    
    
Full Source Code listing
------------------------

Source Code for main.xc
........................

.. literalinclude:: main.xc
   :largelisting:
   
Source Code for endpoint0.xc
.............................

.. literalinclude:: endpoint0.xc
   :largelisting:

Source Code for mass_storage.xc
...............................

.. literalinclude:: mass_storage.xc
   :largelisting:
