AN1003
DS01003A-page 14
©
2005 Microchip Technology Inc.
The USB enumeration process is handled mainly in
usb9.c
. The
SET_CONFIGURATION
request is han-
dled by
USBStdSetCfgHandler()
. This function
calls the function,
MSDInitEP()
. The function,
MSDInitEP()
, configures and initializes a Bulk-In and
a Bulk-Out endpoint.
The
main()
function in file
main.c
is an infinite loop
that services different tasks – USB or mass storage
application tasks. USB tasks are handled by
USBDriverService()
which handles all USB
hardware interrupts. The mass storage application
tasks are handled by
ProcessIO()
.
ProcessIO()
forms the core of the handling of mass storage
communications on Endpoint 1. Figure 9 shows the
flowchart of the
ProcessIO()
.
When Endpoint 1 is initialized, the
MSD_State
is set to
MSD_WAIT
. The firmware basically waits for a CBW to
be received on Endpoint 1. Upon receiving a valid and
meaningful CBW (as defined in the USB Mass Storage
Class Bulk-Only Transport specification, see
“References”
), the CSW data is prepared. Basically,
the
dCBWTag
is copied to
dCSWTag
in order to
associate the CSW with the corresponding CBW and
the
dCSWSignature
field is set to “53425355h” (little-
endian). The
Direction
bit is read to find the direction
of data transfer (i.e., from host to device or vice versa)
and sets
MSD_State
to
MSD_DATA_OUT
or
MSD_DATA_IN
, respectively (see Figure 10). Further,
the first byte of
CBWCB
is the operation code of the
received command. This is used to decode the
command and take the appropriate action
(
MSDCommandHandler
). It may happen that the
command does not require any data transfer. The
Direction
bit is ‘
0
’ in this case and the
MSD_State
is set to
MSD_DATA_OUT
. If there is no data transfer
required for a given command, the command is
executed and the status is sent using
sendCSW()
. The
values of the
dDataResidue
and
bCSWStatus
fields
are set based on the result of the command execution.
Figure 11 shows the flowchart of the
MSDDataIn()
function. This function is used to send the data
prepared while processing the command in
MSDCommandHandler()
, from the device to the host,
using
MSD_BD_IN
. After command execution,
dCSWDataResidue
reflects the number of bytes of
data obtained as a result of the command execution
that are to be sent to the host. In case of an error
(
bCSWStatus
! = 0x00), zero padded data of the size
expected by the host (
dCBWDataTransferLength
) is
sent. If there is no error, the size of data to be sent
(
dCSWDataResidue
), as a result of command execu-
tion, may not be the same as the size expected by the
host (
dCBWDataTransferLength
). In this case, the
dCSWDataResidue
field in the CSW will reflect the dif-
ference. If the data to be sent is greater than
MSD_IN_EP_SIZE
(64 bytes, size of the Endpoint 1 IN
buffer), then
MSD_IN_EP_SIZE
bytes of data are sent;
otherwise, the remaining
dCSWDataResidue
bytes of
data are sent using the
MSD_BD_IN
buffer.
Note that the only command where data needs to be
read from the host is the
WRITE (10)
command. In the
MSD_WAIT
state, the
MSD_BD_OUT
points to the
msd_cbw
structure in order to read the next command
block. But when a
WRITE (10)
command is received,
the device changes to
MSD_DATA_OUT
. In this state,
the device must read more data from the host and write
it to the SD card. This is done using the 512-byte
msd_buffer
. So, in the
MSD_DATA_OUT
state, the
MSD_BD_OUT
(Endpoint 1 OUT) buffer points to
msd_buffer
. In order to read the entire 512-byte data
block, after every read, the
MSD_BD_OUT
points to a
location in the
msd_buffer
incremented by
MSD_OUT_EP_SIZE
(size of the Endpoint 1 OUT
buffer). Once the
msd_buffer
is filled (8 reads of
64 bytes), the block of data is written to a specific loca-
tion in the SD card using the
SECTORwrite(...)
function (defined in
sdcard.c
). This process is
repeated if multiple blocks of data are to be written to
the SD card. The
LBA
field of the
WRITE (10)
CBWCB
gives the information about the starting
LBA
and the
TRANSFER LENGTH
field indicates the number of
contiguous
LBA
s to be written.
EXAMPLE 3:
STRUCTURE FOR COMMAND
BLOCK WRAPPER
Out endpoint size is configured as 64 bytes. The
msd_buffer
is a 512-byte buffer declared in the USB
dual port RAM area. The block size of the SD card is
512 bytes. The
msd_buffer
is used to read 512 bytes
from the host using multiple 64-byte reads from
MSD_BD_OUT
. Once 512 bytes of data are read from the
host (
msd_buffer
is filled), the entire block of data is
written to the SD card using the function,
SECTORWrite()
. For
WRITE (10)
commands where
the
TRANSFER LENGTH
> 1, multiple blocks of 512 bytes
of data are written to consecutive sectors, starting with
the
Logical Block Address
field in the command
block. The translation between
LBA
and the physical
address is as follows: since each sector has
2
9
= 512 bytes, the physical address is obtained by left
shifting the
LBA
by 9 positions. Similarly, for
READ (10)
,
a block of 512 bytes of data is read from the SD card
using the function,
SECTORread()
, and then transmit-
ted to the host in 64-byte packets using the
MSD_BD_IN
typedef struct _USB_MSD_CBW
{
dword dCBWSignature;
dword dCBWTag;
dword dCBWDataTransferLength;
byte bCBWFlags;
byte bCBWLUN;
byte bCBWCBLength;
byte CBWCB[16];
} USB_MSD_CBW;
深圳市英锐恩科技有限公司
www.enroo-tech.com