LittleFS SPI and QSPI wrappers...

Status
Not open for further replies.

KurtE

Senior Member+
Wondering if we should have some version(s) of LittleFS_SPIxxx wrappers and likewise LittleFS_QS... wrappers.

I was getting tired of playing around and trying to remember which chip is which, to then edit the code to match the littlefs class..

So I have played around with a set of classes, trying to figure out the right balance...

So far I sort of like the following: Keep It Simple Stupid (KISS) wrappers, I have in one of my MTP example sketches:

Code:
//----------------------------------------------------------------------------
// Experiment with LittleFS_SPI wrapper
//----------------------------------------------------------------------------
#ifdef ARDUINO_TEENSY41
class lfs_qspi {
public:
  lfs_qspi(){}
  bool begin();
  inline FS * fs() { return plfs;}
  inline const char * displayName() {return display_name;}
  // You have full access to internals.
  uint8_t csPin;
  LittleFS_QSPIFlash flash;
  LittleFS_QPINAND nand;
  LittleFS *plfs = nullptr;
  char display_name[10];
};
bool lfs_qspi::begin() {
  //Serial.printf("Try QSPI");
  if (flash.begin()) {
    //Serial.println(" *** Flash ***");
    strcpy(display_name, (const char *)F("QFlash"));
    plfs = &flash;
    return true;
  } else if (nand.begin()) {
    //Serial.println(" *** Nand ***");
    strcpy(display_name, (const char *)F("QNAND"));
    plfs = &nand;
    return true;
  }
  //Serial.println(" ### Failed ###");
  return false;
}
  lfs_qspi lfsq;
#endif

//----------------------------------------------------------------------------
// Experiment with LittleFS_SPI wrapper
//----------------------------------------------------------------------------
class lfs_spi {
public:
  lfs_spi(uint8_t pin) : csPin(pin) {}
  bool begin();
  inline FS * fs() { return plfs;}
  inline const char * displayName() {return display_name;}
  // You have full access to internals.
  uint8_t csPin;
  LittleFS_SPIFlash flash;
  LittleFS_SPIFram fram;
  LittleFS_SPINAND nand;
  LittleFS *plfs = nullptr;
  char display_name[10];
};
bool lfs_spi::begin() {
  //Serial.printf("Try SPI Pin %u", csPin);
  if (flash.begin(csPin)) {
    //Serial.println(" *** Flash ***");
    sprintf(display_name, (const char *)F("Flash_%u"), csPin);
    plfs = &flash;
    return true;
  } else if (fram.begin(csPin)) {
    //Serial.println(" *** Fram ***");
    sprintf(display_name, (const char *)F("Fram_%u"), csPin);
    plfs = &fram;
    return true;
  } else if (nand.begin(csPin)) {
    //Serial.println(" *** Nand ***");
    sprintf(display_name, (const char *)F("NAND_%u"), csPin);
    plfs = &nand;
    return true;
  }
  //Serial.println(" ### Failed ###");
  return false;
}

Note: this one does not have method to query which one flash, nand, Fram... But easily could.

I have also played with a version like this which the classes were derived from FS or FileImpl, in which case you can simply use it... And it forwards each of the calls
to the underlying FS. Which worked fine, but if you needed LittleFS other functions could be issue.

I have played with deriving from LittleFS, But more problems associated with this, as each would have their own copies of the data structures...

So just wondering if this is something that we maybe should be added somewhere? (LittleFS.h?) And wondering what level of support?
 
Not fully seeing context on a quick read ... header says SPI .vs. QSPI wrapper - class shows QSPI NOR .vs. NAND ?

It is a pain editing types - just built a littleFS QSPI example and NAND failed ... oops NOR.

Question would be any chance of finding the same chip twice - suppose not as SPI gets/needs a unique CS and QSPI only has one usable FLASH pad that could be NAND or NOR.
 
Sorry it just is a quick easy way to configure programs to run with either...

example: if in sketch I define:
Code:
lfs_qspi lfsq;

I can then for example with MTP I can simply start on any of T4.1s that may or may not have a chip on the bottom:
#ifdef ARDUINO_TEENSY41
if (lfsq.begin()) {
storage.addFilesystem(*lfsq.fs(), lfsq.displayName());
}
#endif

Which is in the sketch: https://github.com/KurtE/MTP_Teensy...PI_MTP-logger/SD_SPI_QSPI_MTP-logger.ino#L201


Also in that same sketch, I have an array of the SPI version:
lfs_spi lfs_spi_list[] = {{3}, {4}, {5}, {6}};

which I loop through:
Code:
 // Now lets try our list of LittleFS SPI?
    for (uint8_t i = 0; i < (sizeof(lfs_spi_list) / sizeof(lfs_spi_list[0])); i++) {
      if (lfs_spi_list[i].begin()) {
        storage.addFilesystem(*lfs_spi_list[i].fs(), lfs_spi_list[i].displayName());
      }
    }
So don't have to worry if this case which ones of Pauls board is on which pin... Or if pin 6 is later connected to audio board...

Again no big deal, but found it handy, especially if looking at boards, that things like:
screenshot.jpg
What is it...
 
@KurtE - Dang:) Now I think I understand what's on the mem board and T4.1 pads.
Here's the layout in the Linux filemanager:

Screenshot at 2021-10-28 15-52-47.png

I opened each one and all of the files listed that were on them. It makes it easier to identify which device you are working with and the chip selects they are using.

Can the device part number also be determined by the device ID and be available to display?
 
Last edited:
Can the device part number also be determined by the device ID and be available to display?
Nice picture!

As for finding out what the underlying chip is... Not sure. Again this is really simple wrapper. It tries one type. If it works it uses it, else tried next...
 
Status
Not open for further replies.
Back
Top