I try to use the TinyUSB library with the nRF52840 to create a mass storage device.
I fail to compile a simple example, and after some digging around I suspect that it is a bug inside the TinyUSB library or its library core.
When compiling, there are unexpected errors about classes being purely virtual that shouldn’t be.
I am completely out of ideas on how to tackle this problem and would be happy for any kind of feedback.
Steps to reproduce
The following steps should reproduce the problem.
Dependencies
- Create a new project for the
adafruit_feather_nrf52840
board - Install Dependencies:
adafruit/Adafruit SPIFlash
adafruit/Adafruit TinyUSB Library
adafruit/SdFat - Adafruit Fork
Final platformio.ini
should look like this:
[env:adafruit_feather_nrf52840]
platform = nordicnrf52
board = adafruit_feather_nrf52840
framework = arduino
lib_deps =
adafruit/Adafruit SPIFlash@^3.5.2
adafruit/Adafruit TinyUSB Library@^1.3.2
adafruit/SdFat - Adafruit Fork@^1.2.4
Program code
Copy the following code to main.cpp.
It’s a simplified version of a USB flash driver.
#include "SPI.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
int32_t msc_read_cb(uint32_t lba, void *buffer, uint32_t bufsize);
int32_t msc_write_cb(uint32_t lba, uint8_t *buffer, uint32_t bufsize);
void msc_flush_cb(void);
Adafruit_FlashTransport_QSPI flashTransport;
Adafruit_SPIFlash flash(&flashTransport);
// USB Mass Storage object
Adafruit_USBD_MSC usb_msc;
// the setup function runs once when you press reset or power the board
void setup()
{
flash.begin();
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "External Flash", "1.0");
// Set callback
usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
// Set disk size, block size should be 512 regardless of spi flash page size
usb_msc.setCapacity(flash.size() / 512, 512);
// MSC is ready for read/write
usb_msc.setUnitReady(true);
usb_msc.begin();
}
void loop()
{
}
int32_t msc_read_cb(uint32_t lba, void *buffer, uint32_t bufsize)
{
return flash.readBlocks(lba, (uint8_t *)buffer, bufsize / 512) ? bufsize : -1;
}
int32_t msc_write_cb(uint32_t lba, uint8_t *buffer, uint32_t bufsize)
{
return flash.writeBlocks(lba, buffer, bufsize / 512) ? bufsize : -1;
}
void msc_flush_cb(void)
{
flash.syncBlocks();
}
Expected outcome
It should compile. This example is absolutely the barebone minimum to create a USB Mass Storage Device for the built-in 2MB flash chip of the nRF52840 FeatherWing.
Further, when flashed, it should create a 2MB external drive. But that part is not important for this post as I don’t get it compiled in the first place.
Error Messages
The following errors appear during the build process:
Processing adafruit_feather_nrf52840 (platform: nordicnrf52; board: adafruit_feather_nrf52840; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/nordicnrf52/adafruit_feather_nrf52840.html
PLATFORM: Nordic nRF52 (8.1.0) > Adafruit Feather nRF52840 Express
HARDWARE: NRF52840 64MHz, 243KB RAM, 796KB Flash
DEBUG: Current (blackmagic) External (blackmagic, cmsis-dap, jlink, stlink)
PACKAGES:
- framework-arduinoadafruitnrf52 1.2100.201028 (21.0)
- tool-sreccat 1.164.0 (1.64)
- toolchain-gccarmnoneeabi 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 35 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <Adafruit SPIFlash> 3.5.2
| |-- <SPI> 1.0
| |-- <SdFat - Adafruit Fork> 1.2.4
| | |-- <SPI> 1.0
|-- <Adafruit TinyUSB Library> 1.3.2
|-- <SdFat - Adafruit Fork> 1.2.4
| |-- <SPI> 1.0
|-- <SPI> 1.0
Building in release mode
Compiling .pio\build\adafruit_feather_nrf52840\src\main.cpp.o
Compiling .pio\build\adafruit_feather_nrf52840\lib83f\SPI\SPI.cpp.o
Compiling .pio\build\adafruit_feather_nrf52840\lib83f\SPI\SPI_nrf52832.cpp.o
Compiling .pio\build\adafruit_feather_nrf52840\lib49a\SdFat - Adafruit Fork\FatLib\FatFile.cpp.o
Compiling .pio\build\adafruit_feather_nrf52840\lib49a\SdFat - Adafruit Fork\FatLib\FatFileLFN.cpp.o
src\main.cpp:13:19: error: cannot declare variable 'usb_msc' to be of abstract type 'Adafruit_USBD_MSC'
Adafruit_USBD_MSC usb_msc;
^~~~~~~
In file included from .pio\libdeps\adafruit_feather_nrf52840\Adafruit TinyUSB Library\src/Adafruit_TinyUSB.h:44:0,
from src\main.cpp:3:
.pio\libdeps\adafruit_feather_nrf52840\Adafruit TinyUSB Library\src/arduino/msc/Adafruit_USBD_MSC.h:30:7: note: because the following virtual functions are pure within 'Adafruit_USBD_MSC':
class Adafruit_USBD_MSC : public Adafruit_USBD_Interface {
^~~~~~~~~~~~~~~~~
In file included from C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\cores\nRF5\TinyUSB\Adafruit_TinyUSB_ArduinoCore/Adafruit_TinyUSB_Core.h:35:0,
from C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\cores\nRF5/Arduino.h:72,
from C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\libraries\SPI/SPI.h:24,
from src\main.cpp:1:
C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\cores\nRF5\TinyUSB\Adafruit_TinyUSB_ArduinoCore/Adafruit_USBD_Device.h:33:22: note:
virtual uint16_t Adafruit_USBD_Interface::getDescriptor(uint8_t, uint8_t*, uint16_t)
virtual uint16_t getDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize) = 0;
^~~~~~~~~~~~~
In file included from C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\libraries\SPI\SPI.h:24:0,
from C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\libraries\SPI\SPI.cpp:26:
C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\cores\nRF5/Arduino.h: In instantiation of 'decltype (((b < a) ? b : a)) min(const T&, const L&) [with T = unsigned int; L = int; decltype (((b < a) ? b : a)) = unsigned int]':
C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\libraries\SPI\SPI.cpp:202:50: required from here
C:\Users\Martin\.platformio\packages\framework-arduinoadafruitnrf52\cores\nRF5/Arduino.h:93:15: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
return (b < a) ? b : a;
~~~^~~~
*** [.pio\build\adafruit_feather_nrf52840\src\main.cpp.o] Error 1
============================================================== [FAILED] Took 6.66 seconds ==============================================================
Cross-Checking with Arduino IDE
The given sample code compiles and runs on the Arduino IDE.
It required to install the Adafruit TinyUSB Library
and dependencies.