Adafruit TinyUSB Library for Arduino
This library is a Arduino-friendly version of TinyUSB stack. It is designed with structure and APIs that are easily integrated to an Arduino Core.
Supported device class drivers are:
- Communication (CDC): which is used to implement
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
- Mass Storage Class (MSC): with multiple LUNs
- Musical Instrument Digital Interface (MIDI)
- WebUSB with vendor specific class
Host support is still work-in-progress but currently available with rp2040 core thanks to Pico-PIO-USB. Supported class driver are:
- Communication (CDC)
- MassStorage class
There are 2 type of supported cores: with and without built-in support for TinyUSB. Built-in support provide seamless integration but requires extra code added to core's source code. Unfortunately it is not always easy or possible to make those modification.
Cores with built-in support
Following core has TinyUSB as either the primary usb stack or selectable via menu
Tools->USB Stack. You only need to include
<Adafruit_TinyUSB.h> in your sketch to use.
ESP32 port relies on Espressif's esp32-hal-tinyusb.c for building usb descriptors which requires all descriptors must be specified in usb objects declaration i.e constructors. Therefore all descriptor-related fields must be part of object declaration and descriptor-related API have no effect afterwards for this port.
Cores without built-in support
Following is cores without built-in support
It is still possible to use TinyUSB but with some limits such as:
TinyUSB_Device_Init()need to be manually called in setup()
TinyUSB_Device_FlushCDC()may (or not) need to be manually called in loop()
SerialTinyUSBname instead of Serial for serial monitor
- And there could be more other issues, using on these cores should be considered as experimental
Class Driver API
More document to write ...
To integrate TinyUSB library to a Arduino core, you will need to make changes to the core for built-in support and library for porting the mcu/platform.
Arduino Core Changes
If possible, making changes to core will allow it to have built-in which make it almost transparent to user sketch
- Add this repo as submodule (or have local copy) at your ArduioCore/libraries/Adafruit_TinyUSB_Arduino (much like SPI).
- Since Serial as CDC is considered as part of the core, we need to have
#include "Adafruit_USBD_CDC.h"within your
Arduino.h. For this to work, your
platform.txtinclude path need to have
- In your
main.cppbefore setup() invoke the
TinyUSB_Device_Init(rhport). This will initialize usb device hardware and tinyusb stack and also include Serial as an instance of CDC class.
TinyUSB_Device_Task()must be called whenever there is new USB event. Depending on your core and MCU with or without RTOS. There are many ways to run the task. For example:
- Use USB IRQn to set flag then invoke function later on after exiting IRQ.
- Just invoke function after the loop(), within yield(), and delay()
TinyUSB_Device_FlushCDC()should also be called often to send out Serial data as well.
- Note: For low power platform that make use of WFI()/WFE(), extra care is required before mcu go into low power mode. Check out my PR to circuipython for reference adafruit/circuitpython#2956
In addition to core changes, library need to be ported to your platform. Don't worry, tinyusb stack has already done most of heavy-lifting. You only need to write a few APIs
TinyUSB_Port_InitDevice()hardware specific (clock, phy) to enable usb hardware then call tud_init(). This API is called as part of TinyUSB_Device_Init() invocation.
TinyUSB_Port_EnterDFU()which is called when device need to enter DFU mode, usually by touch1200 feature
TinyUSB_Port_GetSerialNumber()which is called to get unique MCU Serial ID to used as Serial string descriptor.