USB Mass Storage Class module

nRF5 SDK v17.0.2

This information applies to the following SoCs: nRF52820 , nRF52833 , and nRF52840 .

This module covers basic implementation of the USB Mass Storage Class that has been defined in the following specification documents:

Usage

You can use this module to create many instances of the Mass Storage Class. Every instance of the class can handle up to 16 disks. Every disk has a unique LUN (Logical Unit Number) associated with it. Access to every LUN is provided by the block device API. The following figure shows basic flow of data between USB Mass Storage, the block device, and drivers:

Page-1 Sheet.227 Mass Storage Class Mass Storage Class Sheet.235 Sheet.228 Sheet.229 Sheet.230 Block Device API Block Device API Sheet.234 init uninit blk_read blk_write init uninit blk_read blk_write Sheet.238 Block Device Block Device Sheet.239 Driver-specific API Driver-specific API Sheet.244 Sheet.249 Sheet.250 Sheet.251 Sheet.253 Sheet.255 Sheet.245 Sheet.246 Sheet.247 Drivers Drivers Sheet.248 SPI/QSPI Flash SD Card others SPI/QSPI Flash SD Card others Sheet.256
Data flow between USB Mass Storage, block device, and drivers

The block device can be one of the two types:

  • RAM block device
  • Empty block device

USB Mass Storage Class provides a unified block device event handler. This event handler must be assigned to every block device. The following is an example of correct block device initialization for an empty block device:

static const nrf_block_dev_empty_config_t m_block_dev_empty_config = {
. block_size = 512,
.block_count = 1024 * 1024,
};
NRF_BLOCK_DEV_EMPTY_DEFINE (m_block_dev_empty,
&m_block_dev_empty_config,
app_usbd_msc_blockdev_ev_handler);

Host-to-device communication

To create an instance of the USB Mass Storage Class, use the APP_USBD_MSC_GLOBAL_DEF macro. The following example shows correct initialization of a Mass Storage Class instance that handles two block devices as separate logical units:

#define BLOCKDEV_LIST() ( \
&m_block_dev_ram, \
&m_block_dev_empty \
)
#define ENDPOINT_LIST() APP_USBD_MSC_ENDPOINT_LIST(1, 1)
APP_USBD_MSC_GLOBAL_DEF (m_app_msc, 0, msc_user_ev_handler, ENDPOINT_LIST(), BLOCKDEV_LIST(), 512);

The following example shows how to register an instance of the Mass Storage Class:

ret = app_usbd_init ();
ASSERT(ret == NRF_SUCCESS );
app_usbd_class_inst_t const * class_inst_msc = app_usbd_msc_class_inst_get (&m_app_msc);
ret = app_usbd_controller_class_append(class_inst_msc);
ASSERT(ret == NRF_SUCCESS );

Host-to-device communication

The host uses Mass Storage Class Bulk Only Transport to communicate with the device. The figure shows how a single command is executed:

Page-1 Sheet.315 Block2.291 Status Transport (CSW) Status Transport (CSW) Block2.292 Ready Ready Block2.293 Data – in (to host) Data – in (to host) Block2.294 Command Transport (CBW) Command Transport (CBW) Block2.295 Data – out (from host) Data – out (from host) Line2 Line1 Line1.306 Line1.311 Line1.312 Line1.313
Command execution between the host and the device