USB Stack User's Guide
USB Stack User's Guide
1 Overview Contents
This document provides the following:
1 Overview 1
• Detailed steps to compile the USB
examples, download a binary image, and 2 Build the USB examples in Kinetis SDK 2
2.1.1 Hardware
• TWR-K22F120M Tower System module
• (Optional) TWR-SER Tower System module and Elevator
• J-Link debugger (optional)
• USB cables
2.1.2 Software
• KSDK release package
• IAR Embedded Workbench for ARM® Version 7.5.0
• Keil µVision5 Integrated Development Environment Version 5.17, available for Kinetis ARM ®
Cortex®-M4 devices
• Kinetis Design Studio IDE v3.0.0
• Atollic® TrueSTUDIO® v5.4.0
• Makefiles support with GCC revision 4.9-2015-q3-update from ARM Embedded
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
2 Freescale Semiconductor
2.2 USB Code Structure
The USB code is located in the folder:
<install_dir>/middleware/usb_1.0.0
The USB folder includes the source code for stack and examples. Note that the version number of the usb
folder may vary.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 3
2.3 Compiling or Running the USB Stack and Examples
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
4 Freescale Semiconductor
2.3.2 Step-by-step guide for Keil µVision5
This section shows how to use Keil µVision5. Open Keil µVision5 as shown in this figure:
1. Open the workspace corresponding to different examples.
For example, the workspace file is located in
<install_dir>/boards/twrk22f120m/usb_examples/usb_host_hid_mouse/bm/mdk/host_hid
_mouse_bm.uvmpw.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 5
2. Select “File” and “Import” from the KDS IDE Eclipse menu.
3. Expand the General folder and select the “Existing Projects into Workspace”. Then, click
“Next”.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
6 Freescale Semiconductor
4. Point the KDS IDE to the host_hid_mouse_bm project in the K22, which is located in the
<install_dir>/boards/twrk22f120m/usb_examples/usb_host_hid_mouse/bm/kds. The import
projects directory selection window should resemble this figure.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 7
5. After importing, the window should like this.
6. Choose the appropriate build target: “Debug” or “Release” by left-clicking the arrow next to
the hammer icon as shown here.
7. If the project build does not begin after selecting the desired target, left-click the hammer icon
to start the build.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
8 Freescale Semiconductor
8. To check the debugger configurations, click the down arrow next to the green debug button
and select “Debug Configurations”.
9. After verifying that the debugger configurations are correct, click the “Debug” button.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 9
10. The application is downloaded to the target and automatically run to main():
11. Run the code by clicking the “Resume” button to start the application:
2. Select “File” and “Import” from the Atollic TrueSTUDIO IDE Eclipse menu.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
10 Freescale Semiconductor
3. Expand the General folder and select “Existing Projects into Workspace. Then, click the
“Next" button.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 11
4. Point the Atollic TrueSTUDIO IDE to the host_hid_mouse_bm project in the K22, which is
located in the <install_dir>/boards/twrk22f120m/usb_examples/usb_host_hid_mouse/bm/atl.
The import projects directory selection window should resemble this figure.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
12 Freescale Semiconductor
5. After importing, the window should like this.
6. Choose the appropriate build target: “Debug” or “Release” by left-clicking the build
configuration icon as shown here.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 13
Figure-16 Set build configuration
7. If the project build does not begin after selecting the desired target, left-click the build icon to
start the build.
9. After verifying that the debugger configurations are correct, click the “Debug” button.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
14 Freescale Semiconductor
Figure-19 Atollic TrueSTUDIO Debug configurations
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 15
10. The application is downloaded to the target and automatically run to main():
11. Run the code by clicking the “Resume” button to start the application:
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
16 Freescale Semiconductor
5. Add paths C:/MINGW/msys/1.0/bin;C:/MINGW/bin to the system environment. Note that, if
the GCC ARM Embedded tool chain was installed somewhere other than the recommended
location, the system paths added should reflect this change. An example using the
recommended installation locations are shown below.
NOTE
There is a high chance that, if the paths are not set correctly, the tool chain
will not work properly.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 17
2.3.5.4 Add new system environment variable ARMGCC_DIR
Create a new system environment variable ARMGCC_DIR. The value of this variable should be the short name of
the ARM GCC Embedded tool chain installation path.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
18 Freescale Semiconductor
2.3.5.5 Install CMake
1. Download CMake 3.0.1 from www.cmake.org/cmake/resources/software.html.
2. Install Cmake 3.0.1 and ensure that the option "Add CMake to system PATH" is selected.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 19
Figure 27: USB host demo built successfully
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
20 Freescale Semiconductor
Figure 28: SEGGER J-Link GDB Server configuration
Note
The target device selection should be MK22FN512xxx12. The target
interface should be SWD.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 21
3. After connected, the screen should resemble this figure:
Figure 29: SEGGER J-Link GDB Server screen after successful connection
Note
The CPU selection should be CPU to: MK22FN512xxx12.
4. Open the ARM GCC command prompt and change the directory to the output directory of the
desired demo. For this example, the directory is:
<install_dir>/boards/twrk22f120m/usb_examples/usb_host_hid_mouse/bm/armgcc/debug.
5. Run the command “arm-none-eabi-gdb.exe <DEMO_NAME>.elf”. Run these commands:
• “target remote localhost: 2331”
• “monitor reset”
• “monitor halt”
• “load”
• “monitor reset”
6. The application is downloaded and connected. Execute the “monitor go” command to start the
demo application.
7. See the example-specific document for more test information.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
22 Freescale Semiconductor
2.4 USB Stack Configuration
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 23
3 Porting to a new platform
To port the USB stack to a new platform in the SDK, the SoC-related files, board-related files, and a linker
file for a specified compiler are required.
Assume that the new platform’s name is “xxxk22f120m” based on the MK22F51212 SoC.
Note
Different toolchains’ linker files are in the linker directory.
Different toolchains’ SoC startup assembler files are in the arm, gcc, and iar
directories.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
24 Freescale Semiconductor
Figure 31 Clock configuration files
The user can update the MACROs according to the board design. For example, if the XTAL0 crystal
oscillator is 16000000U and the XTAL32K is 32768U, change the above MACROs as follows:
#define BOARD_XTAL0_CLK_HZ 16000000U
#define BOARD_XTAL32K_CLK_HZ 32768U
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 25
4. Copy board.c and board.h from the similar platform, for example, TWR-K22F120M platform.
Ensure that the BOARD_InitDebugConsole is implemented in board.c file and that the
BOARD_InitHardware calls the function. The BOARD_InitHardware function is introduced later.
Update the MACROs according to the board design. For example, the default UART instance on the
board is LPUART1, the type of default UART instance on one specific platform is LPUART, and the
LPUART clock source is the external clock. In this case, change the above MACROs as follows:
#define BOARD_DEBUG_UART_TYPE DEBUG_CONSOLE_DEVICE_TYPE_LPUART
#define BOARD_DEBUG_UART_BASEADDR (uint32_t) LPUART1
#define BOARD_DEBUG_UART_CLKSRC kCLOCK_Osc0ErClk
#define BOARD_DEBUG_UART_BAUDRATE 115200
Note that there are three kinds of UART instances provided in Kinetis devices, UART, LPUART and
LPSCI. The interfaces of the UART instance are different. To provide a uniform UART interface to
an USB Host example in which the UART function is used, a UART instance wrapper is provided.
The wrapper is implemented in the usb_uart_drv.c, usb_lpuart_drv.c, or usb_lpsci_drv.c file and has
a common header file usb_uart_drv.h. For a different UART instance, use the corresponding UART
instance wrapper file in the project.
Copy the existed example’s whole directory from the similar platform, which ensures that all example
source files and project files are copied.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
26 Freescale Semiconductor
For example:
Copy the twrk22f120m/usb/usb_device_audio_generator_lite to the twrkxx/usb location, which ensures
that sources files and project files for usb_device_audio_generator_lite example are copied.
Ensure that the BOARD_InitPins function is implemented in the pin_mux.c file. In this function, the
port clock and pin mux are initialized. Ensure that the BOARD_InitHardware calls the function. The
BOARD_InitHardware function will be introduced later.
For example, on the TWR-K65F180M board, the VBUS of the USB Host is controlled by the
PORTD_8 as a GPIO. Therefore, the PORTD clock needs to be enabled first and then the PORTD_8
configured to GPIO functionality. The debug console uses UART2. The TX/RX pins are PORTE_16
and PORTE_17. As a result, the clock of PORTE needs to be enabled first and then the PORTE_16
and PORTE_17 configured to alternative 3.
This is an example code for TWR-K65F180M:
void BOARD_InitPins(void)
{
/* Initialize UART2 pins below */
CLOCK_EnableClock(kCLOCK_PortE);
PORT_SetPinMux(PORTE, 16u, kPORT_MuxAlt3);
PORT_SetPinMux(PORTE, 17u, kPORT_MuxAlt3);
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 27
/* Initialize usb vbus pin */
CLOCK_EnableClock(kCLOCK_PortD);
PORT_SetPinMux(PORTD, 8u, kPORT_MuxAsGpio);
}
Check the specific board design to find out which port is used to control the USB VBUS and which
port is used for debug console. For example, in the customer’s board design, the PORTC_15 is used to
control the USB VBUS and PORTD_1 and PORTD_2 is used for debug console. This is the example
code:
void BOARD_InitPins(void)
{
/* Initialize UART2 pins below */
CLOCK_EnableClock(kCLOCK_PortD);
CLOCK_EnableClock(kCLOCK_PortC);
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
28 Freescale Semiconductor
}
BOARD_InitPins();
BOARD_BootClockxxx();
BOARD_InitDebugConsole();
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 29
1. Check the project SoC and update to the porting platform SoC.
2. Update the SoC full name, platform name, and board type name macros if the SoC is updated.
For example, for TWR-K22F120M, update the CPU_MK22FN512VDC12,
TWR_K22F120M, and TOWER macros.
2. Check the files in startup group, for example (IAR):
Ensure that the fsl_clock_MK22F51212.c, and fsl_clock_MK22F51212.h are porting SoC files.
Additionally, change the include path.
4. Change the files in board group, for example (IAR):
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
30 Freescale Semiconductor
Figure 38 Change files in board group
Ensure that board.c, board.h, clock_config.c, and clock_config.h are porting platform files.
Additionally, change the include path.
5. Check the files in the sources group, for example (IAR):
The example application source files are copied when copying the example directory.
Change the include path.
6. Change the linker file to the new platform. Ensure that the linker file is the porting SoC file.
7. Debug console may use UART, LPUART, or LPSCI according to the platform. As a result, the
example project needs to contain UART, LPUART, or LPSCI driver files according to the
platform.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 31
Figure 40 UART, LPUART, and LPSCI files
Update MACROs according to board design. For example, the default UART instance on the board is
LPUART1, the type of default UART instance on one specific platform is LPUART, and the LPUART
clock source is the external clock. In this case, change the above MACROs as follows:
#define BOARD_DEBUG_UART_TYPE DEBUG_CONSOLE_DEVICE_TYPE_LPUART
#define BOARD_DEBUG_UART_BASEADDR (uint32_t) LPUART1
#define BOARD_DEBUG_UART_CLKSRC kCLOCK_Osc0ErClk
#define BOARD_DEBUG_UART_BAUDRATE 115200
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
32 Freescale Semiconductor
3.3.5 USB device MSC SD card example
USB device MSC SD card example needs the SDHC driver support and SD card support. The example
works only if the platform supports both SD card and the SDHC. To enable this example using the same
code, the following MACROs are defined in the board.h file:
#define BOARD_SDHC_BASEADDR SDHC
#define BOARD_SDHC_CLKSRC kCLOCK_CoreSysClk
#define BOARD_SDHC_CD_GPIO_BASE GPIOB
#define BOARD_SDHC_CD_GPIO_PIN 20U
#define BOARD_SDHC_CD_PORT_BASE PORTB
#define BOARD_SDHC_CD_PORT_IRQ PORTB_IRQn
#define BOARD_SDHC_CD_PORT_IRQ_HANDLER PORTB_IRQHandler
Update the MACROs according to the board design. For example, the SD card detection GPIO on the
board is PORTD_1. In this case, change the above MACROs as follows:
#define BOARD_SDHC_BASEADDR SDHC
#define BOARD_SDHC_CLKSRC kCLOCK_CoreSysClk
#define BOARD_SDHC_CD_GPIO_BASE GPIOD
#define BOARD_SDHC_CD_GPIO_PIN 1U
#define BOARD_SDHC_CD_PORT_BASE PORTD
#define BOARD_SDHC_CD_PORT_IRQ PORTD_IRQn
#define BOARD_SDHC_CD_PORT_IRQ_HANDLER PORTD_IRQHandler
Update the MACROs according to board design. For example, the I2S instance on the board is I2S2. In
this case, change the above MACROs as follows:
#define DEMO_SAI I2S2
#define DEMO_I2C I2C2
#define DEMO_SAI_CLKSRC kCLOCK_CoreSysClk
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 33
4 Developing a New USB Application
Receive Data This API is used by the application to receive data from the host system.
Send Data This API is used by the application to send data to the host system.
USB Device call Handles the callback by the class driver to inform the application about
back function various USB bus events.
2. Copy the following files from the similar existing applications to the application directory that is
created in Step 1.
usb_device_descriptor.c
usb_device_descriptor.h
The usb_device_descriptor.c and usb_device_descriptor.h files contain the USB descriptors that
are dependent on the application and the class driver.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
34 Freescale Semiconductor
3. Copy the bm directory from the similar existing application directory to the new application directory.
Remove the unused project directory from the bm directory. Modify the project directory name to the
new application project name. For example, to create toolchain-IAR, board-frdmk64 class-hid
related application, create the new application hid_test based on a similar existing application
hid_mouse.
Change <install_dir>/boards/<board>/usb_examples/usb_device_hid_mouse
to <install_dir>/boards/<board>/usb_examples/usb_device_hid_test
4. Modify the project file name to the new application project file name, for example, from
dev_hid_mouse_bm.ewp to dev_hid_test_bm.ewp. Globally replace the existing name to the new project
name by editing the project files. The dev_hid_test_bm.ewp file includes the new application project
setting.
5. Create a new source file to implement the main application functions and callback functions. The
name of this file is similar to the new application name, such as mouse.c and keyboard.c.
The following sections describe the steps to change application files created in the steps above to match
the new application.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 35
Figure 41 Relationship diagram
This is the sample code implementation of the endpoint descriptor for the HID class:
/* HID mouse endpoint information */
usb_device_endpoint_struct_t
g_UsbDeviceHidMouseEndpoints[USB_HID_MOUSE_ENDPOINT_COUNT] =
{
/* HID mouse interrupt IN pipe */
{
USB_HID_MOUSE_ENDPOINT_IN | (USB_IN <<
USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
USB_ENDPOINT_INTERRUPT,
FS_HID_MOUSE_INTERRUPT_IN_PACKET_SIZE,
},
};
The endpoint address, transfer type, and max packet size in this variable are defined
in the usb_device_descriptor.h file. The user may change these value as required. For
example, to implement a CDC class application:
/* Define endpoint for a communication class */
usb_device_endpoint_struct_t
g_UsbDeviceCdcVcomCicEndpoints[USB_CDC_VCOM_ENDPOINT_CIC_COUNT] = {
{
USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT | (USB_IN << 7U), USB_ENDPOINT_INTERRUPT,
FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE,
},
};
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
36 Freescale Semiconductor
{
0U, /* The alternate setting for the interface */
{
USB_HID_MOUSE_ENDPOINT_COUNT, /* Endpoint count */
g_UsbDeviceHidMouseEndpoints, /* Endpoints handle */
},
}
};
The endpoint count and alternate setting of the interface may differ in various
applications. User may change these values as required. For example, the interface
structure of a CDC class application is as follows:
/* Define interface for communication class */
usb_device_interface_struct_t g_UsbDeviceCdcVcomCommunicationInterface[] = {{
1U,
{
USB_CDC_VCOM_ENDPOINT_CIC_COUNT, g_UsbDeviceCdcVcomCicEndpoints,
},
}};
usb_device_interfaces_struct_t
g_UsbDeviceHidMouseInterfaces[USB_HID_MOUSE_INTERFACE_COUNT] =
{
USB_HID_MOUSE_CLASS, /* HID mouse class code */
USB_HID_MOUSE_SUBCLASS, /* HID mouse subclass code */
USB_HID_MOUSE_PROTOCOL, /* HID mouse protocol code */
USB_HID_MOUSE_INTERFACE_INDEX, /* The interface number of the HID mouse */
g_UsbDeviceHidMouseInterface, /* Interfaces handle */
sizeof(g_UsbDeviceHidMouseInterface) / sizeof(usb_device_interfaces_struct_t),
};
The class code, subclass code, and protocol code may differ in various classes. For
example, the usb_device_interfaces_struct of a CDC class is as follows:
/* Define interfaces for the virtual com */
usb_device_interfaces_struct_t
g_UsbDeviceCdcVcomInterfaces[USB_CDC_VCOM_INTERFACE_COUNT] = {
{USB_CDC_VCOM_CIC_CLASS, USB_CDC_VCOM_CIC_SUBCLASS, USB_CDC_VCOM_CIC_PROTOCOL,
USB_CDC_VCOM_COMM_INTERFACE_INDEX,
g_UsbDeviceCdcVcomCommunicationInterface,
sizeof(g_UsbDeviceCdcVcomCommunicationInterface) /
sizeof(usb_device_interfaces_struct_t)},
{USB_CDC_VCOM_DIC_CLASS, USB_CDC_VCOM_DIC_SUBCLASS, USB_CDC_VCOM_DIC_PROTOCOL,
USB_CDC_VCOM_DATA_INTERFACE_INDEX,
g_UsbDeviceCdcVcomDataInterface, sizeof(g_UsbDeviceCdcVcomDataInterface) /
sizeof(usb_device_interfaces_struct_t)},
};
usb_device_interface_list_t
g_UsbDeviceHidMouseInterfaceList[USB_DEVICE_CONFIGURATION_COUNT] =
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 37
{
{
USB_HID_MOUSE_INTERFACE_COUNT, /* The interface count of the HID mouse */
g_UsbDeviceHidMouseInterfaces, /* The interfaces handle */
},
};
The interface count may differ in various applications. For example, the
usb_device_interface_list of a CDC class application is as follows:
/* Define configurations for virtual com */
usb_device_interface_list_t
g_UsbDeviceCdcVcomInterfaceList[USB_DEVICE_CONFIGURATION_COUNT] = {
{
USB_CDC_VCOM_INTERFACE_COUNT, g_UsbDeviceCdcVcomInterfaces,
},
};
usb_device_class_struct_t g_UsbDeviceHidMouseConfig =
{
g_UsbDeviceHidMouseInterfaceList, /* The interface list of the HID mouse */
kUSB_DeviceClassTypeHid, /* The HID class type */
USB_DEVICE_CONFIGURATION_COUNT, /* The configuration count */
};
The interface list, class type and configuration count may differ in various applications. For
example, the usb_device_class_struct of a CDC class application is as follows:
/* Define class information for virtual com */
usb_device_class_struct_t g_UsbDeviceCdcVcomConfig = {
g_UsbDeviceCdcVcomInterfaceList, kUSB_DeviceClassTypeCdc,
USB_DEVICE_CONFIGURATION_COUNT,
};
• g_UsbDeviceDescriptor
This variable contains the USB Device Descriptor.
Sample code implementation of the device descriptor for the HID class is given below:
uint8_t g_UsbDeviceDescriptor[USB_DESCRIPTOR_LENGTH_DEVICE] =
{
USB_DESCRIPTOR_LENGTH_DEVICE, /* Size of this descriptor in bytes */
USB_DESCRIPTOR_TYPE_DEVICE, /* DEVICE Descriptor Type */
USB_SHORT_GET_LOW(USB_DEVICE_SPECIFIC_BCD_VERSION),
USB_SHORT_GET_HIGH(USB_DEVICE_SPECIFIC_BCD_VERSION),/* USB Specification
Release Number in
Binary-Coded Decimal
(i.e., 2.10 is 210H). */
USB_DEVICE_CLASS, /* Class code (assigned by the USB-IF). */
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
38 Freescale Semiconductor
USB_DEVICE_SUBCLASS, /* Subclass code (assigned by the USB-IF). */
USB_DEVICE_PROTOCOL, /* Protocol code (assigned by the USB-IF). */
USB_CONTROL_MAX_PACKET_SIZE, /* Maximum packet size for endpoint zero
(only 8, 16, 32, or 64 are valid) */
0xA2U, 0x15U, /* Vendor ID (assigned by the USB-IF) */
0x7CU, 0x00U, /* Product ID (assigned by the manufacturer) */
USB_SHORT_GET_LOW(USB_DEVICE_DEMO_BCD_VERSION),
USB_SHORT_GET_HIGH(USB_DEVICE_DEMO_BCD_VERSION),/* Device release number in
binary-coded decimal */
0x01U, /* Index of string descriptor describing manufacturer
*/
0x02U, /* Index of string descriptor describing product
*/
0x00U, /* Index of string descriptor describing the
device serial number */
USB_DEVICE_CONFIGURATION_COUNT, /* Number of possible configurations */
};
The macros in the variable above are defined in the usb_device_descriptor.h file, such as the
USB_DEVICE_CLASS, USB_DEVICE_SUBCLASS, and USB_DEVICE_PROTOCOL. Those
values may need to be modified as required. The vendor ID and product ID can also be modified.
• g_UsbDeviceConfigurationDescriptor
This variable contains the USB Configuration Descriptor.
Sample code implementation of the configuration descriptor for the HID class is given below:
uint8_t
g_UsbDeviceConfigurationDescriptor[USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL] =
{
USB_DESCRIPTOR_LENGTH_CONFIGURE, /* Size of this descriptor in bytes */
USB_DESCRIPTOR_TYPE_CONFIGURE, /* CONFIGURATION Descriptor Type */
USB_SHORT_GET_LOW(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL),
USB_SHORT_GET_HIGH(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL),/* Total length of
data returned for this configuration. */
USB_HID_MOUSE_INTERFACE_COUNT, /* Number of interfaces supported by this
configuration */
USB_HID_MOUSE_CONFIGURE_INDEX, /* Value to use as an argument to the
SetConfiguration() request to select this
configuration */
0x00U, /* Index of string descriptor describing this
configuration */
(USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_MASK) |
(USB_DEVICE_CONFIG_SELF_POWER <<
USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_SHIFT) |
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 39
(USB_DEVICE_CONFIG_REMOTE_WAKEUP <<
USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_SHIFT),
/* Configuration characteristics
D7: Reserved (set to one)
D6: Self-powered
D5: Remote Wakeup
D4...0: Reserved (reset to zero)
*/
USB_DEVICE_MAX_POWER, /* Maximum power consumption of the USB
* device from the bus in this specific
* configuration when the device is fully
* operational. Expressed in 2 mA units
* (i.e., 50 = 100 mA).
*/
The macro USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL, which is defined in the
usb_device_descriptor.h, needs to be modified to equal the size of this variable. The
interface count and configuration index may differ in various applications. For
example, this part of a CDC class application is as shown below:
/* Size of this descriptor in bytes */
USB_DESCRIPTOR_LENGTH_CONFIGURE,
/* CONFIGURATION Descriptor Type */
USB_DESCRIPTOR_TYPE_CONFIGURE,
/* Total length of data returned for this configuration. */
USB_SHORT_GET_LOW(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL),
USB_SHORT_GET_HIGH(USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL),
/* Number of interfaces supported by this configuration */
USB_CDC_VCOM_INTERFACE_COUNT,
/* Value to use as an argument to the SetConfiguration() request to select this
configuration */
USB_CDC_VCOM_CONFIGURE_INDEX,
/* Index of string descriptor describing this configuration */
0,
/* Configuration characteristics D7: Reserved (set to one) D6: Self-powered D5:
Remote Wakeup D4...0: Reserved
(reset to zero) */
(USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_D7_MASK) |
(USB_DEVICE_CONFIG_SELF_POWER <<
USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_SHIFT) |
(USB_DEVICE_CONFIG_REMOTE_WAKEUP <<
USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_SHIFT),
/* Maximum power consumption of the USB * device from the bus in this specific
* configuration when the device is
fully * operational. Expressed in 2 mA units * (i.e., 50 = 100 mA). */
USB_DEVICE_MAX_POWER,
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
40 Freescale Semiconductor
USB_DESCRIPTOR_TYPE_INTERFACE, /* INTERFACE Descriptor Type */
USB_HID_MOUSE_INTERFACE_INDEX, /* Number of this interface. */
0x00U, /* Value used to select this alternate setting
for the interface identified in the prior
field */
USB_HID_MOUSE_ENDPOINT_COUNT, /* Number of endpoints used by this
interface (excluding endpoint zero). */
USB_HID_MOUSE_CLASS, /* Class code (assigned by the USB-IF). */
USB_HID_MOUSE_SUBCLASS, /* Subclass code (assigned by the USB-IF). */
USB_HID_MOUSE_PROTOCOL, /* Protocol code (assigned by the USB). */
0x00U, /* Index of string descriptor describing this
interface */
The interface descriptor may differ from various applications. For example, the
interface descriptor of a CDC class application would be as below.
/* Communication Interface Descriptor */
USB_DESCRIPTOR_LENGTH_INTERFACE, USB_DESCRIPTOR_TYPE_INTERFACE,
USB_CDC_VCOM_COMM_INTERFACE_INDEX, 0x00,
USB_CDC_VCOM_ENDPOINT_CIC_COUNT, USB_CDC_VCOM_CIC_CLASS,
USB_CDC_VCOM_CIC_SUBCLASS, USB_CDC_VCOM_CIC_PROTOCOL,
0x00, /* Interface Description String Index*/
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 41
USB_DESCRIPTOR_TYPE_CDC_CS_INTERFACE, /* CS_INTERFACE Descriptor Type */
HEADER_FUNC_DESC, 0x10,
0x01, /* USB Class Definitions for Communications the Communication specification
version 1.10 */
}
• String Descriptors
Users can modify string descriptors to customize their product. String descriptors are written in the
UNICODE format. An appropriate language identification number is specified in the
USB_STR_0. Multiple language support can also be added.
• USB_DeviceGetDeviceDescriptor
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
42 Freescale Semiconductor
This interface function is invoked by the application. This call is made when the application
receives the kUSB_DeviceEventGetDeviceDescriptor event from the Host. Mandatory descriptors
that an application is required to implement are as follows:
o Device Descriptor
o Configuration Descriptor
o Class-Specific Descriptors (For example, for HID class implementation, Report
Descriptor, and HID Descriptor)
Apart from the mandatory descriptors, an application should also implement various string
descriptors as specified by the Device Descriptor and other configuration descriptors.
Sample code for HID class application is given below:
/* Get device descriptor request */
usb_status_t USB_DeviceGetDeviceDescriptor(usb_device_handle handle,
usb_device_get_device_descriptor_struct_t
*deviceDescriptor)
{
deviceDescriptor->buffer = g_UsbDeviceDescriptor;
deviceDescriptor->length = USB_DESCRIPTOR_LENGTH_DEVICE;
return kStatus_USB_Success;
}
User may assign the appropriate variable of the device descriptor. For example, if the device
descriptor variable name is g_UsbDeviceDescriptorUser, the sample code is as follows:
/* Get device descriptor request */
usb_status_t USB_DeviceGetDeviceDescriptor(usb_device_handle handle,
usb_device_get_device_descriptor_struct_t
*deviceDescriptor)
{
deviceDescriptor->buffer = g_UsbDeviceDescriptorUser;
deviceDescriptor->length = USB_DESCRIPTOR_LENGTH_DEVICE;
return kStatus_USB_Success;
• USB_DeviceGetConfigurationDescriptor
This interface function is invoked by the application. This call is made when the application receives
the kUSB_DeviceEventGetConfigurationDescriptor event from the Host.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 43
{
configurationDescriptor->buffer = g_UsbDeviceConfigurationDescriptor;
configurationDescriptor->length = USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL;
return kStatus_USB_Success;
}
return kStatus_USB_InvalidRequest;
}
The macro HID_MOUSE_CONFIGURE_INDEX may differ from various applications. For example, the
implementation of a CDC class application would be as below.
usb_status_t USB_DeviceGetConfigurationDescriptor(
usb_device_handle handle, usb_device_get_configuration_descriptor_struct_t
*configurationDescriptor)
{
if (USB_CDC_VCOM_CONFIGURE_INDEX > configurationDescriptor->configuration)
{
configurationDescriptor->buffer = g_UsbDeviceConfigurationDescriptor;
configurationDescriptor->length = USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL;
return kStatus_USB_Success;
}
return kStatus_USB_InvalidRequest;
}
• USB_DeviceGetStringDescriptor
This interface function is invoked by the application. This call is made when the application
receives the kUSB_DeviceEventGetStringDescriptor event from the Host.
See the usb_device_hid_mouse example for sample code.
• USB_DeviceGetHidReportDescriptor
This interface function is invoked by the application. This call is made when the application
receives the kUSB_DeviceEventGetHidReportDescriptor event from the Host.
See the usb_device_hid_mouse example for sample code.
• USB_DeviceSetSpeed
Because HS and FS descriptors are different, the device descriptors and configurations need to be
updated to match the current speed. By default, the device descriptors and configurations are
configured using FS parameters for both EHCI and KHCI. When the EHCI is enabled, the
application needs to call this function to update the device by using the current speed. The updated
information includes the endpoint max packet size, endpoint interval, and so on.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
44 Freescale Semiconductor
4.1.2.3 Changing the application file
1. Main application function
The main application function is provided by two functions: USB_DeviceApplicationInit and
APP_task(optional).
2. The USB_DeviceApplicationInit enables the clock and the USB interrupt and also initialize the
specific USB class. See the usb_device_hid_mouse example for the sample code.
3. USB device call back function
The device callback function handles the USB device-specific requests. See the
usb_device_hid_mouse example for the sample code.
4. USB Class-specific call back function
The class callback function handles the USB class-specific requests. See the
usb_device_hid_mouse example for the sample code.
4.2.1 Background
In the USB system, the host software controls the bus and talks to the target devices following the rules
defined by the specification. A device is represented by a configuration that is a collection of one or more
interfaces. Each interface comprises one or more endpoints. Each endpoint is represented as a logical pipe
from the application software perspective.
The host application software registers a callback with the USB host stack, which notifies the application
about the device attach/detach events and determines whether the device is supported or not. The
following figure shows the enumeration and detachment flow.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 45
Wait
event
Return
kStatus_USB_NotSupported
No
The configuration
DEVICE_ATTACH_EVENT
is supported
Yes
Save interface
handle and Return
kStatus_USB_Success
Class de-initialize
The USB host stack is a few lines of code executed before starting communication with the USB device.
The examples on the USB stack are written with class driver APIs. Class drivers work with the host API as
a supplement to the functionality. They make it easy to achieve the target functionality (see example
sources for details) without dealing with the implementation of standard routines. The following code
steps are taken inside a host application driver for any specific device.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
46 Freescale Semiconductor
2. Copy the following files from the similar existing applications to the application directory that is
created in step 1.
app.c
usb_host_config.h
The app.c file contains the common initialization code for USB host and the usb_host_config.h file
contains the configuration MACROs for the USB host.
3. Copy the bm directory from the similar existing application directory to the new application
directory. Remove the unused project directory from the bm directory. Modify the project directory
name to the new application project name. For example, to create toolchain-IAR, board-frdmk64
class-hid related application, create the new application hid_test based on a similar existing
application hid_mouse.
Copy <install_dir>/boards/frdmk64f/usb_examples/usb_host_hid_mouse/bm
to <install_dir>/boards/frdmk64f/usb_examples/usb_host_hid_test/bm
4. Modify the project file name to the new application project file name, for example, from
host_hid_mouse_bm.ewp to host_hid_test_bm.ewp. Globally replace the existing name to the new
project name by editing the project files. The host_hid_test_bm.ewp file includes the new application
project setting.
5. Create a new source file to implement the main application function, application task function, and the
callback function. The name of this file is similar to the new application name, such as host_mouse.c
and host_keyboard.c.
The following sections describe the steps to modify application files created in the steps above to match
the new application.
Create tasks
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 47
1. Initialize the USB clock.
Call KSDK API to initialize the KHCI or the EHCI USB clock.
2. Initialize the host controller.
This allows the stack to initialize the necessary memory required to run the stack and register the
callback function to the stack.
For example:
status = USB_HostInit(CONTROLLER_ID, &g_HostHandle, USB_HostEvent);
USB_HostKhciTaskFunction(g_HostHandle);
#endif /* USB_HOST_CONFIG_KHCI */
USB_HostEhciTaskFunction(g_HostHandle);
#endif /* USB_HOST_CONFIG_EHCI */
USB_HostMsdTask(&g_MsdCommandInstance);
Note that in this code, the g_MsdCommandInstance variable contains all states and pointers used
by the application to control or operate the device.
If implementing the application task as USB_HostHidTestTask and use g_HidTestInstance to
maintain the application states, modify the code as follows:
while (1)
USB_HostKhciTaskFunction(g_HostHandle);
#endif /* USB_HOST_CONFIG_KHCI */
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
48 Freescale Semiconductor
USB_HostEhciTaskFunction(g_HostHandle);
#endif /* USB_HOST_CONFIG_EHCI */
USB_HostHidTestTask(&g_HidTestInstance);
4. The Host stack checks the next device’s configuration if the current configuration is not supported by
the application.
5. When the Host stack checks all configurations and all are not supported by the application, it notifies
the kUSB_HostEventNotSupported.
6. When the device detaches, the Host stack notifies the kUSB_HostEventDetach.
This is the sample code for the HID mouse application. The USB_HostHidMouseEvent function should be
called by the USB_HostEvent. In this code, the g_HostHidMouse variable contains all states and pointers
used by the application to control or operate the device:
usb_status_t USB_HostHidMouseEvent
(
usb_device_handle deviceHandle,
usb_host_configuration_handle configurationHandle,
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 49
uint32_t eventCode
)
{
/* Process the same and supported device's configuration handle */
static usb_host_configuration_handle s_ConfigHandle = NULL;
usb_status_t status = kStatus_USB_Success;
uint8_t id;
usb_host_configuration_t *configuration;
uint8_t interfaceIndex;
usb_host_interface_t *interface;
switch (eventCode)
{
case kUSB_HostEventAttach:
/* judge whether is configurationHandle supported */
configuration = (usb_host_configuration_t *)configurationHandle;
for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount;
++interfaceIndex)
{
interface = &configuration->interfaceList[interfaceIndex];
id = interface->interfaceDesc->bInterfaceClass;
if (id != USB_HOST_HID_CLASS_CODE)
{
continue;
}
id = interface->interfaceDesc->bInterfaceSubClass;
if ((id != USB_HOST_HID_SUBCLASS_CODE_NONE) && (id !=
USB_HOST_HID_SUBCLASS_CODE_BOOT))
{
continue;
}
id = interface->interfaceDesc->bInterfaceProtocol;
if (id != USB_HOST_HID_PROTOCOL_MOUSE)
{
continue;
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
50 Freescale Semiconductor
}
else
{
/* the interface is supported by the application */
g_HostHidMouse.deviceHandle = deviceHandle;
g_HostHidMouse.interfaceHandle = interface;
s_ConfigHandle = configurationHandle;
return kStatus_USB_Success;
}
}
status = kStatus_USB_NotSupported;
break;
case kUSB_HostEventNotSupported:
break;
case kUSB_HostEventEnumerationDone:
if (s_ConfigHandle == configurationHandle)
{
if ((g_HostHidMouse.deviceHandle != NULL) &&
(g_HostHidMouse.interfaceHandle != NULL))
{
/* the device enumeration is done */
if (g_HostHidMouse.deviceState == kStatus_DEV_Idle)
{
g_HostHidMouse.deviceState = kStatus_DEV_Attached;
}
else
{
usb_echo("not idle mouse instance\r\n");
}
}
}
break;
case kUSB_HostEventDetach:
if (s_ConfigHandle == configurationHandle)
{
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 51
/* the device is detached */
s_ConfigHandle = NULL;
if (g_HostHidMouse.deviceState != kStatus_DEV_Idle)
{
g_HostHidMouse.deviceState = kStatus_DEV_Detached;
}
}
break;
default:
break;
}
return status;
}
switch (eventCode)
{
case kUSB_HostEventAttach:
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
52 Freescale Semiconductor
/* judge whether is configurationHandle supported */
configuration = (usb_host_configuration_t *)configurationHandle;
for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount;
++interfaceIndex)
{
interface = &configuration->interfaceList[interfaceIndex];
id = interface->interfaceDesc->bInterfaceClass;
if (id != USB_HOST_HID_TEST_CLASS_CODE)
{
continue;
}
id = interface->interfaceDesc->bInterfaceSubClass;
if (id != USB_HOST_HID_TEST_SUBCLASS_CODE)
{
continue;
}
id = interface->interfaceDesc->bInterfaceProtocol;
if (id != USB_HOST_HID_TEST_PROTOCOL)
{
continue;
}
else
{
/* the interface is supported by the application */
g_HidTestInstance.deviceHandle = deviceHandle;
g_HidTestInstance.interfaceHandle = interface;
s_ConfigHandle = configurationHandle;
return kStatus_USB_Success;
}
}
status = kStatus_USB_NotSupported;
break;
case kUSB_HostEventNotSupported:
break;
case kUSB_HostEventEnumerationDone:
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 53
if (s_ConfigHandle == configurationHandle)
{
if ((g_HidTestInstance.deviceHandle != NULL) &&
(g_HidTestInstance.interfaceHandle != NULL))
{
/* the device enumeration is done */
if (g_HidTestInstance.deviceState == kStatus_DEV_Idle)
{
g_HidTestInstance.deviceState = kStatus_DEV_Attached;
}
else
{
usb_echo("not idle mouse instance\r\n");
}
}
}
break;
case kUSB_HostEventDetach:
if (s_ConfigHandle == configurationHandle)
{
/* the device is detached */
s_ConfigHandle = NULL;
if (g_HidTestInstance.deviceState != kStatus_DEV_Idle)
{
g_HidTestInstance.deviceState = kStatus_DEV_Detached;
}
}
break;
default:
break;
}
return status;
}
Note that the kStatus_DEV_Attached, kStatus_DEV_Detached MACROs are defined in the example.
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
54 Freescale Semiconductor
4.2.2.4 Class initialization
When the supported device is attached, the device’s class needs to be initialized.
For example, the HID mouse initialization flow is as follows:
Initialize class
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
Freescale Semiconductor 55
5 Revision history
This table summarizes revisions to this document since the release of the previous version
Revision History
Revision number Date Substantive changes
Freescale KSDK USB Stack Porting New Platform User’s Guide, Rev. 1, 01/2016
56 Freescale Semiconductor
How to Reach Us: Information in this document is provided solely to enable system and software
implementers to use Freescale products. There are no express or implied copyright
Home Page:
licenses granted hereunder to design or fabricate any integrated circuits based on the
www.freescale.com information in this document.
Web Support: Freescale reserves the right to make changes without further notice to any products
www.freescale.com/support herein. Freescale makes no warranty, representation, or guarantee regarding the
suitability of its products for any particular purpose, nor does Freescale assume any
liability arising out of the application or use of any product or circuit, and specifically
disclaims any and all liability, including without limitation consequential or incidental
damages. “Typical” parameters that may be provided in Freescale data sheets and/or
specifications can and do vary in different applications, and actual performance may vary
over time. All operating parameters, including “typicals,” must be validated for each
customer application by customer’s technical experts. Freescale does not convey any
license under its patent rights nor the rights of others. Freescale sells products pursuant to
standard terms and conditions of sale, which can be found at the following address:
freescale.com/SalesTermsandConditions.
Freescale, Kinetis, and the Freescale logo are trademarks of Freescale Semiconductor,
Inc., Reg. U.S. Pat. & Tm. Off. All other product or service names are the property of their
respective owners.
©2016 Freescale Semiconductor, Inc.