Got Error when using Adafuit TinyUSB with RP2040
platformio.ini
[env]
platform = raspberrypi
framework = arduino
lib_deps = adafruit/Adafruit TinyUSB Library
board_build.f_cpu = 120000000L
[env:pico]
board = pico
main.cpp
#include <Arduino.h>
void printAll(int ch);
boolean delay_without_delaying(unsigned long time);
/*
This example demonstrates the use of multiple USB CDC/ACM "VirtualSerial"
ports Written by Bill Westfield (aka WestfW), June 2021. Copyright 2021 by
Bill Westfield MIT license, check LICENSE for more information
The example creates two virtual serial ports. Text entered on
any of the ports will be echoed to the all ports with
- all lower case in port0 (Serial)
- all upper case in port1
libraries/Adafruit_TinyUSB_Arduino/src/arduino/ports/rp2040/tusb_config_rp2040.h
#define CFG_TUD_CDC 2 // default 1
Requirement:
The max number of CDC ports (CFG_TUD_CDC) has to be changed to at least 2.
Config file is located in
Adafruit_TinyUSB_Arduino/src/arduino/ports/{platform}/tusb_config_{platform}.h
where platform is one of: nrf, rp2040, samd
NOTE:
Currnetly multiple CDCs on ESP32-Sx is not yet supported.
An PR to update core/esp32/USBCDC and/or pre-built libusb are needed.
We would implement this later when we could.
*/
#include <Adafruit_TinyUSB.h>
#define ARDUINO_ARCH_RP2040
#define LED LED_BUILTIN // Create 2nd instance of CDC Ports.
#ifdef ARDUINO_ARCH_ESP32
#error \
"Currnetly multiple CDCs on ESP32-Sx is not yet supported. An PR to update core/esp32/USBCDC and/or pre-built libusb are needed."
// for ESP32, we need to specify instance number when declaring object
Adafruit_USBD_CDC USBSer1(1);
#else
Adafruit_USBD_CDC USBSer1;
#endif
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(9600); // check to see if multiple CDCs are enabled
if (CFG_TUD_CDC < 2) {
digitalWrite(LED, HIGH); // LED on for error indicator
while (1) {
Serial.print("CFG_TUD_CDC must be at least 2, current value is ");
Serial.println(CFG_TUD_CDC);
Serial.println(" Config file is located in "
"Adafruit_TinyUSB_Arduino/src/arduino/ports/{platform}/"
"tusb_config_{platform}.h");
Serial.println(" where platform is one of: nrf, rp2040, samd");
digitalWrite(LED, HIGH);
delay(1000);
digitalWrite(LED, LOW);
delay(1000);
}
}
// initialize 2nd CDC interface
USBSer1.begin(9600);
while (!Serial || !USBSer1) {
if (Serial) {
Serial.println("Waiting for other USB ports 1");
}
if (USBSer1) {
USBSer1.println("Waiting for other USB ports 0");
}
delay(1000);
}
Serial.print("You are port 0\n\r\n0> ");
USBSer1.print("You are port 1\n\r\n1> ");
}
void loop() {
int ch;
int LEDstate = 0;
ch = Serial.read();
if (ch > 0) {
printAll(ch);
}
ch = USBSer1.read();
if (ch > 0) {
printAll(ch);
}
if (delay_without_delaying(500)) {
LEDstate = !LEDstate;
digitalWrite(LED, LEDstate);
}
}
// print to all CDC ports
void printAll(int ch) {
// always lower case
Serial.write(tolower(ch));
// always upper case
USBSer1.write(toupper(ch));
}
// Helper: non-blocking "delay" alternative.
boolean delay_without_delaying(unsigned long time) {
// return false if we're still "delaying", true if time ms has passed.
// this should look a lot like "blink without delay"
static unsigned long previousmillis = 0;
unsigned long currentmillis = millis();
if (currentmillis - previousmillis >= time) {
previousmillis = currentmillis;
return true;
}
return false;
}
Error When Compiling:
.pio\libdeps\pico\Adafruit TinyUSB Library\src\arduino\cdc\Adafruit_USBH_CDC.h:30:49: error: expected class-name before '{' token
30 | class Adafruit_USBH_CDC : public HardwareSerial {
| ^
.pio\libdeps\pico\Adafruit TinyUSB Library\src\arduino\cdc\Adafruit_USBH_CDC.h:79:16: error: type 'arduino::Print' is not a base type for type 'Adafruit_USBH_CDC'
79 | using Print::write; // pull in write(str) from Print
| ^~~~~
*** [.pio\build\pico\libec7\Adafruit TinyUSB Library\arduino\cdc\Adafruit_USBH_CDC.cpp.o] Error 1
fixed by adding arduino::
before HardwareSerial
in Adafruit_USBH_CDC.h
file
and I got another error from ld:
Linking .pio\build\pico\firmware.elf
c:/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: .pio\build\pico\libec7\libAdafruit TinyUSB Library.a(rp2040_usb.c.o): in function `_hw_endpoint_buffer_control_update32':
rp2040_usb.c:(.text._hw_endpoint_buffer_control_update32+0x3a): undefined reference to `busy_wait_at_least_cycles'
fixed by add code below to main.cpp
extern "C" {
void busy_wait_at_least_cycles(volatile uint32_t minimum_cycles) {
while (minimum_cycles--);
}
}
then got another error: failed to download the binary file to the board
...
Checking size .pio\build\pico\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM: [== ] 16.3% (used 44172 bytes from 270336 bytes)
Flash: [ ] 0.2% (used 4382 bytes from 2097152 bytes)
Configuring upload protocol...
AVAILABLE: cmsis-dap, jlink, picotool, raspberrypi-swd
CURRENT: upload_protocol = picotool
Looking for upload port...
Auto-detected: COM4
Forcing reset using 1200bps open/close on port COM4
Uploading .pio\build\pico\firmware.elf
rp2040load 1.0.1 - compiled with go1.15.8
.....................
*** [upload] Error 1
auto-reseting do works, but uploading failed,
but then I can upload the code by copying the .pio\build\pico\firmware.uf2
file to the RP2040 board after auto-uploading failed
After uploading the code, the code does not work as expected
the 2nd CDC port does not initialize properly, the serial puts Waiting for other USB ports 1
forever
What should I do to fix this error?