Skip to content

Rework TinyUSB lib #80

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ee507d5
update tinyusb API changes
hathach May 5, 2021
6d9cbc9
clean up
hathach May 5, 2021
d61bc3c
major changes, move tinyusb source from core to this library
hathach May 6, 2021
4fda2f2
minor clean up
hathach May 6, 2021
003c5e0
add USE_TINYUSB guard
hathach May 6, 2021
a106cbc
move files to arduino sub folder, separate port api header
hathach May 6, 2021
7759332
improve port API with TinyUSB_Port_GetSerialNumber
hathach May 6, 2021
485b51a
fix typo
hathach May 6, 2021
cc7d439
tested working with nrf
hathach May 6, 2021
46b4133
rename file
hathach May 6, 2021
4bfd54a
improve device & cdc
hathach May 7, 2021
9e1402e
rename getInterfaceDescriptor()
hathach May 7, 2021
1723633
improve device begin
hathach May 7, 2021
8640830
support dropping Serial, add no_serial example
hathach May 7, 2021
4c6637a
use TUSB_OPT_DEVICE_ENABLED wihtin lib instead of USE_TINYUSB
hathach May 7, 2021
a1f94a0
clean up
hathach May 7, 2021
f2ef5db
rename to Adafruit_TinyUSB_PortAPI.h
hathach May 7, 2021
3287414
add rp2040 port
hathach May 7, 2021
2b16928
move files
hathach May 7, 2021
39068c4
move files around, updating API
hathach May 10, 2021
568f4a8
more rename
hathach May 10, 2021
49ac372
add TinyUSB_Device_Task() to API
hathach May 10, 2021
d80d579
add TinyUSB_Device_FlushCDC
hathach May 10, 2021
18ea164
update port for rp2040
hathach May 10, 2021
8f58b13
readme update
hathach May 10, 2021
a4a9303
fix typo
hathach May 10, 2021
9675803
change port TinyUSB_Port_InitDevice() to also call tusb_init() for fl…
hathach May 17, 2021
124763e
update TinyUSB_Port_InitDevice for nrf
hathach May 17, 2021
779dc3f
update rp2040 port
hathach May 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/githubci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ jobs:
uses: actions/setup-python@v1
with:
python-version: '3.x'

- name: Checkout code
uses: actions/checkout@v2

- name: Checkout adafruit/ci-arduino
uses: actions/checkout@v2
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/examples/**/build/
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,44 @@

[![Build Status](https://github.com/adafruit/Adafruit_TinyUSB_Arduino/workflows/Build/badge.svg)](https://github.com/adafruit/Adafruit_TinyUSB_Arduino/actions) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)

This library works with platform that includes [TinyUSB stack](https://github.com/hathach/tinyusb), typically you will see **Adafruit_TinyUSB_Core** inside core folder. Supported platform are:
This library is a Arduino-friendly version of [TinyUSB](https://github.com/hathach/tinyusb) stack. It is designed with structure and APIs that are easily integrated to existing or new Arduino Core. Supported platform including:

- [Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino)
- [Adafruit ArduinoCore-samd](https://github.com/adafruit/ArduinoCore-samd) **TinyUSB** must be selected in menu `Tools->USB Stack`

In addition to CDC that provided by the platform core, this library provide platform-independent for
Current class drivers supported are

- Communication (CDC): which is used to implement `Serial` monitor
- 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

For supported ArduinoCore, to use this library, you only need to have `<Adafruit_TinyUSB.h>` in your sketch. If your ArduinoCore does not support TinyUSB library yet, it is rather simple to port.

## Class Driver API

More document to write ...

## Porting Guide

It is rather easy if you want to integrate TinyUSB lib to your ArduinoCore.

### ArduinoCore Changes

1. Add this repo as submodule (or have local copy) at your ArduioCore/libraries/Adafruit_TinyUSB_Arduino (much like SPI).
2. 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.txt` include path need to have `"-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"`.
3. In your `main.cpp` before 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.
4. `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()
5. `TinyUSB_Device_FlushCDC()` should also be called often to send out Serial data as well.
6. 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 https://github.com/adafruit/circuitpython/pull/2956

### Library Changes

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

1. `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.
2. `TinyUSB_Port_EnterDFU()` which is called when device need to enter DFU mode, usually by touch1200 feature
3. `TinyUSB_Port_GetSerialNumber()` which is called to get unique MCU Serial ID to used as Serial string descriptor.
36 changes: 36 additions & 0 deletions examples/CDC/no_serial/no_serial.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
Copyright (c) 2019 Ha Thach for Adafruit Industries
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/

#include "Adafruit_TinyUSB.h"

/* This sketch demonstrates USB CDC Serial can be dropped by simply
* call Serial.end() within setup(). This must be called before any
* other USB interfaces (MSC / HID) begin to have a clean configuration
*
* Note: this will cause device to loose the touch1200 and require
* user manual interaction to put device into bootloader/DFU mode.
*/

int led = LED_BUILTIN;

void setup()
{
Serial.end();
pinMode(led, OUTPUT);
}

void loop()
{
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}
26 changes: 19 additions & 7 deletions examples/Composite/mouse_external_flash/mouse_external_flash.ino
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,26 @@
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"

#if defined(__SAMD51__) || defined(NRF52840_XXAA)
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
// Uncomment to run example with FRAM
// #define FRAM_CS A5
// #define FRAM_SPI SPI

#if defined(FRAM_CS) && defined(FRAM_SPI)
Adafruit_FlashTransport_SPI flashTransport(FRAM_CS, FRAM_SPI);

#else
#if (SPI_INTERFACES_COUNT == 1)
Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
// On-board external flash (QSPI or SPI) macros should already
// defined in your board variant if supported
// - EXTERNAL_FLASH_USE_QSPI
// - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
#if defined(EXTERNAL_FLASH_USE_QSPI)
Adafruit_FlashTransport_QSPI flashTransport;

#elif defined(EXTERNAL_FLASH_USE_SPI)
Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);

#else
Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
#error No QSPI/SPI flash are defined on your board variant.h !
#endif
#endif

Expand Down Expand Up @@ -82,7 +95,7 @@ void setup()
usb_hid.begin();

Serial.begin(115200);
while ( !Serial ) delay(10); // wait for native usb
//while ( !Serial ) delay(10); // wait for native usb

Serial.println("Adafruit TinyUSB Mouse + Mass Storage (external flash) example");
}
Expand Down Expand Up @@ -143,4 +156,3 @@ void msc_flush_cb (void)
{
flash.syncBlocks();
}

8 changes: 4 additions & 4 deletions examples/Composite/mouse_ramdisk/mouse_ramdisk.ino
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ uint8_t const desc_hid_report[] =
Adafruit_USBD_HID usb_hid;
Adafruit_USBD_MSC usb_msc;

#if defined ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS
#if defined ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS || defined ARDUINO_NRF52840_CIRCUITPLAY
const int pin = 4; // Left Button
bool activeState = true;
#elif defined ARDUINO_NRF52840_FEATHER
const int pin = 7; // UserSw
#elif defined PIN_BUTTON1
const int pin = PIN_BUTTON1;
bool activeState = false;
#else
const int pin = 12;
Expand Down Expand Up @@ -128,4 +128,4 @@ int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
void msc_flush_cb (void)
{
// nothing to do
}
}
25 changes: 21 additions & 4 deletions src/Adafruit_TinyUSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,26 @@
#ifndef ADAFRUIT_TINYUSB_H_
#define ADAFRUIT_TINYUSB_H_

#include "Adafruit_USBD_HID.h"
#include "Adafruit_USBD_MIDI.h"
#include "Adafruit_USBD_MSC.h"
#include "Adafruit_USBD_WebUSB.h"
#include "tusb_option.h"

//#ifndef USE_TINYUSB
//#error TinyUSB is not selected, please select it in Tools->Menu->USB Stack
//#endif

#if TUSB_OPT_DEVICE_ENABLED

#include "arduino/Adafruit_USBD_Device.h"
#include "arduino/Adafruit_USBD_CDC.h"

#include "arduino/hid/Adafruit_USBD_HID.h"
#include "arduino/midi/Adafruit_USBD_MIDI.h"
#include "arduino/msc/Adafruit_USBD_MSC.h"
#include "arduino/webusb/Adafruit_USBD_WebUSB.h"

// Initialize device hardware, stack, also Serial as CDC
// Wrapper for USBDevice.begin(rhport)
void TinyUSB_Device_Init(uint8_t rhport);

#endif

#endif /* ADAFRUIT_TINYUSB_H_ */
30 changes: 28 additions & 2 deletions src/Adafruit_TinyUSB.cpp → src/arduino/Adafruit_TinyUSB_API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,37 @@
* THE SOFTWARE.
*/

#include "tusb_option.h"

#if TUSB_OPT_DEVICE_ENABLED

#include "Adafruit_TinyUSB.h"
#include "Arduino.h"

//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
extern "C"
{

void TinyUSB_Device_Init(uint8_t rhport)
{
USBDevice.begin(rhport);
}

// RP2040 has its own implementation since it needs mutex for dual core
#ifndef ARDUINO_ARCH_RP2040
void TinyUSB_Device_Task(void)
{
tud_task();
}
#endif

void TinyUSB_Device_FlushCDC(void)
{
// TODO multiple CDCs
tud_cdc_n_write_flush(0);
}

}

//------------- IMPLEMENTATION -------------//
#endif
72 changes: 72 additions & 0 deletions src/arduino/Adafruit_TinyUSB_API.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef ADAFRUIT_TINYUSB_API_H_
#define ADAFRUIT_TINYUSB_API_H_

#include <stdint.h>
#include <stdbool.h>

//--------------------------------------------------------------------+
// Core API
// Should be called by BSP Core to initialize, process task
// Weak function allow compile arduino core before linking with this library
//--------------------------------------------------------------------+
#ifdef __cplusplus
extern "C" {
#endif

// Called by core/sketch to initialize usb device hardware and stack
// This also initialize Serial as CDC device
void TinyUSB_Device_Init(uint8_t rhport) __attribute__((weak));

// Called by core/sketch to handle device event
void TinyUSB_Device_Task(void) __attribute__((weak));

// Called by core/sketch to flush write on CDC
void TinyUSB_Device_FlushCDC(void) __attribute__((weak));

#ifdef __cplusplus
}
#endif

//--------------------------------------------------------------------+
// Port API
// Must be implemented by each BSP core/platform
//--------------------------------------------------------------------+

// To enter/reboot to bootloader
// usually when host disconnects cdc at baud 1200 (touch 1200)
void TinyUSB_Port_EnterDFU(void);

// Init device hardware.
// Called by TinyUSB_Device_Init()
void TinyUSB_Port_InitDevice(uint8_t rhport);

// Get unique serial number, needed for Serial String Descriptor
// Fill serial_id (raw bytes) and return its length (limit to 16 bytes)
// Note: Serial descriptor can be overwritten by user API
uint8_t TinyUSB_Port_GetSerialNumber(uint8_t serial_id[16]);

#endif
Loading