App Note Programmers Guide MSP430 USB API

Programmers_Guide_MSP430_USB_API

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 130

DownloadApp Note  Programmers Guide MSP430 USB API
Open PDF In BrowserView PDF
March 2017

Programmer’s Guide: MSP430 USB API & Descriptor Tool
MSP430
ABSTRACT
The MSP430 USB API implements four USB device classes: the Communications Device
Class (CDC), the Human Interface Device (HID) class, the Mass Storage class (MSC),
and the Personal Healthcare Device Class (PHDC). It’s designed for easy creation of
USB applications on MSP430 microcontrollers that are equipped with an on-chip USB
module.
Contents
1

INTRODUCTION ......................................................................................................................................................... 5
1.1
1.2

2

OVERVIEW ....................................................................................................................................................................5
THE MSP430 USB DEVELOPERS’ PACKAGE ........................................................................................................................6

INTRODUCTION TO THE MSP430 USB API .................................................................................................................. 8
2.1
MSP430 USB API STACKS: OVERVIEW ............................................................................................................................8
2.1.1 Devices Classes Supported by the MSP430 API Stacks ..........................................................................................8
2.1.2 Development Environments Supported by the API ................................................................................................8
2.1.3 Hardware Requirements .......................................................................................................................................9
2.1.4 Host Operating System Support ............................................................................................................................9
2.1.5 USB Certification....................................................................................................................................................9
2.1.6 driverlib Support ..................................................................................................................................................10
2.1.7 Stack Organization ..............................................................................................................................................10
2.1.8 Usage of MCU Peripheral Resources ...................................................................................................................13
2.1.9 XT2 Frequency Auto-Detection ............................................................................................................................13
2.1.10
Memory Requirements ...................................................................................................................................14
2.1.11
Using an RTOS .................................................................................................................................................14
2.1.12
Support for Composite USB Devices ................................................................................................................14
2.1.13
Transmission Speeds .......................................................................................................................................15
2.1.14
Release Notes, and Migration from Previous Versions ...................................................................................16
2.2
THE COMMUNICATIONS DEVICE CLASS (CDC) API .............................................................................................................16
2.2.1 CDC Overview ......................................................................................................................................................16
2.2.2 Host Considerations.............................................................................................................................................16
2.3
THE HUMAN INTERFACE DEVICE (HID) API .......................................................................................................................17
2.3.1 HID Overview .......................................................................................................................................................17
2.3.2 HID-Datapipe vs. HID-Traditional ........................................................................................................................18
2.3.3 Host Considerations.............................................................................................................................................19
2.4
THE MASS STORAGE CLASS (MSC) API ............................................................................................................................19
2.4.1 MSC Overview .....................................................................................................................................................19
2.4.2 Storage Device Types...........................................................................................................................................20
2.4.3 File System Software ...........................................................................................................................................20
2.4.4 Host Considerations.............................................................................................................................................20

1

2.5

THE PERSONAL HEALTHCARE DEVICE CLASS (PHDC) API .................................................................................................... 21

3

GETTING STARTED WITH EVALUATION .................................................................................................................... 22

4

GETTING STARTED WITH DEVELOPMENT ................................................................................................................. 23
4.1
STARTING DEVELOPMENT FROM AN EMPTY USB PROJECT IN THE TI RESOURCE EXPLORER ......................................................... 23
4.2
STARTING DEVELOPMENT FROM AN EMPTY USB API PROJECT ............................................................................................. 25
4.3
STARTING DEVELOPMENT FROM AN EXISTING EXAMPLE ...................................................................................................... 25
4.4
ADDING USB INTO AN EXISTING MSP430 APPLICATION ..................................................................................................... 25
4.4.1 Adding in the Files ............................................................................................................................................... 25
4.4.2 Managing #includes ............................................................................................................................................ 26
4.4.3 Project Settings ................................................................................................................................................... 27

5

MSP430 USB DESCRIPTOR TOOL .............................................................................................................................. 28
5.1
WHAT IS THE TOOL? ..................................................................................................................................................... 28
5.2
WHAT IS A “USB INTERFACE”?....................................................................................................................................... 29
5.3
WHAT ARE USB DESCRIPTORS? ...................................................................................................................................... 30
5.4
WHEN TO USE THE TOOL? ............................................................................................................................................. 30
5.5
USING THE TOOL.......................................................................................................................................................... 30
5.5.1 Minimum Steps to Begin Development............................................................................................................... 31
5.5.2 Using the Tool Before Final Production ............................................................................................................... 34
5.6
THE TOOL’S GENERATED OUTPUT ................................................................................................................................... 34
5.7
ACCESSING INTERFACES FROM THE APPLICATION ................................................................................................................ 35
5.8
USB CONFIGURATIONS ................................................................................................................................................. 36
5.9
TROUBLE OPENING THE TOOL? ....................................................................................................................................... 36

6

USB STATES/EVENT MANAGEMENT ......................................................................................................................... 37
6.1
6.2
6.3
6.4
6.5
6.6
6.7
6.8
6.9
6.10
6.11
6.12

7

USB MANAGEMENT FUNCTION CALLS ............................................................................................................................. 37
USB STATES/EVENTS.................................................................................................................................................... 38
INITIALIZING THE API .................................................................................................................................................... 42
DETECTION OF THE HOST VIA VBUS ................................................................................................................................ 42
CONNECTION TO THE HOST ............................................................................................................................................ 42
ENUMERATION ............................................................................................................................................................ 43
SUSPEND/RESUME ....................................................................................................................................................... 43
SELECTIVE SUSPEND...................................................................................................................................................... 44
REMOTE WAKEUP ........................................................................................................................................................ 44
FAILED ENUMERATION .................................................................................................................................................. 45
REMOVAL FROM THE BUS .............................................................................................................................................. 46
USB HARDWARE CONDITIONS IN EACH STATE ................................................................................................................... 46

DATA EXCHANGE USING DATAPIPE INTERFACES (CDC AND HID-DATAPIPE) ............................................................. 47
7.1
INTRODUCTION ............................................................................................................................................................ 47
7.2
DATAPIPE FUNCTION CALL / EVENT SUMMARY .................................................................................................................. 48
7.3
CREATING A DATAPIPE INTERFACE ................................................................................................................................... 49
7.4
SEND/RECEIVE “OPERATIONS” ....................................................................................................................................... 49
7.4.1 User Buffer .......................................................................................................................................................... 50
7.4.2 Background Execution ........................................................................................................................................ 51
7.4.3 How Many Operations Can be Open Simultaneously? ....................................................................................... 52
7.4.4 Behavior During Suspend/Resume ...................................................................................................................... 52
7.4.5 Lifecycle of a Send Operation .............................................................................................................................. 53

Programmer's Guide: MSP430 USB API v4.10

2

7.4.6 Lifecycle of a Receive Operation ..........................................................................................................................54
7.4.7 How Long (in Real-Time) Does an Operation Stay Active? ..................................................................................55
7.5
HOST-SIDE CONSIDERATIONS WHEN INTERFACING TO THE DATAPIPE .....................................................................................55
8

MSC: SOFTWARE ARCHITECTURE .............................................................................................................................57
8.1
MSC ARCHITECTURE: HIGH-LEVEL OVERVIEW ..................................................................................................................57
8.2
MSC DEVICE TYPES ......................................................................................................................................................59
8.3
STORAGE “ADDRESS SYSTEM”: LUNS & LBAS ..................................................................................................................59
8.4
MSC FUNCTION CALL / EVENT SUMMARY.........................................................................................................................61
8.5
COMPONENTS OF AN MSP430-BASED MSC APPLICATION ..................................................................................................61
8.5.1 Defining the Interface’s LUNs ..............................................................................................................................62
8.5.2 Registering the Location of the Buffer: USBMSC_registerBufferInformation() ..................................................63
8.5.3 Registering the Buffer Info Structures: USBMSC_fetchInformationStructure() ..................................................64
8.5.4 Informing the API about the Media: USBMSC_updateMediaInformation() .......................................................64
8.5.5 Periodically Initiating SCSI Command Handling, using USBMSC_pollCommand() ..............................................66
8.5.6 Processing Buffer Events .....................................................................................................................................67
8.6
MANAGING DUAL ACCESS TO THE MEDIUM ......................................................................................................................74

9

TRADITIONAL HID INTERFACES .................................................................................................................................75
9.1
9.2
9.3
9.4
9.5

10

EVENT HANDLING .....................................................................................................................................................84
10.1
10.2
10.3
10.4
10.5
10.6

11

INTRODUCTION ............................................................................................................................................................75
CREATING A MOUSE OR KEYBOARD ..................................................................................................................................76
CREATING A CUSTOM HID INTERFACE ..............................................................................................................................79
GENERATING A CUSTOM HID REPORT DESCRIPTOR.............................................................................................................81
WRITING APPLICATION CODE FOR TRADITIONAL HID DEVICES ..............................................................................................82

THE RELATIONSHIP BETWEEN INTERRUPTS AND EVENTS .......................................................................................................84
WAKING FROM EVENT HANDLERS....................................................................................................................................84
CALLING API FUNCTIONS FROM EVENT HANDLERS ..............................................................................................................85
ENABLING EVENTS ........................................................................................................................................................85
EVENT HANDLER FUNCTIONS ..........................................................................................................................................85
EVENT HANDLER SUMMARY ...........................................................................................................................................85

PRACTICAL MATTERS: WRITING USB PROGRAMS WITH THE API .............................................................................88
11.1
POWER MANAGEMENT .................................................................................................................................................88
11.1.1
Directing Power into VUSB from an External Source ......................................................................................88
11.1.2
The API’s Effect on Power Settings ..................................................................................................................89
11.1.3
VCORE Setting .................................................................................................................................................89
11.1.4
Managing VBUS Power During USB Suspend..................................................................................................89
11.1.5
Selective Suspend ............................................................................................................................................90
11.1.6
Use of Low-Power Modes ...............................................................................................................................90
11.2
CLOCK MANAGEMENT ...................................................................................................................................................91
11.2.1
Summary of USB Clock System ........................................................................................................................91
11.2.2
MCLK Requirements ........................................................................................................................................92
11.2.3
Sourcing the USB PLL Reference Clock ............................................................................................................92
11.2.4
API Delay Loops ...............................................................................................................................................92
11.2.5
XT2 Startup Times ...........................................................................................................................................93
11.2.6
Using XT2 for Non-USB Functions ...................................................................................................................93
11.3
“BUS ERRORS”.............................................................................................................................................................93
11.4
USE OF DMA ..............................................................................................................................................................94

Programmer's Guide: MSP430 USB API v4.10

3

11.5
USING AN RTOS .......................................................................................................................................................... 94
11.6
SYSTEM INTERRUPTS ..................................................................................................................................................... 94
11.6.1
Ensuring the MSP430 Services USB Interrupts ................................................................................................ 94
11.6.2
USB ISR Latency .............................................................................................................................................. 94
11.7
USB DESIGN CONSIDERATIONS ....................................................................................................................................... 95
11.7.1
Robustness: Handling Surprise Removal or Suspend ..................................................................................... 95
11.7.2
The Impact of USB State on Functionality ...................................................................................................... 95
11.8
STATE-DEPENDENT FUNCTIONALITY: MAIN LOOP FRAMEWORK ........................................................................................... 97
11.9
STATE-INDEPENDENT FUNCTIONALITY .............................................................................................................................. 99
11.10
TIPS FOR SENDING DATA OVER DATAPIPE INTERFACES .................................................................................................. 101
11.10.1 Conditions to Consider When Sending Data ................................................................................................. 101
11.10.2 Background Processing ................................................................................................................................. 102
11.10.3 Anticipating a Lost Bus ................................................................................................................................. 107
11.11
TIPS ON RECEIVING DATA OVER CDC OR HID-DATAPIPE ............................................................................................... 108
11.11.1 USBCDC_receiveDataInBuffer() and USBHID_receiveDataInBufferr() .......................................................... 108
11.11.2 Continuously-Open Receive .......................................................................................................................... 112
11.11.3 Fixed-Size Receive ......................................................................................................................................... 113
11.12
TIPS ON INVOKING BSL WHILE USB IS ACTIVE ............................................................................................................ 115
12

DEBUGGING TIPS ................................................................................................................................................... 116
12.1
THE DEVICE ENUMERATION PROCESS............................................................................................................................. 116
12.1.1
Summary of the Enumeration Process.......................................................................................................... 116
12.1.2
Determining Whether the Device Enumerated............................................................................................. 117
12.1.3
Determining if the Device Asserted Itself to the Host ................................................................................... 119
12.1.4
D+ Was Asserted, but Driver Association Failed ........................................................................................... 119
12.2
COMMON PROBLEMS ................................................................................................................................................. 120
12.2.1
Problems that Can Cause USB Failure at Any Time ...................................................................................... 120
12.2.2
Problems that Can Cause Failed Enumeration (Driver Association) ............................................................. 120
12.3
AVOIDING DEVICE CONFLICTS ON THE HOST DURING USB DEVELOPMENT ............................................................................ 121

13

USING THE API WITH RTOSES ................................................................................................................................. 122
13.1
GENERAL DESIGN CONSIDERATIONS............................................................................................................................... 122
13.2
USING THE USB API WITH TI’S SYS/BIOS ..................................................................................................................... 122
13.2.1
SYS/BIOS Thread Types: Hardware Interrupts (Hwi) .................................................................................... 123
13.2.2
SYS/BIOS Thread Types: Software Interrupts (Swi) ...................................................................................... 124
13.2.3
Tasks (Task) .................................................................................................................................................. 124
13.2.4
Idle Thread .................................................................................................................................................... 125

14

FOR MORE INFORMATION ..................................................................................................................................... 126

APPENDIX A. GLOSSARY ................................................................................................................................................. 127
USB DEFINITIONS ................................................................................................................................................................... 127
API STACK DEFINITIONS ........................................................................................................................................................... 129
GENERAL DEFINITIONS ............................................................................................................................................................. 130

Programmer's Guide: MSP430 USB API v4.10

4

1 Introduction
1.1

Overview
The USB API (application programming interface) stack for the MSP430 is a turnkey API. It’s
intended to enable easy and reliable creation of a simple USB data connection between an
MSP430 and a USB host. It includes support for these USB device classes:

Communications Device Class (CDC)

Human Interface Device class (HID)

Mass Storage Class (MSC)

Personal Healthcare Device class (PHDC)
The API is designed to minimize the USB knowledge required to write an application:

All USB protocol is handled automatically by the API

The data interface presented to the application is simple to use, abstracting the application
from USB protocol

USB descriptors, and stack configuration, are automatically handled by the MSP430 USB
Descriptor Tool
The user shouldn’t need to modify the API source. However, for experienced USB
programmers, the source is open and available for editing. Accessing the API’s source can also
be useful for system debug and gaining a deeper knowledge of the USB system.
Application examples are included in the MSP430 USB Developers Package.

Programmer's Guide: MSP430 USB API v4.10

5

1.2

The MSP430 USB Developers’ Package
This Programmer’s Guide documents the USB API, Descriptor Tool, and USB examples.
However, these are part of a larger collection: the USB Developers Package.
The table shows the contents of the Dev Package. The organization in the table matches the
directory structure of the Dev Package files; but the names are expanded, for human readability.
Table 1.

MSP430 USB Developers Package Contents

Item

Description

Host USB Software
Java HID Demo App

Host-side example for implementing HID. It complements the MSP430’s HIDDatapipe API, simplifying creation of a general-purpose USB HID device.

Python USB Firmware Upgrader

One of two host-side USB firmware update solutions provided TI-MSP430. (The
other is based on Microsoft Visual Studio and not included in the USB Dev
Package; see the note below this table.)
This upgrader is not documented within this Programmer’s Guide. See the
upgrader’s directory in the USB Developers Package for documentation.

MSP430 USB Software
Documentation
API Functional Reference

Doxygen-generated function reference for all the USB API calls

Examples Guide

A guide for the person evaluating the USB API, using the examples

MSP430 USB API
Programmer’s Guide

This document. A detailed reference for someone that’s decided to develop a
USB device using the USB Developer’s Package.

Release Notes HTML file
MSP430 USB API

API software library for implementing USB devices
Contains anything unique to a particular revision, including bug fixes,
benchmarks, compiler dependencies, and migration information.

Examples
emptyUsbProject

A project containing only a main.c populated with a suggested main loop
framework. The framework is commented with instructions.

CDC Examples

Examples for implementing virtual COM ports using the CDC class.

HID Examples

Examples using the HID class

HID-Datapipe

Examples of HID-Datapipe, a means of UART-style data exchange based on the
HID class.

HID-Traditional

Examples of ordinary HID interfaces, like mice and keyboards

MSC Examples

Examples for implementing mass storage devices, like SD-card and emulated
on-chip flash drives.

Composite Examples

Examples of composite USB devices; that is, devices comprising more than one
of the interfaces above

SYS/BIOS Examples

Examples showing us of the USB API with TI’s SYS/BIOS RTOS

driverlib (driver library)

Contains the standard MSP430 driverlib. It is referenced by all the examples.

USB_API

These are the actual USB API code files. It is referenced by all the examples.

MSP430 USB Descriptor Tool

Automatically generates reliable descriptors for literally any combination of USB
interfaces. It saves the developer’s time, and reduces the chance for errors.
Using the Tool is part of the standard recommended design flow.

USB Dev Package Manifest

Information related to licensing and origins of the code.

Programmer's Guide: MSP430 USB API v4.10

6

Separate from the USB Developers Package is an application note MSP430 USB Field
Firmware Updater (slaa452), and its associated firmware update host application based on
Microsoft Visual Studio. This application note discusses design considerations when
implementing updates over USB using the MSP430’s on-chip bootstrap loader (BSL). It
especially targets applications where the end user performs this in the field. This updater based
on Visual Studio is completely unrelated to the Python-based one above.

Programmer's Guide: MSP430 USB API v4.10

7

2 Introduction to the MSP430 USB API
2.1

MSP430 USB API Stacks: Overview
The MSP430 API stack allows easy creation of USB devices on MSP430 derivatives equipped
with an on-chip USB module. The architecture emphasizes compact code space and light
execution. Resource usage outside the USB module is minimized, allowing easy integration into
the end application.

2.1.1 Devices Classes Supported by the MSP430 API Stacks
A USB device must contain one or more USB interfaces. Each interface must be of a particular
USB device class type. Device classes define a USB protocol to support a given type of device.
Table 2.

Supported USB Device Classes

Device Class

Description

Communications Device Class (CDC)

Results in a virtual COM port on the USB host

Human Interface Device (HID) class

Traditional HID devices include mice and keyboards. The MSP430
USB API also defines a subclass called HID-Datapipe, which creates a
UART-like free-form datastream on top of the HID interface.

Mass Storage Class (MSC)

A USB interface through which a storage volume can be mounted on
the host

Personal Healthcare Device Class (PHDC)

Used with Continua healthcare devices

CDC, HID, and MSC are often used in general-purpose USB applications. In contrast, PHDC is
very specific to Continua applications, and requires higher-level software layers to implement
Continua compatibility.
All of these share a common USB layer.

2.1.2 Development Environments Supported by the API
The USB API stack and examples build and run on both the IAR and CCS environments for
MSP430. See the Release Notes HTML file in the USB Developers Package for specific
IAR/CCS version information.
Support for GCC is available only on CCS 6.0 and v4.10 of the USB API stack supports
MSP430 GCC natively.
IAR and CCS are both available in free, code-size-limited versions (8K and 16K, respectively, of
object code). Applications that fit under 8K of memory can be run on both free versions.
Applications that are greater than 8K cannot be built using the free IAR Kickstart tool. Instead,
the free version of CCS can be used; or a licensed version of either environment.
See the Release Notes within the USB Developers Package zip file for additional information
specific to a given release.

Programmer's Guide: MSP430 USB API v4.10

8

2.1.3 Hardware Requirements
The API stack and examples run, unmodified, on all four USB-equipped MSP430 families:
 F552x/551x
 F550x (including the F5510)
 F663x/563x
 F665x/565x
(Note that the F5510 is considered a member of the F550x family, and not the F551x family.)
The only hardware configuration required is to select the appropriate MSP430 derivative in the
project settings. A few of the examples use buttons or an SD-card, which may be hardwaredependent. See the Examples Guide within the USB Developers Package for step-by-step
instructions for configuring this. For starting a new USB project, see Sec. 4.

2.1.4 Host Operating System Support
All the USB device classes supported by the USB API are supported natively within Windows,
MacOS, and Linux distributions. This has been true for over ten years. For specific information
about the versions against which the API has been tested, see the Release Notes HTML file
within the USB Developers Package.
Native host OS support has several advantages:
 Less hassle for the OEM (no need to prepare a kernel-mode driver installation)
 Less hassle for the end user (doesn’t have to perform one)
 Problems are less likely to occur; leading to greater stability and lower support costs
For CDC, there are considerations unique to Windows and the Mac OS. Sec. 2.2.2 discusses
this in detail.
Since virtual COM ports (CDC) and storage volumes (MSC) are generic interfaces supported by
all these host operating systems, there’s a wealth of support in the public domain for how to
write host applications interfacing to them. In contrast, HID is more specific to USB, and less
familiar to most developers. To help with this, the MSP430 USB Developers Package includes
a Java-based HID application called the Java HID Demo App.

2.1.5 USB Certification
The MSP430 device derivatives, running the USB API, have passed USB certification testing for
all four device classes (CDC/HID/MSC/PHDC). All certification was performed at MCCI.
An output of the USB certification process is a test ID, or TID. The TID’s for all current MSP430
silicon is shown in the table below.

Programmer's Guide: MSP430 USB API v4.10

9

Table 3.

MSP430 Device Test IDs (TIDs)

MSP430 Derivative
MSP430F552x
MSP430F550x/5510

Package

TID

PT/RGC/RGZ (QFP/QFN)

40000973

ZQE (BGA)

40001139

PT, RGC, RGZ (QFP/QFN)

40001138

(Note: F5504RGZ not included
in this TID; see below)

MSP430F5504RGZ

RGZ (QFN)

41001138

MSP430F563x
MSP430F663x

PZ (QFP)

40001250

ZQW (BGA)

40001442

MSP430F565x
MSP430F665x

PZ (QFP/QFN)

40001444

ZQW (BGA)

40001443

All MSP430 devices were certified under MSP430’s own vendor ID, 0x2047. This VID is
separate from TI’s main VID (0x0451).

2.1.6 driverlib Support
Starting with v4.0 of the USB API, projects now depend on the MSP430 driverlib (“driver
library”) HAL layer. driverlib brings portability and standardization among MSP430’s software
offering, especially for basic MCU functions like clocks and power.
For those porting applications from earlier versions of the API, the move to driverlib will not be
very noticeable. The application examples in the USB Dev Package, however, have all been
updated to include driverlib. The “HAL core library” used by previous versions has been
deprecated by TI MSP430. Please see the Release Notes HTML file for migration information.
Besides being included in the USB Developers Package, driverlib can be obtained for general
MSP430 development with MSP430Ware.

2.1.7 Stack Organization
The software stack is shown in the figure below.

Programmer's Guide: MSP430 USB API v4.10

10

Application
TX/RX
Constructs

Application space

CDC HID MSC
API API API

Event
USB
Handlers Config

API space

USB API
driverLib
MSP430 header file

Figure 1.

MSP430 API Stack Diagram

The individual device class layers (CDC, HID, MSC) all share a common USB layer (USB API).
The application makes calls to these APIs, and also directly to the USB layer.
The stack is shown as API space and application space. In most cases TI recommends to only
modify application space, not the API itself. This helps preserve the USB compliance of the API,
increasing the chance of passing USB certification and avoiding complications. The
send/receive constructions and event handlers are constructs provided with the API, but they
are considered to be in application space.
The sections “USB Config” and “Event Handlers” are special spaces that straddle
API/application space (and thus are shaded grey). They are core to the API, but are controlled
by the user.
The files are shown in the table below. The table’s organization reflects the actual file/directory
organization.

Programmer's Guide: MSP430 USB API v4.10

11

Table 4.

MSP430 USB API Stack Files

File/Directory
Standard
MSP430
libraries

USB API
Space

Description

driverlib

Used to configure power and clocks, and to read the device’s TLV
structure (Tag-Length-Value) in MSP430 flash, to obtain the
device’s unique die ID number.

MSP430 header file
(for example, msp430f5529.h)

Standard header file for the particular MSP430 device derivative
being used. Ships with IAR/CCS. Selection is automatically
controlled by project settings.

USB_API
USB_Common
defMSP430USB.h

Definitions related to the MSP430 USB module

device.h

Helps configure the stack for the device derivative selected in the
IAR/CCS project settings.

types.h

Deprecated. The USB stack has been converted to use C99 types.

usbdma.c

Functions related to DMA transfers

usb.c/h

Functionality common to all USB applications.

UsbIsr.h

Header file for UsbIsr.c, located in \USB_Config

USB_CDC_API

CDC-related functionality

UsbCdc.c/h
USB_HID_API

HID-related functionality

UsbHid.c/h
UsbHidReq.c/h
USB_MSC_API

MSC-related functionality

UsbMsc.h
UsbMscReq.c/h
UsbMscScsi.c/h
UscMscStateMachine.c/h
USC_PHDC_API

PHDC-related functionality

UsbPHDC.c/h
USB Config
Space

Application
Space

USB_config

Configures the API’s characteristics, including what interfaces the
device contains.
Generate these files using the MSP430 USB Descriptor Tool.

descriptors.c/h

Contains the device’s USB descriptors and other information that
configures the API.

UsbIsr.c

USB interrupt service routine handler, and related functionality

USB_app
usbEventHandling.c

Event handlers, for responding to USB-generated events. Write
application-specific code into these handlers.

usbConstructs.c/h

Example constructs for send/receive operations. The functions here
reflect the approaches described in Sec. 11

(other application files)

Other user-defined application files.

hal.c/h

Included with the USB examples. It contains hardware-specific
adjustments for the F5529 Launchpad, F5529 Experimenter’s
Board, and all relevent FET target boards, making it simple to run
the examples on any of these boards.

main.c

User application

Programmer's Guide: MSP430 USB API v4.10

12

2.1.8 Usage of MCU Peripheral Resources
Within the USB API, the resources shown below are considered to be owned by the API. If the
application accesses them, it should be aware of how the API uses them.
Table 5.
Resource

Resource Ownership

Owned by the API When

How It’s Used

USB module

Always

Generally speaking, the application should not
attempt to control the USB module’s registers or pins
(see note)

XT2 oscillator

Always

The API configures, starts, and stops XT2 as it
needs, in order to perform USB communication. The
behavior can be modified by the
USB_DISABLE_XT_SUSPEND configuration
constants (handled by the Descriptor Tool). Although
the application can use XT2 to drive the CPU’s
MCLK, there’s usually little value to this, and it’s not
recommended.

DMA channel

While both conditions are true:

During these times, the API owns this channel, used
for both TX/RX. The application should not attempt
to use it.

 DMA functionality is enabled using
USB_DMA_CHAN (via Descriptor
Tool).
Timer A

 the USB state is ST_ENUM_ACTIVE
When the XT2 Frequency Auto-Detection
is used

It is used when the USB stack is initialized. The
USB_determineXT2Freq API feeds TimerA1 with the
unknown frequency SMCLK=XT2 and feeds CCI2A
to a known frequency ACLK=REFO.

Note: The pins associated with the USB module can be used as special I/O pins when not used for USB.
The application has permission to manipulate these pins directly only when the USB module has been
disabled using the USB_disable() call. Once the USB module is enabled using USB_enable(), only
the API has the right to control these pins.

These are the only peripherals used by the API. The only other resources used are memory,
and CPU cycles.

2.1.9 XT2 Frequency Auto-Detection
The MSP430 USB API uses a routine called USB_determineXT2Freq() to measure the
frequency of the external oscillator (XT2) that is used in the application. Frequencies of 4MHz,
8MHz, 12MHz, 16MHz and 24MHz are detected automatically by the USB stack. The function
uses Timer A to compares the speed of XT2 to a known calibrated internal clock REFO (32KHz).
In the case of a different XT2 Frequency the initialization of the variables USB_XT2Freq and
USB_XT2PLL can be modified inside the USB_init(). For example if we had a 32 MHz crystal we
would modify the following lines of code (included in the USB_init API):
USB_XT2Freq = USB_determineXT2Freq();
USB_XT2PLL = USB_lookUpPll(USB_XT2Freq);
to

Programmer's Guide: MSP430 USB API v4.10

13

USB_XT2Freq = 32;
USB_XT2PLL = USBPLL_SETCLK_32_0;

2.1.10 Memory Requirements
The MSP430 USB API object code is compact and uses relatively few cycles to execute.
Please see the Release Notes accompanying the source code, for code size information specific
to a particular code release.
Because of the shared USB layer, adding more interfaces only has incremental effects on
memory requirements.
The API’s RAM usage is static.

2.1.11 Using an RTOS
The MSP430 USB API stacks were designed to not require an RTOS. However, the API stacks
are intended to be straightforward to port to an RTOS. In the accompanying USB application
examples, examples are provided showing use of the API with TI’s SYS/BIOS RTOS.

2.1.12 Support for Composite USB Devices
The MSP430 USB API is unusually easy to configure for any combination of USB interfaces
(i.e., in creating a composite USB device). All that’s required is to use the Descriptor Tool to
select the interfaces; the API becomes automatically configured. The resulting USB descriptors
are in the exact format required by Windows, the MacOS, and Linux. All that remains is to write
the application. (See Sec. 3 for more information about the Descriptor Tool.)
A composite USB device is a single physical device containing multiple USB interfaces. A USB
interface is defined by the USB device class it supports – for example, CDC, HID, or MSC.
Thus, a USB device might be:

a CDC device only

an HID device only

an MSC device only

CDC+HID in composite

HID+MSC in composite

CDC+CDC in composite

HID+HID+HID+HID+MSC in composite
and so on.
A software engineer may wish to create composite devices for a variety of reasons. If two COM
ports are desired, this would be accomplished with two CDC interfaces in composite. MSC
doesn’t lend itself well to generic command/status information, so creating a composite device
with MSC and either CDC or HID can enable a device that has both storage capability and
general communication.
The number of composite interfaces is limited only by the number of endpoints in the MSP430
USB module. As examples of what is possible, MSP430 has enough endpoints to create:
Programmer's Guide: MSP430 USB API v4.10

14





Three CDC interfaces
Two CDC interfaces and two HID interfaces
Two MSC interface, three HID interfaces, and one CDC interface

This is more than enough for the vast majority of applications.
Note that only one MSC interface can be implemented, which is a restriction of USB. If more
than one storage volume is desired, use more than one logical units (LUNs).

2.1.13 Transmission Speeds
Full-speed USB is rated 12Mbps. This is a theoretical maximum, and it includes protocol
overhead – so it isn’t possible for a practical application to achieve this rate for data payload.
Another concern that can affect bandwidth on any USB device is software on the USB MCU.
The MCU application must prepare data to be sent, and process data that’s arrived; this can put
the CPU in the critical path, slowing bandwidth.
If bandwidth is a priority, DMA should be used. (This can be enabled using the Descriptor Tool.)
For an application in which bandwidth is primarily limited by MCU data handling, bandwidth is
roughly linear to MCLK. Running at the maximum MCLK can often achieve bandwidth close to
what is shown for DMA.
2.1.13.1 Considerations for CDC/MSC Interfaces
If bulk transfers are used – for example, as CDC and MSC interfaces do -- then the speed is
further impacted by host/bus conditions:
 Host application. USB is very host-driven, which means the host initiates all data transfers,
whether sending or receiving. If the host application doesn’t initiate transfers often enough,
data will be slower.
 Bus loading. Bulk transfers have the potential to reach the highest data rates by using any
spare bandwidth. However, the tradeoff to this is that bandwidth scarcity will cause slowed
transfers.
Because high bandwidth are often desirable for CDC/MSC interfaces, TI does benchmarking of
these interfaces. The results are shown in the Release Notes.
2.1.13.2 Considerations for HID Interfaces
Interrupt transfers – used by HID interfaces -- are immune to these effects; they maintain steady
bandwidth, no matter what else is happening on the bus. However, they’re also limited in
bandwidth, to 64KB/sec. As a result, if the required bandwidth is low and the bus may
experience heavy loading, HID’s steady bandwidth can be an advantage.
For an HID interface to achieve this 64KB/sec, the polling interval must be set to 1ms. (Each
USB packet is 64 bytes.) This can be done with the Descriptor Tool (see Sec. 3). The polling
interval determines the rate at which the host will exchange data with this interface.

Programmer's Guide: MSP430 USB API v4.10

15

If 64KB/sec isn’t fast enough, the device might be able to still use HID by creating multiple HID
interfaces in composite. The Descriptor Tool can easily do this. The MSP430 and host
applications could then both be written to interleave their data across them.

2.1.14 Release Notes, and Migration from Previous Versions
A “Release Notes” HTML file accompanies each release of the USB Developers Package.
Reference this file for any information specific to this release, including:

All changes from the previous versions

Instructions for migration from previous versions

Code size / memory calculations

CDC/MSC performance benchmarks

Updated IDE configuration information

Known issues

2.2

The Communications Device Class (CDC) API

2.2.1 CDC Overview
An MSP430 running this API and attached to a USB host via USB will establish a virtual COM
port on that host.
COM ports are a popular, simple software mechanism through which a host can communicate
with a peripheral. Originally designed for RS232 serial ports, it’s often today used with other
protocols, such as USB and Bluetooth. Since the physical RS232 port no longer exists, these
COM ports are often called “virtual COM ports”.
The Communications Device Class (CDC) is one of the standard USB device class protocols. It
is supported natively by most host operating systems.
This API supports only a subset of the CDC specification. This is because CDC has a scope
that goes far beyond virtual COM ports, encompassing a wide range of telecommunications
equipment. This API supports the Abstract Communication Model (ACM) of the PSTN subclass
of the CDC. The ACM provides for a control mechanism using common V.250 AT commands.
This configuration establishes a fully-functional virtual COM port interface.
This API supports up to three CDC interfaces in composite.

2.2.2 Host Considerations
CDC support varies somewhat among the major host operating systems, which is described
below.
Placing a CDC interface alongside other interfaces in a composite USB device is a little
problematic. The CDC specification didn’t leave room for this, which has forced the need for
other solutions. The official, supported solution is the use of an auxiliary USB descriptor called
the Interface Association Descriptor (IAD). This has been adopted by Windows and Linux; but it
has not been adopted by the MacOS.

Programmer's Guide: MSP430 USB API v4.10

16

2.2.2.1 Microsoft Windows
The CDC class is supported by all versions of Windows going back to Windows 2000.
Although Windows natively contains the driver binaries, it doesn’t contain an INF file. (Windows
uses INF files as a means of associating devices with drivers.) Therefore, the OEM must
provide an INF file to the end user, and the end user must walk Windows through a device
installation process. In this process, Windows must somehow be guided to the INF file. The
Descriptor Tool generates an appropriate INF file when generating its output, so there is no
need to create one manually.
If the device is composite, then the INF file needs to be tailored to the chosen set of USB
interfaces. The Descriptor Tool accounts for this when it generates its INF file.
In addition to a CDC driver, the host needs an application to interface with the resulting virtual
COM port. Although a custom application is probably desirable, any “terminal” application can
be used to communicate with an MSP430 equipped with the CDC interface.
Windows XP Service Pack 3, Vista, 7 and 10 all support the IAD, and thus they’re able to
support CDC interfaces alongside other interfaces within a composite USB device.
However, earlier versions of Windows do not support the IAD, and therefore they do not support
composite CDC devices. The Descriptor Tool will alert the user if this is attempted.
2.2.2.2 MacOS
The CDC class is supported on any recent version of the MacOS.
However, the MacOS does not support the IAD. As a result, it is not possible for a Mac to
enumerate a composite device that contains a CDC interface; only single-interface CDC devices
are supported. The Descriptor Tool will alert the user if this is attempted.
2.2.2.3 Linux
The CDC class is supported on any recent, common Linux distribution.
Recent versions of Linux support the IAD, and therefore can work with composite CDC devices.

2.3

The Human Interface Device (HID) API

2.3.1 HID Overview
The Human Interface Device class is perhaps the oldest and most established USB device
class, in that it was created for use with the most basic USB application: mice and keyboards. It
also supports a wide variety of other “PC peripherals” that consist primarily of various “controls”
(buttons, joysticks, volume knobs, etc.).
Like CDC and MSC, HID is supported natively in any common host operating system. This has
several advantages, discussed below.

Programmer's Guide: MSP430 USB API v4.10

17

A unique aspect of host interaction with HID devices is that often the OS itself is the application
interfacing with the device, as in the case of mice and keyboards. In other cases – usually in
more general-purpose applications – regular applications interface with the device, just as with
CDC.
When using HID for general-purpose applications, it’s soon discovered that developing host
support for HID isn’t like CDC/MSC. CDC/MSC generate interfaces on the host that are
extremely common and popular (virtual COM port or storage volume, respectively). In contrast,
host operating systems don’t generate a similar generic interface for HID. For many host
programmers, then, HID represents a small learning curve. To help with this, TI makes available
the Java HID Demo App, which is designed to pair with the MSP430 HID API stack.
There is a sub-protocol in HID called the boot protocol. This is a “light” version of USB HID that
can be run from a PC’s BIOS program, prior to loading the OSes' full HID drivers. This allows
mice and keyboards to begin operating from the very beginning of the boot process. This
protocol is supported by the API.
Some legacy HID implementations request the host to send data via control endpoint zero.
Usually, the host only uses this endpoint for management functions. Note that endpoint zero on
the MSP430 is only eight bytes wide (compared to 64 for the others). API functions are provided
to enable compatibility with these legacy implementations.

2.3.2 HID-Datapipe vs. HID-Traditional
At a basic level, all HID interfaces send/receive HID reports. Unlike freeform data packets,
reports are heavily formatted, using a complex scheme not unlike a scripting language. This
script is placed within a report descriptor, reported to the host during enumeration.
There is a learning curve associated with this. Report organization is not flat; it is filled with
concepts such as collections and usages, which can be placed inside each other to several
levels.
Since there are otherwise advantages to using HID for general-purpose use, TI creates a special
predefined HID configuration called HID-Datapipe, which use a special set of function calls. To
the MSP430 application, this interface appears as a UART-style unformatted datastream. And
in fact, these calls are identical to the ones used with CDC interfaces. The application prepares
a data buffer of any size, and sends/receives the entire chunk. Underneath the HID-Datapipe
calls, a special report format is used that is comprised only of two fields: a size byte, with the
remainder of the USB packet reserved for data. In other words, this report uses the simplest
possible configuration, allowing the application to format the data however it wishes.
Any HID interface that isn’t a datapipe is called traditional. Traditional HID interfaces
send/receive reports. The developer must provide a report descriptor, and use the HIDTraditional function calls to send/receive reports. Some engineers need to create traditional HID
interfaces in order to use previously-existing host HID applications, or because the host
operating system interacts with the device directly (like mice or keyboards).
The developer enters the report descriptor into the Descriptor Tool. The Tool contains predefined report descriptors for mice and keyboards. Any other traditional HID interface is termed
‘custom’, and the developer must enter the raw report descriptor.

Programmer's Guide: MSP430 USB API v4.10

18

Sec. 7 describes datapipe interfaces, including CDC and HID-Datapipe. Sec. 9 describes
traditional HID interfaces.

2.3.3 Host Considerations
Unless the device being created is one the host operating system interacts with (like a mouse or
keyboard), a host application will be required. Unlike CDC, which can be used with ordinary
“terminal” applications, a HID interface generally requires a custom application (unless it’s of a
type recognized by the host OS).
TI provides the Java HID Demo App to assist with this. By default, it supports the HID-Datapipe
model and HID report format. However, it could be adapted for customized reports as well.
Being Java, it runs on Windows, Mac, and Linux, provided a Java Runtime Engine is present.
2.3.3.1 Microsoft Windows
The HID class is supported by all versions of Windows going back to Windows 2000.
Unlike CDC (but like MSC), HID devices always load silently onto Windows hosts. They also
load silently on Mac/Linux, without the help of an INF file. This is much simpler and trouble free
for the end user.
2.3.3.2 MacOS/Linux
The HID class is supported on any version of the MacOS or Linux. See the Release Notes
HTML file for specific version information.

2.4

The Mass Storage Class (MSC) API

2.4.1 MSC Overview
An MSP430 running this API will be seen by the USB host as a storage volume. Storage
volumes are supported natively by practically any host operating system. Native support has
significant advantages, discussed in Sec. 2.4.4 below.
MSC devices are sometimes called “MSD” (Mass Storage Device). They refer to the same USB
device class.
This API implements the Mass Storage Class, as specified by the USB Implementers Forum. It
specifically implements the bulk-only transport (BOT) protocol, rather than the
control/bulk/interrupt (CBI) protocol. The latter is only intended for legacy applications.
A primary purpose of the MSC protocol is to receive and execute SCSI commands from the
host. SCSI (Small Computer System Interface, pronounced “scuzzy”) is a set of specifications
covering various levels of protocol, including a physical cable interface. One of the SCSI
command sets – the SCSI transparent command set – has been adopted for use with the MSC
protocol. This is the command set supported by this API.
All handling of SCSI commands is performed automatically by the API, with some support by the
application.
Programmer's Guide: MSP430 USB API v4.10

19

Compared to CDC/HID, the application carries a heavier role: it must implement the volume to
be mounted. The API can’t handle this itself, because there are many types of media that might
get implemented. If the application doesn’t do this, the MSC interface might enumerate, but the
volume won’t mount in the system.
Unlike CDC/HID, only one MSC interface can be created within a physical USB device. (It can
still contain multiple CDC/HID interfaces in composite with that MSC interface.) If multiple
storage volumes are desired, this can be accomplished with multiple logical units (LUNs). The
API supports any number of LUNs.

2.4.2 Storage Device Types
The API implements two sets of SCSI commands, selectable by the application. Each is
associated with a particular peripheral device type value; the host treats these types differently.
Table 6.
Device Type

Storage Device Types

SCSI Command Set

Description

Direct-Access Block Devices

SCSI Block Commands (SBC)

Hard drives, flash drives, memory cards

CD-ROM/DVD

MultiMedia Commands (MMC).

CD-ROM and DVD players.

(Not to be confused with MultiMedia Cards,
which use the SBC command set.)

The developer selects this in the Descriptor Tool. The tool will automatically use the correct
SCSI command set. Since the host uses a different file system for each, the implementation of
the volume may need to be different.

2.4.3 File System Software
If the MSP430 application needs to comprehend files on the medium -- rather than simply
handling the host’s access requests -- file system software must be added. (This is discussed
in more detail in Sec. 8). The API is designed to be usable with any file system the developer
chooses, and many third party and open source options are available. But as an example, the
USB Developers Package’s MSC examples demonstrate usage with the popular open-source
FatFs file system software

2.4.4 Host Considerations
To access the volume on any host operating system, a host application is required. Writing such
an application is generally straightforward, because of the wealth of information and tools
available for file access and storage volumes. (In this, the situation is similar to that of virtual
COM ports.)
2.4.4.1 Microsoft Windows
The MSC class is supported by Windows 2000, XP, Vista, 7, 8 and 10.
Unlike CDC (but like HID), MSC devices always load silently onto Windows hosts, without the
help of a user-provided INF file.

Programmer's Guide: MSP430 USB API v4.10

20

2.4.4.2 MacOS/Linux
The MSC class is supported on any modern version of the MacOS or Linux. See the Release
Notes HTML file for specific version information.
Like on Windows, MSC interfaces load silently on Mac/Linux.

2.5

The Personal Healthcare Device Class (PHDC) API
PHDC is the USB layer within a USB device that supports the Continua Health Alliance. In such
a device, the data follows the data/messaging standards ISO/IEEE 11073-20601 + ISO/IEEE
11073-10407. Note that these IEEE layers are not provided with this software package. Texas
Instruments offers a complete Continua-certified PHDC solution.
Note that it isn’t supported to have more than one PHDC interface in a composite USB device;
the Descriptor Tool will prevent this from being implemented.
Because of the tight association of PHDC with Continua, it is not treated in the USB Developers
Package as CDC/HID/MSC are. High-level information about PHDC is provided in this
Programmer’s Guide, as well as how to create PHDC interfaces. (PHDC is fully supported by
the Descriptor Tool.) However, this Programmer’s Guide doesn’t describe how to interact with a
PHDC interface, and the USB examples don’t include any for PHDC. For these resources, see
MSP430’s Continua page.

Programmer's Guide: MSP430 USB API v4.10

21

3 Getting Started With Evaluation
To get started with evaluating and studying the MSP430 USB API, refer to the Examples Guide,
also within the USB Developers Package. It contains all information needed to evaluate the
examples.
The example set includes:

7 CDC (virtual COM port) examples

7 HID-Datapipe examples

2 traditional HID devices (a mouse and a keyboard)

4 MSC examples

4 composite examples

2 examples using TI’s SYS/BIOS RTOS

1 example for how to reduce interrupt latency
The Examples Guide contains information on:

Step-by-step directions for loading and running the examples, on CCS or IAR

The dynamics of INF files on Windows for CDC interfaces

Using the Java HID Demo App
In short, it contains the information needed by the person only evaluating the USB Developers
Package, while this Programmer’s Guide contains information for the person beginning
development.

Programmer's Guide: MSP430 USB API v4.10

22

4 Getting Started With Development
Three separate approaches to beginning development with the USB API are described here:

Starting development from an existing example

Starting development from an “empty” USB API project

Adding the USB API into an existing MSP430 application
The first two approaches are advantageous for new development. When an application already
exists, into which USB is being added, the third approach may be necessary.
It’s assumed that the reader is using a recent version of IAR Embedded Workbench, or Code
Composer Studio v5.5 or later.
The details of CCS/IAR interaction are not discussed here; please refer to the appropriate
documentation, as needed.

4.1

Starting Development from an Empty USB Project in the TI Resource Explorer
The TI Resource Explorer contains a wizard that helps you create a new USB API project.
The wizard performs these steps:
1) Creates an empty USB project
2) Walks you through using the Descriptor Tool to create your USB interfaces
3) Prompts you to adjust the MSP430 device derivative, for your hardware
4) You can begin developing your application!
The wizard is shown below.

Programmer's Guide: MSP430 USB API v4.10

23

Figure 2.

TI Resource Explorer: “Create an Empty USB Project” Wizard

After the wizard completes, it provides a framework main(), including the suggested main loop
framework discussed in Sec. 11.8. You can insert code directly into this framework, borrowing
from examples and referencing this Programmer’s Guide.
In this empty project, the recommended project settings and source directories are already in
place, with no need to edit them.

Programmer's Guide: MSP430 USB API v4.10

24

4.2

Starting Development from an Empty USB API Project
IAR users not having access to the wizard discussed above may wish to copy or import the
project emptyUsbProject in the \examples directory of the USB Developers Package, and begin
development from this project. This is the same project as is produced by the wizard, except
that the Descriptor Tool has not been run. You can accomplish the same effect by running the
Descriptor Tool by double-clocking on its executable file, and depositing the generated output in
your target project.
As with starting from an example, the recommended project settings and source directories are
already in place, with no need to edit them.
It’s recommended to make a copy of this project, rather than using it directly, in case the empty
project is desired again at a later time.

4.3

Starting Development from An Existing Example
It’s also possible to start development from an existing example project; by removing nonapplicable example code, and adding new code.
If you find an example that has your desired USB interfaces already defined, then for the time
being, you may not need to run the Descriptor Tool. Although this is enough for experimentation
or simple development, bear in mind that if taking a product to market, additional tuning of the
descriptors will eventually be needed. The Tool is a good way to do that.
Be aware that not all the necessary code is located in the specific example’s directory; the
\driverlib and \USB API directories, external to the example’s directory, are required.
If using IAR and wanting to make a copy of the example, manually copy the directories to a new
location: the example’s directory, \driverlib directory, and \USB_API. Be sure to keep the same
directory structure that the example used.
If using CCS, simply import the example into your workspace. Beginning with v4.0 of the USB
Developers Package, the examples are based on the “projectspec” feature present in CCS v5.5
and later. The .projectspec file present in each example’s directory will cause a CCS import to
always result in a new copy of the example. It will replicate the same directory structure used by
the example.

4.4

Adding USB into an Existing MSP430 Application
When USB is being added into an existing application, the appropriate USB API directories must
be manually copied into the target project, and merged.
Various directories within the USB API projects are discussed below; please reference Table 4.

4.4.1 Adding in the Files
The USB API core files, located in the \USB_API directory, must be added. It’s easiest to
simply add the entire directory \USB_API, as a whole, to the target project. Files within this
directory have relative #include pathways, and won’t be broken by this copy.
Programmer's Guide: MSP430 USB API v4.10

25

1) The files descriptors.c/h and UsbIsr.c are typically located in a directory \USB_config, outside
of \USB_API. This is because of the special role they play in configuring the API, and
because their files originate from outside the API – from the Descriptor Tool. If desired, the
developer can put these files anywhere. To support this, their path has not been hardcoded
into the API; the #include path for these files is kept in the project settings. If moving them to
a different directory, the developer must adjust this path.
2) It’s suggested that applications using CDC and HID-Datapipe interfaces use the construct
functions in usbConstructs.c/h, to send and receive data. Copy these into the target
application.
3) Copy \driverlib into the target project. As of v4.0 of the USB API, it’s now based on driverlib.
driverlib may also be useful to the application, for accessing peripherals. Note that the
version of driverlib distributed in the USB Developers Package is only a subset of the full
distribution; MSP430Ware contains the full version of driverlib.
Although the USB examples use a \USB_app directory, there’s no requirement for how the
application places its own files.
The files are now present in the target directory. #includes must be added to ensure the files
are found.

4.4.2 Managing #includes
The application will need to #include several files for basic USB functionality:
#include "descriptors.h"
#include "USB_API/USB_Common/device.h"
#include "USB_API/USB_Common/usb.h"

4) #includes to *.h files for the selected USB interfaces must be made. The directories are
\USB_CDC_API, \USB_HID_API, and/or \USB_MSC_API. For example, if your application
has a CDC interface, be sure to include every *.h file in \USB_CDC_API, within any file
referencing CDC API function calls. The same applies to HID and MSC.
5) Applications using the CDC/HID-Datapipe constructs in usbConstructs.c will need to include
usbConstructs.h.
Having taken these steps, the project code should be ready for USB development.
As discussed above, multiple #include links are made within the \USB_API directory, from one
file to another within \USB_API. It’s recommended not to make organizational changes within
this directory.
The files normally placed in \USB_config – descriptors.c/h and UsbIsr.c – can actually be
located anywhere. But if moving them out of \USB_config, the include path for these files in the
project settings must also be changed.

Programmer's Guide: MSP430 USB API v4.10

26

4.4.3 Project Settings
Add global paths to:
 the directory containing \USB_API. Don’t include \USB_API itself, just the directory that
contains it. (In the USB examples, this is the project root directory.)
 the directory containing the Descriptor Tool output files. (In the USB examples, this is
\USB_config.)
 For driverlib, add an include for driverlib\MSP430F5xx_6xx
Stack size must also be managed; the USB examples can be used to get an idea of the
requirements, which are generally modest.

Programmer's Guide: MSP430 USB API v4.10

27

5 MSP430 USB Descriptor Tool
The Descriptor Tool is a part of doing development with the MSP430 USB API. It can generate
descriptors for any combination of USB interfaces – whether single-interface or composite.
Unlike creating them manually, it does so reliably, and on the first try – saving valuable
development time.
The Tool has built-in help – both an overview sheet that’s available from the Help Menu, and
also contextual information in the Help Pane. But, additional information is provided here.

Figure 3.

5.1

The Descriptor Tool

What is the Tool?
The Descriptor Tool generates a set of USB descriptors for your project. In so doing, it also
builds the USB interfaces your application can use to interface with the host. After it runs, you
can write your application to send/receive data over these interfaces.
An example of a USB device with three interfaces is shown below.

Programmer's Guide: MSP430 USB API v4.10

28

Figure 4.

The Descriptor Tool

In addition to USB descriptors, the Tool collects other compile-time information related to
resources owned by the USB API, so that the API can manage them properly. (See Table 5.)
Once the Tool’s output is generated and placed into the target project, the developer can
immediately begin writing application-specific code that sends/receives data over USB. The
provided examples are a good starting point for this.

5.2

What is a “USB Interface”?
A USB interface is essentially a partitioned stream of data between the USB device and the
host. An interface is of a particular device class, each with its own protocol. The host responds
differently for each device class:
CDC (Comms Device Class): Presents a virtual COM port
HID (Human Interface Device): Subtypes include mice, keyboards, other PC peripherals, or
simply "generic".
MSC (Mass Storage Class): Causes the host to mount a storage volume over this interface
PHDC (Personal Healthcare Device Class): Only used with Continua medical devices
The device tells the host what interfaces it contains by reporting the information in the USB
descriptors. Most devices contain only a single interface, but some contain more; these are
called composite USB devices.
The Descriptor Tool can quickly build descriptors for any combination of CDC, HID, and MSC
interfaces, according to whatever your application needs.

Programmer's Guide: MSP430 USB API v4.10

29

5.3

What are USB Descriptors?
Every USB device contains descriptors, which communicate the device’s “identity” to the host.
This includes which USB interfaces are supported, as well as other capabilities. In the MSP430
USB API, they’re defined in the files descriptors.c/h.
Another set of important information in the descriptors is vendor-specific identification
information, including the vendor ID and product ID (VID/PID), and also several strings that may
be displayed by the host in connection with this device. The VID/PID combination serves as a
identifier for a given product, and therefore it’s important that it be unique to this particular
product. (When developing a USB device, it’s recommended to change the PID any time the
USB descriptors change in any way, since most hosts keep archived information about a device,
indexed by the VID/PID.)

5.4

When to Use the Tool?
Before you can write USB code, you need to create your USB interfaces with the Tool. So, run
the Tool, before beginning your development.
When you run the Tool, the inputs are saved into the MSPUSBDesc.xml file. This way, you can
make changes to the .xml file and re-generate your output later. This is often necessary; for
example, a product’s VID/PID often is not finalized until later in the project.

5.5

Using the Tool
At the beginning of development, users are often most concerned about setting up their USB
interfaces and starting development. Before sending a device or product into the field, however,
every field needs to be fine-tuned.
Both approaches are described below.
While using the Tool, always check the Help Pane text for each field – it helps you understand
the tradeoffs of the decision you need to make. Float over each field, or click on it, to update the
Help pane.

Programmer's Guide: MSP430 USB API v4.10

30

Figure 5.

The Descriptor Tool’s Help Pane

5.5.1 Minimum Steps to Begin Development
These are the minimum steps required to build interfaces, to start development.
1) Select your interfaces, by pressing the buttons at the top. Before this step, you will have
needed to decide on your interfaces; read more about them in this Programmer’s Guide.

Figure 1.

Selecting Your USB Interfaces

Upon doing this, the interfaces will appear in the Navigation View, at left.

Programmer's Guide: MSP430 USB API v4.10

31

Figure 2.

Interfaces in the Navigation View

The Tool catches certain situations that might have caused you trouble, and warns or corrects
you about them. An example of this is that it will always move an MSC interface to the front of
the list; this maximizes compatibility with Windows/Mac/Linux operating systems.

2) With the tree formed, now click on each node, filling out relevant information in each node’s
pane. The items below are the minimum requirements to create the interfaces.
a) MSP430 View --> XT2 Oscillator Frequency: Select the frequency to match the
clock you're applying on your MSP430's XT2 oscillator. If this doesn't match your
hardware's oscillator, your USB won't function.

Figure 3.

XT2 Oscillator Frequency Field

b) USB Device View --> PID: The VID field is already filled out with TI-MSP430's VID,
but you must enter a PID. The Help Pane text includes an "experimenter's range" of
PIDs you can use.

Programmer's Guide: MSP430 USB API v4.10

32

Figure 4.

PID Field

c) HID interfaces: choose your device type (datapipe, mouse, keyboard, or custom)
d) MSC interfaces: choose the number of LUNs and whether the media is removable
For c) and d), reference the Help Pane text for these fields, as well as this Programmer’s Guide.

3) You can either manually save your *.xml input file. (File --> Save As...) or when the
‘Generate’ button is pressed, the tool will automatically save a .xml file named
MSPUSBDesc.xml. This way, you can load your inputs at a later time, modify, and re-generate.
(The Tool cannot read descriptors.c/h output files, only the *.xml file.)

Figure 5.

Save As…

4) Generate your output, by pressing the "Generate" button. Direct the output to your target
project. In the typical project structure for the USB API, these files are usually stored in
\USB_config (see the example projects). But they can go anywhere, as long as the project's
#include settings are adjusted accordingly.
5)

Build your project. It’s recommended to use the “Rebuild all” option the first time compiling
after replacing the default files with Descriptor Tool output files.

Programmer's Guide: MSP430 USB API v4.10

33

5.5.2 Using the Tool Before Final Production
The items above tell the host what kind of device it is, and help configure the MSP430’s
minimum information to function as a USB device. But the fields that were skipped over are
important.
Some of them may even be needed prior to development for some projects, like the one
indicating the project will be used with the SYS/BIOS RTOS. Other fields, like the
vendor/product/configuration/interface strings, are used by the host to identify the USB device.
To do a complete job of using the Tool, follow the same procedure as above, but pay attention to
every field. Use the Help Pane to understand the decisions you’re making. If the information
there isn’t sufficient, please reference relevant portions of this Programmer’s Guide.

5.6

The Tool’s Generated Output
The Tool outputs five files:
 descriptors.c
 descriptors.h
 usbisr.c (contains the USB interrupt service routine, and related functions)
 an INF file (if one of the interfaces is CDC)
 an XML file (contains the configuration data for the interfaces)
When a CDC interface is attached for the first time to a particular Windows host, Windows
needs the user to provide an INF file (*.inf). Windows uses INF files to associate devices with
particular drivers, and for HID/MSC interfaces, the INF is included in Windows. For CDC it isn't.
The INF contains specific information about the device, including its VID/PID and some strings.
Since the Tool already has this information, it generates an INF file for you and gives the user
the option of saving it to the directory. Also note that if your USB device is composite, the INF
file must change according to the interfaces you selected. The Tool handles this for you,
automatically.
A diagram of how the Tool configures the API is shown below.

Programmer's Guide: MSP430 USB API v4.10

34

Figure 6.

5.7

Descriptor Tool: File Interaction

Accessing Interfaces from the Application
For USB devices including multiple CDC or HID interfaces, it can be important for the host and
device to agree on how the interfaces are mapped, so that they can send/receive data on the
appropriate interface.
intfNum is the index you provide to API function calls on the MSP430 side, to select the
appropriate interface. In the Descriptor Tool, every USB interface has an intfNum parameter.
This is seen on each interface's view:

Figure 7.

Programmer's Guide: MSP430 USB API v4.10

The intfNum Parameter

35

For every interface you define, the Tool places a constant in the descriptors.h file, like
CDC0_INTFNUM or HID0_INTFNUM. You can use these as the intfNum parameter in your
application code:
// Sends data to the CDC interface with intfNum=1, the second CDC
// interface defined in this device
USBCDC_sendDataInBackground(buf, size, CDC1_INTFNUM);

For single-interface (non-composite) devices, the sole interface's intfNum is always zero.
There can only be one MSC interface in a USB device, so there is no intfNum parameter in the
MSP430's MSC API calls. If MSC is used in composite, it's always reported as the first interface
in the device, per USB requirements.

5.8

USB Configurations
The USB specification provides for multiple USB configurations to be defined within a given USB
descriptor set. Each configuration contains a set of USB interfaces that are in effect at any
given time, and the host theoretically has the option to change configurations at any time.
So for example, the device could report two configurations: one with an HID keyboard interface,
and another with both a keyboard and mouse HID interfaces. The host could choose to switch
between those two interfaces, almost like selecting two different logical devices within the same
physical device.
However, in practice, this feature doesn’t see much use. The MSP430 USB API only supports
definition of a single configuration within its descriptor set.

5.9

Trouble Opening the Tool?
The Tool requires Java Runtime Engine v1.6+ to run properly. As a result, you may need to
download the most recent version of the JRE. The Tool is designed to automatically sense the
JRE version on your machine upon being opened, and guide you to http://www.java.com if
necessary.
Due to Java limitations, the Tool may give an error upon being opened if there is a semicolon or
space in the pathname, or if the pathname is very long. If the Tool fails to open, with an unclear
error, please move the entire directory for the tool into a different path that addresses these two
problems.

Programmer's Guide: MSP430 USB API v4.10

36

6 USB States/Event Management
6.1

USB Management Function Calls
The USB API uses the following function calls to manage basic USB states. Related USB event
handlers are also shown.
Table 7.
Function
BYTE USB_setup()

USB Management Call Summary
Description
Intended to be called at the beginning of execution.
 Calls USB_init()
 Calls USB_setEnabledEvents() to enable all events
 If a USB host is found to be already present, calls USB_reset(),
USB_enable(), and USB_connect() to prompt enumeration.

BYTE USB_init()

Prepares the USB module to detect VBUS events from the host.
(Calling this from the application has been deprecated; use
USB_setup() instead.)

BYTE USB_enable()

Activates the USB module, PLL, and transceiver (PHY).

BYTE USB_enable_PLL()

Special functions used only if the developer has decided to reduce
USB resume interrupt latency, by assuming responsibility for
oscillator/PLL delay periods. USB_enable_PLL() starts the PLL lock
after the application has ensured that XT2 has stabilized.
USB_enable_final() finishes the resume, after the application has
ensured the PLL lock period has expired. See USB example #G1.

BYTE USB_enable_final()

BYTE USB_disable()

Disables USB module, PLL, and transceiver (PHY).

BYTE USB_setEnabledEvents()

Enables/disables detection of the available events.

BYTE USB_getEnabledEvents()

Returns the status of USB event enabling

BYTE USB_connect()

Instructs USB module to make itself available to the host for
enumeration, by pulling the PUR pin high.

BYTE USB_disconnect()

Causes a logical disconnect from the host by pulling PUR low

BYTE USB_forceRemoteWakeup()

Forces a remote wakeup of the USB host

BYTE
USB_getConnectionInformation()

Returns low-level information about the USB connection

BYTE USB_getConnectionState()

Returns the state of the USB connection

Table 8.
Event Handler functions
BYTE USB_handleClockEvent()

USB Event Handler Summary
Event Description
The USB PLL has failed (out of range). This may also
mean the XT2 crystal oscillator has failed.

BYTE USB_handleVbusOnEvent()

Indicates that a valid voltage is now available on the VBUS
pin (a host is now present on the bus)

BYTE USB_handleVbusOffEvent()

Indicates that a valid voltage is no longer available on the
VBUS pin (a host was present on the bus, but has now
been removed)

BYTE USB_handleResetEvent()

Indicates that the USB host has initiated a port reset. This
has a similar effect to calling USB_reset(), including that
enumeration (if it had been achieved) will be lost, and the
USB state will change.

Programmer's Guide: MSP430 USB API v4.10

37

BYTE USB_handleSuspendEvent()

Indicates that the USB host has suspended this device.

BYTE USB_handleResumeEvent()

Indicates that the USB host has resumed this device from
suspend mode.

BYTE
USB_handleEnumerationCompleteEvent()

Indicates that the USB device has just become
enumerated.

BYTE USB_handleCrystalStarted()

Special functions used only if the developer has decided to
reduce USB resume interrupt latency, by assuming
responsibility for oscillator/PLL delay periods.
USB_handleCrystalStarted() indicates the API has
started the stabilization process, and the application should
take responsibility to finish it and then call
USB_enable_PLL(). USB_handlePLLStarted()
indicates the API has started the PLL lock process, and the
application should wait the specified delay and then call
USB_enable_final(). See USB example #G1.

BYTE USB_handlePLLStarted()

For reference details on these functions, including description, parameters, and calling
conditions, please see the API Functional Reference within the USB Developers Package. The
functions are further described below.

6.2

USB States/Events
Every USB device passes through a set of states that describes its interaction with the host.
These are shown below. The diagram makes references to function calls within the API,
described later in this document.

Programmer's Guide: MSP430 USB API v4.10

38

Figure 8.

USB Device State Diagram

The state of the connection is returned by the function USB_getConnectionState(). The
underlying information that defines the state can be returned with the function
USB_getConnectionInformation(). The relationship between these are shown in the
table below.

Programmer's Guide: MSP430 USB API v4.10

39

Table 9.

USB State Definitions

USB_getConnectionState()

USB_getConnectionInformation()
VBUS
detected?

PUR
high?

Enumerated?

Suspended?

ST_PHYS_DISCONNECTED
ST_PHYS_CONNECTED_NOENUM

X

ST_ENUM_IN_PROGRESS

X

X

ST_ENUM_ACTIVE

X

X

X

ST_ENUM_SUSPENDED

X

X

X

ST_PHYS_CONNECTED_NOENUM_SUSP

X

X

X
X

Although each of these factors is discussed in the sections below, here is a brief description:
 VBUS: 5V power from the host. If present, the application can usually assume a host is
attached.
 PUR: PUllup Resistor. A USB device signals its presence to the host by pulling up the D+
signal through a resistor. The MSP430 implements this pullup with the PUR pin, controlled
by software.
 Enumerated: When a USB device has been successfully enumerated, it means the host has
successfully interpreted the device’s descriptors and loaded the appropriate driver. The
process requires a series of USB device requests to complete.
 Suspended: A host can suspend a USB device at any time, at which point no
communication can take place, and current allowed to be drawn from 5V VBUS is restricted
Many applications are best served by using USB_getConnectionState() to direct program
flow.
The states are reflected in the suggested main loop framework shown below. This same
framework is located within the empty USB project.

Programmer's Guide: MSP430 USB API v4.10

40

void main (void)
{
// Set up clocks/IOs. USBHAL_initPorts()/USBHAL_initClocks() will need to be customized
// for your application, but MCLK should be between 4-25MHz. Using the
// DCO/FLL for MCLK is recommended, instead of the crystal. For examples
// of these functions, see the complete USB code examples. Also see the
// Programmer's Guide for discussion on clocks/power.
WDT_A_hold(WDT_A_BASE); // Stop watchdog, so it doesn't reset your app
USBHAL_initPorts();
// Configure all GPIOs
USBHAL_initClocks();
// Configure clocks
// Initialize the USB module, and connect to the USB host (if one is present)
USB_setup(TRUE, TRUE);
__enable_interrupt();

// Enable general interrupts

while (1)
{
// This switch() creates separate main loops, depending on whether USB
// is enumerated and active on the host, or disconnected/suspended. If
// you prefer, you can eliminate the switch, and just call USB_getConnectionState()
// prior to sending data (to ensure the state is ST_ENUM_ACTIVE).
switch(USB_getConnectionState())
{
// This case is executed while your device is connected to the USB
// host, enumerated, and communication is active. Never enter LPM3/4/5
// in this mode; the MCU must be active or LPM0 during USB communication
case ST_ENUM_ACTIVE:
// These cases are executed while your device is:
case ST_PHYS_DISCONNECTED: // physically disconnected from the host
case ST_ENUM_SUSPENDED:
// connected/enumerated, but suspended
case ST_PHYS_CONNECTED_NOENUM_SUSP: // connected, enum started, but host unresponsive
// In this example, for all of these states we enter LPM3. If
// the host performs a "USB resume" from suspend, the CPU will
// automatically wake. Other events can also wake the CPU, if
// their event handlers in eventHandlers.c are configured to return TRUE.
__bis_SR_register(LPM3_bits + GIE);
break;
// The default is executed for the momentary state
// ST_ENUM_IN_PROGRESS. Almost always, this state lasts no more than a
// few seconds. Be sure not to enter LPM3 in this state; USB
// communication is taking place, so mode must be LPM0 or active.
default:;
}
} //while(1)
} //main()

This framework is used in most of the examples, and described in more detail in Sec. 11.8.
A device is likely to spend most of its time in the disconnected, active, and suspended states.

Programmer's Guide: MSP430 USB API v4.10

41

6.3

Initializing the API
Before any other API call, the application must initialize the USB module. Prior to v4.0 of the
USB API, this was done with a call to USB_init(). Events were then enabled using
USB_setEnabledEvents().
These functions still exist and are used internal to the API, but for the USB API v4.0 and later, TI
now recommends most application use a new function instead: USB_setup().
This function:


calls USB_init()



optionally enables all events (selectable by its first parameter)



optionally performs an immediate USB_connect() if it finds that a physical host connection
is present. (selectable by its second parameter)

These behaviors are common to the vast majority of applications, allowing all of them to be
handled within a single function call. If there is a desire to control individual event enables, the
old method can still be used.
USB_setup(TRUE, TRUE) can be seen in the code segment shown in the previous section.

6.4

Detection of the Host via VBUS
A device can usually know an active host is present by sensing the availability of 5V on the
VBUS signal.
Note: A couple of unusual situations may result in 5V on the VBUS pin without a valid host. One is if the
device is attached to a self-powered hub without a host being present. Another is if the host is powered,
but has become hung. A USB device has no way of distinguishing these from an active host, and will
generally assert PUR to attempt enumeration (for example, call USB_connect()). If this is attempted,
the USB state will fail to enter ST_ENUM_ACTIVE, and instead will enter
ST_PHYS_CONNECTED_NOENUM_SUSP indefinitely. The application may need to take this into account.

When VBUS transitions on or off, an API event is generated. These events are handled by
USB_handleVbusOnEvent() and USB_handleVbusOffEvent(), respectively. They can
be thought of as interrupts (or callbacks), and in fact are derived from the USB interrupt service
routine handler. These events must be enabled, using either USB_setEnabledEvents() or
USB_setup().
There are various ways to use these mechanisms. The recommended way is to put code in
USB_handleVbusOnEvent() that connects to the host, since this is the behavior usually
expected of a USB device when VBUS appears (see below).

6.5

Connection to the Host
Connecting to the host usually consists of subsequent calls to USB_enable(), USB_reset(),
and USB_connect():

Programmer's Guide: MSP430 USB API v4.10

42

if (USB_enable() == USB_SUCCEED)
{
USB_reset();
USB_connect();
}

Most of the USB API examples include this code in USB_handleVbusOnEvent().
Note that USB_setup() can perform an automatic connection, if instructed to by its parameters,
and if it finds VBUS already present. This is useful for initial startup of execution, where if VBUS
is already present, no VBUS-on event will be seen.

6.6

Enumeration
A full-speed USB device makes its presence known to the host by activating a pull-up resistor on
the D+ signalling line. MSP430 integrates this with the PUR pin. As mentioned above, the
default USB_handleVbusOnEvent() handler activates this pullup by calling USB_connect().
When the host sees this pull-up, it begins the enumeration process, by which it polls the device
and loads it onto the system. The API handles enumeration automatically. As it does so, it
makes use of the descriptor information in descriptors.c.
When enumeration is complete, a call to USB_getConnectionState() reflects this, and the
system is ready to transfer data. A USB_handleEnumerationCompleteEvent() is also
generated. (The API determines the completion of enumeration by the point at which the host
sends a SET_CONFIGURATION request.)
The enumerated state ends when VBUS is removed (state automatically reverts to
ST_PHYS_DISCONNECTED and a USB_handleVbusOffEvent() is generated), or when a call
is made to USB_disconnect() or USB_disable().

6.7

Suspend/Resume
At any point after successful enumeration, the host may choose to suspend the device. This is
characterized by 3ms of inactivity on the data signals (D+/D-). Once the USB device recognizes
this event, it has seven more milliseconds to move into a state where it consumes minimal
current from VBUS. After this, it cannot communicate with the host until the host resumes it.
Power management of the MSP430’s internal USB functionality is handled automatically by the
USB module and API. They disable the PLL and shut down much of the USB circuitry, only
keeping active what is necessary to detect a resume event (that is, when the host begins
communicating on the data signals again). With the PLL disabled, the USB module becomes
clocked by the MSP430’s VLO oscillator (low-frequency, low-power).
With the PLL no longer using XT2 as a reference, XT2 can be disabled during suspend. If
selected in the Descriptor Tool, the API will attempt to do this. However, keep in mind that if any
peripherals have selected XT2 as their clock source, then XT2 will remain enabled due to those
peripherals issuing it a “clock request”. The current draw required for XT2 should be considered
in the VBUS budget during suspend.

Programmer's Guide: MSP430 USB API v4.10

43

Although the above actions are taken automatically, the application developer is responsible for
ensuring that the device doesn’t consume more power than it should from the host VBUS line.
This may occur if the MSP430 DVCC or the rest of the board is powered from VBUS. See Sec.
11.1 for more information.
A host’s decision to suspend is largely based on its own activity state and its sensitivity to power
drain. Desktop PCs are likely to keep the device active for a long period of time, and only
suspend when the PC itself enters a powerdown state. Laptops are similar, except of course
they tend to enter a powerdown state more often, due to being battery-powered. Mobile hosts
may cut power even more frequently.

6.8

Selective Suspend
The description above applies to USB suspend in general. Traditionally, all USB devices were
suspended at the same time. In contrast, selective suspend is a newer feature by which the
host may suspend individual USB devices selectively, without suspending the others. Usually
this would be done after the host decided that communication had been idle for a period of time.
Use of selective suspend has grown in recent years, mostly in the realm of mobile devices like
phones and tablets.
From the USB device standpoint (i.e., MSP430), there is no difference between a general
suspend or selective suspend. In either case, what the MSP430 sees is 3ms of inactivity, and it
responds the same way. Thus, it supports selective suspend.
Having said this, the USB application may have some impact on whether the USB host
considers the device “inactive”, and thus whether it selectively suspends the device. .Also,
Windows requires a device to have remoted itself as having remote wakeup functionality, before
it will consider it for selective suspend. Sec. 11.1.5 for additional information on optimizing
selective suspend.

6.9

Remote Wakeup
A remote wakeup event is a mechanism by which a suspended USB device can prompt the host
to resume it, perhaps waking the host in the process. A common example of remote wakeup is
when a USB mouse is attached to a PC, and the PC goes into standby mode. Some
configurations allow the mouse to wake the PC when moved, by issuing a remote wakeup event.
After waking, the host resumes the mouse.
A device first must declare itself as capable of remote wakeup within its configuration descriptor.
The Descriptor Tool can configure the API to do this. The host may choose to grant the ability
for remote wakeup, or it may choose not to. Whether it does so is OS-dependent and may also
be dependent on user configuration.
The application can issue a remote wakeup using the USB_forceRemoteWakeup() function.
If it returns USB_SUCCEED, it means the host indeed had enabled the remote wakeup function
and may choose to respond to the request by resuming the device. A resume will be evident to
the application through means of a return to the ST_ENUM_ACTIVE state, and the
USB_handleResumeEvent() handler will execute, if enabled. If
USB_forceRemoteWakeup() returns with USB_GENERAL_ERROR, it means the host did not
enable remote wakeup for this device.
Programmer's Guide: MSP430 USB API v4.10

44

6.10 Failed Enumeration
If the device is attached to a host, and software calls USB_connect(), the host usually begins
enumerating it immediately. The state shifts to ST_ENUM_IN_PROGRESS. Usually enumeration
finishes quickly, and the state moves to USB_ENUM_ACTIVE.
However, for a variety of reasons, this may not happen:
 the device becomes physically attached to a powered hub that doesn’t have a host upstream
from it. It sees VBUS, and interprets this as the presence of a host, and calls
USB_connect(). But there is no host, and so the bus remains idle.
 the device becomes physically attached to a host that is indeed powered, but in a ‘standby’
mode (during which all USB devices are suspended). It sees VBUS and calls
USB_connect(). But because the host is in standby, the bus remains idle. (In other words,
the host suspends the device, just like all USB devices that were already attached.)
 the device becomes physically attached to a host that is indeed powered, but hung; i.e., “blue
screened”, or unusually busy. It sees VBUS and calls USB_connect(). But because the
host is hung, the bus remains idle, or the process otherwise doesn’t complete.
 the device becomes physically attached to a host, and the host begins enumeration. But
something goes wrong in the process; this could be the fault of either the host or device. The
host gives up and suspends the device.
USB suspend is defined as >3ms of no activity from the host. Therefore if the host fails to finish
(or even start) the process, and instead the bus goes idle, then the device’s state will shift from
ST_ENUM_IN_PROGRESS to ST_PHYS_CONNECTED_NOENUM_SUSP. It will remain there until
the host finishes enumeration, or until software “cancels” it (using USB_disconnect() or
USB_disable()).
Since the events listed above are very possible in the lifetime of the USB device, it’s a good idea
for the software developer to consider what will happen in the
ST_PHYS_CONNECTED_NOENUM_SUSP state. Software could choose to stay in this state until
the bus situation changes. If so, it remains ready for the host to enumerate it at any time.
MSP430 low-power modes down to LPM3 are allowed in this state.
Alternatively, software could choose to call USB_disconnect(), and/or USB_disable(),
shifting the state to ST_PHYS_CONNECTED_NOENUM. However, there’s no obvious advantage to
this; and the developer should be aware that if the host does later become available while the
device is attached to it, no event will be received by the device to make it aware of this and reconnect. Therefore the user will probably need to detach/re-attach before enumeration will take
place.

Programmer's Guide: MSP430 USB API v4.10

45

6.11 Removal from the Bus
When the end user detaches the device from the host, this is recognized by the device as a
VBUS-off event (bus power is no longer available on the VBUS pin). The API responds by
automatically disabling the USB module. It also calls USB_handleVbusOffEvent(), where
application software might be written to take action. After the VBUS-off event, a call to
USB_getConnectionState() will return ST_PHYS_DISCONNECTED.
As with suspend events, it is very important that the software designer consider that the end
user may remove the bus at any moment during execution. This is sometimes referred to as a
“surprise removal”. Software must anticipate that this and be able to recover gracefully.

6.12 USB Hardware Conditions in Each State
Each state is associated with certain hardware conditions, as shown below.
Table 10.

USB State Hardware Conditions
USB
Module
Enabled

USB
1
Transceiver

Integrated
2
LDOs

XT2
Oscillator

PLL
Enabled

ST_PHYS_DISCONNECTED
ST_PHYS_CONNECTED_NOENUM

X

Idle

X

X

X

ST_ENUM_IN_PROGRESS

X

Active

X

X

X

ST_ENUM_ACTIVE

X

Idle/Active

X

X

X

ST_ENUM_SUSPENDED

X

Idle

X

(see note
3)

ST_PHYS_CONNECTED_NOENUM_SUSP

X

Idle

X

(see note
3)

Note 1:

Note 2:
Note 3:

Idle means the transceiver is powered, but not transceiving any data, which means it is consuming minimal current.
Active means data is being transceived, raising the current draw. Idle/Active means the transceiver might be in either
condition during this state.
The API enables both the 3.3V and 1.8V USB LDOs.
XT2 can be kept enabled during suspend, using the Descriptor Tool.

The USB module must be enabled in order to detect suspend/resume events from the host, as
well as to transceive data, thus it must be enabled in the majority of states. The other four
columns relate primarily to power consumption. In particular, the PLL is a major source of power
draw, and must be shut down during USB suspend. Similarly, an active USB transceiver
consumes much more current than an idle one. See the device datasheet for specific
parameters.

Programmer's Guide: MSP430 USB API v4.10

46

7 Data Exchange using Datapipe Interfaces (CDC and HID-Datapipe)
The discussion in this section applies to any CDC interface, and any HID interfaces using the
datapipe function calls. It does not apply to traditional HID interfaces.
This section is a reference guide for how datapipe interfaces work. For practical usage
information, see Sec. 11.10 and Sec. 11.11.

7.1

Introduction
The MSP430 USB API provides a simple scheme of exchanging data with the USB host using
either a CDC or HID interface. This scheme is called the datapipe. It defines an architecture in
which the developer’s MSP430 application can define a continuous data block at any address
and of any size, and send it to the host; or receive a block of any size from the host, to be
deposited at any particular address. In this sense, it’s much like interfacing with a COM port or
UART, freeing the developer from thinking about the USB plumbing.

Terminal App

Virtual
COM Port

HID Demo App

What the USB
host sees

HID
Interface

USB Host PC
CDC
Interface

HID-Datapipe
Interface

size

addr

size

addr

USB interfaces built
by the Descriptor Tool

User buffer
User buffer
USBCDC_sendData(addr,
USBHID_sendData(addr,
size,
size,
intfNum);
intfNum);

Application Software

MSP430-Based USB Device
Figure 9.
Programmer's Guide: MSP430 USB API v4.10

Datapipe Interfaces
47

All CDC interfaces in this API are datapipe interfaces. HID interfaces in the MSP430 USB API
can be either traditional or datapipe. This section does not apply to HID-Traditional devices, like
mice or keyboards.
HID-Datapipe was created because HID has some advantages over CDC; for example, the fact
that HID devices enumerate silently on the host, without an INF file. But HID-Traditional is more
difficult to develop; thus HID-Datapipe offers the best of both world (at the expense of
throughput, limited at 64KB/sec).
Either way, the datapipe interface looks exactly the same. The calls are symmetrical, differing
only in their prefix (USBCDC_ vs. USBHID_). Since the text in this discussion applies equally to
both, the function calls are sometimes shown to have the prefix USBxxx_. The same applies to
the prefix for return values (USBxxx_).

7.2

Datapipe Function Call / Event Summary
A table summarizing the datapipe function calls is shown below. For complete documentation,
see the API call reference within the USB Developers Package.
Table 11.

Function
BYTE USBCDC_sendData()
BYTE USBHID_sendData()

Datapipe Function Call Summary
Description
Begins a send operation to the USB host

BYTE USBCDC_receiveData()
BYTE USBHID_receiveData()

Begins a receive operation from the USB host

BYTE USBCDC_bytesInUSBBuffer()
BYTE USBHID_bytesInUSBBuffer()

Returns the number of bytes residing in the USB endpoint buffer
awaiting a receive operation to move them to a user buffer.

BYTE USBCDC_abortSend()
BYTE USBHID_abortSend()

Aborts an active send operation

BYTE USBCDC_abortReceive()
BYTE USBHID_abortReceive()

Aborts an active receive operation

BYTE USBCDC_rejectData()
BYTE USBHID_rejectData()

Rejects payload data residing in the USB buffer, for which a receive
operation has not yet been initiated

BYTE USBCDC_getInterfaceStatus()
BYTE USBHID_getInterfaceStatus()

Returns status information specific to a particular datapipe interface

Programmer's Guide: MSP430 USB API v4.10

48

Table 12.

Datapipe Event Handlers

BYTE USBCDC_handleDataReceived()
BYTE USBHID_handleDataReceived()

Indicates that data has been received for CDC or HID interface
intfNum, for which no data receive operation is underway

BYTE USBCDC_handleSendCompleted()
BYTE USBHID_handleSendCompleted()

Indicates that a send operation on CDC or HID interface
intfNum has just been completed

BYTE USBCDC_handleReceiveCompleted()
BYTE USBHID_handleReceiveCompleted()

Indicates that a receive operation on CDC or HID interface
intfNum has just been completed

For reference details on these functions, including description, parameters, and calling
conditions, please see the API Functional Reference within the USB Developers Package. The
functions are further described below.

7.3

Creating a Datapipe Interface
It’s recommended to use the Descriptor Tool to create the device’s interfaces. Any CDC
interface created by the Tool is a datapipe interface, so all the CDC function calls are datapipe
calls. To create an HID-Datapipe interface, add an HID interface in the Tool, and in its
“Interface” pane, select “HID-Datapipe”. Then after generating the interfaces, interact with this
interface using the HID-Datapipe function calls.
HID-Datapipe interfaces are distinguished from HID-Traditional in two main ways:
 The HID report format is different. HID-Datapipe defines a report format with a single byte
field, and the remainder defined as a large data field. Unlike most HID reports, it doesn’t
attempt to define an intricate report structure.
 The use of the HID-Datapipe calls instead of the HID-Traditional calls. (for example,
USBHID_sendData() vs. HID-Traditional’s HID_sendReport()). The HID-Datapipe calls
assume the aforementioned report format.

7.4

Send/Receive “Operations”
The basic unit of all sending/receiving in the datapipe is the operation. Sending data requires
the start of a send operation. Receiving data requires the start of a receive operation.
For all sending and receiving, the application must first prepare a data source/sink, called the
user buffer. The application passes the buffer, the number of bytes to be transceived, and the
desired USB interface (index with intfNum) to USBxxx_sendData() or
USBxxx_receiveData(). The user buffer is any contiguous block within the MSP430
memory map, described by an address addr and size size.

Programmer's Guide: MSP430 USB API v4.10

49

USBCDC_sendData(addr, size, intfNum);

size

addr
CDC Interface
#intfNum

USB

COM port on
the host

User buffer

USBHID_sendData(addr, size, intfNum);

size

addr
HID Interface
#intfNum

USB

HID device on
host

User buffer

Figure 10. Send Operation
A single call to USBxxx_sendData() initiates a send operation. The API begins to copy the
buffer to the USB endpoint buffer (128 bytes), which is made available to the host. At the host’s
discretion and timing, it reads the packet from the MSP430’s endpoint buffers. As the endpoint
buffer is emptied, the API fills it with the next data from the user buffer. When all the data has
been read by the host, the operation is complete.
Similarly, a single call to USBxxx_receiveData() initiates a receive operation.. The user
buffer acts as a data sink to any data subsequently received from the host over this interface.
As data is received into the USB endpoint buffers for this interface, the API copies it into the
user buffer. When the buffer is full, the operation is complete.

7.4.1 User Buffer
The term “buffer” implies a RAM source, but it can also be flash or peripherals – any contiguous
block in the MSP430’s memory map.
The buffer can be of any size, whether one byte or several kilobytes. All packetization is
automatic.

Programmer's Guide: MSP430 USB API v4.10

50

The user buffer is separate from the endpoint buffers, which can be thought of as registers
within the USB module that store USB data as it waits to be sent to the host, or data that has
been received from the host and is waiting to be read by MSP430 software. Unlike the user
buffer, the endpoint buffers are limited to a small 64 bytes. The API handles all interactions with
the endpoint buffers automatically, so they’re not part of the API application interface model.
During a send operation, the data is only copied out of the user buffer; the contents of the buffer
remain unchanged. However, care should be taken that the application not write to the buffer
until a send operation is known to be complete, as doing so could disrupt the operation.

7.4.2 Background Execution
Send/receive operations are executed “in the background”. For example, when a call to
USBxxx_sendData() returns, this has no bearing on whether the operation has completed or
not -- only that is has started, or will start very soon. The operation will occur in the background
as the bus is available, until it’s completed.
In other contexts, this concept is called asynchronous operation, in that it happens
asynchronous to the application’s code execution, driven by an alternate interrupt source (the
host). Another way of looking at it is that the USB MCU’s execution is “decoupled” from the
host, rather than being dependent on it for a quick response.
Background execution has several advantages:
1. Execution is not held in one place while long transfers complete
2. Execution is not held at the mercy of the host/bus’ availability
3. Efficiency is increased, because the API isn’t waiting idle while waiting for the host to fetch
the next packet. Other useful activities can be performed during this time.
When the MSP430 software starts (for example) a send operation using USBCDC_sendData(),
it prepares communication with the host, and then waits for the host to read all the USB packets
necessary to complete the operation. (USB is a very host-centric bus, and no byte can be
sent/received without the host requesting it.) Then, possibly even before a byte of data is
transferred, USBCDC_sendData() returns, and the application execution continues.
As the host begins pulling the data, interrupts occur in the MSP430 to fulfill the operation. The
application is not mindful of this. The API effectively has “standing orders” to send/receive the
user buffer.
Once these standing orders no longer apply – that is, once the buffer has been processed – the
API calls USBxxx_handleSendCompleted()to inform the application. The interface is once
again available for a new operation.
This is directly analogous to sending a block of memory over a SPI interface, using DMA to
move the block to the SPI transmit register as the register becomes available. In this example,
the DMA module is in control of the operation; in the USB context, the API is in control.

Programmer's Guide: MSP430 USB API v4.10

51

The application can know that an operation has completed by one of two means:
1. A USBxxx_handleSendCompleted() or USBxxx_handleReceiveCompleted()
event occurs
2. A call to USBxxx_getInterfaceStatus() shows whether or not an operation is still in
progress
From the application’s point of view, send/receive operations are automatic; but the software
designer should be mindful of the background processing. For example, software should check
for the presence of an open operation before starting another one, or before accessing the user
buffer of an open operation. That can be done with a call to
USBxxx_getInterfaceStatus().
Note that the developer can effectively avoid background execution (or in the terminology used
in other software contexts, achieve synchronous operation), by polling the interface with
USBxxx_getInterfaceStatus() before allowing application execution to resume. The API
provides two example constructs for each case, for example
USBHID_sendDataInBackground() and USBHID_sendDataAndWaitTillDone(), which
implement both approaches – see Sec. 11.10.

7.4.3 How Many Operations Can be Open Simultaneously?
An interface may have one send operation and one receive operation in progress at any time –
but not more than one of either. If more than one interface exists, each can have their own
simultaneous operations.

7.4.4 Behavior During Suspend/Resume
If the device gets suspended by the USB host or if the bus is removed, any active send or
receive operations remain open.

Programmer's Guide: MSP430 USB API v4.10

52

7.4.5 Lifecycle of a Send Operation
A call to USBxxx_intfStatus() returns...
Before the
call...

USBxxx_sendData(addr,size,intfNum)

kUSBxxx_waitingForSend is
clear

USBxxx_sendData() returns,
either during or after the operation.
Program execution continues...

Time

Returns
During the kUSBxxx_waitingForSend
operation...
0 < bytesSent < size

USBxxx_handleSendComplete(intfNum)

After the
kUSBxxx_waitingForSend)
operation
is clear
completes...

Figure 11. Lifecycle of a Successful Send Operation
As discussed earlier, a send operation is begun with a call to USBxxx_sendData(). The
application can make its first call to this function at any point it wishes while the state is
ST_ENUM_ACTIVE. A successful call to this function returns USBxxx_SEND_STARTED.
If a call to USBxxx_sendData() is made while a previous send operation is underway, it will
immediately return with a value of USBxxx_INTERFACE_BUSY_ERROR. This is because only
one send operation (and one receive operation) may be open for a given interface at a time. The
previous operation continues, unaffected.
When a send operation is complete, the API makes a call to
USBxxx_handleSendCompleted(). User code may be placed here, perhaps flagging the
application to begin another send operation, or to alert the user that all data has been
transmitted.
After USBxxx_sendData() returns USBxxx_SEND_STARTED, software should be aware the
operation might still be open. Therefore, any subsequent calls to USBxxx_sendData() should
check to ensure that no previous operation is underway.

Programmer's Guide: MSP430 USB API v4.10

53

Send operations usually complete fairly quickly, but remember that this is dependent on the host
and bus conditions. If an operation is open, it can be aborted with USBxxx _abortSend().
After aborting the operation, this function returns how many bytes were successfully sent.

7.4.6 Lifecycle of a Receive Operation
A call to USBxxx_intfStatus() returns...
Before the
call...

USBxxx_receiveData(addr,size,intfNum)

kUSBxxx_waitingForReceive
is clear

USBxxx_receiveData() returns,
either during or after the operation.
Program execution continues...
During the
operation...

Returns
kUSBxxx_waitingForReceive

Time

0 < bytesSent < size

USBxxx_handleReceiveComplete(intfNum)

After the
kUSBxxx_waitingForReceive
operation
is clear
completes...

Figure 12. Successful Receive Operation
Similarly, a receive operation is begun with a call to USBxxx_receiveData(). The application
can make its first call to this function any point it wishes after enumeration is complete. A
successful call returns USBxxx_RECEIVE_STARTED.
If a call to USBxxx_receiveData() is made while a previous receive operation is underway, it
will immediately return with a value of USBxxx_INTERFACE_BUSY_ERROR. This is because
only one receive operation (and one send operation) may be open for a given interface at a time.
The previous operation continues, unaffected.
When a receive operation is complete, the API makes a call to
USBxxx_handleReceiveComplete(). User code may be placed there; for example, it may
set a flag that signals main() to begin another receive operation.

Programmer's Guide: MSP430 USB API v4.10

54

If data is received into the USB endpoint buffer without an open receive operation, the API has
nowhere to put it. After this, any subsequent attempts by the host to send more data will be
NAK’ed by the device, and thus the pipe is effectively “clogged”. If this situation occurs, the API
makes a call to USBxxx_handleDataReceived(). This gives the application an opportunity
to “unclog” the pipe by either opening an operation or calling USBxxx_rejectData(). The
former gives the incoming data a place to go. The latter flushes the USB endpoint buffer; the
“pipe” becomes unclogged again; but the data that was in it is lost.
The function USBxxx_bytesInUSBBuffer() can be used to determine how many bytes are
waiting in the USB endpoint buffer. This can be useful when the event
USBxxx_handleDataReceived() occurs; the application can respond by calling
USBxxx_bytesInUSBBuffer(), and then calling USBxxx_receiveData() for the exact
number of bytes that are waiting.

7.4.7 How Long (in Real-Time) Does an Operation Stay Active?
When a send operation is begun, the data is transmitted as quickly as the host, device, and bus
conditions will allow. Usually, this is very fast. Obviously, the larger the data size, the longer the
transmission takes.
However, any factor that affects bandwidth also has an effect on the duration of a send
operation. The bus conditions can potentially have significant ability to delay transactions, and
so it’s important for software to account for this – including the unknown timelength of open
operations.
Send operations are sent as quickly as conditions will allow. Receive operations are subject to
an additional factor: depending on the application, it’s sometimes unknown when the host will
send data. So while send operations are almost assured to happen somewhat continuously,
receive operations might be fulfilled in piecewise fashion. If the developer controls both the host
and device, and/or if communication conforms to a defined protocol, the application may know
when the data is arriving. If this isn’t the case, software may need to be written in a more openended fashion.
USBxxx_sendData(), USBxxx_receiveData(), and USBxxx_getInterfaceStatus()
have all the return codes necessary to manage this. Also, Sec. 11 provides clear example
coding constructs that ensure proper operation.

7.5

Host-Side Considerations When Interfacing to the Datapipe
When using CDC, there are no considerations specifically related to send/receive operations.
From the host’s perspective, data is simply sent/received through the COM port, as with any
other virtual COM port application.
The downside of CDC, on a Windows host, is that an INF file is required, and Microsoft has
made it difficult to install this without it being signed. On Linux/Mac, CDC enumerates silently as
a virtual COM port. (See Sec. 2.2.2 for more discussion.)

Programmer's Guide: MSP430 USB API v4.10

55

With HID, the host situation is reversed. An HID interface (datapipe or otherwise) enumerates
silently on Windows/Mac/Linux hosts. However, the application end is a little more complicated.
HID is mostly unique to USB, and therefore the knowledge of how to interface with it on the host
is less common. Writing an HID application requires defining a report format. To interface with
HID-Datapipe, the application will need to specify the report format used by the MSP430 HIDDatapipe interface, shown below.
Table 13.
Field

Reports Described by the Default Report Descriptor
Size

Description
IN report (into the host)

Report ID

1 byte

The report ID of the chosen report (automatically
assigned to 0x3F by the HID-Datapipe calls)

Size

1 byte

The number of valid bytes in the data field

Data

62 bytes

Data payload
OUT report (out of the host)

Report ID

1 byte

The report ID of the chosen report (must be assigned to
0x3F by the host)

Size

1 byte

The number of valid bytes in the data field

Data

62 bytes

Data payload

This format effectively converts the usually-complicated HID report mechanism into a simple
data carrier.
The MSP430 application sees only an unformatted stream of data. The Java HID Demo App,
provided within the MSP430 USB Developer’s Package, does the same thing for any host
equipped with a Java Runtime Engine.

Programmer's Guide: MSP430 USB API v4.10

56

8 MSC: Software Architecture
The mass storage class (MSC) defines an interface through which the USB host expects to
mount a storage volume. MSC essentially acts as a carrier for industry-standard SCSI
commands. After the host enumerates/installs an MSC interface, it uses SCSI commands to
attempt to mount a storage volume.
This section explains how to implement an MSC interface using the MSP430 USB API.

8.1

MSC Architecture: High-Level Overview
Unlike CDC and HID-Datapipe, an application using an MSC interface doesn’t “send” and
“receive” data over an unformatted datastream. Instead, it provides a large (“mass”) pool of data
– a storage volume, written on a medium – on which the host can “read” and “write”. In an
MCU-based application, the medium might be the MCU’s internal memory, or an external device
accessible via an externally-facing interface (for example, SPI, I2C, or parallel memory
interface).

USB
Host

USB Device

USB
Host

USB Device
Application
software

Application
software

File System
Media Access Layer

Media Access Layer

Media

Media

Figure 13. Simplified High-Level MSC Architecture

Programmer's Guide: MSP430 USB API v4.10

57

Whatever the medium, the host expects this volume to be formatted in a manner consistent with
a standard storage volume format it understands, such as the common FAT (File Allocation
Table) standard. FAT has been used since MS-DOS days, and is still popular for smaller
volumes based on random-access media. Support for it is universal among the major operating
systems.
Compared to CDC and HID, in which the application’s task is simply to send/receive data, MSC
applications have more work to do. The application is responsible for acting upon any
READ/WRITE commands received from the host, which is receives from the API. This work is
heavily defined by the chosen media -- which is why the API is limited in the extent to which it
can automate it. If the application doesn’t faithfully access the volume at the host’s request,
then although the MSC interface can be seen as enumerated on the host, the volume won’t
mount.
The examples accompanying the USB Developer’s Package include implementations for
common media, like SD-cards (#M2).
In Figure 13, the image at left shows an implementation in which the MSP430 application
doesn’t need access to the volume’s data for its own purposes. It’s able to carry out the lowlevel read/write requests from the host; but since it can’t parse the volume’s format, it can’t find
any particular file on the volume. In this sense, it’s essentially acting as a “flash drive”.
The image at right shows the more typical case where the MSP430 application does need to find
files on the volume. To accomplish this, it uses file system software capable of parsing the
volume’s formatting. Through this software, it’s able to access files by directory and filename.
All block requests from the host are still passed through the application, this time to the file
system’s low-level media access functions.
A popular open-source software solution for the FAT storage is FatFs. Many of the MSC
application examples include an MSP430 port of FatFs.
Another example, #M1, works around the need for file system software by using “file system
emulation”. This approach solves the problem of the application finding files, by restricting
where the host can put files. However, it imposes limits on the host with respect to how many
files can be stored, and where.

Programmer's Guide: MSP430 USB API v4.10

58

8.2

MSC Device Types
MSC devices must report a media type to the host. The MSP430 MSC API supports two types,
shown in the table below.
Table 14.
Name

MSC Device Types Supported by the MSP430 USB API
Common Examples

SCSI Command
Set Used

File System
Typically Used

Direct-Access
Block Devices

Hard drives, flash drives, SD-card,
MultiMedia Card. Most forms of
random-access, magnetic/flashbased media.

SBC-2

FAT16/32 (File
Allocation Table)

CD/DVD

CD-ROM drives; DVD drives

MMC-4

ISO9660 (CD File
System)

The determination of which type is reported to the host is made by whether the configuration
constant CDROM_SUPPORT is defined. If it is not defined, then the device is reported as a directaccess block device. The Descriptor Tool automatically defines this constant (or not), based on
settings chosen within the Tool.
Although the MSP430 is capable of being used as the USB interface for a CD-ROM drive, the
purpose of the CDROM function is more about CD-ROM emulation. Files on a CD-ROM can be
“autorun” executed, and this works on multiple host operating system platforms, unlike a directaccess block device.
To accomplish this emulation, the media must be pre-formatted as an ISO image. This is
sometimes emulated as a file located on a FAT-formatted volume. Example #M5 shows this
kind of implementation.
Since FAT-based direct-access block devices are much more common, most of the forthcoming
discussion, as well as the examples, are written from that perspective. However, the API is
intended to be flexible enough to adapt to other file formatting systems.

8.3

Storage “Address System”: LUNs & LBAs
Storage is divided into logical blocks; and each is addressed with a logical block address (LBA).
In the FAT file system, one block consists of 512 bytes. Blocks are sometimes also called
sectors.
The USB host uses LBAs when making requests to the storage device for READ/WRITE
operations. Usually the MCU application will pass the LBA to the file system software, which
then accesses the volume on the medium. LBAs begin at zero.
Usually the LBA gets passed as a parameter to the MSP430 application’s file system software,
as the target location for READ/WRITE. Usually the number of blocks is also passed (starting at
the given LBA).

Programmer's Guide: MSP430 USB API v4.10

59

Alternatively, if the MSP430 application doesn’t need to interpret the volume for its own use, the
application might choose to convert the LBA to a byte address within the target medium, by
multiplying the LBA by the size (in bytes) per logical block, or sector; then add this to any
appropriate offset within flash.
The LBA has meaning within the context of a logical unit. Logical units are referenced with a
logical unit number, or LUN. There might be multiple LUNs within an MSC interface. The host
operating system (i.e., Windows) presents each LUN to the user as a separate volume. If an
equipment maker wishes to have multiple storage media on a single physical mass storage
device – for example, a removable media card as well as a separate volume located in internal
MSP430 flash – they may choose to implement these as two separate LUNs. In certain
respects, this is analogous to having multiple interfaces within a composite USB device (keeping
in mind that only one MSC interface is allowed, within a given device).
This is illustrated in the figure below.
Physical USB Device
CDC or HID
interface

CDC or HID
interface

MSC interface
LUN: 0
LBA:
LBA:
LBA:
LBA:
LBA:

0
1
.
.
n

LUN: 0
LBA: 1

LUN: 1
LBA: 0
LBA:
LBA:
LBA:
LBA:

1
.
.
n

Figure 14. MSC Interface LUN/LBA Addressing
The API supports multiple LUNs, containing any 32-bit number and size of logical blocks. The
number of LUNs can be selected within the Descriptor Tool. Since the MSC interface only
prepares a substrate upon which the host can mount volumes, each LUN’s volume must still be
implemented within the application.

Programmer's Guide: MSP430 USB API v4.10

60

When the host sends a SCSI command over the MSC protocol, it designates the LUN for which
the command is intended. If the command reads/writes data, it also includes the LBA being
accessed and the number of sequential blocks requested. Since the API must rely on the
application to access the volume when it receives a SCSI read or write command, it passes the
SCSI command’s LUN, initial LBA, and number of requested blocks to the application.
Only one SCSI command at a time can be handled by an MSC interface. This means that if a
command is received for LUN 0, it must be handled in full before a command can be received
for LUN 1. For this reason, only a single interchange buffer is needed for the interface (or two, if
double-buffering is used).

8.4

MSC Function Call / Event Summary
A table summarizing the MSC API function calls is shown below. For complete documentation,
see the API call reference within the USB Developers Package.
Table 15.

MSC Management and Data Handling Call Summary

Function
BYTE USBMSC_pollCommand()

Initiates the handling of the current SCSI command for this MSC interface.

Description

BYTE
USBMSC_registerBufferInformation()

Registers with the API which buffers it should use for READ/WRITE
command handling.

BYTE
USBMSC_fetchInformationStructure()

Returns the pointer(s) to the API’s instance(s) of USBMSC_RWBuf_Info

BYTE USBMSC_processBuffer()

Returns a buffer back to the API after processing it, in the course of SCSI
READ or WRITE handling.

BYTE
USBMSC_updateMediaInformation()

Posts an update to the host about the media being used for a LUN with
removable media.

Table 16.
BYTE USBMSC_handleBufferEvent()

MSC Event Handler Summary

Indicates that the API needs for the application to process a buffer.

For reference details on these functions, including description, parameters, and calling
conditions, please see the API Functional Reference within the USB Developers Package. The
functions are further described below.

8.5

Components of an MSP430-Based MSC Application
The table below shows the responsibilities of the application to handle MSC request.
Performing all these duties allows the volume to mount on the host, and be maintained there
until removal.

Programmer's Guide: MSP430 USB API v4.10

61

Table 17.
When

Actions the Application Must Take

Action

How

Define the LUN structure and characteristics

Define a USBMSC_config structure

Allocate the data buffer exchange space, and
then register it with the API

USBMSC_registerBufferInformation()

Returns the pointer to the API’s
USBMSC_RWBuf_Info structure, which is
used by the API to describe any buffer
operations it requests of the application.

USBMSC_fetchInformationStructure()

Inform the API about the medium (if any)
initially present for each LUN

USBMSC_updateMediaInformation()

Periodically

Check for any received SCSI commands and
initiate their handling

USBMSC_pollCommand()

Eventdriven

Process any buffer events the API generates
during its SCSI READ/WRITE handling

Access the file system, in response to
USBMSC_handleBufferEvent(), then call
USBMSC_processBuffer()

If the medium is designated as ‘removeable’,
and the medium changes state, inform the
API

USBMSC_updateMediaInformation()

Initialization

Each is defined in more detail below.

8.5.1 Defining the Interface’s LUNs
An application must define its LUNs. The API then uses this definition when responding to SCSI
commands.
This is done using the Descriptor Tool. When an MSC interface is added, its view provides a
pulldown menu to select the number of LUNs, and the characteristics of each LUN.

Figure 15. Selecting LUN Attributes
Use the Descriptor Tool’s instructions to set these fields. When the output has been generated,
it contains a structure named USBMSC_config, which reflects the characteristics of the LUNs.
The information in this structure is as shown below.

Programmer's Guide: MSP430 USB API v4.10

62

Table 18.
Field

LUN Information in the USBMSC_config Structure

Format

Description

.LUN.number

BYTE

The logical unit number. The first one is 0x00, and they must increment
sequentially.

.LUN.PDT

BYTE

Peripheral Device Type. This is a code that identifies to the host which set of SCSI
commands to use with this device. (Currently must be 0x00, which is for SBC
devices. Most flash-based USB devices use this class.)

.LUN.removable

BYTE

Indicates whether the device’s media can be removed – for example, flash media
cards. 0x80 indicates the medium is removable; 0x00 indicates it is not.

.LUN.t10VID

BYTE[8]

A vendor ID assigned by the T10 organization.

.LUN.t10PID

BYTE[16]

A product ID assigned by the owner of the T10 VID.

.LUN.t10rev

BYTE[4]

A revision code assigned to a device with this T10 VID/PID.

T10 is the organization that oversees the SCSI specification. (http://www.t10.org) T10 VIDs are
freely available. There is no certification process that checks to ensure a unique VID is used,
nor does the choice of VID/PID have any significant effect on most USB hosts.
T10 VIDs/PIDs should not be confused with USB VIDs/PIDs; they are not related. However,
since unique T10 values are needed, the Tool gives the option to borrow these values from the
USB vendor/product information.

8.5.2 Registering the Location of the Buffer: USBMSC_registerBufferInformation()
Exchanging data between the host and the file system requires a memory buffer large enough to
hold at least one block. A block size is defined as discussed in Sec. 8.5.4; for the FAT file
system, a block is 512 bytes. The buffer can be larger than one block; if this is done, it should
always be a multiple of the block size.
Since this represents a significant amount of available RAM, the API gives as much control of its
allocation to the application as possible. The application must allocate the buffer, and then
“register” it with the API. It does this with USBMSC_registerBufferInformation().
This function passes in three parameters:
 Address of the X-buffer
 Address of the Y-buffer
 The size of the X- and Y-buffers (must be equal)
If the address of the Y-buffer is non-null, this enables double-buffering to be used by the API,
which increases throughput. If null, then single-buffering will be used. Double-buffering enables
modest speed gains. (See the Release Notes HTML file, for benchmark information.)
The application is allowed to dynamically change the buffer location. It can also disable the
buffer completely. The latter is advantageous for re-allocating the memory when USB isn’t
attached. It can be accomplished by calling USBMSC_registerBufferInformation() with
an X-buffer address of null. The API always uses the address/size from the most recent call to
the function.

Programmer's Guide: MSP430 USB API v4.10

63

If the host attempts to access the MSC interface, but the most recent call to
USBMSC_registerBufferInformation() de-activated the buffer, then the API has no way
to exchange data with the application. It begins failing READ/WRITE commands received from
the host, telling it that the unit isn’t ready. During this time, calls to USBMSC_pollCommand()
return USB_GENERAL_ERROR.
Therefore, if the buffer is to be dynamically managed, it is strongly recommended to re-instate it
in response to USB_handleVbusOnEvent() (which occurs when USB is attached). Also, if the
buffer is de-activated during USB suspend, it should be re-instated in response to
USB_handleResumeEvent().

8.5.3 Registering the Buffer Info Structures: USBMSC_fetchInformationStructure()
The API allocates an instance of the structure USBMSC_RWBuf_Info to describe any buffer
operations it wants the application to process.
The application needs the pointer to this structure, so that it can access the buffer operation
description. It must call this function near the beginning of operation, after
USBMSC_registerBufferInformation() but before USB enumeration.

8.5.4 Informing the API about the Media: USBMSC_updateMediaInformation()
For each LUN defined with USBMSC_config, the application must describe the storage medium
to the API. It must do this in two situations:
1. Initially, before the USB device enumerates (that is, before calling USB_setup() or
USB_connect()). USB_setup()sets the MediaPresent and WriteProtected flags to
default values so if changes to these values are required, they must be done before
calling USB_connect().
2. If the media is removable, it must also inform the API as soon as after changes in the
medium.
The function that accomplishes this is USBMSC_updateMediaInformation(). With the
information provided by this function, the API can respond appropriately to any related SCSI
commands from the host.
The application must declare an instance of the API-defined structure USBMSC_mediaInfoStr
and pass it into USBMSC_updateMediaInformation().

Programmer's Guide: MSP430 USB API v4.10

64

Table 19.

USBMSC_mediaInfoStr

Type
BYTE

Name
mediaPresent

Description

BYTE

mediaChanged

Indicates that the medium present is a different one than during the
last call to USBMSC_updateMediaInformation()

BYTE

writeProtected

Indicates that the medium is write-protected (non-zero) or not writeprotected (zero).

DWORD

lastBlockLba

LBA of the last block in the media (effectively, the medium’s size)

DWORD

bytesPerBlock

Number of bytes per block in this medium (for FAT, this is typically
512)

Indicates that the medium is present (0x81) or not present (0x82).

The last three fields are only valid if mediaPresent is 0x81. .
If the media is removable (which should be reflected in USBMSC_config), then the application
needs functionality to detect it. The means of detection vary, depending on the media type. As
an example, SD-card interfaces can detect a pullup in the card, using an I/O pin interrupt.
If the application detects that media has been inserted, it should:


Create an instance of USBMSC_mediaInfoStr



Set mediaPresent and mediaChanged



Determine whether the media is write-protected, and set writeProtected accordingly



Detemine the media’s size, and set lastBlockLba accordingly.



Call USBMSC_updateMediaInformation().

If instead the application detects that media has been removed, it should:


Create an instance of USBMSC_mediaInfoStr



Clear mediaPresent



Set mediaChanged



Call USBMSC_updateMediaInformation()

To determine the media’s size and write-protected status, file system calls are usually available.
If necessary, it could parse the volume’s master boot record manually.
To reset either mediaPresent or writeProtected flags during program execution, USB
has to be first disconnected and disabled, the flag changes done and then USB enabled, reset
and connected.

Programmer's Guide: MSP430 USB API v4.10

65

8.5.5 Periodically Initiating SCSI Command Handling, using USBMSC_pollCommand()
The application must initiate the handling of any SCSI commands that have been received,
using USBMSC_pollCommand(). Any SCSI commands received by the API will not be handled
until USBMSC_pollCommand() is called. The API does not interrupt the application to tell it
commands have been received; rather the application needs to call USBMSC_pollCommand()
periodically.
8.5.5.1 Main Loop, No LPM Mode
Many USB devices derive their power from the host (VBUS) while enumerated and active, and
so they don’t have tight power requirements. Developers of these devices might choose not to
enter a low-power mode.
If the application is based on a main loop, and doesn’t enter LPM0, the calling of
USBMSC_pollCommand() can simply be placed within the main loop. Note that if the function
is called when there is no SCSI command to handle, it will quickly return with no action taken.
8.5.5.2 Main Loop, Entering an LPM Mode
The API is designed for LPM0 to be entered within a main loop structure. If a SCSI command
occurs while the CPU is in LPM0, it automatically wakes the CPU, allowing the application’s
main loop to call USBMSC_pollCommand().
Most SCSI commands are handled automatically when USBMSC_pollCommand() is called,
without any help needed from the application. By the time USBMSC_pollCommand() returns,
the command has been handled. However, SCSI READ/WRITE commands require the
application to “process” buffers. When this occurs, the API automatically wakes the CPU out of
LPM0, and execution resumes from its point of entry.
Given this, the following coding structure is recommended in applications entering LPM0:
__disable_interrupt();
if(USBMSC_pollCommand() == USBMSC_OK_TO_SLEEP)
{
__bis_SR_register(LPM0_bits + GIE);
}
__enable_interrupt();

This structure ensures robust handling. The condition it guards against is one in which the CPU
enters LPM0 even though the API is waiting for it to process a buffer. It does this by first
disabling interrupts, to prevent the API from servicing any subsequently-received SCSI
commands. USBMSC_pollCommand() then checks to see if any SCSI commands have been
received up to that time. If not, it returns USBMSC_OK_TO_SLEEP. Then, atomically with the
LPM0 entry, it re-enables interrupts. This way, if a SCSI READ/WRITE command was received
during USBMSC_pollCommand(), the application won’t miss the fact that it’s supposed to
remain awake; instead, the API will begin processing it immediately after the LPM0 entry, and
the application will immediately wake again.

Programmer's Guide: MSP430 USB API v4.10

66

Alternatively, if a READ/WRITE command was already received and the API is waiting for the
application to process a buffer, USBMSC_pollCommand() will return
USBMSC_PROCESS_BUFFER, keeping the loop awake.
Note that if LPM0 is not being entered – rather the CPU will be kept continuously active during
the USB connection – then it is not necessary to disable interrupts or check the return value
from USBMSC_pollCommand().
8.5.5.3 Frequency of Calling USBMSC_pollCommand()
It is important that USBMSC_pollCommand() be called with sufficient frequency. There are two
main concerns the developer should consider:
 Slow “average” polling frequency, leading to slow bandwidth performance
 Any “long” polling period, causing a host timeout to be violated
The more frequently an application calls USBMSC_pollCommand() during periods of peak
mass storage activity, the higher the bandwidth will be. In contrast, having a long average
period between USBMSC_pollCommand() calls during heavy mass storage activity can result in
very slow performance. When setting the average polling frequency, the developer should call
USBMSC_pollCommand() as often as the application can afford. It may be a good idea to
perform experimental benchmarks.
The second concern is that a single long period between USBMSC_pollCommand() calls could
exceed a host timeout period. The timeout periods vary by operating system and situation. On
READs/WRITEs, these tend to be fairly long, such that an occasional delay of even a few
seconds may not cause the timeout to be exceeded. However, one notable exception is when
the LUN is marked as having removable media (with USBMSC_config), on a Windows
machine. Windows sends these LUNs a “TEST UNIT READY” SCSI command every second, to
see if the medium is present. The MSC device has until the next TEST UNIT READY– that is,
one second -- to respond. Some embedded applications could experience delays long enough
to exceed this delay. If that were to happen, the Windows host would issue a USB bus reset;
this should be avoided.
An advantage of using an RTOS is more direct control over the call frequency.

8.5.6 Processing Buffer Events
8.5.6.1 What Are They?
As discussed in Sec. 8.1, MSC applications typically require file system software. In this
arrangement, both the application and the host (via the API) access the storage volume though
the file system.

Programmer's Guide: MSP430 USB API v4.10

67

USB
Host

USB Device
Application
software

File System
Media Access Layer

Media

Figure 16. File System Access – Simplified
There is a wide variety of file system middleware on the market, with various specialties. Some
are optimized for code size, while some have advanced features. Since users may have
different preferences, a file system has not been integrated within the API. Rather, it exists at
the application level, under the control of the software developer, allowing flexibility to choose
the right one for the application. (An MSP430 port of the open-source file system software
“FatFs” is included in the examples.)
Putting the file system in the application requires a defined process by which the API can
request the application to access the file system, which it needs to do during the handling of
READ/WRITE SCSI commands from the host.
READ/WRITE operations usually involve multiple blocks per command, and each block (for the
FAT file system) is typically 512 bytes. As a result, the total amount of data being moved for a
single READ or WRITE operation is often fairly large. In many cases the data storage is not
even within the MSP430 memory map, but rather in an off-chip medium. The combination of
large data size, off-chip location, and limited RAM resources necessitates a multi-stage, iterative
system in which data is paged between the medium and host through an intermediary RAM
buffer.
This entire process is coordinated by the API; all the application must do is service buffer
operations (that is, process the buffer) when requested to do so by the API. As the API
prepares to send or receive a block as part of a multi-block READ/WRITE operation, it makes
these requests:
 When handling READ commands, the application is requested to “fill” the buffer (i.e., using
the file system to pull the data from the medium) so that the API can send it to the host.

Programmer's Guide: MSP430 USB API v4.10

68



When handling WRITE commands, the application is requested to “empty” the buffer (i.e.,
using the file system to move the data into the medium) so that the API can receive more
blocks from the host.

Since the API must ask the application to handle this function, the figure above isn’t sufficient to
describe what actually happens. Instead, see the figure below.

USB
Host

USB Device
MSC API

Buffer processing

MCU Application

Media accesses initiated
by the MCU app

File System

Media accesses passed
through the MCU app
from the host

Media Access
Layer

Media

Figure 17. File System Access – Actual
The MCU application can access the media for its own purposes. It also acts as a go-between
whenever the API needs media access to fulfill a READ/WRITE command from the host. The
figure below details the latter, showing the complete cycle of a buffer operation.

Programmer's Guide: MSP430 USB API v4.10

69

MSC API
The API requests the application to process a buffer:

1

1) Sets operation field of USBMSC_RWBuf_Info structure to
USBMSC_READ or USBMSC_WRITE
2) Triggers a USBMSC_handleBufferEvent()

4

The application informs the API
that the buffer has been processed,
using USBMSC_bufferProcessed()

MCU Application
The application accesses the
storage volume, emptying/
filling the buffer

3
2

File System and/or
media

Figure 18. Buffer Processing
Buffer processing is further detailed below.
8.5.6.2 The USBMSC_RWbuf_Info Structure
The API defines an instance of this structure. (If the API is configured for double-buffering, the
API defines two such structures.) It is considered a shared resource between the API and the
application. Its purpose is to describe buffer operations requested by the API. Prior to USB
enumeration, the application must call USBMSC_fetchInformationStructure() to obtain
the pointer to this structure.

typedef struct
{
BYTE
lun;
BYTE
operation;
DWORD
lba;
BYTE
lbCount;
BYTE
*bufferAddr;
BYTE
returnCode;
BYTE
XorY;
}USBMSC_RWbuf_Info;

Programmer's Guide: MSP430 USB API v4.10

70

Table 20.

USBMSC_RWbuf_Info Definition

Type
BYTE

Name
lun

Direction

Description

BYTE

operation

DWORD

lba

BYTE

lbCount

The number of blocks being requested.

BYTE*

bufferAddr

The address of the RAM intermediary buffer the application
should use to exchange the data.

BYTE

returnCode

The logical unit on which the buffer operation is taking place.
Zero-based.

From API to
application

From
application
to API

The type of operation being performed (USBMSC_READ or
USBMSC_WRITE), or NULL if no operation is active for this
instance.
The logical block address (LBA) of the block the application needs
to read/write.

The result of the buffer operation. (To be written by the
application.) Valid return codes are described in the definition of
USBMSC_processBuffer().

8.5.6.3 The Lifecycle of a Buffer Operation
When the API wants to request the application to process a buffer:
1. It populates this structure. (As part of this, it sets the operation field to USBMSC_READ or
USBMSC_WRITE.)
2. It clears the LPM bits in the MCU’s status register, to ensure the CPU stays awake after the
USB interrupt service routine exits. (These actions usually take place out of this ISR.)
3. It generates a USBMSC_handleBufferEvent().
To determine whether the API is waiting for the application to process a buffer, the application
can check the operation field. A good place for this is immediately after calling
USBMSC_pollCommand() – refer to Sec. 8.5.5 regarding when in the application to do this.
Alternatively, checking the operation field can be prompted from within
USBMSC_handleBufferEvent().
Once the condition has been detected, the application should promptly process the buffer. It
usually does this by accessing the medium to either fill the buffer (for READ operations) or
empty it (for WRITE operations). It uses the information in the USBMSC_RWbuf instance to learn
what kind of operation is being requested, and how it should be fulfilled. During this time, the
host is waiting for the USB device to either send a block of data (READ) or to send status that
the block has been written (WRITE).
When the media access is complete, the application must write a value into the returnCode
field. Finally, it must call USBMSC_processBuffer() to inform the API that it has finished
processing the buffer. This marks the end of the buffer operation lifecycle.

Programmer's Guide: MSP430 USB API v4.10

71

The API then resumes communication with the host. When it does, it uses the value in
returnCode to tell the host the result of the operation. If an error was returned, the host will
probably end the READ/WRITE SCSI command cycle. The information may further be passed
to the application running on the host, in the form of an error code. The origin of this return code
depends on the storage medium. If a file system is used, it is likely derived from error codes
returned from the file system’s function calls. Values the application may write into this field are
shown in the table below.
Table 21.

Accepted Values for returnCode

Name
USBMSC_RW_SUCCESS

The operation succeeded.

Description

USBMSC_RW_NOT_READY

The device was not ready.

USBMSC_RW_ILLEGAL_REQUEST

Illegal request

USBMSC_RW_LBA_OUT_OF_RANGE

The LBA was out of range.

USBMSC_RW_MEDIA_NOT_PRESENT

The media isn’t present.

USBMSC_RW_DEVICE_WRITE_FAULT

Device write fault

USBMSC_RW_UNRECOVERED_READ

Unrecovered read

USBMSC_RW_WRITE_PROTECTED

The media is write protected

The buffer lifecycle is shown in the figure below.

Programmer's Guide: MSP430 USB API v4.10

72

MCU Application

API
READ or WRITE SCSI command received from
the host. Occurs within the USB ISR.
API prepares a buffer operation by populating the
appropriate registered instance of
USBMSC_RWBuf_Info
API sets USBMSC_RWBuf_Info.operation =
kUSBMSC_READ or kUSBMSC_WRITE
API clears the low-power-mode bits in the status
register
API calls USBMSC_handleBufferEvent()
API modifies the status register, to ensure CPU
awakes after the ISR exits

Main loop runs, and/or RTOS task executes; checks
the “operation” field of USBMSC_RWBuf_Info

Finds the operation that was begun in the USB ISR;
the application executes the operation, using the
information in USBMSC_RWBuf_Info

Application populates returnCode, then calls
USBMSC_bufferProcessed()

USBMSC_bufferProcessed() sets operation to
NULL

USBMSC_bufferProcessed() triggers the
resumption of SCSI command handling

USBMSC_bufferProcessed() exits, while SCSI
command handling resumes in the background

Figure 19. Buffer Lifecycle

Programmer's Guide: MSP430 USB API v4.10

73

8.6

Managing Dual Access to the Medium
The application should take care not to allow both itself and the USB host to access the medium
at the same time. The host oftens keeps a cached version of the volume in its own memory
that becomes out of sync with the one on the USB device. For this reason, it’s best to avoid
accessing the volume from the MCU application while the device is connected to a host over
USB.

Programmer's Guide: MSP430 USB API v4.10

74

9 Traditional HID Interfaces
This section applies to traditional HID interfaces, including mice, keyboards, and HID interfaces
using custom report formats. This chapter does not apply to datapipe interfaces, such as CDC
HID-Datapipe; these are discussed in Sec. 7.

9.1

Introduction
The table below summarizes the different HID types provided within the API. The API predefines three sub-types of HID: datapipe, mouse, and keyboard. Any other HID interface is
considered ‘custom’.
Table 22.
Functionality

HID Interface Types, Within the MSP430 USB API

Description

Report Format

Function Call
Set to Use

How to Create

UART-like PC/device
communication.

A minimal format for
simple data transfer

Select ‘Datapipe’ as the HID
interface type in the Descriptor
Tool

Mouse

Mouse functionality

Standard mouse report
format

Select ‘Mouse’ as the HID
interface type in the Descriptor
Tool

Keyboard

Keyboard
functionality

Standard keyboard
report format

Select ‘Keyboard’ as the HID
interface type in the Descriptor
Tool

Custom

Any other HID
device/interface

User-customized

Select ‘Custom’ for this
interface type, in the Descriptor
Tool; then follow the instructions
in this chapter

Datapipe

HID-Datapipe

HID-Traditional

HID-Datapipe interfaces use a specific report format, and they use the datapipe function calls.
Any HID interface not using both of these are considered HID-Traditional. HID-Datapipe
interfaces are discussed in Sec. 7, and not in this chapter.
All HID-Traditional interfaces use the HID-Traditional function calls. Traditional devices are
further distinguished by their report formats into mice, keyboard, or custom HID interfaces. The
application must also interact with each type differently.
Except for ‘custom’ HID interfaces, the Descriptor Tool automates much of the interface’s
creation, as will be described later. The USB Developers Package also has examples of various
HID interface types.
HID interfaces types differ in how host-side communication is performed, as shown below.

Programmer's Guide: MSP430 USB API v4.10

75

Table 23.

HID Interface Types, Host Considerations

Functionality
Datapipe

Requires an application to be written, which recognizes
the HID-Datapipe report and protocol. TI provides the
Java HID Demo App for this purpose.

Mouse

The host operating system interacts with the device,
rather than a host application.

Keyboard
Custom

9.2

Host Considerations

Requires an application to be written. Although the
Java HID Demo App is written for HID-Datapipe, it can
easily be leveraged for custom reports as well.

Creating a Mouse or Keyboard
Creating a mouse or keyboard with the MSP430 USB API is very simple. To get started,
examples are provided in the USB Developers Package: example #H7 implements a singleinterface HID mouse, while example #H8 implements a single-interface HID keyboard. These
examples can be built and modified for experimentation purposes.
For more serious development, use the Descriptor Tool to create the interfaces. This may
especially be desirable if adding a mouse or keyboard in composite with other interfaces.

Figure 20. Using the Descriptor Tool to Create a Mouse or Keyboard HID Interface
Using the Tool allows all the custom information to be easily modified. If the mouse/keyboard is
to be part of a composite USB device alongside other interfaces, the Tool greatly simplies the
process of generating the needed descriptors.
After using the Tool, application code is needed to interact with the newly-created interfaces.
The application code from the examples can be borrowed for this purpose. The polling
frequency may need to be adjusted within the Tool, according to the application. (This is the
rate at which the host will poll for reports from the HID interface.)

Programmer's Guide: MSP430 USB API v4.10

76

The standard mouse report descriptor, and resulting report format, are shown below.

BYTE const report_desc_HIDx[] =
{
0x05, 0x01,
// Usage Pg (Generic Desktop)
0x09, 0x02,
// Usage (Mouse)
0xA1, 0x01,
// Collection: (Application)
0x09, 0x01,
// Usage Page (Vendor Defined)
0xA1, 0x00,
// Collection (Linked)
0x05, 0x09,
// Usage (Button)
0x19, 0x01,
// Usage Min (#)
0x29, 0x05,
// Usage Max (#)
0x15, 0x00,
// Log Min (0)
0x25, 0x01,
// Usage Maximum
0x95, 0x05,
// Report count (5)
0x75, 0x01,
// Report Size (1)
0x81, 0x02,
// Input (Data,Var,Abs)
0x95, 0x01,
// Report Count (1)
0x75, 0x03,
// Report Size (3)
0x81, 0x01,
// Input: (Constant)
0x05, 0x01,
// Usage Pg (Generic Desktop)
0x09, 0x30,
// Usage (X)
0x09, 0x31,
// Usage (Y)
0x09, 0x38,
// Usage (Wheel)
0x15, 0x81,
// Log Min (-127)
0x25, 0x7F,
// Log Max (127)
0x75, 0x08,
// Report Size
0x95, 0x03,
// Report Count (3)
0x81, 0x06,
// Input: (Data, Variable, Relative)
0xC0,
// End Collection
0xC0
// End Collection
};

Figure 21. Mouse Report Descriptor
The mouse report descriptor describes the report shown in the table below.
Table 24.
Field

Mouse Report Format

Size

Description
IN report (into the host)

Buttons

1 byte

3 button bits and padding

dX

1 byte

X position

dY

1 byte

Y position

dZ

1 byte

Wheel position.

Programmer's Guide: MSP430 USB API v4.10

77

The standard report descriptor for keyboards, and the resulting report format, are shown below.

BYTE const report_desc_HIDx[]=
{
0x05, 0x01,
// Usage Page (Generic Desktop)
0x09, 0x06,
// Usage (Keyboard)
0xA1, 0x01,
// Collection (Application)
0x05, 0x07,
// Usage Page (Key Codes)
0x19, 0xE0,
// Usage Minimum (224)
0x29, 0xE7,
// Usage Maximum (231)
0x15, 0x00,
// Logical Minimum (0)
0x25, 0x01,
// Logical Maximum (1)
0x75, 0x01,
// Report Size (1)
0x95, 0x08,
// Report Count (8)
0x81, 0x02,
// Input (Data, Variable, Absolute) -- Modifier byte
0x95, 0x01,
// Report Count (1)
0x75, 0x08,
// Report Size (8)
0x81, 0x03,
// (81 01) Input (Constant) -- Reserved byte
0x95, 0x05,
// Report Count (5)
0x75, 0x01,
// Report Size (1)
0x05, 0x08,
// Usage Page (Page# for LEDs)
0x19, 0x01,
// Usage Minimum (1)
0x29, 0x05,
// Usage Maximum (5)
0x91, 0x02,
// Output (Data, Variable, Absolute) -- LED report
0x95, 0x01,
// Report Count (1)
0x75, 0x03,
// Report Size (3)
0x91, 0x03,
// (91 03) Output (Constant) -- LED report padding
0x95, 0x06,
// Report Count (6)
0x75, 0x08,
// Report Size (8)
0x15, 0x00,
// Logical Minimum (0)
0x25, 0x66,
// Logical Maximum(102) // was 0x65
0x05, 0x07,
// Usage Page (Key Codes)
0x19, 0x00,
// Usage Minimum (0)
0x29, 0x66,
// Usage Maximum (102) // was 0x65
0x81, 0x00,
// Input (Data, Array) -- Key arrays (6 bytes)
0xC0
// End Collection
};

Figure 22. Keyboard Report Descriptor
Table 25.
Field

Keyboard Report Format

Size

Description
IN report (into the host)

Modifier

1 byte

Modifier keys (SHIFT, CTRL etc)

Reserved

1 byte

reserved

Key
Arrays

6 bytes

Non-modifier key
OUT report (out of the host)

LED

1 byte

LED report and padding

Programmer's Guide: MSP430 USB API v4.10

78

9.3

Creating a Custom HID Interface
The API and Descriptor Tool pre-define mice, keyboards, and datapipe report formats. Any
other report format results in a “custom” HID interface.
The developer must generate the report descriptor that describes this custom report. General
information about doing so is given below.
Developing a custom HID device is more complicated than some other interfaces, and so the
developer should have a clear idea why it’s being chosen. There are generally two such
situations:
 PC peripherals other than mice/keyboards
 Maintaining backward-compatibility with an existing host application that already uses a
custom report format
The HID class was originally created for PC peripherals. The basic unit of data exchange was
called a report, which could be of varying formats. A USB device communicates its report
format using what is essentially a complex tag/scripting language. This provided flexibility,
allowing one device class to be used with a wide variety of PC peripherals. If creating a
peripheral, where the host OS itself handles the interaction with the device, and if the
functionality isn’t mouse/keyboard, then a custom report is required, and therefore a custom HID
interface.
Although initially intended for OS-driven peripherals, HID has also been used in general-purpose
applications where a host application program interacts with the device. HID-Datapipe is an
example of this. However, if the developer is trying to maintain compatibility with an existing
host application that uses a particular report format, then HID-Datapipe won’t work with it; HIDDatapipe has its own report format. As such, a custom HID interface on the MSP430 is
required, as well as a report descriptor describing the existing report format.
To create a custom HID interface, the recommended approach is:
1. Use the Descriptor Tool to generate a HID interface . For the HID report type, select
‘Custom’.

Figure 23. Creating a Custom HID Device

Programmer's Guide: MSP430 USB API v4.10

79

2. A pop-up text box allows the custom report descriptor to be input. (See Sec. 9.4 for how
to generate this.)

Figure 24. Entering a Custom HID Report Descriptor into the Descriptor Tool

3. Input the report’s data length at the bottom of this popup window, in bytes. Note that this is
not the length of the report descriptor, but the length of the reports that will be transferred
in normal operation.
4. Be sure to choose the correct polling interval (in the “interface view”) required for your
application.
5. In the application, use the HID-Traditional function calls to send and receive HID reports
See Sec. 5 for more information on using the Descriptor Tool.

Programmer's Guide: MSP430 USB API v4.10

80

9.4

Generating a Custom HID Report Descriptor
If generating a custom HID interface, the developer must provide a report descriptor.
Report descriptors may come from these sources:
 If the function is a PC peripheral, in which the host OS handles the interaction, then the OS
documentation may specify a required report format.
 Examples may be found in the public domain
 The USB-IF’s HID Descriptor Tool
The first two sources tend to provide intact report descriptors that can be pasted directly into the
MSP430 USB Descriptor Tool.
If the developer is creating a report truly from scratch, the HID Descriptor Tool can be used.
This is a tool provided by the USB Implementers Forum (USB-IF) to aid the creation of HID
report descriptors. Note that despite the similar name, the functionality of the USB-IF's tool is
very different than the MSP430 HID Descriptor Tool.

Figure 25. The USB-IF's HID Descriptor Tool

Programmer's Guide: MSP430 USB API v4.10

81

As seen in the figure above, even though the HID Descriptor Tool is helpful with formatting and
syntax, it still requires an understanding of the complex language used to define HID reports.
This knowledge is outside the scope of this Programmer's Guide; the developer motivated to
learn this language can reference materials from the USB-IF and other sources.
Once the report format is created, the output from the HID Descriptor Tool is a series of hex
values that can be pasted directly into the MSP430 USB Descriptor Tool’s pop-up text box , as
described in the previous section.

9.5

Writing Application Code for Traditional HID Devices
Traditional HID interfaces (any HID interface other than HID-Datapipe) use the HID-Traditional
function calls.
Table 26.

HID-Traditional Function Call Summary

Function
BYTE USBHID_sendReport()

Sends a report to the USB host

BYTE USBHID_receiveReport()

Receives a report from the USB host

Table 27.

Description

HID-Traditional Event Handler Summary

BYTE
USBHID_handleSendCompleted()

Interrupt for the input endpoint
associated with this data
interface

Indicates that an INPUT report has
been fetched by the host, for HID
interface intfNum

BYTE
USBHID_handleReceiveCompleted()

Interrupt for the output endpoint
associated with this data
interface

Indicates that an OUTPUT report
has been received from the host,
for HID interface intfNum

For reference details on these functions, including description, parameters, and calling
conditions, please see the API Functional Reference within the USB Developers Package. The
functions are further described below.
The application must allocate and populate a report buffer (up to 64 bytes), and then pass it into
the API using USBHID_sendReport(). This buffer contains, byte for byte, the report that will
be given to the host the next time the host polls this interface for a report. It is up to the
application to format these bytes in the exact same way they were defined by the report
descriptor.
Similarly, USBHID_receiveReport() receives a buffer (up to 64 bytes) that is formatted in the
manner described by the report descriptor. It is best to call it in response to a
USBHID_handleDataReceived() event.
In either case, the report length is defined by USBHID_REPORT_LENGTH, in descriptors.h.

Programmer's Guide: MSP430 USB API v4.10

82

If the HID interface defined a custom report descriptor, this descriptor might have defined
multiple reports, each with a unique “report ID” field. The application can therefore send/receive
multiple reports by setting the correct report ID value prior to calling USBHID_sendReport(),
and similarly can separate reports once received with USBHID_receiveReport() by reading
the report ID field.
All bytes described by the report descriptor are the responsibility of the application; the API does
not change them.

Programmer's Guide: MSP430 USB API v4.10

83

10 Event Handling
The USB interrupt service routine (ISR) is a resource owned by the API, and is not intended to
be modified. Rather, the API generates events the application sometimes need to handle.
Most of the defined events are called from within the USB ISR, in response to various USB
interrupts.
Developers with a hardware background may think of event handlers as similar to ISRs. Using
the function USB_setEnabledEvents() function can be thought of similarly to setting/clearing
interrupt enable bits. Developers with a software background may think of event handlers as
pre-defined callback functions.
The handler functions are located in USB_eventhandling.c. This file is considered to be an
application-owned resource; the software designer has freedom to modify each handler’s
content (but not the function’s declared parameters).

10.1 The Relationship between Interrupts and Events
The vast majority of event handlers are called out of the USB ISR. As a result, general
interrupts are disabled during the event handlers, and any precautions about good ISR coding
apply to event handlers as well.
For example, it’s recommended the handler be kept as short as possible, so that the ISR can
finish quickly; this avoids delays in handling other interrupts. If this isn’t possible, then another
option is to set a flag within the event handler and handle the function in main(); that is, no
longer in an interrupt-handling context. (If main() makes use of LPM0, it may be necessary for
the USB ISR to keep the MSP430 awake after the ISR returns; see the next section for more
information.)
Another recommendation is to not enable general interrupts (GIE) within the event handler. The
MSP430 disables general interrupts during event handlers, to avoid the potential for a stack
overflow. Enabling interrupts within an event handler would incur this risk.

10.2 Waking from Event Handlers
MSP430 coding frequently makes use of its low-power modes. The program spends most of its
time in a low-power mode, experiences an interrupt, and then goes back to sleep. Sometimes
the interrupt handling requires that the CPU stay awake after the ISR completes; this can be
accomplished with an intrinsic function such as:
__bic_SR_register_on_exit(LPM3_bits);

This intrinsic reaches into the stack and modifies the status register bits indicating what power
mode the MSP430 should return to after the ISR, forcing them to an active CPU state.
Therefore, if the MSP430 was in a low-power mode when the interrupt occurred, then the CPU
will resume execution when the ISR returns, starting from the point at which the low-power mode
had been entered. (This technique is well-documented in other MSP430 material, including the
application note MSP430 Software Coding Techniques (slaa294).)
Programmer's Guide: MSP430 USB API v4.10

84

Since events are generally extensions of the USB ISR, they often have a similar need to keep
the CPU active after return. The developer may wish to reduce interrupt latency by simply
setting a flag in the event handler, and do the actual handling in main(), triggered by the flag.
Event handlers can accomplish this by returning TRUE when exiting. This forces the CPU to
active mode. Returning a value of FALSE causes the CPU to return to whatever power state
was active when the ISR was triggered.

10.3 Calling API Functions from Event Handlers
Generally speaking, it isn’t recommended to call datapipe sending functions from within an event
handler. If the interface should happen to be busy at the point of sending, then it won’t become
available until after the event handler (and USB ISR) returns. Performing these functions in a
non-ISR context allows the USB interface to finish any open operations before starting a new
one. If data transmission is to be triggered from an event, a flag can be set from within the event
handler, and the handler can return TRUE, as described above.
All other API calls can be made from within event handlers.

10.4 Enabling Events
The event handlers only run in response to an event if their respective event is enabled. By
default, they are all disabled. However, if the function USB_setup() is used at initialization, it
enables all available events. Further enabling/disabling can be done with
USB_setEnabledEvents().
The only reason to keep an event disabled is to avoid wasting execution cycles by calling
“empty” event handlers. In some cases these wasted cycles could affect bandwidth.

10.5 Event Handler Functions
A summary of the event handler functions is shown in the table below. For complete
information, see the Doxygen reference within the USB Developers Package. Also see
discussion of various events elsewhere within this Programmer’s Guide.

10.6 Event Handler Summary
The event handlers are summarized below.
For reference details on these functions, including description, parameters, and calling
conditions, please see the API Functional Reference within the USB Developers Package.

Programmer's Guide: MSP430 USB API v4.10

85

Table 28.
Event Handler functions
BYTE USB_handleClockEvent()

Summary of Event Handlers
Interrupt source

Event Description

USBVECINT_PLL_RAN
GE

USB PLL failed (out of range)

BYTE USB_handleVbusOnEvent()

USBVECINT_PWR_VB
USOn

Indicates that a valid voltage is now available
on the VBUS pin (i.e., the bus is now
attached)

BYTE USB_handleVbusOffEvent()

USBVECINT_PWR_VB
USOff

Indicates that a valid voltage is no longer
available on the VBUS pin (i.e., the bus has
been removed)

BYTE USB_handleResetEvent()

USBVECINT_RSTR

Indicates that the USB host has initiated a
port reset. This has a similar effect to calling
USB_reset(), including that any
enumeration will be lost.

BYTE USB_handleSuspendEvent()

USBVECINT_SUSR

Indicates that the USB host has put this
device into suspend mode.

BYTE USB_handleResumeEvent()

USBVECINT_RESR

Indicates that the USB host has resumed this
device from suspend mode.

BYTE
USB_handleEnumerationCompleteEvent()

Interrupt for control
endpoint 0

Indicates that the USB device has just
become enumerated.

BYTE USBCDC_handleDataReceived()

Interrupt for the output
endpoint associated
with this data interface

Indicates that data has been received for
CDC interface intfNum, for which no data
receive operation is underway

BYTE USBCDC_handleSendCompleted()

Interrupt for the input
endpoint associated
with this data interface

Indicates that a send operation on CDC
interface intfNum has just been completed

BYTE USBCDC_handleReceiveCompleted()

Interrupt for the output
endpoint associated
with this data interface

Indicates that a receive operation on CDC
interface intfNum has just been completed

Programmer's Guide: MSP430 USB API v4.10

86

Table 29.

Summary of Event Handlers (continued)

BYTE USBHID_handleDataReceived()

Interrupt for the output
endpoint associated with
this data interface

Indicates that data has been received for HID
interface intfNum, for which no data receive
operation is underway

BYTE USBHID_handleSendCompleted()

Interrupt for the input
endpoint associated with
this data interface

Indicates that a send operation on HID
interface intfNum has just been completed

BYTE USBHID_handleReceiveCompleted()

Interrupt for the output
endpoint associated with
this data interface

Indicates that a receive operation on HID
interface intfNum has just been completed

BYTE USBMSC_handleBufferEvent()

Interrupt for the
endpoints associated
with this interface

Indicates that the API needs the application
to process a buffer.

Programmer's Guide: MSP430 USB API v4.10

87

11 Practical Matters: Writing USB Programs with the API
11.1 Power Management
USB provides 5V of power via the cable, called VBUS. The MSP430’s USB module has an
integrated LDO regulator that reduces this to 3.3V. The output of this regulator is called VUSB.

3.0-3.6V VUSB
(out to system, or in from LDO)

5V VBUS

3.3V
LDO

1.8V
LDO

PUR
Driver

1.8-3.6V DVCC

USB
Core

XT2
Oscillator

USB
PLL

CPU /
Peripherals

USB
PHY

MSP430 with USB
Figure 26. MSP430 Power Flow, with Respect to USB
Note: This is not a schematic. Please see electrical reference circuits for guidance on the
hardware.
The developer has some options with respect to the VUSB rail. Using the internal LDO’s, VBUS
can source the USB module. The LDO has sufficient output capability to drive other
components in the system, or to the DVCC pin; see the device datasheet for maximum output
current.

11.1.1 Directing Power into VUSB from an External Source
It’s possible to drive power into the VUSB rail from an external source, rather than using the
integrated 3.3V LDO. The reason this might be desirable is that the quiescent current on the
integrated 3.3V LDO is in area of 100uA. Even though host power is usually available to power
this, in some cases the host’s supply itself might be limited. If an external LDO is present
nearby, it can be directed into VUSB.
If this is done, the 3.3V LDO should be disabled. An option is available in the Descriptor Tool to
do this automatically, shown below.

Programmer's Guide: MSP430 USB API v4.10

88

Figure 27. Descriptor Tool Selection for External VBUS Source
Please be aware that the on-chip USB BSL is not designed to operate this way; it always
enables the integrated LDO. If this operation is desired, a small software change can be made
to the BSL source (available as app note slaa450), and the modified BSL can be re-programmed
into the MSP430.
If this option is chosen, it’s still important to connect 5V VBUS to the USB connector, because
this is the way a USB device is able to tell that a host is present.

11.1.2 The API’s Effect on Power Settings
The only USB API call that affects the MSP430’s power settings is USB_setup().
(USB_init() does as well, but this function has been deprecated in v4.0.) USB_setup()
enables the 3.3V and 1.8V USB LDOs. The USB API does not affect the MSP430F5xx’s
VCORE setting.

11.1.3 VCORE Setting
The MSP430F5xx’s Power Management Module (PMM) includes an LDO (separate from the
ones in the USB module) that sources a nominal 1.8V to the digital core. There are actually four
settings for VCORE: 0-3. Usually the choice of VCORE setting is determined by the MCLK
speed.
When the USB PLL is enabled, however, the minimum required setting is “2”, no matter the
speed of MCLK. The USB PLL is enabled with USB_enable() and disabled with
USB_disable. The PLL is also automatically disabled during USB suspend. If VCORE is set
to “0” or “1” when the PLL is enabled, errors will result.
The VCORE setting is controlled by the PMMCOREV field in the PMMCTL0 register. It’s
recommended to configure the PMM using the driverlib call PMM_setVCore(). A copy of
driverlib is included with all the examples and empty USB project.

11.1.4 Managing VBUS Power During USB Suspend
When the host suspends a USB device, the current being drawn from the host via VBUS must
be reduced. It must do this within 7ms of the suspend event, which the application sees as a
USB_handleSuspendEvent(). The application may need to shut down circuitry to avoid
violating this USB requirement.
Programmer's Guide: MSP430 USB API v4.10

89

According to the USB specification, the amount most devices are allowed to draw is 500uA.
However, the USB Implementers Forum reliably gives waivers to any device that consumes in
the range of 500uA to 2.5mA.
If a crystal is used on XT2 to drive the USB PLL (typically the case in most applications), then
the oscillator consumes a couple hundred uA’s. The Descriptor Tool can configure the API to
attempt to power down XT2 during suspend. However, if any peripherals derive their clocking
from XT2, the oscillator will remain on, due to the peripheral issuing a “clock request”. (See the
F5xx Family User’s Guide for more information.)
When the host resumes the device from suspend, it is probably desirable for software to reactivate the components that were disabled. This can be performed within
USB_handleResumeEvent().
In battery-powered systems, the engineer is encouraged to draw most of the device’s power
from VBUS while it’s available. Being attached to a USB host may keep the device active for
longer periods of time than would occur for a non-USB mobile device, so if VBUS power is not
used, the battery will experience extra power draw.

11.1.5 Selective Suspend
As discussed in Sec. 6.8, from a USB device’s standpoint, there is no difference between a
whole-bus USB suspend, and selective suspend. The USB device only knows that it’s been
suspended. The host determines whether to selectively suspend a device based on a set of
rules determining whether the device has been inactive for a sufficient period of time.
The only way in which the USB device can prevent entry into selective suspend is if the nature
of communication between the device and host is such that the operating system decides that
the device is not idle. For example, the most may have certain timeout periods that must expire,
and perhaps the USB device is communicating too frequently. It may be beneficial to consult
with the operating system’s technical documentation to determine whether this is the case.
There are sometimes settings on the host operating system that are required to enable selective
suspend. Some of these settings might be required on a per-device basis. HID on Windows
sometimes requires a special INF file that enables selective suspend.

11.1.6 Use of Low-Power Modes
The software engineer is encouraged to use the MSP430’s low power modes in the application,
because maximizing the time spent in these modes can increase power efficiency. They can be
used in a manner similar to any MSP430 application. The only restriction is that while the USB
PLL is enabled, the power mode should not be “less” than LPM0 (in other words, do not use
LPM3/4/5). The USB PLL is enabled with USB_enable() and disabled with USB_disable().
The PLL is also automatically disabled during USB suspend. During USB suspend, the CPU
can be placed into LPM3 (but not LPM4/5).
LPM entry often needs to be conditional upon USB events. Since USB events are typically
interrupt-driven and can happen at any time, it is recommended to disable interrupts prior to
evaluating these conditions, and re-enabling flags atomically with the LPM entry:

Programmer's Guide: MSP430 USB API v4.10

90

__disable_interrupt();
if(!dataReceivedFlag)
__bis_SR_register(LPM0_bits + GIE); //Simultaneous LPM0 entry & re-enabling ints
__enable_interrupt();
//Enable ints if LPM0 was not entered

In this example, dataReceivedFlag is set in USBxxx_handleDataReceivedEvent(). If
interrupts had not been disabled, then it would have been possible for the flag to have changed
state after the evaluation but before the LPM entry. If this were to happen, the LPM entry would
be in error, and the device may possibly never wake from LPM0. Disabling interrupts before the
evaluation ensures the event won’t occur.

11.2 Clock Management
11.2.1 Summary of USB Clock System
MSP430 devices supporting USB include a PLL that generates a 48MHz USB clock from a
reference clock sourced by the XT2 oscillator. The PLL is sourced directly from XT2.

(Used for lowfrequency clocking
during USB suspend)

VLO

MCLK

48MHz
for USB

USB
PLL

DCO/
FLL
-OR-

USB

XT2
Oscillator

LFXT1

REFO

MSP430

Figure 28. Recommended Clocking in a USB-Equipped MSP430
XT2 is considered an API-owned resource. The API enables and disables it as needed. Some
configurability of this behavior is provided in the Descriptor Tool. The Tool also sets certain
values the API needs to properly manage XT2 and the PLL.
During USB suspend, the API disables the PLL, and optionally XT2. During this time, the USB
module begins receiving clocking from the always-on VLO (very low-frequency, low-power
oscillator). This low-power oscillator is sufficient for the module’s functions during suspend.

Programmer's Guide: MSP430 USB API v4.10

91

11.2.2 MCLK Requirements
USB operation can take place over a wide range of MCLK values. Most testing has taken place
with MCLK at least 4MHz, but this may not be the practical lower limit.
The application developer has complete freedom to set MCLK speed. The driverlib library
accompanying the examples and empty USB project can be used to set the system clocks.
It is not supported to use REFO, LFXT1, or the VLO for MCLK.

11.2.3 Sourcing the USB PLL Reference Clock
The simplest method to source the PLL reference is placing a crystal on XT2. An alternative
that might reduce cost is to inject a clock from outside the MSP430 into XT2, with XT2 placed in
“bypass mode”. The Descriptor Tool can place the XT2 in Bypass mode via the value
USB_XT2_BYPASS_MODE.
The PLL reference must adhere to certain frequency, precision, and jitter requirements. (See
the device datasheet.) Crystals driven by the XT2 oscillator easily meet these requirements.
Some ceramic resonators do as well.
But if bypass mode is used -- meaning a clean clock is driven into XT2’s input pin -- the designer
must consider these requirements. The tolerance requirement is provided by the USB
specification: 2500ppm. The MSP430’s DCO/FLL output does not meet the PLL’s jitter
requirements, and thus it cannot be used for USB. The low-frequency oscillators on the device
(LFXT1, REFO, and VLO) do not run at a high enough frequency to source XT2 for USB.
Therefore, the PLL reference must come from either:
 a crystal or compliant ceramic resonator on XT2, or
 a clock source from elsewhere on the board – injected into XT2 in bypass mode – that
originates from a crystal or perhaps some ceramic resonators capable of the needed
precision

11.2.4 API Delay Loops
The API employs CPU-driven delay loops in a couple places to implement delays required by
the USB module. Such delays must compensate for varying MCLK speeds. Prior to v4.0 of the
API, it obtained this information from the Descriptor Tool, via the value USB_MCLK_FREQ.
Since this was a compile-time value, it did not adapt to any changes in MCLK over time.
As of v4.0, an internal function is employed that determines the MCLK speed from the UCS
registers. The delay is adjusted according to the perceived clock speed. As a result, there’s no
longer a need to input this value via the Descriptor Tool, and it always adjusts to whatever
MCLK is set to at run-time.

Programmer's Guide: MSP430 USB API v4.10

92

11.2.5 XT2 Startup Times
It’s important that the load capacitors for XT2 be chosen properly, according to the crystal’s
rating. An improperly-tuned oscillator circuit will result in either oscillator failure, or extended
startup times. Startup times are important if XT2 is disabled during suspend, because once the
host resumes the USB device, it has 10ms to begin communicating with the host. A properlytuned XT2 oscillator circuit stabilizes well within this range, but an improperly-tuned one can
take significantly longer.

11.2.6 Using XT2 for Non-USB Functions
Although XT2 is considered an API-owned resource, it’s possible for it to be used for non-USB
functions. For example, it can drive the CPU, via the system clock MCLK; and it can drive
peripherals, via the system clock SMCLK.
It should be kept in mind that crystal precision generally has no advantage for MCLK; the CPU
will not execute any differently with crystal precision. Crystal precision may be useful for certain
analog/digital conversion functions.
If any MSP430 component is configured to use XT2 (via MCLK or SMCLK), then XT2 will remain
enabled whenever it’s needed by that component. The API will not be able to disable it, due to
“clock requests” that keep it active.

11.3 “Bus Errors”
During USB suspend, the PLL is disabled, and the USB module is clocked by the VLO oscillator.
The VLO operates at a much slower frequency than the PLL. If the CPU attempts to access the
USB RAM at this time, a non-maskable interrupt (NMI) will occur, called a “bus error”. (USB
RAM is accessed anytime there is an active USB connection; see the F5xx Family User’s Guide
for details.)
USB RAM is “multi-port” – that is, it’s mutually accessible by the USB module and the CPU, and
thus affected by both clock domains. The gap in speed between MCLK and the VLO will cause
timeouts to occur on the MSP430’s internal data bus if an access is attempted. This generates
a bus-error NMI.
This error should not occur in normal operation, because the API knows not to access USB
RAM when the PLL is inactive. If it does happen, it might be a sign that the PLL (or XT2) failed
unexpectedly.
Bus error NMIs must be handled by resetting the USB module, with USB_disable().

case SYSUNIV_BUSIFG:
SYSBERRIV = 0;
USB_disable();

To re-attempt the USB connection, subsequent calls to USB_enable() and USB_connect()
are required. Applications should contain the code to handle this.
Programmer's Guide: MSP430 USB API v4.10

93

11.4 Use of DMA
USB transfers will generally occur more quickly and efficiently if DMA is enabled. This can be
configured using the Descriptor Tool.

11.5 Using an RTOS
See Sec. 13 for a discussion on using the USB API with real-time operating systems (RTOSes).

11.6 System Interrupts
USB operation involves a large number of interrupts. It’s important that the developer consider
the impact of the non-USB operation on the USB interrupt handling, and vice versa.

11.6.1 Ensuring the MSP430 Services USB Interrupts
In some cases the host enforces timeout periods if the device doesn’t respond in time. Usually
the critical timeouts are services at a hardware level, and in the majority of cases handled by
software, the device is able to “NAK” (no-acknowledge) the host, essentially asking it to wait until
the device is ready. However, in some cases and with enough delay, the application software
may be capable of causing the host to timeout.
USB interrupts fall below several other kinds of interrupts on the MSP430’s interrupt priority list –
specifically the ones shown in the table below.
Table 30.

Interrupts with Higher Priority than USB
Interrupt Source

Priority

System Resets

63 (highest)

System/User NMIs

61-62

Comparator_B

60

TB0

58-59

Watchdog Timer (interval timer)

57

USCI_A0/B0 (SPI/I2C/UART)

55-56

ADC12_A (12-bit A/D)

54

Timer_A

52-53

USB

51

Other interrupts

0-50

If these other interrupts occur with unusually high frequency in the application, or with high
duration, they might prevent the USB interrupts from being serviced.

11.6.2 USB ISR Latency
On the MSP430, new interrupts are disabled while an interrupt service routine is handling an
interrupt. This makes latency important – the time required for the USB ISR to complete. For
most sources of USB interrupts, the latency is quite small. (See the Release Notes HTML file in
the USB Developers Package for specific metrics.)

Programmer's Guide: MSP430 USB API v4.10

94

An exception is when the host resumes the USB device out of USB suspend. At these times,
USB_enable() is called. This function starts the XT2 oscillator, if it wasn’t already running.
This can take several hundred microseconds. The PLL must also then be locked, and the
datasheet indicates this can take up to 2ms. (See the device datasheet for up-to-date
parametrics.)
If this is unacceptable in your application, it’s possible to divide the USB resume functionality
into three phases, most of which does not take place within an interrupt context. The tradeoff is
that the application must take responsibility to ensure that the XT2 oscillator has stabilized, and
that the PLL delay period has expired. Example #G1 in the USB examples shows how to do
this; the example is also explained in detail in the Examples Guide. The divided functions are
described in Sec. 6.1

11.7 USB Design Considerations
11.7.1 Robustness: Handling Surprise Removal or Suspend
It’s important for the software designer to consider that a USB connection can be lost at any
time, due to being suspended by the host, or by the user disconnecting it (a “surprise removal”).
A device should recover from these events gracefully. The API functions and the example
constructs provide return values that help in this effort.

11.7.2 The Impact of USB State on Functionality
As discussed in Sec. 6, a USB device can be in one of several different bus states, returned by
USB_getConnectionState(). A device spends most of its time in
ST_PHYS_DISCONNECTED, ST_ENUM_ACTIVE, and ST_ENUM_SUSPENDED. The state can
change at any time.
For some USB devices, these states have a deep impact on functionality. For example, a digital
still camera’s main function when not connected to a host is to take pictures. But once
connected to the host, its purpose is now to upload pictures. It may even prevent pictures from
being taken under these conditions.
Thus the state of the bus has completely altered the software flow. This is in contrast to most
equipment that uses an RS232 serial port; such devices typically do not change “identity”
according to the connection state.
USB state may also affect the power configuration. A battery-powered device may rely on
VBUS for power while USB is attached, which means it needs to significantly reduce
functionality when the host suspends it.
Such devices are referred to below as state-dependent.
Not all USB devices behave this way. Devices that are purely bus-powered (like a mouse or
keyboard) do nothing when not attached to a host.
And for other devices, USB sending and receiving is incidental to the main application, and the
application is relatively unaffected if data sending fails due to a detached bus, or if data is never
received.
Programmer's Guide: MSP430 USB API v4.10

95

These devices are referred to below as state-independent.
Several example devices are shown in the table below, describing how they behave in the three
primary states mentioned above.
Table 31.

State-Dependence of Some Example Devices

ST_DISCONNECTED

ST_ENUM_ACTIVE

ST_ENUM_SUSPENDED

Digital camera

Functions as a camera

Playback and upload; pictures
can’t be taken

Functions as a camera

Cell phone

Functions as a phone

Enumerates as mass storage;
phone calls can’t be made

Functions as a phone; stops
charging the battery

Mouse

Unpowered

Functions as a mouse

Does nothing, except may be
capable of remote wakeup

Printer

Allows configuration from
its control panel

Allows configuration, and also
responds to print requests

Allows configuration from its
control panel

Data sensor/logger
(example)

Logs data into internal
MSP430 flash

Continues to log data, but also
sends log entries over USB

Logs data in internal
MSP430 flash

Therefore, the designer should consider how (or if) the USB state will impact functionality.

Programmer's Guide: MSP430 USB API v4.10

96

11.8 State-Dependent Functionality: Main Loop Framework
One option for state-dependent devices is a main loop construct like the one shown below.

VOID main(VOID)
{
WDTCTL = WDTPW + WDTHOLD;
Init_System();
USB_setup();

// Configure watchdog

while(1)
{
switch(USB_getConnectionState())
{
case ST_ENUM_ACTIVE:
__bis_SR_register(LPM0_bits + GIE);
function_as_USB_active();
break;
case ST_PHYS_DISCONNECTED:
case ST_ENUM_SUSPENDED:
case ST_PHYS_CONNECTED_NOENUM_SUSP:
__bis_SR_register(LPM3_bits + GIE);
function_as_USB_inactive();
break;
default:;
}
}

// Enter LPM0

// Enter LPM3

}
BYTE USB_handleVbusOnEvent() {
if (USB_enable() == USB_SUCCEED) {
USB_reset();
USB_connect();
}
return TRUE;
// Wake the main loop to give it a chance
}
// to respond to the change in state
BYTE USB_handleVbusOffEvent()
return TRUE;
}

{

BYTE USB_handleSuspendEvent()
return TRUE;
}

{

BYTE USB_handleResumeEvent()
return TRUE;
}

{

// Wake the main loop to give it a chance
// to respond to the change in state
// Wake the main loop to give it a chance
// to respond to the change in state
// Wake the main loop to give it a chance
// to respond to the change in state

Execution within this main loop “forks” depending on the state of the USB, creating alternate
main loops. As such, USB state becomes a central part of managing software flow.

Programmer's Guide: MSP430 USB API v4.10

97

In this particular example, software behaves the same whether the device is attached to a host
but suspended, not attached to a host, or in ST_PHYS_CONNECTED_NOENUM_SUSP, which
generally means a powered hub without a host present, or an unresponsive host. In those
cases, the main loop functionality is determined by function_as_USB_inactive(). If the
device is not attached and then becomes so, USB_handleVbusOnEvent() can be configured
to initiate a connection, changing the state to ST_ENUM_ACTIVE. (There is no rule that says a
USB connection must be made upon attachment; so if this isn’t desired, this code could be
removed.)
When enumeration completes, the main loop waits for an interrupt to begin executing
function_as_bus_active().
Notice that the four events shown are enabled and set to return TRUE. These allow the main
loop be “refreshed” to reflect the new state that result after these events. If these handlers
execute and return with a TRUE return value, they will cause the main loop to execute once. If
the loop is asleep at an LPM instruction inside one of the case statements, this allows it to leave
the main loop and make another call to USB_getConnectionState(). It can then handle
whatever functionality is required in the new state.
Most of the examples and the empty USB project reflect a similar approach to the one shown
above.

Programmer's Guide: MSP430 USB API v4.10

98

11.9 State-Independent Functionality
For devices that don’t significantly change their functionality according to USB state, something
similar to below could be employed.
VOID main(VOID){
WDTCTL = WDTPW + WDTHOLD;
Init_SystemAndTimer();
USB_setup();

// Configure watchdog

while(1)
{
__bis_SR_register(LPM0_bits + GIE);
process_data();
prepare_buffer(buffer,size);
USBCDC_sendData(buffer,size,0);

// LPM3 if possible, but must
// Do what we woke up to do

// Return value is ignored, because success or
// failure doesn’t affect program flow

} // while(1)
} //main()
BYTE USB_handleVbusOnEvent(){
if (USB_enable() == USB_SUCCEED)
{
USB_reset();
USB_connect();
}
switchPowerToVBUS();
return FALSE;
}
BYTE USB_handleVbusOffEvent(){
switchPowerToBattery();
return TRUE;
}
BYTE USB_handleSuspendEvent(){
switchPowerToBattery();
return FALSE;
}
BYTE USB_handleResumeEvent(){
switchPowerToVBUS();
return FALSE;
}
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
__bic_SR_register_on_exit(LPM3_bits);
}

Programmer's Guide: MSP430 USB API v4.10

// Exit LPM

99

This example wakes periodically and processes data. If USB happens to be available, it also
broadcasts the data to the host. The functionality is largely the same whether USB is attached
or not.
The example enters LPM0 in all cases, even though it could be entering LPM3 if USB wasn’t
active. This was done for simplicity, but in an actual power-sensitive application, LPM3 may be
desirable.
This example shows the use of events to manage power. If USB is present, the system relies
on VBUS for power. Otherwise it uses a battery. Using VBUS during USB may be essentail for
a battery-powered USB system, because staying active on USB requires considerable power
Notice that this time, the events return FALSE. The main loop in this case doesn’t require any
“refreshing”, as the state-dependent loop did.
This particular example doesn’t check for pre-existing send operations before calling
USBCDC_sendData(), as arguably it should. However, if one already exists, the function
simply returns an error and execution continues. The only consequence is that this particular
data transmission was missed.

Programmer's Guide: MSP430 USB API v4.10

100

11.10 Tips for Sending Data over Datapipe Interfaces
11.10.1 Conditions to Consider When Sending Data
When using USBCDC_sendData() and USBHID_sendData() to send data over datapipe
interfaces, two things need to be considered:


Background Processing (or “asynchronous” operation). These functions only begin a send
operation and then return. The actual send operation can continue to execute after
USBxxx_sendData() returns. Software must anticipate that a previous operation may still
be in progress, before making another call to USBxxx_sendData().



Bus disconnect/suspend. The end user may disconnect the bus at any time, or the host
may suspend the device at any time. Software must anticipate that the bus may suddenly
become unavailable.

To account for these, TI provides example construct functions that take these concerns into
account. The developer is free to edit them, or use them as-is.
Table 32.

Construct Functions for Datapipe Sending

Construct Function
USBCDC_sendDataInBackground()

Description
Calls USBCDC_sendData() asynchronously, checking first for an open
interface and exiting if the bus isn’t available

USBCDC_sendDataAndWaitTillDone()

Calls USBHID_sendData() synchronously; does not return until the
data has all been sent, or until it’s been determined the host is not
available.

USBHID_sendDataInBackground()

Same as USBCDC_sendDataInBackground(), except using an HIDDatapipe interface.

USBHID_sendDataAndWaitTillDone()

Same as USBCDC_sendDataAndWaitTillDone(), except using an
HID-Datapipe interface.

Equivalent construct functions are provided for CDC and HID-Datapipe, reflecting the symmetry
between these two interfaces. The prefixes are cdc or hid, respectively. Since the text in this
section applies equally to both types, they’re frequently shown in this section with the prefix xxx
-- for example, “USBxxx_sendDataInBackground()”.
The construct functions are included with the application examples, in the file usbConstructs.c/h.

Programmer's Guide: MSP430 USB API v4.10

101

11.10.2 Background Processing
As discussed in Sec. 7.4.2, background send/receive operations increase efficiency, and they
avoid blocking MSP430 software execution if the host or bus are slow. The tradeoff is that if
more than one send attempt will be performed, software must be mindful that a previous
operation can still be in progress.
There are three general approaches to handling background processing, shown below.
Table 33.
Approach

Approaches to Background Processing
How

Tradeoff

Eliminate it

After calling USBxxx_sendData(), poll the
interface’s status until it’s no longer busy. Or
simply call
USBxxx_sendDataAndWaitTillDone().

Simplest to code, but blocks execution until
the transfer is complete.

Fully take
advantage of it

Arrange software to trigger new send
operations in response to the last one ending

More coding effort, but is the most efficient
and least blocking.

Mostly take
advantage of it

Before calling USBxxx_sendData(), poll the
interface’s status until it’s no longer busy. Or
simply call
USBxxx_sendDataInBackground().

Allows most of the sending to take place
during other software execution, but could
still end up spending time polling the
interface if it’s still busy handling a previous
send operation.

The first and last approaches are simple to implement within a function, and so they are
provided with the API in the form of the “construct” functions
USBxxx_sendDataAndWaitTillDone() and USBxxx_sendDataInBackground(). (The
CDC ones are shown as examples.)

Programmer's Guide: MSP430 USB API v4.10

102

BYTE USBCDC_sendDataAndWaitTillDone (BYTE* dataBuf,
WORD size,
BYTE intfNum,
ULONG ulRetries)
{
ULONG sendCounter = 0;
WORD bytesSent, bytesReceived;
switch (USBCDC_sendData(dataBuf,size,intfNum))
{
case USBCDC_SEND_STARTED:
break;
case USBCDC_BUS_NOT_AVAILABLE:
return (2) ;
case USBCDC_INTERFACE_BUSY_ERROR:
return (3) ;
case USBCDC_GENERAL_ERROR:
return (4) ;
default:;
}
// If execution reaches here, the operation successfully started.
// Now wait til it's finished.
while (1){
BYTE ret = USBHID_getInterfaceStatus(intfNum,&bytesSent,&bytesReceived);
if (ret & USBHID_BUS_NOT_AVAILABLE){
// This may happen at any time
return (2) ;
}
if (ret & USBHID_WAITING_FOR_SEND)
{
if (ulRetries && (sendCounter++ >= ulRetries)) // Incr & try again
{
return (1) ;
// Timed out
}
}
else
{
return (0);
// If succeeded
}
}

The function USBHID_sendDataAndWaitTillDone() is identical to this, except that it’s for
HID-Datapipe interfaces.
This function doesn’t return until all the data has been transferred (or an error has occurred).
This effectively eliminates background processing altogether, which makes coding simpler in
some respects. However, it has two disadvantages: it wastes CPU cycles during polling, and it
also can block execution in the event of a slow host or busy bus.
If the host and bus are “fast”, this synchronicity isn’t a problem. But host/bus performance are
outside the device’s control, and can’t be guaranteed. An example of synchronicity being
problematic is if the host is writing large amounts of data to a USB hard drive located on the
same bus, making the host and/or bus “slow”. In this situation, synchronous operation (post-call
polling) might impact MCU code execution.

Programmer's Guide: MSP430 USB API v4.10

103

The function exits if the host is unavailable, or if the interface takes too long to finish its previous
operation (optional). If they return a zero value, all went well. If the return value is non-zero, it
did not go well; the value should be evaluated and handled accordingly.
An example of calling this function twice in succession is shown below.
while(1)
{
switch(USB_connectionState())
{
case ST_ENUM_ACTIVE:
{
.
.
dataBuffer = temporaryBuffer1;
if(cdcSendDataWaitTilDone(dataBuffer,100,1,0)
{
USBCDC_abortSend(&x,1);
break;
}
.
.
dataBuffer = temporaryBuffer2;
if(cdcSendDataWaitTilDone(dataBuffer,100,1,0)
{
USBCDC_abortSend(&x,1);
break;
}
Operations complete when
.
.
sendData_waitTilDone() returns
.
}
}
}

Figure 29. Calling USBxxx_sendDataAndWaitTillDone()
In this example, two send operations are initiated in succession. Notice that dataBuffer is
edited between the two calls, without needing to be concerned that the buffer is still in use. This
is because USBxxx_sendDataAndWaitTillDone() guarantees the operation was complete
before returning.
Notice that each call checks for a non-zero return value. Such a value would indicate a serious
bus issue – either the bus has become unavailable, or the host for whatever reason isn’t
cooperating. In each case, the operation is aborted.
The parameters for the construct functions are the three for USBxxx_sendData() and also one
for a retry value. This retry is an inexact mechanism, but it effectively ensures that executation
doesn’t stay here forever.
USBCDC_sendDataInBackground() is shown below.
Programmer's Guide: MSP430 USB API v4.10

104

BYTE USBCDC_sendDataInBackground (BYTE* dataBuf,
WORD size,
BYTE intfNum,
ULONG ulRetries)
{
ULONG sendCounter = 0;
WORD bytesSent, bytesReceived;
while (USBCDC_getInterfaceStatus(intfNum,&bytesSent,
&bytesReceived) & USBCDC_WAITING_FOR_SEND)
{
if (ulRetries && ((sendCounter++) > ulRetries)){ // A send operation is underway; incr
{
// counter & try again
return (1) ;
// Timed out
}
}
// The interface is now clear. Call sendData().
switch (USBCDC_sendData(dataBuf,size,intfNum))
{
case USBCDC_SEND_STARTED:
return (0);
case USBCDC_BUS_NOT_AVAILABLE:
return (2);
default:
return (4);
}
}

In this approach, the order of events is reversed. The interface is polled, and if not busy, data is
sent using USBxxx_sendData() and returns, while the API sends the data in the background.
If USBxxx_sendDataInBackground() is called again at a later time, there’s a good chance
the data has been fully transferred. If not, then the polling time is less than it would have been
with USBxxx_sendDataAndWaitTillDone().
The disadvantage relative to USBxxx_sendDataAndWaitTillDone() is that the application
isn’t allowed to edit the user buffer associated with the previous send operation, unless it’s sure
that operation has been completed in the background. (This can be handled using an X/Y buffer
scheme -- see below.)
The function exits if the host is unavailable, or if the interface takes too long to finish its previous
operation (optional). If they return a zero value, all went well. If the return value is non-zero, it
did not go well; the value should be evaluated and handled accordingly.

Programmer's Guide: MSP430 USB API v4.10

105

while(1)
{
switch(USB_connectionState())
{
case ST_ENUM_ACTIVE:
{
.
.
.
dataBufferX = temporaryBuffer1;
if(cdcsendDataInBackground(dataBufferX,100,1,0)
{
USBCDC_abortSend(&x,1);
Second operation
may be open; don’t break;
First operation may be
}
edit dataBufferY
open; don’t edit dataBufferX
.
.
dataBufferY = temporaryBuffer2;
if(cdcSendDataInBackground(dataBufferY,100,1,0)
{
USBCDC_abortSend(&x,1);
break;
}
.
.
.
}
}
}

Figure 30. Calling USBxxx_sendDataInBackground()
Two send operations are initiated in succession. Notice that two different buffers are used –
dataBufferX and dataBufferY. Each buffer is not allowed to be edited while its operation
may still be underway, which is the reason why two are necessary. Effectively, then, this
arrangement uses an switched X/Y buffer scheme.
Notice that each call checks for a non-zero return value. Such a value would indicate a serious
bus issue – either the bus has become unavailable, or the host for whatever reason isn’t
cooperating. In each case, the operation is aborted.
As with USBxxx_sendDataAndWaitTillDone(), the last passed-in parameter is a retry
value. Large values are recommended.
A third approach to background processing is true “asynchronous” sending. Each send is
triggered by the completion of the previous operation. As such, there’s no need to ever poll
USBxxx_getInterfaceStatus(). Sending is triggered by
USBxxx_handleSendCompleted().

Programmer's Guide: MSP430 USB API v4.10

106

Here are some guidelines:


USBxxx_sendDataAndWaitTillDone() can generally be used for small transfers
without negative consequence. If fast development is the priority, and the system has
cycles to spare, this might be the best approach.



USBxxx_sendDataInBackground() provides a very good balance of efficiency and
ease of use. It is also much more asynchronous with the host. Therefore, it’s a good
choice for performing larger transfers, pre-call polling might be better, because it
maximizes bandwidth and minimizes dependency on the host.



True asynchronous operation might be desirable and/or more natural to implement in
RTOS-based implementations that want to completely eliminate the possibility of polling,
or if maximum CPU efficiency is required.



Use caution if mixing approaches. For example, if using
USBxxx_sendDataAndWaitTillDone() after a previous call to
USBxxx_sendDataInBackground(), be sure to poll
USBxxx_getInterfaceStatus() to ensure the previous send operation is complete.

11.10.3 Anticipating a Lost Bus
The USB connection might be disconnected or suspended at any time; and as Sec. 11.6.2
indicated, the program should respond to these changes in USB state. For example, it’s
undesirable for the program to “hang up” in a location that no longer fits the current state of the
bus because it made an incorrect assumption about bus availability. By checking return values,
software can break from the main loop and re-assess the situation.
The construct functions return a value that indicates whether the bus is available or not, so that
the application may choose to handle a lost bus. For example, software may need to close
down certain operations. If this occurs and execution is in a section that is very USB-specific, it
should break from this location.

Programmer's Guide: MSP430 USB API v4.10

107

11.11 Tips on Receiving Data over CDC or HID-Datapipe
When sending data over USB, the application controls:
 the point within application flow where the transfer will be initiated, and
 how many bytes will be sent
But when receiving data, neither of these is certain to the application; the host controls both
factors.
This dictates the need for a wider range of constructs than for send operations. Many variations
can be created, but the ones described below cover most usage scenarios.
Table 34.

Receive Construct Options

Size
Known
Ahead of
Time?

USBCDC_receiveDataInBuffer()
USBHID_receiveDataInBufferr()

Continuously-Open Receive

Fixed Receive

No

No

Yes

Expected
Size

Description

“Small”

Receive operations aren’t opened until data is
already waiting in the USB endpoint buffers.
Therefore, the operations are immediately
completed. The application must always be
available to respond to
handleDataReceived().

“Large”

The application maintains an open, largerthan-needed receive operation at all times.
When it wants to use the data, it simply looks
inside the user buffer.

(Not
applicable)

A receive operation is opened for the exact
amount of data expected. When this amount
is received, a handleReceiveCompleted()
event is generated, and the application
handles it.

As with the sending constructs , equivalent receive construct functions are provided for both
CDC and HID-Datapipe, reflecting the symmetry between these two interfaces. The prefixes are
cdc or hid, respectively. Since the text in this section applies equally to both types, they’re
frequently shown in this section with the prefix xxx-- for example,
“USBxxx_receiveDataInBuffer()”.
The construct functions are included with the application examples, in the file usbConstructs.c/h.

11.11.1 USBCDC_receiveDataInBuffer() and USBHID_receiveDataInBufferr()
The USBxxx_receiveDataInBuffer()function opens a receive operation only for data that
has already been received into the USB endpoint buffers; this operation completes immediately.
(Recall that the endpoint buffers contain a single packet of data from the host – see Sec. 7.)

Programmer's Guide: MSP430 USB API v4.10

108

The benefit of this is that the application doesn’t need to worry about the future reception of
data; it only polls to see what is already present. This method works best when the expected
block of data is small in size, but the exact number of bytes is unknown.

The CDC version of the function is shown below.

// This call only retrieves data that is already waiting in the USB buffer –
// that is, data that has already been received by the MCU. It assumes a previous,
// open receive operation (began by a direct call to USBxxx_receiveData()) is NOT
// underway on this interface; and no receive operation remains open after this
// call returns. It doesn't check for USBxxx_BUS_NOT_AVAILABLE, because it doesn't
// matter if it's not. size is the maximum that is allowed to be received before
// exiting; i.e., it is the size allotted to dataBuf. Returns the number of bytes
// received.
WORD USBCDC_receiveDataInBuffer (BYTE* dataBuf, WORD size, BYTE intfNum)
{
WORD bytesInBuf;
WORD rxCount = 0;
BYTE* currentPos = dataBuf;
while (bytesInBuf = USBCDC_bytesInUSBBuffer(intfNum))
{
if ((WORD)(currentPos - dataBuf + bytesInBuf) <= size)
{
rxCount = bytesInBuf;
USBCDC_receiveData(currentPos,rxCount,intfNum);
currentPos += rxCount;
}
else
{
rxCount = size - (currentPos - dataBuf);
USBCDC_receiveData(currentPos,rxCount,intfNum);
currentPos += rxCount;
return (currentPos - dataBuf);
}
}
return (currentPos - dataBuf);
}

Figure 31. USBCDC_receiveDataInBuffer()
The function ignores the return from USBCDC_receiveData(), because it already knows the
answer will be USBCDC_RECEIVE_COMPLETED. It knows this because the bytes are already in
the USB endpoint buffer; it doesn’t matter of the bus has been disconnected, and none of the
other return codes are possible.

Programmer's Guide: MSP430 USB API v4.10

109

USBCDC_bytesInUSBBuffer() is called repeatedly, in case more data arrived while the first
data was retrieved. This situation could repeat indefinitely, so it continues to poll until
USBCDC_bytesInUSBBuffer() returns zero. This will happen when the stream of host data
stops.
The same commentary applies to USBHID_receiveDataInBufferr().

Programmer's Guide: MSP430 USB API v4.10

110

VOID main(VOID)
{
WDTCTL = WDTPW + WDTHOLD;
Init_System();
USB_setup();
while(1)
{
switch(USB_getConnectionState())
{
case ST_ENUM_ACTIVE:
if(!bDataReceived_event)
__bis_SR_register(LPM0_bits + GIE);

// Configure watchdog

// Enter LPM0

// CPU was awakened from LPM0
while(bDataReceived_event)
{
bDataReceived_event = FALSE;
BYTE count = USBCDC_receiveDataInBuffer(buffer,size,0); // Fetch contents of
buffer
process_the_data(buffer,count);
}
break;

// Process them

.
.
default:;
}
} // while(1)
} //main()
BYTE USBCDC_handleDataReceived(BYTE intfNum)
{
bDataReceived_event = TRUE;
// Signal that data has been received
return TRUE;
// Keep CPU awake after returning from event
}

Figure 32. Usage of USBCDC_receiveDataInBuffer()
USBxxx_handleDataReceived() is used to set a flag that data is available in the USB
endpoint buffers. The event handler returns TRUE to signal the CPU to remain awake. As a
result, execution proceeds from the LPM0 entry in main.
The flag is evaluated by a while() loop. This is because more data might be received during this
branch of code, which would need to be handled before entering LPM0 again. It’s for this same
reason that the flag is immediately cleared before fetching the data. If
USBxxx_receiveDataInBuffer() gets called and there are no bytes there, no harm is
done, so it’s better to call it more times than necessary than to miss data.
The application could have chosen to simply poll USBxxx_receiveDataInBuffer(), rather
than set a flag. The problem with this is that more data might be received while the last data is
being processed. For this same reason, the flag gets evaluated immediately before re-entering
LPM0.

Programmer's Guide: MSP430 USB API v4.10

111

This approach requires that the data be fetched from the USB buffer quickly. The endpoint
buffers only store 128 bytes, and if the host tries to send more data before the existing bytes
have been fetched, the device will begin NAKing the host (refusing to accept more data).
A good application of the USBxxx_receiveDataInBuffer() approach might be receiving
text entry from a terminal application on the host. The number of incoming bytes isn’t known,
but it will be small. Using this method, a few characters can be received at a time, and
accumulated into a longer string. This is demonstrated in several of the application examples
that accompany the API.

11.11.2

Continuously-Open Receive

This approach keeps an “open ear” at all times. A single call is made to
USBxxx_receiveData() immediately after enumeration, of a size larger than the amount of
expected data. The API automatically moves all received data to the user buffer as it’s received.
When the application wants to, it can go to the user buffer and process the data.
Unlike USBxxx_receiveDataInBuffer(), the application isn’t pressured to find a place for
the data when it comes in, since the API has “standing orders” to deposit the data into the user
buffer. The user buffer should be large enough that it won’t run out of space. When done, the
application can re-open another large operation, and the cycle continues.
This approach is therefore favorable to situations where the application isn’t able to respond
quickly.

Programmer's Guide: MSP430 USB API v4.10

112

VOID main(VOID)
{
WDTCTL = WDTPW + WDTHOLD;
Init_Ports();
Init_Clock();
USB_setup();
while(1)
{
switch(USB_getConnectionState())
{
case ST_ENUM_ACTIVE:
if
(!(USBCDC_getInterfaceStatus(1,&bytesTx,&bytesRx)&USBCDC_WAITING_FOR_RECEIVE))
BYTE ret = USBCDC_receiveData(RXBuffer,MEGA_SIZE,1);
.
.
USBCDC_getInterfaceStatus(1,&bytesTx,&bytesRx);
if(bytesRx > threshold)
{
abortReceive(bytesRx,1);
process_the_data(RXBuffer,bytesRx);
}
break;
.
.
default:;
}
}
}

Figure 33. Continuously-Open Receive
As the main loop executes, it checks to make sure a receive operation is open; if not, it opens
one. Separately, it polls to see if the amount of received data has reached a certain threshold.
If it has, then it processes it.

11.11.3 Fixed-Size Receive
If the amount of data to be received is known in advance, a receive operation for that exact
amount can be opened at any time. When that amount has been received, a
USBxxx_handleReceiveCompleted() event will occur. This event handler can process the
data directly, or set a flag for main() to process it.
Suppose a protocol is to be implemented in which all commands from the host consist of a twobyte command code and 32 bytes of payload data. Once received, the device is to execute the
command and respond with a two-byte acknowledge.
2
bytes

32 bytes

code

data

Figure 34. Command Packet

Programmer's Guide: MSP430 USB API v4.10

113

VOID main(VOID)
{
WDTCTL = WDTPW + WDTHOLD;
Init_System();
USB_setup();

// Configure watchdog

while(1)
{
switch(USB_getConnectionState())
{
case ST_ENUM_ACTIVE:
__disable_interrupt();
ret = USBCDC_receiveData(command,34,0);
if((ret == USBCDC_RECEIVE_STARTED) || (ret == USBCDC_INTERFACE_BUSY_ERROR))
__bis_SR_register(LPM0_bits + GIE);
__enable_interrupt();
// CPU was awakened from LPM0
if(bReceiveCompleted_event)
{
bReceiveCompleted_event = FALSE;
execute_the_command(command);
if(USBCDC_receiveData(command,34,1)==USBCDC_BUS_NOT_AVAILABLE) //Open new RX op
{
USBCDC_abortReceive(&x,1);
break;
}
}
.
.
default:;
}
} // while(1)
} //main()
BYTE USBCDC_handleReceiveCompleted(BYTE intfNum)
{
bReceiveCompleted_event = TRUE; // Signal that data has been received
return TRUE;
// Keep CPU awake after returning from event
}

Figure 35. Fixed-Size Receive
A receive operation is kept open at all times for 34 bytes. When fulfilled, the IF-branch clears
the flag, executes the command, and opens a new receive operation.
LPM0 is entered after beginning the receive operation, but only if the return value is
USBCDC_RECEIVE_STARTED or USBCDC_INTERFACE_BUSY_ERROR, both of which would
mean a receive operation is open and the application should wait in LPM0 for it to finish. If the
return were USBCDC_BUS_NOT_AVAILABLE, then it means the state is no longer
ST_ENUM_ACTIVE, and the main loop should be allowed to refresh.

Programmer's Guide: MSP430 USB API v4.10

114

Since it’s possible for a receive operation to be completed between the point that the function
assigns its return value and the point at which the value is evaluated in main(), and since the
consequences of that return value are high (going to sleep), interrupts are disabled first and reenabled simultaneous to entering LPM0. This way the receive operation can’t begin until LPM
has been entered.

11.12 Tips on Invoking BSL While USB is Active
Detailed information on BSL is documented in two TI-MSP430 documents:
 MSP430 Programming via the Bootstrap Loader (slau319)
 Creating a Custom Flash-Based BSL (slaa450)
This section discusses the steps to be taken to invoke BSL while USB is operating.
If the USB stack is active and the target device is in CDC, MSC or HID mode, the USB stack
should be disconnected first before BSL is invoked via software. BSL is invoked when the
program counter jumps to memory location 0x1000.
The following example shows the sequence of events using the USB APIs:

void invokeBSL(){
__disable_interrupt();
USB_disconnect ();

//PUR high, disable VBUS interrupt

USB_disable();

//Disable USB module, disable PLL

__delay_cycles(500000);

//Delay (if required)

((void (*)())0x1000)();

//Jump to 0x1000 to start of BSL.

}

Figure 36. Invoking BSL

Programmer's Guide: MSP430 USB API v4.10

115

12 Debugging Tips
12.1 The Device Enumeration Process
If a USB connection fails to operate as expected, a common first step is to determine whether
the USB device enumerated successfully on the host. Enumeration is the process by which the
host identifies the device and associates it with the appropriate driver. If enumeration did not
complete, then it’s important to understand how far it proceeded.

12.1.1 Summary of the Enumeration Process
Device is physically attached to host via USB
5V now sourced to device.
USB’s D+ signal is pulled high by the device. This tells the host that a
full-speed device has been attached.
Host sees D+ high and begins pulling the device’s USB descriptors.
These contain (among other things) the VID/PID & device class.
The host parses the descriptors and determines whether it has the
appropriate driver.
The algorithm for this is OS-specific, but it always involves the VID/PID and
device class.
If the host recognizes the VID/PID from a previous attachment, it may use
information recorded from that previous event.

Does the host have the
driver? (might involve asking
the user to locate them)

NO

Enumeration
fails

YES
Driver is loaded
The host may record information from this event for future use,
indexed by the VID/PID.
Enumeration was successful.
If the device contains an MSC interface, the host then mounts the
storage volume (LUNs) declared by that host.
USB communication can begin

Figure 37. Basic Enumeration Flow
Programmer's Guide: MSP430 USB API v4.10

116

Pulling the D+ signal high via a pullup resistor is how a full-speed USB device tells the host it’s
available for enumeration. On an MSP430, this pullup is normally driven by the PUR pin.
USB_connect() (perhaps via USB_setup()) activates the pullup; USB_disconnect() deactivates it.
The first time a device is attached, enumeration will probably take longer than subsequent
attachments. This is because the first attachment usually involves a “device installation”, in
which information about the device is recorded. (Windows does this in the system registry.)
Device installation can take several seconds, even on interfaces that install silently (HID/MSC).
On Windows, a message often is shown in the system tray, indicating that the device is “now
ready to use”.
Subsequent attachments may happen more quickly.

12.1.2 Determining Whether the Device Enumerated
Host operating systems provide ways to determine how far the enumeration process proceeded.
On Windows, the first attachment of a device may result in activity in the system tray. A CDC
interface, as discussed elsewhere, will result in an uninstalled device, until the user directs
Windows to the INF file. Both of these indicate that the host at least saw the presence of the
USB device. In turn, this means that the D+ signal was successfully pulled high.
If the enumeration process succeeds – that is, a driver is loaded -- Windows plays audible alert
tones. It can also be verified by checking the Windows Device Manager.
To open the Device Manager on a Windows PC, navigate to the Start Menu, select “Run…”,
enter “devmgmt.msc”, and press “Enter” or “OK”.

Figure 38. Starting the Windows Device Manager
If Windows asks if you want to allow the program to make changes to your computer, select
“Yes”; however, the Device Manager is very useful for viewing purposes, without having to
change anything.

Programmer's Guide: MSP430 USB API v4.10

117

Figure 39. The Windows Device Manager
Programmer's Guide: MSP430 USB API v4.10

118

Groups in the Device Manager that are relevant to MSP430 USB work include:
 Ports (for virtual COM ports)
 Human Interface Devices (for HID interfaces).
 Disk Drives (for any drives that have been mounted via an MSC interface)
 Universal Serial Bus controllers. (Hubs and MSC interfaces appear here, as do root entries
for composite USB devices.)
Whichever category it’s listed under, attaching or detaching should both cause a refresh action
in the display. Selecting “Properties” for the device can reveal the VID, PID, and serial number
for that device.
Other operating systems have similar ways of determining enumeration. For example, the Mac
OS provdies this in the “System Information” window.

12.1.3 Determining if the Device Asserted Itself to the Host
If the Device Manager doesn’t refresh itself upon inserting/detaching the device, it suggests the
host didn’t see the device asserting its presence (pulling D+ high via the PUR pin). This can be
confirmed with a voltmeter or oscilloscope on the PUR or D+ pins. PUR is supposed to be
pulled high when USB_connect() is called. It this isn’t happen, it could be a problem with
hardware (a short to ground), or perhaps software didn’t call this function as expected.

12.1.4 D+ Was Asserted, but Driver Association Failed
If the device was seen by the host, but enumeration didn’t complete successfully, then somehow
the OS failed to associate the device with the appropriate driver. Windows sometimes reacts to
this situation by showing a “yellow bang” on this device in the Device Manager, or another
negative result. This indicates the device was seen, but the driver was not loaded.

Figure 40. Failed Enumeration Results in the Device Manager

Programmer's Guide: MSP430 USB API v4.10

119

12.2 Common Problems
12.2.1 Problems that Can Cause USB Failure at Any Time
The following items are fundamental to USB operation. If any of these is violated, it can cause
failure at any time during operation.
First, always check the hardware against the reference schematic located in the application note
“Starting a USB Design with MSP430 MCUs”. Missing a critical schematic element will probably
cause USB failure very quickly after attempting enumeration.
Clocking is critical. If failure occurs at any time, double-check that an appropriate clock
frequency is available on XT2. It’s best not to probe on the XT2 oscillator directly; instead, send
XT2 to SMCLK or ACLK, activate the output pins for these clocks, and probe these output pins.
(See Sec. 11.2 for more information on configuring the clocks.)
Check to see if the MSP430 is experiencing any clock oscillator faults. Also check for a “bus
error” NMI, which generally indicates the PLL isn’t operating at an expected time (see Sec.
11.3).
Finally, the API can only do its job if it’s allowed to handle USB interrupts. If the application
prevents this somehow, then USB will fail. An application might disable general interrupts
directly, or it can do it indirectly by spending a lot of time in interrupt service routine handlers.
(See Sec. 11.6.)

12.2.2 Problems that Can Cause Failed Enumeration (Driver Association)
The API handles enumeration automatically, but it needs a proper environment in which to do
so.
First, double-check the items in the previous section, as these can cause problems in USB
communication at any time.
If none of the fundamental items is at fault (hardware, clocks, and power), then the problem may
be occuring at the level of USB descriptors and the host’s handling of them. One common
problem is that a record of the device’s VID/PID already exists on this host machine, but the
information on record is in conflict with this device’s USB descriptors. This is caused by using
the same VID/PID on this host machine earlier, but with a different USB descriptor set.
Therefore, when making changes in the interface set or certain descriptor fields, always either
delete the previous entry, or give it a new VID/PID pair. See Sec. 12.3.
Another possibility is that the descriptors themselves contain an error. If the Descriptor Tool was
used to generate the descriptors, then this shouldn’t occur. It can occur, however, f the Tool’s
output was manually modified. After fixing the error, be sure to either delete the device’s
previous entry, or give this descriptor set a new VID/PID. See Sec. 12.3..

Programmer's Guide: MSP430 USB API v4.10

120

12.3 Avoiding Device Conflicts on the Host During USB Development
As indicated above, when a USB device is enumerated for the first time, it undergoes a “device
installation”. The host records information from the device’s USB descriptors, indexed by the
device’s VID/PID. The next time this host machine encounters this VID/PID, it uses this
recorded information, rather than re-installing the device.
In the field, end users should never see a problem from this. There’s no reason for USB
descriptors for a given VID/PID to change, once a product is released.
During development, however, the USB descriptors may change as the developer modifies the
device toward the final goals. It’s therefore easy for the developer’s host machine to see
multiple descriptor sets for the same VID/PID. As a result, unless the developer remains
conscious of the possibility of conflicts, problems are likely to occur on this host machine.
Handling this is part of USB development.
One way to deal with this is to operate by this rule: if the descriptors change, increment the PID
to a new value. This ensures the host machine always sees the device as a new one. (Note
that the INF file used with CDC interfaces also contains a VID/PID pair, and so this must match
the one reported by the device in order to be recognized. The Descriptor Tool automatically
generates the INF file alongside the USB descriptors; so in short, the files generated at a given
time should be used together.)
Another approach, which doesn’t result in registry clutter, is to uninstall/install the device anytime
the descriptors are changed for a given VID/PID. This will usually force the OS to discard old
information and re-acquire it.
Before the USB device is released to end users, the final VID/PID should be determined. The
same applies to custom strings in the descriptors and the INF file. The Descriptor Tool can be
used for this purpose.

Programmer's Guide: MSP430 USB API v4.10

121

13 Using the API with RTOSes
Until now, the API has been shown as being called from a main loop, rather than with real time
operating systems (RTOS). A main loop approach is accessible to the entire range of MSP430
USB customers. It effectively demonstrates the API. It also avoids the fact that there are many
different RTOSes the developer may wish to use, and there’s no way to demonstrate all of them.
Further, many USB API applications don’t require an RTOS.
However, the USB API fully supports usage with RTOSes, including:
 TI’s SYS/BIOS
 Micrium’s uC/OS-II and III
 FreeRTOS
This section contains guidance for using the API with RTOSes. The application examples also
include two that demonstrate use with SYS/BIOS (examples #CHM2 and #CHM3).

13.1 General Design Considerations
When using the API with an RTOS, it’s often necessary to call RTOS API functions out of the
USB event handlers, for the reason of posting semaphores, sending messages to tasks etc.
However, the event handlers are called within an ISR context, and this may be a problem for
many RTOSes. Specific changes to the ISR are often required. In the case of the USB API, this
means the developer may need to directly modify the USB ISR in UsbIsr.c.
Because the API is not fully re-entrant, there is a restriction with respect to the relationship
between USB interfaces and tasks: a given USB interface should not be accessed by more than
one task; doing so could result in conflicts. The exception to this is a multi-LUN MSC interface,
where each LUN is allowed its own task, if desired.
If the USB device contains an MSC interface, then USBMSC_pollCommand() needs to be
called as part of the idle loop or task.

13.2 Using the USB API with TI’s SYS/BIOS
SYS/BIOS is an RTOS freely-available from TI. It supports a wide range of embedded
processors, including the MSP430. It provides a wide range of services, including:
 Pre-emptive multitasking
 Hardware abstraction
 Real-time analysis
 Memory management
 Configuration tools
SYS/BIOS is very scalable and can be configured to fit into memory-constrained MCUs. It’s
integrated into Code Composer Studio (CCS), making it very simple to create SYSBIOS projects
within CCS. All SYS/BIOS tools are integrated into CCS as Eclipse plugins. (For MSP430specific features and examples please visit the SYS/BIOS for MSP430 wiki page.)
Programmer's Guide: MSP430 USB API v4.10

122

This section discusses considerations for using the USB API with SYS/BIOS.

13.2.1 SYS/BIOS Thread Types: Hardware Interrupts (Hwi)
Hardware interrupt (Hwi) threads are essentially interrupt service routines (ISRs), and have the
highest priority in the RTOS. They can be triggered by device peripherals, or externally. When
an interrupt gets triggered, the CPU vectors into the ISR. As with all MSP430 interrupt handling,
interrupts are automatically disabled within the ISR; the ISR will run to completion.
SYS/BIOS contains a Hwi module that can be used to manage ISRs. Handling of the interrupt
vector is re-directed into the Hwi module, which then calls an application-defined function to
handle the interrupt. This abstraction makes it possible for the interrupt handler – now an
ordinary function – to call SYS/BIOS API functions. (If calling SYS/BIOS API functions isn’t
required, then the application may handle the ISR vector directly.)
With this in mind, in an application incorporating the USB API with SYS/BIOS, it’s often valuable
to make SYS/BIOS API calls within the USB event handlers. Since these handlers are called
within the USB ISR, the aforementioned abstraction is needed. The USB ISR function
iUsbInterruptHandler() needs to be made into an ordinary function, rather than a vector;
and this function needs to be registered with the Hwi module.
The Descriptor Tool aids this process. The Tool always generates the USB ISR function, in the
file UsbIsr.c. A checkbox in the Tool’s MSP430 view results in the USB ISR being declared as
an ordinary function.

Figure 41. SYS/BIOS Checkbox in the Descriptor Tool
The application then needs to register iUsbInterruptHandler() with the SYS/BIOS Hwi
module, using the following lines in the SYS/BIOS configuration script.
/* Create a Hwi Object and plug in the USB interrupt handler */
var hwi0Params = new Hwi.Params();
/* Have to make sure USB interrupt wakes up CPU */
hwi0Params.keepAwakeEnabled = true;
Program.global.hwi0 = Hwi.create(51, "&iUsbInterruptHandler", hwi0Params);

This enables the use of SYSBIOS API calls such as Semaphore_post(), Event_post(),
Swi_post() within the USB event handlers.
Programmer's Guide: MSP430 USB API v4.10

123

The USB API package provides two examples that use SYSBIOS: #CHM2 and #CHM3. See
the Examples Guide in the USB Developers Package for details.
Two other important configuration parameters for the Hwi module are given below. The first -Hwi.dispatcherAutoNestingSupport -- needs to be set to false, in order to prevent
interrupt nesting. (This is actually the default setting for MSP430, but worth double-checking, as
an incorrect setting could result in a stack overflow.)
The other configuration is that Hwi.fillVectors needs to be set to false. This is because
most applications have interrupts managed by the application, and the Hwi module should not
generate duplicate vectors.
/* Do not allow interrupts to nest */
Hwi.dispatcherAutoNestingSupport = false;
/* Do not automatically fill un-used vectors. */
Hwi.fillVectors = false;

13.2.2 SYS/BIOS Thread Types: Software Interrupts (Swi)
The Swi module in SYS/BIOS provides software interrupt (Swi) capability. Software interrupts
are patterned after hardware ones, but are scheduled by application software (using a
SYS/BIOS API call such as Swi_post()), rather than generated from a hardware-based
trigger. SYS/BIOS Swi threads have lower priority that Hwi threads, but higher priority than
tasks.
Swi threads can be assigned a relative priority; lower priority Swi threads are pre-empted by
higher priority Swi threads. The number of Swi priorities supported by SYS/BIOS is derived from
a configuration parameter for the Swi module. Swi’s are always pre-empted by Hwi threads.
Swi threads are suitable for handling application tasks that occur at slower rates, or are subject
to less severe real-time deadlines than those of Hwis.
When using SYS/BIOS with the USB API, use of Swi’s is optional. As discussed in Sec. 13.1, a
USB interface shouldn’t be handled by more than a single Swi thread.
The #CHM3 example demonstrates use of SYS/BIOS Swi threads.

13.2.3 Tasks (Task)
The Task module in SYS/BIOS provides tasking capability. Tasks have lower priority than either
hardware or software interrupts.
The Task module dynamically schedules and pre-empts tasks, based on the task’s priority level
and the task’s current execution state. This ensures that the CPU always executes the highestpriority available task. There’s a maximum of 32 priority levels available for tasks, configurable
by a parameter in the Task module.
The lowest priority level – “0” -- is reserved for running the idle loop. It cannot be used by the
application.
Programmer's Guide: MSP430 USB API v4.10

124

To enable switching between tasks, SYS/BIOS maintains a run-time stack for each Task thread.
On the MSP430, this task stack uses approximately 100 bytes.
When using SYS/BIOS with the USB API, the use of Tasks is optional. As discussed in Sec.
13.1, a USB interface shouldn’t be handled by more than a single task thread.
The USB API provides the #CHM2 example that using SYS/BIOS Tasks.

13.2.4 Idle Thread
The idle thread runs continuously in SYS/BIOS whenever no Hwi, Swi, or Task is running. Idle
functions are used to poll non-real-time devices that do not (or cannot) generate interrupts.
Idle functions all run at the same priority, sequentially, and in the same order in which they were
created. An idle function runs to completion, before the next idle function starts running. When
the last idle function has completed, the Idle Loop returns to executing the first idle function .
The idle thread can be used to contain all the USB functionality, in place of the main() function
shown in this Programmer’s Guide. This is demonstrated in the provided examples; the idle
thread contains the forever while loop which checks the USB connection state, and puts the
CPU into a low power mode whenever needed.
For applications using an MSC interface, the USBMSC_pollCommand() should be called from
the idle thread.

Programmer's Guide: MSP430 USB API v4.10

125

14 For More Information
Additional resources are shown below.
Note that the MSP430 method of organizating device information is to place architectural
information – which is common to an entire family – is located with the family user’s guide. Any
device-specific information, and parametric information, is placed within the datasheet. This
reduces the overall length of documentation, in an efficient manner.
General
USB Developers Package Download

API software, examples, tools, and documentation for
implementing USB on the MSP430. (Contains this
Programmer’s Guide.)

MSP430 landing page

General MSP430 information

MSP430 USB landing page

Information specific to doing USB on the MSP430

MSP430F5xx/6xx Family User’s Guide

Architectural information about all devices in the F5xx family
(including all the USB-equipped MSP430 derivatives).

Product Pages for USB-Equipped MSP430 Derivatives
Device-specific information for USB-equipped MSP430
derivatives (including datasheets).

MSP430F552x
MSP430F550x/5510
MSP430F563x
MSP430F663x
MSP430F565x
MSP430F665x

USB Specifications
USB 2.0 Specification

Specification for USB 2.0

Communications Device Class (CDC) Specifications

Specifications related to the Communications Device Class

Human Interface Device (HID) Class Specifications

Specifications related to the Human Interface Device class

Mass Storage Class (MSC) Specifications

Specifications related to the Mass Storage Class

Programmer's Guide: MSP430 USB API v4.10

126

Appendix A. Glossary
USB Definitions


USB-IF: The USB Implementers Forum. This is the standards body the defines USB
specifications, governs USB certification, runs compliance workshops, and owns the legal
rights to the USB logo.



USB Host: USB is hierarchial, with one (and only one) host that controls all communication.



USB Device: Also called a USB “function” or “peripheral”. This is a logical or physical entity
on the bus containing one or more USB interfaces. It possesses one upstream-capable USB
connector. The system being built with the MSP430 is the USB device.



USB Hub: A device that provides communication between one upstream connector and
multiple downstream connectors, allowing more USB devices to be attached to a host. In
any given bus configuration, a device is either a host, device, or hub.



Device Class: A defined USB protocol for a particular class of devices. Common device
classes include the Communications Device Class (CDC), Human Interface Device (HID)
class, and Mass Storage Class (MSC).



USB Interface: A logical USB entity that performs a particular function. An interface is
typically associated with a particular device class – for example, a “CDC interface”.



Composite USB Device: a physical USB device (one USB connector) that contains more
than one USB interface – for example, two CDC interfaces, or CDC+HID. The host
enumerates each interface as a separate logical entity.



USB Descriptors: Data structures contained within a physical USB device that describe the
device (including the interfaces it supports) and its capabilities. The host reads these during
enumeration.



Enumeration: The process by which a host interrogates a physical USB device to
determine what it is, and loads an appropriate driver so that the host application can
interface with it. Enumeration happens every time the device is attached.



Device Installation: The first time a USB device is enumerated, the host may perform onetime functions to “install” the device. For example, Windows records information about the
device in the system registry, using the device’s VID/PID as an index. In subsequent
enumerations, the host draws from the registry for much of its information about the device.
Device installation may be “silent” (mostly invisible to the end user), or in the case of CDC on
Windows, may require user action.



INF (*.inf) file: A text-based file required during any USB device installation on Windows,
allowing Windows to associate the device with a particular driver. For some device classes,
Windows contains the INF internally, allowing for a silent device installation. For CDC,
Windows prompts the end user for the INF file.



Vendor ID (VID): A unique 16-bit value assigned by the USB Implementers Forum to a
particular USB hardware vendor.

Programmer's Guide: MSP430 USB API v4.10

127



Product ID (PID): A unique 16-bit value assigned by a USB hardware vendor to one of its
products. A VID/PID pair uniquely identifies a product type. (As a rule of thumb, if the USB
descriptors of two products differ in any way, they should have different PIDs as well.)



USB Serial Number: A unique string that allows a host to differentiate between devices
attached to it that contain the same VID/PID values.



VBUS: The host is required to make 5V power available to the device via the USB cable.
The name of this power rail is VBUS. In addition to sourcing power, the USB device uses
VBUS to determine whether an active host is present. Devices often respond to a VBUS-on
event by asserting their presence to the host, by pulling up the D+ signal.



Pipe: A single line of communication between host and device. Pipes are either IN (into the
host) or OUT (out of the host). They are characterized by a particular transfer type (i.e., bulk
or interrupt).



Endpoint: The end of a pipe. It acts as a “mailbox” on the USB device for that pipe, and
USB transfers happen through the pipe, between the host’s endpoint and the device’s
endpoint. When the host communicates on the bus, it first identifies the physical USB
device, then the endpoint number within that device that it wishes to speak to. Endpoints are
assigned specific functions according to the USB interfaces that were created. HID/MSC
each use one IN and one OUT endpoint, while CDC uses two IN and one OUT endpoint. In
the MSP430 API stacks, endpoint management is fully automated by the Descriptor Tool.



Control Transfers: One of four data transfer types on the USB bus. Control transfers are
used for functions of USB management. Such transfers are called USB device requests:
commands from the host, and responses from the device. This takes place on the control
endpoint, which is always endpoint zero. Control transfers are used during USB
enumeration. Individual USB interfaces may also use them for control functions, but
generally send/receive data over the other endpoints, which are designated for
bulk/interrupt/isochronous transfers.



Bulk Transfers: One of four data transfer types on the USB bus. Bulk transfers are
designed for moving high volumes of data. They’re capable of using any free bandwidth on
the bus (that is, bandwidth not already used by the other transfer types). This allows them to
achieve the highest data rates; but they’re given no reserved bandwidth, so on a busy bus,
bulk transfers might receive small bandwidth or experience high latency. Transfer types are
fully determined by interface selection. For example, CDC and MSC interfaces use bulk
transfers.



Interrupt Transfers: Another of the four USB data transfer types. Interrupt transfers are
designed for guaranteed latency and bandwidth. However, the bandwidth is limited to only a
single USB packet (64 bytes for full-speed USB) per frame (1ms). This leads to a maximum
bandwidth of 64KB/sec. Transfer types are fully determined by interface selection. For
example, HID interfaces use interrupt transfers.



USB suspend: A low-power state imposed on USB devices by the host. When a USB
device has been suspended, the amount of power it’s allowed to draw from the host via the
VBUS line within the USB cable is restricted. A USB device detects the signal to suspend by

Programmer's Guide: MSP430 USB API v4.10

128

sensing 3ms of inactivity on the bus. (Typically the host sends a Start of Frame packet every
1ms, thus a suspend occurs when SOF packets are no longer sent.)


USB resume: After suspending a USB device, the host can later resume it to full operation.
A resume is, effectively, the resumption of Start of Frame packets. Once a resume has been
triggered, the device has 10ms to become fully operational.



VBUS: The power rail within a USB cable. Through VBUS, the host can supply power to
the USB device.



PUR: After a USB device has become physically connected to the host, it can logically
connect by pulling the D+ signal high (on full-speed devices) through a pullup resistor. The
MSP430 pulls this resistor high via the PUR pin, controlled by software.



USB speeds: A USB connection is characterized by one of four speeds: low-speed
(1.5Mbps), full-speed (12Mbps), high-speed (480Mbps), or super-speed (4.8Gbps). MSP430
is a USB 3.0 full-speed device.



HID report. In a HID USB interface, the host reads/writes reports. A report is smaller than a
USB packet (<64 bytes, in full-speed USB), and is organized according to a format defined
by a report descriptor during enumeration.

API Stack Definitions


API Stack: The USB API library provided by TI for the MSP430.



API Space: The actual API source files. The API space is generally meant to be left
unedited, although advanced users are free to change it, as needed.



Application Space: An application is needed, to make calls to the API. This application
exists in the application space. It is owned by the software developer. Technically speaking,
the application space includes the event handlers, since these must be written by the
software developer.



Events. The API keeps the handling of USB interrupts internal. Instead, the API generates
events. The software engineer can write handlers for events. Events function similarly to
callbacks.



HID-Datapipe Interface: HID interfaces in this API can either be datapipe or traditional.
Datapipe eases the creation of general-purpose applications over HID. Defining features
include use of a special, very simple report descriptor, and accessing the interface via the
HID-Datapipe function calls.



HID-Traditional Interface: This is any HID interface that isn’t HID-Datapipe (see above).
Mice, keyboards, and any HID interface with a custom report format are traditional HID
interfaces.



User Buffer: All data transfer with the API stack involves a user buffer as a point of mutual
exchange. It is defined by address and size parameters. It can be any contiguous block in
the MSP430 memory map, and it can be of any size. The term generally refers to any

Programmer's Guide: MSP430 USB API v4.10

129

interface other than HID-Traditional, where the primary unit of information interchange is the
HID report.


USB Endpoint Buffer: The actual USB endpoint, limited in size to 64 bytes. The
application does not access it directly, but rather the API stack exchanges data between the
endpoint buffer and the user buffer. It automatically packetizes/de-packetizes data in the
background, as the buffer is filled/emptied by the host.



Send/Receive Operation: When using a CDC interface or HID-Datapipe interface to move
data, all sending/receiving takes place in the context of an operation of a specific size.
Operations may be handled in the background while the application performs other tasks.
The operation is complete when all data has been moved between the endpoint buffer and
user buffer.

General Definitions


COM port: A software mechanism historically was associated with RS232 serial port
interfaces. As RS232 was replaced by USB, Bluetooth, and other interfaces, the software
mechanism was continued in form of a virtual COM port, implementing the same unformatted
UART-style communication over these other interfaces. The term COM port is specific to the
Windows group of operating systems; but the MacOS, Linux, and other operating systems
provide similar mechanisms. The term “COM port” is used throughout this document to refer
to all of them.

Programmer's Guide: MSP430 USB API v4.10

130



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.5
Linearized                      : No
Page Count                      : 130
Language                        : en-US
Tagged PDF                      : Yes
Title                           : App Note Template
Author                          : a0199742
Keywords                        : Version, 3.1
Creator                         : Microsoft® Word 2010
Create Date                     : 2017:03:23 15:49:11-05:00
Modify Date                     : 2017:03:23 15:49:11-05:00
Producer                        : Microsoft® Word 2010
EXIF Metadata provided by EXIF.tools

Navigation menu