LittleFS port to Teensy/SPIFlash

>> Look at post #152 for QSPI first for FILES then this one for DIRS

This reproduced in 3 loops - which is when the first deletes/removes start.

I'll upload a ZIP soon. Cleaned the QSPI FORMAT sketch of startup and other and added as 2nd INO and move the SPI FORMAT func to 3rd INO.

I find that the Beta PJRC T_4.1 with QSPI must be repowered after the Format - a Restart doesn't do it - as the chip ID won't read with the chip left in QSPI mode perhaps?

Looks like I need to error check the DIR creation for QSPI! That is done in setup() and it never created the 4th directory!

Caught this because I just added ERR check on file open:
Code:
printDirectory QSPI_DISK --Add---- ++ H 
:: /3_dir/I_file.txt   waited 102 us
  waited 174 us
printDirectory QSPI_DISK --Add---- ++ I 
[B][COLOR="#FF0000"]:: /4_dir/J_file.txt Fail File open [/COLOR][/B]
[  0.26] Awaiting input 0123456789rdchkfvp? loops left 2
printDirectory QSPI_DISK
--------------DIR	0_dir / 
DIR	1_dir / 
DIR	2_dir / 
DIR	3_dir / 

[  0.54] Awaiting input 0123456789rdchkfvp? loops left 2

Err doesn't seem to propagate from mkdir? { not sure if this means failure wasn't detected ? Or unknown error occurred in mkdir? } Enable of their prints failing :(

Also, On Restart the 3_dir is missing - though it shows as above before restart - this is as reported and easy to repro as the code it written in setup -
>> though as posted below hidden under #ifdef ROOTONLY once the files themselves are reliable.

Didn't post this before ... look as following post first for errors on root file write.
 
Last edited:
Here is current :: LFSintegrity.zip [ does not include SPIFFS_t4 ]

Main sketch :: LFSintegrity.ino
Saved with #define TEST_RAM that works - as does #define TEST_SPI. Working with RAM will let behavior be observed and prevent extra QSPI formatting perhaps when using :: #define TEST_QSPI

As saved it is also set :: #define ROOTONLY - only does 26 files on root - which currently results in failure to write. This can be commented once the ROOT files are working.

For TEST_QSPI :
...
QSPI flash begin
Flash ID: EF 40 18
Flash size is 16.00 Mbyte
...

The following can be run as in included ZIP with #define TEST_RAM - Have not seen that fail.

NOTE: Wild speculation - confirm initial : "attemping to mount freshly formatted media ... success"
> It seems once I saw "couldn't mount media, attempting to format" on restarting where the drive had been formatted on prior restart.

Edited code to do open read verify after write of file and it quickly FAILS to be able to OPEN a file just written.
>> Build Sketch { set to #define TEST_QSPI when ready and leave as #define ROOTONLY and upload
>> FORMAT QSPI
>> REPOWER TEENSY
>> Enter '1' to single pass run the creation loop, Repeat Until it fails.
>> Enter 'd' to display directory - as below even the files Verified to read are not shown, but only "B" through "F", which were verified with read after write.
- once that test can run to satisfaction, restart Teensy and observe directory data for those file to be maintained
- With that complete comment out the #define ROOTONLY and repeat confirming the test passes to created and maintain 10 directories and the A-Z files as written.

Here it once failed on 1st file "B_file.txt" - below it failed on Creation of I_file.txt. { Yes "A" is created after "Z" when you get that far }
Code:
T:\tCode\littleFS\LFSintegrity\LFSintegrity.ino Nov  9 2020 23:09:06
LittleFS Test : File Integrity
QSPI flash begin
Flash ID: EF 40 18
Flash size is 16.00 Mbyte
attemping to mount existing media
couldn't mount media, attempting to format
  waited 28989 us
  waited 122 us
  waited 24698 us
  waited 122 us
attemping to mount freshly formatted media
success
printDirectory QSPI_DISK
--------------
 0, 1-9 '#' passes continue loop before Pause
 'r' Restart Teensy
 'd' Directory of LittleFS
 'c' Continuous Loop
 'h' Hundred loops
 'k' Thousand loops
 'f' Format then Restart : 'SPI EraseEverything'
 'v' Verbose All Dir Prints - TOGGLE
 'p' Pause after all Dir prints - TOGGLE
 '?' Help list
[  0.01] Awaiting input 0123456789rdchkfvp? loops left 0
printDirectory QSPI_DISK
--------------
:: /B_file.txt   waited 102 us
  waited 94 us
printDirectory QSPI_DISK --Add---- ++ B 
:: /C_file.txt   waited 103 us
  waited 106 us
printDirectory QSPI_DISK --Add---- ++ C 
[  0.15] Awaiting input 0123456789rdchkfvp? loops left 0
:: /D_file.txt   waited 102 us
  waited 116 us
printDirectory QSPI_DISK --Add---- ++ D 
:: /E_file.txt   waited 102 us
  waited 129 us
printDirectory QSPI_DISK --Add---- ++ E 
[  0.33] Awaiting input 0123456789rdchkfvp? loops left 0
:: /F_file.txt   waited 102 us
  waited 140 us
printDirectory QSPI_DISK --Add---- ++ F 
:: /G_file.txt   waited 103 us
  waited 151 us
printDirectory QSPI_DISK --Add---- ++ G 
[  0.40] Awaiting input 0123456789rdchkfvp? loops left 0
:: /H_file.txt   waited 102 us
  waited 162 us
printDirectory QSPI_DISK --Add---- ++ H 
:: /I_file.txt   waited 103 us
  waited 27695 us
  waited 358 us
  waited 204 us
  waited 102 us
  waited 162 us
  waited 207 us
[B][COLOR="#FF0000"]printDirectory QSPI_DISK --Add---- ++ I Fail File open /I_file.txt[/COLOR][/B]
[  0.42] Awaiting input 0123456789rdchkfvp? loops left 0
printDirectory QSPI_DISK
--------------[B]FILE	B_file.txt		11
FILE	C_file.txt		21
FILE	D_file.txt		31
FILE	E_file.txt		41
FILE	F_file.txt		51[/B]

[  5.63] Awaiting input 0123456789rdchkfvp? loops left 0

[  5.63] Awaiting input 0123456789rdchkfvp? loops left 0
 
@defragster

Directory listings known issue for QSPI = check post #143 and Paul's response in post #144.
 
@defragster

Directory listings known issue for QSPI = check post #143 and Paul's response in post #144.

Yes, it is known as a known issue.
These test cases should really help!
Goal is to provide a repro and test case for seeing it fixed. Have left it running 45 mins on Audio card SPI Flash and it runs great.

Not just files - but dirs fail to create and are lost. Just swapped back to QSPI from SPI and this time the formatted chip is happy: so perhaps the format is sticking
> "attemping to mount existing media ... success"

But they aren't just failing after restart - post #152 sketch - identifies them as Missing trying to re-open after create/write/close - they cannot be re-opened.

And the MultiDir says it created 3 - but only two show in dir - but yet they can seem to work some time if they are not verified ...

Feel free to try and steal the code - format integrated for SPI and QSPI and what seems a nice way to get user input processed.
 
@defragster

Directory listings known issue for QSPI = check post #143 and Paul's response in post #144.

@mjs513 - would be cool if you gave it a try and confirm the QSPI format code properly integrated after gutting it and got it right. Maybe the speed is not perfect? I saw tons of small [0,1] and large 24000 us delays passing by at times.

Also if it works well for you then Paul may have an easy time with it. Start sketch : 1+Enter a couple times and boom.

Plus I think the CmdLine usage worked out really well with two useful functions.

Also nice with the SPI format that works well - with reset to reenter setup().

Not sure the Format of QSPI has to have a cold restart? Is there maybe something not right to get the chip out of QSPI mode for the ID detect on warm restart? It restarts okay when not formatted AFAIK.

<edit> : Also cool is the DIR print names the disk media type in the #ifdef for type - so copy/paste of output makes clear what media was in use - RAM, SPI, QSPI
 
Last edited:
MTP Responder for LittleFS

Got a semi-working copy of a version of MTP Responder for use with Little FS (does not support SD Cards). Tested with DMAMEM for ramdisk and QSPI Flash. My SPIFlash chip doesn't seem to want to work with it right now. To change the storage area you do need to edit the defines in storage.cpp for the storage area at the top of the file (thanks @KurtE and @defragster). The lib is too big to attach so here is a link to a Github repository: https://github.com/mjs513/mtp_responder-for-LittleFs. WARNING: This is still a work in progress.
 
Doesn’t seem to want to recognize my chip. Going to hook it up to a prop shield when I wake up as a double check. Have to get some zzzs now beginning to see double. It’s one of those things that should work buts not. Probabably missing something.
 
Doesn’t seem to want to recognize my chip. Going to hook it up to a prop shield when I wake up as a double check. Have to get some zzzs now beginning to see double. It’s one of those things that should work buts not. Probabably missing something.

Bummer. I'll give it a try after Zzz's here ... plus a few hours ... I have a T_4.0 with Audio&Flash on top and a T_4.1 with Audio&Flash under. Both work with the sketch I posted above.
 
Bummer. I'll give it a try after Zzz's here ... plus a few hours ... I have a T_4.0 with Audio&Flash on top and a T_4.1 with Audio&Flash under. Both work with the sketch I posted above.

1. I reopened the thread - maybe i did it last night when I posted from the phone?
2. Did a bit of debugging and it just can't seem to access the SPI chip - begin I think works? But its getting stuck right away on doing a remove file?
 
MTP Responder for LittleFS

Got a semi-working copy of a version of MTP Responder for use with Little FS (does not support SD Cards). Tested with DMAMEM for ramdisk and QSPI Flash. My SPIFlash chip doesn't seem to want to work with it right now. To change the storage area you do need to edit the defines in storage.cpp for the storage area at the top of the file (thanks @KurtE and @defragster). The lib is too big to attach so here is a link to a Github repository: https://github.com/mjs513/mtp_responder-for-LittleFs. WARNING: This is still a work in progress.

Hi Mike, If I wish to try it out, Do I need to modify core files with the stuff in the directories, or just use the code in that library.... And does this replace the other MTP_t4 library...
 
Hi Mike, If I wish to try it out, Do I need to modify core files with the stuff in the directories, or just use the code in that library.... And does this replace the other MTP_t4 library...

Morning Kurt. No core files need to be modified, tried to keep it within the bounds - for instance had to delete the functionality to move and rename files since the core rename function isn't supported. Also had to do a real hack to the correct directory structure into the MTP responder format.

Right now its a replace so you won't be able to use MTP with your SD Card. Hopefully later today I will get it updated so it will just be an add to the libraries folder. Also, I just can't figure out whats going with SPIFlash - tried on the propshield as well and it didn't work.
 
Ok figured out the issue with SPIFlash using SPI - was trying to blink the LED at the same time - dumb right :).

Heres is a corrected test sketch;
Code:
#include "Arduino.h"
#ifndef USE_SDIO
  #define USE_SDIO 1 // change to 1 if using SDIO 
#endif

  #include "MTP.h"
  #include "usb1_mtp.h"

  MTPStorage_SD storage;
  MTPD       mtpd(&storage);


void logg(uint32_t del, const char *txt)
{ static uint32_t to;
  if(millis()-to > del)
  {
    //Serial.println(txt); 
#if USE_SDIO==1
    digitalWriteFast(2,!digitalReadFast(2));
#endif
    to=millis();
  }
}

void setup()
{ 
  while(!Serial); 
  usb_mtp_configure();
  if(!Storage_init()) {delay(1000);Serial.println("No storage"); while(1);};

  Serial.println("MTP test");

#if USE_SDIO==1
  pinMode(2,OUTPUT);
#endif

}

void loop()
{ 
  mtpd.loop();

  logg(1000,"loop");
  //asm("wfi"); // may wait forever on T4.x
}

Now all works :)
 
Still playing around with MTP but now I am kind of stuck - really on how c++ issue so here goes the explanation.

Requirement: need to tell the storage class (in storage.h and storage.cpp) what storage are to use - SPIflash, RAM, QSPFlash or whatever. Stuck on how to do this simply with the user editing storage.h to tell what to use.

In the sketch you set it up via:
Code:
  MTPStorage_SD storage;
  MTPD       mtpd(&storage);

in mtp.h:
Code:
class MTPD {
public:
  explicit MTPD(MTPStorageInterface* storage) : storage_(storage) {}

private:
  MTPStorageInterface* storage_;

in storage.h i currently have:
Code:
#include "LittleFS.h"
//#define TEST_RAM
#define TEST_SPI
//#define TEST_QSPI

  bool Storage_init(void);

and this is also defined:
Code:
// This interface lets the MTP responder interface any storage.
// We'll need to give the MTP responder a pointer to one of these.
class MTPStorageInterface {
public:
.....
.....
// Storage implementation for SD. SD needs to be already initialized.
class MTPStorage_SD : public MTPStorageInterface 
{
private:
   File index_;
   File file_;
   File child_;
,,,
,,,
probably easier to look at the library. But just can't see how to implement what I want to implement.

Help would be greatly appreaciated.
 
I was about to ask you how to configure or figure out what it is configured for.

Note: in the storage.h file I don't see any of the TEST_RAM... (By github the files were uploaded maybe 6 hours ago?)

As you know I really don't like having to edit of header files to configure as may have multiple setups... To get around on some of my own projects put everything in header files. But that sort of sucks...

Also maybe the options like has_included if something like that can work or not...
 
I was about to ask you how to configure or figure out what it is configured for.

Note: in the storage.h file I don't see any of the TEST_RAM... (By github the files were uploaded maybe 6 hours ago?)

As you know I really don't like having to edit of header files to configure as may have multiple setups... To get around on some of my own projects put everything in header files. But that sort of sucks...

Also maybe the options like has_included if something like that can work or not...

oops - your copy has it in storage.cpp - trying things out

Also maybe the options like has_included if something like that can work or not...
That might work - will have to give something like it a try - after my nap :)
 
Another question/possibility?

Could it compile to handle all three?
Right now in the sketch you have:
Code:
  if (!Storage_init()) {
Could this be setup like:
Storage_init(my_buffer, sizeof(buffer)); // user want the RAM drive version.
Storage_init(6); // Assuming 6 is CS pin so SPI
Storage_init(SDCARD_BUILTIN); // use QSPI?

EDIT: if this works, obviously the SDCARD_BUILTIN is probably not the best name here but maybe pin of -1.
Also init(6, SPI1);

Would be good to be allowed as well. Pas by reference and default to SPI...
 
Last edited:
When I first looked into MTP my understanding was that one should derive a storage specific implementation from Interface

So one would have something like

Code:
  MTPStorage_SD storage1;
  MTPD       mtpd1(&storage1);

  MTPStorage_LFS storage2;
  MTPD       mtpd2(&storage2);
etc.

So my suggestion is to have multiple implementations in parallel (optimized to the task).
Anyhow, the actual Storage_SD implementation is only one way to do it.
E.g. at the certain point, Teensies may have sufficient RAM to keep index table in RAM
 
When I first looked into MTP my understanding was that one should derive a storage specific implementation from Interface

So one would have something like

Code:
  MTPStorage_SD storage1;
  MTPD       mtpd1(&storage1);

  MTPStorage_LFS storage2;
  MTPD       mtpd2(&storage2);
etc.

So my suggestion is to have multiple implementations in parallel (optimized to the task).
Anyhow, the actual Storage_SD implementation is only one way to do it.
E.g. at the certain point, Teensies may have sufficient RAM to keep index table in RAM

Actually that would be the way to do it when and if I merge the LFS into the main branch of MTPResponder so you have access to both SD and LFS. The problem is in the storage class itself you need 3 defines (RAM, SPI, and QSPI) to set up the correct constructor and the correct begins for each. That is where I am having a problem.

Don't really want to set up 3 storage classes for LFS for RAM, SPI and QSPI when the only difference is in the constructor/begin.
 
Don't really want to set up 3 storage classes for LFS for RAM, SPI and QSPI when the only difference is in the constructor/begin.

I guess, it is proper C++ to allow multiple constructors.
It may also be useful to combine the different FS interfaces into a own class (or Paul augments his interface class)
e.g. SD has no rename, and begin is not flexible enough (for this reason Paul made public access to sdfs)
Note: my actual "#define sd_begin" etc. differentiation is only to facilitate my style of porting and should be made properly
 
@WMXZ
No problem with your coding style at all. I managed to get it working for SPIFFs without a problem.

Think I got a work around for my problem though. Not even going to try and get it incorporated into the master - getting confused enough with c++ as is :)
 
@mjs513 - did a build from your test - my machine shows device Teensy MTP Disk - but 'Unavailable' ...

I started with mtp-test.ino - but replaced with your posted code dropping the pin13 toggle?

It built fine : on a T_4.0 with Audio card - so something isn't set right perhaps ...

Not sure about the 'locked' - I was here late too - didn't see that and didn't try to do it ... fixed now.
 
Back
Top