Compare commits

...

11 commits

Author SHA1 Message Date
Tyeth Gundry
b3c0d36521
Update library.properties - bump version to 1.2.1 2025-06-17 12:02:54 +01:00
Limor "Ladyada" Fried
86685d54f0
Merge pull request #5 from adafruit/adafruit_sdfat
update sdfat include in header
2025-06-03 19:56:38 -04:00
Liz
bc38541bb0 clang 2025-06-03 18:19:35 -04:00
Liz
c0b49b9146 update sdfat include in header
this fixes a compilation error that otherwise occurs with the philhower rp2040 bsp since there is a conflict with the internal sdfat library and the adafruit fork sdfat library
2025-06-03 18:12:15 -04:00
Phillip Burgess
7e391a76f4 clang-format 2023-06-20 18:53:24 -07:00
Phillip Burgess
9a2737d871 Add msc flag to begin() (breaking API change) 2023-06-20 18:41:57 -07:00
Paint Your Dragon
ba575cee3e
Merge pull request #4 from adafruit/pb-msc-flag
RP2040: add idle flag to begin()
2023-06-16 08:38:31 -07:00
Paint Your Dragon
6b2c7ff4e5
Update library.properties 2023-06-16 08:32:28 -07:00
Phillip Burgess
7f1dde74f2 RP2040: add idle flag to begin() 2023-06-16 08:01:07 -07:00
Phillip Burgess
7b3c5e3008 Add rw flag to begin() 2023-06-14 17:37:54 -07:00
dherrada
6e4eb043fe Update CI action versions 2023-05-15 10:47:38 -04:00
5 changed files with 71 additions and 40 deletions

View file

@ -7,11 +7,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/setup-python@v1 - uses: actions/setup-python@v4
with: with:
python-version: '3.x' python-version: '3.x'
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
repository: adafruit/ci-arduino repository: adafruit/ci-arduino
path: ci path: ci

View file

@ -51,7 +51,7 @@
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
static Adafruit_FlashTransport_ESP32 _transport; static Adafruit_FlashTransport_ESP32 _transport;
#elif defined(ARDUINO_ARCH_RP2040) #elif defined(ARDUINO_ARCH_RP2040)
static Adafruit_FlashTransport_RP2040_CPY _transport; static Adafruit_FlashTransport_RP2040_CPY *_transport;
#elif defined(EXTERNAL_FLASH_USE_QSPI) #elif defined(EXTERNAL_FLASH_USE_QSPI)
static Adafruit_FlashTransport_QSPI _transport; static Adafruit_FlashTransport_QSPI _transport;
#elif defined(EXTERNAL_FLASH_USE_CS) && defined(EXTERNAL_FLASH_USE_SPI) #elif defined(EXTERNAL_FLASH_USE_CS) && defined(EXTERNAL_FLASH_USE_SPI)
@ -66,11 +66,11 @@ static Adafruit_FlashTransport_SPI _transport(EXTERNAL_FLASH_USE_CS,
// members are pointers, initialized at run-time depending on arguments // members are pointers, initialized at run-time depending on arguments
// passed (or not) to the begin() function. // passed (or not) to the begin() function.
#define HAXPRESS #define HAXPRESS
static Adafruit_FlashTransport_SPI *_transport; static Adafruit_FlashTransport_SPI *_transport; // Unused if internal
static void *_flash; static void *_flash; // Is cast internal/SPI as needed in callbacks
#endif #endif
#if !defined HAXPRESS #if !defined HAXPRESS
static Adafruit_SPIFlash _flash(&_transport); static Adafruit_SPIFlash *_flash;
#endif #endif
static Adafruit_USBD_MSC _usb_msc; static Adafruit_USBD_MSC _usb_msc;
@ -131,23 +131,23 @@ static void msc_flush_cb_spi(void) {
// Flash type is known at compile time. Simple callbacks. // Flash type is known at compile time. Simple callbacks.
static int32_t msc_read_cb(uint32_t lba, void *buffer, uint32_t bufsize) { static int32_t msc_read_cb(uint32_t lba, void *buffer, uint32_t bufsize) {
return _flash.readBlocks(lba, (uint8_t *)buffer, bufsize / 512) ? bufsize return _flash->readBlocks(lba, (uint8_t *)buffer, bufsize / 512) ? bufsize
: -1; : -1;
} }
static int32_t msc_write_cb(uint32_t lba, uint8_t *buffer, uint32_t bufsize) { static int32_t msc_write_cb(uint32_t lba, uint8_t *buffer, uint32_t bufsize) {
_changed = 1; _changed = 1;
return _flash.writeBlocks(lba, buffer, bufsize / 512) ? bufsize : -1; return _flash->writeBlocks(lba, buffer, bufsize / 512) ? bufsize : -1;
} }
static void msc_flush_cb(void) { static void msc_flush_cb(void) {
_flash.syncBlocks(); _flash->syncBlocks();
_fatfs.cacheClear(); _fatfs.cacheClear();
} }
#endif // end !HAXPRESS #endif // end !HAXPRESS
FatVolume *Adafruit_CPFS::begin(int cs, void *spi) { FatVolume *Adafruit_CPFS::begin(bool msc, int cs, void *spi, bool idle) {
if (_started) if (_started)
return &_fatfs; // Don't re-init if already running return &_fatfs; // Don't re-init if already running
@ -160,27 +160,32 @@ FatVolume *Adafruit_CPFS::begin(int cs, void *spi) {
if ((_transport = new Adafruit_FlashTransport_SPI(cs, (SPIClass *)spi))) { if ((_transport = new Adafruit_FlashTransport_SPI(cs, (SPIClass *)spi))) {
if ((_flash = (void *)new Adafruit_SPIFlash(_transport))) { if ((_flash = (void *)new Adafruit_SPIFlash(_transport))) {
((Adafruit_SPIFlash *)_flash)->begin(); ((Adafruit_SPIFlash *)_flash)->begin();
_usb_msc.setID("Adafruit", "External Flash", "1.0"); if (msc) {
_usb_msc.setReadWriteCallback(msc_read_cb_spi, msc_write_cb_spi, _usb_msc.setID("Adafruit", "External Flash", "1.0");
msc_flush_cb_spi); _usb_msc.setReadWriteCallback(msc_read_cb_spi, msc_write_cb_spi,
_usb_msc.setCapacity(((Adafruit_SPIFlash *)_flash)->size() / 512, 512); msc_flush_cb_spi);
_usb_msc.setUnitReady(true); _usb_msc.setCapacity(((Adafruit_SPIFlash *)_flash)->size() / 512,
_usb_msc.begin(); 512);
_usb_msc.setUnitReady(true);
_usb_msc.begin();
}
if (_fatfs.begin((Adafruit_SPIFlash *)_flash)) if (_fatfs.begin((Adafruit_SPIFlash *)_flash))
return &_fatfs; return &_fatfs;
} // end if new flash } // end if new flash
} // end if new transport } // end if new transport
} else { // Internal flash } else { // Internal flash
if ((_flash = (void *)new Adafruit_InternalFlash(INTERNAL_FLASH_FS_START, if ((_flash = (void *)new Adafruit_InternalFlash(INTERNAL_FLASH_FS_START,
INTERNAL_FLASH_FS_SIZE))) { INTERNAL_FLASH_FS_SIZE))) {
((Adafruit_InternalFlash *)_flash)->begin(); ((Adafruit_InternalFlash *)_flash)->begin();
_usb_msc.setID("Adafruit", "Internal Flash", "1.0"); if (msc) {
_usb_msc.setReadWriteCallback(msc_read_cb_internal, msc_write_cb_internal, _usb_msc.setID("Adafruit", "Internal Flash", "1.0");
msc_flush_cb_internal); _usb_msc.setReadWriteCallback(
_usb_msc.setCapacity(((Adafruit_InternalFlash *)_flash)->size() / 512, msc_read_cb_internal, msc_write_cb_internal, msc_flush_cb_internal);
512); _usb_msc.setCapacity(((Adafruit_InternalFlash *)_flash)->size() / 512,
_usb_msc.setUnitReady(true); 512);
_usb_msc.begin(); _usb_msc.setUnitReady(true);
_usb_msc.begin();
}
if (_fatfs.begin((Adafruit_InternalFlash *)_flash)) if (_fatfs.begin((Adafruit_InternalFlash *)_flash))
return &_fatfs; return &_fatfs;
} // end if new flash } // end if new flash
@ -188,15 +193,27 @@ FatVolume *Adafruit_CPFS::begin(int cs, void *spi) {
#else #else
_flash.begin(); #if defined(ARDUINO_ARCH_RP2040)
_usb_msc.setID("Adafruit", "Onboard Flash", "1.0"); if ((_transport = new Adafruit_FlashTransport_RP2040_CPY(idle))) {
_usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb); if ((_flash = new Adafruit_SPIFlash(_transport))) {
_usb_msc.setCapacity(_flash.size() / 512, 512); #else
_usb_msc.setUnitReady(true); { // _transport is declared globally, no test needed, pass address-of
_usb_msc.begin(); if ((_flash = new Adafruit_SPIFlash(&_transport))) {
#endif
if (_fatfs.begin(&_flash)) _flash->begin();
return &_fatfs; if (msc) {
_usb_msc.setID("Adafruit", "Onboard Flash", "1.0");
_usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
_usb_msc.setCapacity(_flash->size() / 512, 512);
_usb_msc.setUnitReady(true);
_usb_msc.begin();
}
if (_fatfs.begin(_flash))
return &_fatfs;
} // end if new flash
} // end if new transport
#endif // end HAXPRESS #endif // end HAXPRESS

View file

@ -34,7 +34,7 @@
#if defined(USE_TINYUSB) || defined(ESP32) #if defined(USE_TINYUSB) || defined(ESP32)
#include <SdFat.h> #include <SdFat_Adafruit_Fork.h>
/*! /*!
@brief Adafruit_CPFS is a minimal class to assist in using a board's @brief Adafruit_CPFS is a minimal class to assist in using a board's
@ -68,6 +68,10 @@ public:
available to code and to a host computer over USB. available to code and to a host computer over USB.
IMPORTANT: this function should always be called BEFORE IMPORTANT: this function should always be called BEFORE
Serial.begin(). Serial.begin().
@param msc OPTIONAL Enable mass storage connection to host computer
over USB (if connected at boot time). Default is
true. If set false, flash filesystem can be read
by user code, but is not accessible on host.
@param cs OPTIONAL SPI flash chip-select pin. This should ONLY be @param cs OPTIONAL SPI flash chip-select pin. This should ONLY be
used on "Haxpress" boards (QT Py or Trinket M0 used on "Haxpress" boards (QT Py or Trinket M0
with flash chip retrofitted). For most boards, with flash chip retrofitted). For most boards,
@ -76,12 +80,19 @@ public:
@param spi OPTIONAL Pointer to SPI peripheral interfaced with flash @param spi OPTIONAL Pointer to SPI peripheral interfaced with flash
chip. Again, only for a couple of Haxpress M0 chip. Again, only for a couple of Haxpress M0
boards. boards.
@param idle OPTIONAL Relevant to RP2040 devices only. Selects whether
second core should be paused when writing/erasing
flash. Default is true, and should ONLY be changed
in super esoteric cases that require special
linker setup. Failure to handle this correctly
will cause crash and flash corruption.
@return FatVolume* On success, a non-NULL pointer to a FatVolume @return FatVolume* On success, a non-NULL pointer to a FatVolume
object, where files can then be opened and accessed. object, where files can then be opened and accessed.
NULL on error (uninitialized CIRCUITPY drive, or NULL on error (uninitialized CIRCUITPY drive, or
invalid cs/spi combo).. invalid cs/spi combo)..
*/ */
static FatVolume *begin(int cs = -1, void *spi = NULL); static FatVolume *begin(bool msc = true, int cs = -1, void *spi = NULL,
bool idle = true);
/*! /*!
@brief Checks if USB-connected host computer has made any changes @brief Checks if USB-connected host computer has made any changes

View file

@ -23,9 +23,12 @@ FatVolume *fs = NULL; // CIRCUITPY flash filesystem, as a FAT pointer
void setup(void) { void setup(void) {
// Start the CIRCUITPY flash filesystem FIRST. Very important! // Start the CIRCUITPY flash filesystem FIRST. Very important!
fs = Adafruit_CPFS::begin(); fs = Adafruit_CPFS::begin();
// An optional initial true/false flag passed to begin() selects whether
// the flash filesystem is presented to a USB-attached host computer (true),
// or accessible only to code on the microcontroller (false).
// For "Haxpress" boards (small M0 boards retrofitted with SPI flash), // For "Haxpress" boards (small M0 boards retrofitted with SPI flash),
// a chip-select pin and/or SPI instance can be passed to begin(): // a chip-select pin and/or SPI instance can follow like so:
// fs = Adafruit_CPFS::begin(SS1, &SPI1); // QT Py M0 Haxpress // fs = Adafruit_CPFS::begin(true, SS1, &SPI1); // QT Py M0 Haxpress
// Start Serial AFTER Adafruit_CPFS, or CIRCUITPY won't show on computer. // Start Serial AFTER Adafruit_CPFS, or CIRCUITPY won't show on computer.
Serial.begin(115200); Serial.begin(115200);

View file

@ -1,5 +1,5 @@
name=Adafruit CPFS name=Adafruit CPFS
version=1.0.0 version=1.2.1
author=Adafruit author=Adafruit
maintainer=Adafruit <info@adafruit.com> maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for accessing a board's CircuitPython flash filesystem and presenting it over USB. sentence=Arduino library for accessing a board's CircuitPython flash filesystem and presenting it over USB.