Skip to content

Commit daeef23

Browse files
authored
Merge pull request adafruit#80 from adafruit/major-v1
Rework TinyUSB lib
2 parents 031c295 + 779dc3f commit daeef23

File tree

82 files changed

+26151
-106
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+26151
-106
lines changed

.github/workflows/githubci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ jobs:
4545
uses: actions/setup-python@v1
4646
with:
4747
python-version: '3.x'
48+
4849
- name: Checkout code
4950
uses: actions/checkout@v2
51+
5052
- name: Checkout adafruit/ci-arduino
5153
uses: actions/checkout@v2
5254
with:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/examples/**/build/

README.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,44 @@
22

33
[![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)
44

5-
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:
5+
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:
66

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

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

12+
- Communication (CDC): which is used to implement `Serial` monitor
1213
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
1314
- Mass Storage Class (MSC): with multiple LUNs
1415
- Musical Instrument Digital Interface (MIDI)
1516
- WebUSB with vendor specific class
1617

18+
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.
19+
20+
## Class Driver API
21+
1722
More document to write ...
23+
24+
## Porting Guide
25+
26+
It is rather easy if you want to integrate TinyUSB lib to your ArduinoCore.
27+
28+
### ArduinoCore Changes
29+
30+
1. Add this repo as submodule (or have local copy) at your ArduioCore/libraries/Adafruit_TinyUSB_Arduino (much like SPI).
31+
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"`.
32+
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.
33+
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:
34+
- Use USB IRQn to set flag then invoke function later on after exiting IRQ.
35+
- Just invoke function after the loop(), within yield(), and delay()
36+
5. `TinyUSB_Device_FlushCDC()` should also be called often to send out Serial data as well.
37+
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
38+
39+
### Library Changes
40+
41+
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
42+
43+
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.
44+
2. `TinyUSB_Port_EnterDFU()` which is called when device need to enter DFU mode, usually by touch1200 feature
45+
3. `TinyUSB_Port_GetSerialNumber()` which is called to get unique MCU Serial ID to used as Serial string descriptor.

examples/CDC/no_serial/no_serial.ino

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*********************************************************************
2+
Adafruit invests time and resources providing this open source code,
3+
please support Adafruit and open-source hardware by purchasing
4+
products from Adafruit!
5+
6+
MIT license, check LICENSE for more information
7+
Copyright (c) 2019 Ha Thach for Adafruit Industries
8+
All text above, and the splash screen below must be included in
9+
any redistribution
10+
*********************************************************************/
11+
12+
#include "Adafruit_TinyUSB.h"
13+
14+
/* This sketch demonstrates USB CDC Serial can be dropped by simply
15+
* call Serial.end() within setup(). This must be called before any
16+
* other USB interfaces (MSC / HID) begin to have a clean configuration
17+
*
18+
* Note: this will cause device to loose the touch1200 and require
19+
* user manual interaction to put device into bootloader/DFU mode.
20+
*/
21+
22+
int led = LED_BUILTIN;
23+
24+
void setup()
25+
{
26+
Serial.end();
27+
pinMode(led, OUTPUT);
28+
}
29+
30+
void loop()
31+
{
32+
digitalWrite(led, HIGH);
33+
delay(1000);
34+
digitalWrite(led, LOW);
35+
delay(1000);
36+
}

examples/Composite/mouse_external_flash/mouse_external_flash.ino

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,26 @@
1919
#include "Adafruit_SPIFlash.h"
2020
#include "Adafruit_TinyUSB.h"
2121

22-
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
23-
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
22+
// Uncomment to run example with FRAM
23+
// #define FRAM_CS A5
24+
// #define FRAM_SPI SPI
25+
26+
#if defined(FRAM_CS) && defined(FRAM_SPI)
27+
Adafruit_FlashTransport_SPI flashTransport(FRAM_CS, FRAM_SPI);
28+
2429
#else
25-
#if (SPI_INTERFACES_COUNT == 1)
26-
Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
30+
// On-board external flash (QSPI or SPI) macros should already
31+
// defined in your board variant if supported
32+
// - EXTERNAL_FLASH_USE_QSPI
33+
// - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
34+
#if defined(EXTERNAL_FLASH_USE_QSPI)
35+
Adafruit_FlashTransport_QSPI flashTransport;
36+
37+
#elif defined(EXTERNAL_FLASH_USE_SPI)
38+
Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);
39+
2740
#else
28-
Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
41+
#error No QSPI/SPI flash are defined on your board variant.h !
2942
#endif
3043
#endif
3144

@@ -82,7 +95,7 @@ void setup()
8295
usb_hid.begin();
8396

8497
Serial.begin(115200);
85-
while ( !Serial ) delay(10); // wait for native usb
98+
//while ( !Serial ) delay(10); // wait for native usb
8699

87100
Serial.println("Adafruit TinyUSB Mouse + Mass Storage (external flash) example");
88101
}
@@ -143,4 +156,3 @@ void msc_flush_cb (void)
143156
{
144157
flash.syncBlocks();
145158
}
146-

examples/Composite/mouse_ramdisk/mouse_ramdisk.ino

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ uint8_t const desc_hid_report[] =
3131
Adafruit_USBD_HID usb_hid;
3232
Adafruit_USBD_MSC usb_msc;
3333

34-
#if defined ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS
34+
#if defined ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS || defined ARDUINO_NRF52840_CIRCUITPLAY
3535
const int pin = 4; // Left Button
3636
bool activeState = true;
37-
#elif defined ARDUINO_NRF52840_FEATHER
38-
const int pin = 7; // UserSw
37+
#elif defined PIN_BUTTON1
38+
const int pin = PIN_BUTTON1;
3939
bool activeState = false;
4040
#else
4141
const int pin = 12;
@@ -128,4 +128,4 @@ int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
128128
void msc_flush_cb (void)
129129
{
130130
// nothing to do
131-
}
131+
}

src/Adafruit_TinyUSB.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,26 @@
2525
#ifndef ADAFRUIT_TINYUSB_H_
2626
#define ADAFRUIT_TINYUSB_H_
2727

28-
#include "Adafruit_USBD_HID.h"
29-
#include "Adafruit_USBD_MIDI.h"
30-
#include "Adafruit_USBD_MSC.h"
31-
#include "Adafruit_USBD_WebUSB.h"
28+
#include "tusb_option.h"
29+
30+
//#ifndef USE_TINYUSB
31+
//#error TinyUSB is not selected, please select it in Tools->Menu->USB Stack
32+
//#endif
33+
34+
#if TUSB_OPT_DEVICE_ENABLED
35+
36+
#include "arduino/Adafruit_USBD_Device.h"
37+
#include "arduino/Adafruit_USBD_CDC.h"
38+
39+
#include "arduino/hid/Adafruit_USBD_HID.h"
40+
#include "arduino/midi/Adafruit_USBD_MIDI.h"
41+
#include "arduino/msc/Adafruit_USBD_MSC.h"
42+
#include "arduino/webusb/Adafruit_USBD_WebUSB.h"
43+
44+
// Initialize device hardware, stack, also Serial as CDC
45+
// Wrapper for USBDevice.begin(rhport)
46+
void TinyUSB_Device_Init(uint8_t rhport);
47+
48+
#endif
3249

3350
#endif /* ADAFRUIT_TINYUSB_H_ */

src/Adafruit_TinyUSB.cpp renamed to src/arduino/Adafruit_TinyUSB_API.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,37 @@
2222
* THE SOFTWARE.
2323
*/
2424

25+
#include "tusb_option.h"
26+
27+
#if TUSB_OPT_DEVICE_ENABLED
28+
2529
#include "Adafruit_TinyUSB.h"
26-
#include "Arduino.h"
2730

2831
//--------------------------------------------------------------------+
2932
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
3033
//--------------------------------------------------------------------+
34+
extern "C"
35+
{
36+
37+
void TinyUSB_Device_Init(uint8_t rhport)
38+
{
39+
USBDevice.begin(rhport);
40+
}
41+
42+
// RP2040 has its own implementation since it needs mutex for dual core
43+
#ifndef ARDUINO_ARCH_RP2040
44+
void TinyUSB_Device_Task(void)
45+
{
46+
tud_task();
47+
}
48+
#endif
49+
50+
void TinyUSB_Device_FlushCDC(void)
51+
{
52+
// TODO multiple CDCs
53+
tud_cdc_n_write_flush(0);
54+
}
55+
56+
}
3157

32-
//------------- IMPLEMENTATION -------------//
58+
#endif

src/arduino/Adafruit_TinyUSB_API.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2019 Ha Thach for Adafruit Industries
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
#ifndef ADAFRUIT_TINYUSB_API_H_
26+
#define ADAFRUIT_TINYUSB_API_H_
27+
28+
#include <stdint.h>
29+
#include <stdbool.h>
30+
31+
//--------------------------------------------------------------------+
32+
// Core API
33+
// Should be called by BSP Core to initialize, process task
34+
// Weak function allow compile arduino core before linking with this library
35+
//--------------------------------------------------------------------+
36+
#ifdef __cplusplus
37+
extern "C" {
38+
#endif
39+
40+
// Called by core/sketch to initialize usb device hardware and stack
41+
// This also initialize Serial as CDC device
42+
void TinyUSB_Device_Init(uint8_t rhport) __attribute__((weak));
43+
44+
// Called by core/sketch to handle device event
45+
void TinyUSB_Device_Task(void) __attribute__((weak));
46+
47+
// Called by core/sketch to flush write on CDC
48+
void TinyUSB_Device_FlushCDC(void) __attribute__((weak));
49+
50+
#ifdef __cplusplus
51+
}
52+
#endif
53+
54+
//--------------------------------------------------------------------+
55+
// Port API
56+
// Must be implemented by each BSP core/platform
57+
//--------------------------------------------------------------------+
58+
59+
// To enter/reboot to bootloader
60+
// usually when host disconnects cdc at baud 1200 (touch 1200)
61+
void TinyUSB_Port_EnterDFU(void);
62+
63+
// Init device hardware.
64+
// Called by TinyUSB_Device_Init()
65+
void TinyUSB_Port_InitDevice(uint8_t rhport);
66+
67+
// Get unique serial number, needed for Serial String Descriptor
68+
// Fill serial_id (raw bytes) and return its length (limit to 16 bytes)
69+
// Note: Serial descriptor can be overwritten by user API
70+
uint8_t TinyUSB_Port_GetSerialNumber(uint8_t serial_id[16]);
71+
72+
#endif

0 commit comments

Comments
 (0)