LittleFS port to Teensy/SPIFlash

That didn't help with data integrity however, it dies on QSPI creating First file 'B' with current timing.

Will wait for Paul to investigate QSPI timing.

That was trying to put B in dir 0 - and NONE of the Subddirs were created? Second out put below.

Turned it back to ROOTONLY and creating /B_file.txt fails too:
Code:
[  0.09] Awaiting input 0123456789rdchkfvp? loops left 0 >
d
[  0.09] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /B_file.txt Fail File open 
[  0.15] Awaiting input 0123456789rdchkfvp? loops left 0 >


Code:
?[  0.02] Awaiting input 0123456789rdchkfvp? loops left 0 >attemping to format existing media
  waited 27590 us
  waited 122 us
  waited 25582 us
  waited 123 us
success
f
printDirectory QSPI_DISK
--------------
 0 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes
[  0.09] Awaiting input 0123456789rdchkfvp? loops left 0 >
[  0.18] Awaiting input 0123456789rdchkfvp? loops left 0 >
printDirectory QSPI_DISK
--------------
 0 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes

[  0.20] Awaiting input 0123456789rdchkfvp? loops left 0 >
d
[  0.20] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /0_dir/B_file.txt Fail File open 
[  2.80] Awaiting input 0123456789rdchkfvp? loops left 0 >1
 QSPI_DISK +++ Add ++++ ++ B Fail File open /0_dir/B_file.txt
[  2.82] Awaiting input 0123456789rdchkfvp? loops left 1 >1

:: /0_dir/C_file.txt Fail File open 
[  2.85] Awaiting input 0123456789rdchkfvp? loops left 1 >

Here's the code in use - require the added ::format() hack >> View attachment LFSintegrity.zip
 
That didn't help with data integrity however, it dies on QSPI creating First file 'B' with current timing.

Will wait for Paul to investigate QSPI timing.

That was trying to put B in dir 0 - and NONE of the Subddirs were created? Second out put below.

Turned it back to ROOTONLY and creating /B_file.txt fails too:
...........

Here's the code in use - require the added ::format() hack >> View attachment 22428

Ok so think its kind of working - guess Paul will have to see if I did it correctly.

I actually tried format to see if it helped with data integrity with QSPI but saw the same thing as you saw - but until issues fixed we still can make progress. The odds are if it works on SPI it will work with QSPI once its fixed.

"RENAME" added function, works from the sketch from my limited testing but in my version of MTP only works for one file change and a bit inconsistent so that looks like it needs some more work. Going to try and debug a bit today. Think what is happening is that after the first update I have to refresh the directory listing but don't know yet.

Did you notice that @WMXZ has an updated version of MTP responder that allows multiple SD Cards?

EDIT: Just as a test I ran MTPResponder (before multiple CS pins version) and the same thing happens with renaming multiple files - you can only do rename 1 file during the session. If you reboot you can do another. Note this does not apply when you are doing it from within a sketch not and not using MTP_LFS
 
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

A little lost on exactly how to do this in the lib, think its in MTP.h
Code:
// MTP Responder.
class MTPD1 {
public:
  explicit MTPD1(MTPStorageInterface1* storage1) : storage1_(storage1) {}
private:
  MTPStorageInterface1* storage1_;

Then would have to change storage to storage1 in rest of mtp.h and mtp.cpp? Could I then get away with doing:
 
I added functions to report the number of bytes used and total size of each filesystem.

https://github.com/PaulStoffregen/cores/commit/7f02c72b15b0c9a35b5f60a0b8ab3410c9f52049
https://github.com/PaulStoffregen/SD/commit/9b52e7d63979cfbd8908ef8dd1f48e5b3ab0678f
https://github.com/PaulStoffregen/LittleFS/commit/a283a8b9ef876a6596ac80a6b86c39ef7076e827

Hopefully together with rename() this gets us closer to FS providing everything MTP needs from the storage class?

Thanks Paul - was just looking at LittleFs to add in the check for unmount so perfect timing. Think thats about it for MTP at this point - haven't run into any other issues so far in testing. Will update to for bytes used and total bytes. My kludge is not a very eloquent one :)
 
I added functions to report the number of bytes used and total size of each filesystem.

https://github.com/PaulStoffregen/cores/commit/7f02c72b15b0c9a35b5f60a0b8ab3410c9f52049
https://github.com/PaulStoffregen/SD/commit/9b52e7d63979cfbd8908ef8dd1f48e5b3ab0678f
https://github.com/PaulStoffregen/LittleFS/commit/a283a8b9ef876a6596ac80a6b86c39ef7076e827

Hopefully together with rename() this gets us closer to FS providing everything MTP needs from the storage class?

Looks like your bytes use and total size functions are operational, just tested with SPIFlash which gave me:
Code:
LittleFS Test

flash begin

Flash ID: EF 70 18
Flash size is 16.00 Mbyte
attemping to mount existing media

success

started

printDirectory
--------------

FILE	PRINTOUTPUT1.txt		4396

FILE	PRINTOUTPUT2.txt		4410

FILE	file1.txt		224

FILE	file10.txt		112

FILE	file2.txt		224

FILE	file20.txt		112

FILE	file3.txt		224

FILE	file30.txt		112

DIR	structuredData / 

	FILE	logger.txt		3360

DIR	test1 / 

	FILE	file1.txt		112

DIR	test2 / 

	FILE	file2.txt		112

DIR	test3 / 

	FILE	file3.txt		112



Disk Usuage:
Blocks: 15, Block Count: 4096, Block Size; 4096
Block Count: 4096, Block Size; 4096
Bytes Used: 61440, Bytes Total:16777216

Just as a note so no one goes crazy, the 2 functions return uint64 so when you print use something like the following:
Code:
  Serial.printf("Bytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());

now on to some more playing.
 
Quick update - I am still in other diversions...

I did just sync up Core and it does not build ;) usb.c line 1002
Code:
#if #ifdef USB_MTPDISK

Also looks like I need to update the SD library as well. as get link errors.
 
Alcon

Just did an update to to MTP_LFS does a couple things hopefully:
1. added functionality for rename and uses the new LittleFS functions for bytes used and total size.
2. Changed include name for MTP.h to MTP_LFS.h and updated to use a different storage identifer (storagae1) - i updated the mtp example accodinly.

Also updated LittleFS on my fork to unmount the storage media first before format and then do the reformat: https://github.com/mjs513/LittleFS. This change has been issued to Pauls repository until @defragster gets at it :)
 
Quick update - I am still in other diversions...

I did just sync up Core and it does not build ;) usb.c line 1002
Code:
#if #ifdef USB_MTPDISK

That was a pretty dumb mistake on my part - trying to edit too many files at the same time. Just issued the PR to fix back to Paul
 
'LFSIntegrity.ino' : Using now current pjrc LittleFS and mjs513 disk size info print in PrintDir.
Also the myfs.format(); Now in use for SPI and QSPI:

Code:
printDirectory SPI_DISK
--------------FILE	A_file.txt		101
FILE	B_file.txt		22
FILE	C_file.txt		42
FILE	D_file.txt		62
FILE	E_file.txt		82
FILE	F_file.txt		102
FILE	G_file.txt		122
FILE	H_file.txt		142
FILE	I_file.txt		162
FILE	J_file.txt		182
FILE	K_file.txt		202
FILE	L_file.txt		222
FILE	M_file.txt		242
FILE	N_file.txt		262
FILE	O_file.txt		282
FILE	P_file.txt		151
FILE	Q_file.txt		161
FILE	R_file.txt		171
FILE	S_file.txt		181
FILE	T_file.txt		191
FILE	U_file.txt		201
FILE	V_file.txt		211
FILE	W_file.txt		221
FILE	X_file.txt		231
FILE	Y_file.txt		241
FILE	Z_file.txt		251

 0 dirs with 26 files of Size 4440 Bytes
 Total 26 files of Size 4440 Bytes
Bytes Used: 32768, Bytes Total:16777216

Then re-running Just creating the empty 10 root dirs:
Code:
printDirectory SPI_DISK
--------------DIR	0_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	1_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	2_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	3_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	4_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	5_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	6_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	7_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	8_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	9_dir / 

 0 dirs with 0 files of Size 0 Bytes
FILE	A_file.txt		101
FILE	B_file.txt		22
FILE	C_file.txt		42
FILE	D_file.txt		62
FILE	E_file.txt		82
FILE	F_file.txt		102
FILE	G_file.txt		122
FILE	H_file.txt		142
FILE	I_file.txt		162
FILE	J_file.txt		182
FILE	K_file.txt		202
FILE	L_file.txt		222
FILE	M_file.txt		242
FILE	N_file.txt		262
FILE	O_file.txt		282
FILE	P_file.txt		151
FILE	Q_file.txt		161
FILE	R_file.txt		171
FILE	S_file.txt		181
FILE	T_file.txt		191
FILE	U_file.txt		201
FILE	V_file.txt		211
FILE	W_file.txt		221
FILE	X_file.txt		231
FILE	Y_file.txt		241
FILE	Z_file.txt		251

 10 dirs with 26 files of Size 4440 Bytes
 Total 26 files of Size 4440 Bytes
Bytes Used: 114688, Bytes Total:16777216

Then takes 2.5 M to run 9 loops to get to :
Code:
 10 dirs with 26 files of Size 7008 Bytes
 Total 262 files of Size 44496 Bytes
Bytes Used: 442368, Bytes Total:16777216

Windy here - my power just went off :(
 
Windy here too, it has blinked a couple of times, but still on. Keeping fingers crossed.

But first back to diversion...
 
As a result of @WMXZ update of the MTP Responder library to use multiple SD Cards decided to give it a try with multiple SPI Flash chips using a Winbond breakout and the propshield. After a few hours of figuring it out was able to get it working this morning. Limited testing but doesnt seem to copy between flash chips. Think there is still some bugs in it though. Here is a quick screen shot

Capture.PNG

Heres the WIP Branch - no guarantees everything is working correctly: https://github.com/mjs513/mtp_responder-for-LittleFs/tree/MTP-LittleFS---WIP.
 
Alcon
Added in RAM and QSPI. With RAM disk you can actually have multiple ram disks if I did it right :) I updated the WIP branch for all three now: https://github.com/mjs513/mtp_respon...LittleFS---WIP.

This can not have two instances open though, say 1 for RAM and the other for QSPI. Can only do one at a time. What happens if you try both you get:
Code:
In file included from D:\Users\Merli\Documents\Arduino\libraries\MTP_t4_littlefs\examples\mtp-test_combined1\mtp-test_combined1.ino:13:0:
D:\Users\Merli\Documents\Arduino\libraries\MTP_t4_littlefs\src/MTP_QSPI.h: At global scope:
D:\Users\Merli\Documents\Arduino\libraries\MTP_t4_littlefs\src/MTP_QSPI.h:47:42: error: expected ')' before '*' token
   explicit MTPD_QSPI(MTPStorageInterface3* storage3) : storage3_(storage3) {}
                                          ^
D:\Users\Merli\Documents\Arduino\libraries\MTP_t4_littlefs\src/MTP_QSPI.h:49:3: error: 'MTPStorageInterface3' does not name a type
   MTPStorageInterface3* storage3_;
   ^
D:\Users\Merli\Documents\Arduino\libraries\MTP_t4_littlefs\examples\mtp-test_combined1\mtp-test_combined1.ino:61:24: error: variable or field 'storage_configure' declared void
   void storage_configure(MTPStorage_QSPI *storage3, const char **qspi_str, const int *qspiIdx, LittleFS_QSPIFlash *sdr, int num)
but I can not figure out how to resolve this type of issue.

If you run the mtp_test_combined1.ino sketch you will see what I mean. However, mtp_test_combined works fine
 
First, please allow me to apologize for not keeping up with this thread for the last several days. I've missed or only lightly skimmed the last ~100 messages.

Can anyone give me a quick recap of the remaining QSPI problems and the smallest test code I could use to reproduce them? I'd like to get QSPI working well before packaging up 1.54-beta5 "soon". I do have some time to work on QSPI today and tomorrow morning.

I also haven't had any time to yet to work with MTP. But my hope is for the FS class to eventually replace the various storage classes. So a second question is what else are those storage classes doing that FS would need to provide?
 
@Paul - on QSPI:

>> Updated from github:: CORES, SD, SdFat-Beta, LittleFS

Looking at my LFSIntegrity sketch for simple repro ...

Just saw it create files okay - and be able to read them - but DIR failed to show G_file.txt - created next file and then it was indicated ???

This is new behavior with updated files. It does indicate a problem - just not what it was before ...

Will look to see repro - but here is my output showing that:
Code:
[  0.47] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /F_file.txt   waited 106 us
  waited 144 us
 QSPI_DISK +++ Add ++++ ++ F 
:: /G_file.txt   waited 105 us
  waited 156 us
 QSPI_DISK +++ Add ++++ ++ G 
[  0.51] Awaiting input 0123456789rdchkfvp? loops left 0 > Verbose onv
[  0.57] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /H_file.txt   waited 105 us
  waited 167 us
 QSPI_DISK +++ Add ++++ ++ H 
	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]	FILE	G_file.txt		61
[/B]
 0 dirs with 6 files of Size 216 Bytes

:: /I_file.txt   waited 106 us
  waited 24346 us
  waited 367 us
  waited 372 us
  waited 132 us
 QSPI_DISK +++ Add ++++ ++ I 
	FILE	B_file.txt		11
	FILE	C_file.txt		21
	FILE	D_file.txt		31
[B][COLOR="#FF0000"]	FILE	E_file.txt		41
	FILE	F_file.txt		51
[/COLOR][/B]	FILE	H_file.txt		71
	FILE	I_file.txt		81

 0 dirs with 7 files of Size 307 Bytes

[  0.64] Awaiting input 0123456789rdchkfvp? loops left 0 > 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
?
[  1.09] Awaiting input 0123456789rdchkfvp? loops left 0 >
printDirectory QSPI_DISK
--------------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][COLOR="#FF0000"]FILE	G_file.txt		61[/COLOR][/B]
FILE	H_file.txt		71
FILE	I_file.txt		81

 0 dirs with 8 files of Size 368 Bytes
 Total 8 files of Size 368 Bytes
Bytes Used: 8192, Bytes Total:16777216

Note: DIR during create specifies a single folder and bypasses the 'total bytes' printed in the Full disk directory
 
@Paul
First - no need to apologize at all considering all the other things you have on your plate. Besides thread got pretty long :)

In a similar vain to @defragster's sketch if you run and load the following sketch for QSPI (creates a bunch of files in root and 4 sub-directories, at the end it printsL
Code:
#include <LittleFS.h>

//LittleFS_RAM myfs;
//LittleFS_SPIFlash myfs;
LittleFS_QSPIFlash myfs;
char buf[200000];

File file1, file2, file3;

char fname[32] = "my_file1";
int szLen = strlen( buf );
elapsedMicros my_us;
uint32_t lCnt = 0;
uint32_t cCnt = 0;

//define a struct of various data types
 struct MYDATA_t {
  bool data_0;
  float data_1; 
  long data_2; 
  int data_3;
  char data_4[32];
};

//define a struct joining MYDATA_t to an array of bytes to be stored
 union MYDATA4RAM_t {
 MYDATA_t datastruct;
 char Packet[sizeof(MYDATA_t)];
};

MYDATA4RAM_t mydata; //data to be written in memory
MYDATA4RAM_t readdata; //data read from memory


void setup() {
  //pinMode(13, OUTPUT);
  //digitalWrite(13, HIGH);
  while (!Serial) ; // wait
    Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
  Serial.println("LittleFS Timer Test"); delay(5);
  
  //if (!myfs.begin(buf, sizeof(buf))) {
pinMode(10, OUTPUT); digitalWrite(10, HIGH);
  //if(!myfs.begin(10)) {
  if(!myfs.begin()) {
    Serial.println("Error starting ramdisk");
    while (1) ;
  }

  //printDirectory();

  //Serial.printf("Disk Usuage:\n");
  //Serial.printf("Bytes Used: %d, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());

  //test of print
  Serial.println("Using println and printf to printoutput file");
  file1 = myfs.open("PRINTOUTPUT1.txt", FILE_WRITE);
  Serial.println("opened PRINTOUTPUT1.txt");
  file2 = myfs.open("PRINTOUTPUT2.txt", FILE_WRITE);
  Serial.println("opened PRINTOUTPUT2.txt");

  for(uint8_t i = 0; i < 10; i++) {
    file1.println("abcdefghijklmnopqrstuvwxyz");
    file1.printf("Rec: %d, Float: %f, Int: %d\n",i,i+26.4, i+98);
    file2.println("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    //eRAM.println("THIS IS A TEST");
    file2.printf("Rec: %d, Float: %f, Int: %d\n",i,i+56.4, i+198);
  }

  file1.close();
  file2.close();

  printDirectory();
  
  Serial.println("-------------------------------");
  Serial.println("File1 contents:");
  Serial.println("-------------------------------");

  file1 = myfs.open("PRINTOUTPUT1.txt");
  Serial.printf("File1 size: %d\n", file1.size());
  int filesize = file1.size();
  for(uint8_t i = 0; i <30; i++){
      char buf[256];
      int n = file1.read(buf, 256);
      //Serial.printf("read %d bytes\n", n);
      if (n > 255) n = 255;
      buf[n] = 0;
      Serial.println(buf);
      //Used this in place of a file1.eof() function
      //if((file1.position()+1) > filesize) break;
      if(file1.available() == 0) break;
  }
  file1.close();

  structuredWrite();

}
  
void structuredWrite(){
  Serial.println("-------------------------------");
  Serial.println("File3 byte conversion test:");
  Serial.println("-------------------------------");
  Serial.println();
  
  uint32_t arraySize = sizeof(MYDATA_t);
  
  //---------init data - load array
  mydata.datastruct.data_0 = true;
  Serial.print("Data_0: ");
  if (mydata.datastruct.data_0) Serial.println("true");
  if (!mydata.datastruct.data_0) Serial.println("false");
  mydata.datastruct.data_1 = 1.3575;
  Serial.print("Data_1: ");
  Serial.println(mydata.datastruct.data_1, DEC);
  mydata.datastruct.data_2 = 314159L;
  Serial.print("Data_2: ");
  Serial.println(mydata.datastruct.data_2, DEC);
  mydata.datastruct.data_3 = 142;
  Serial.print("Data_3: ");
  Serial.println(mydata.datastruct.data_3, DEC);
  //string test
  String string_test = "The Quick Brown Fox";
  int stringLen = string_test.length();
  Serial.println(stringLen);
  string_test.toCharArray(mydata.datastruct.data_4,stringLen+1);
  Serial.println(string_test);
    
  Serial.println("Init Done - array loaded");
  Serial.println("...... ...... ......");

  Serial.println("create folder");
  if (myfs.mkdir("structuredData")) {
    Serial.println("  success");
  } else {
    Serial.println("  failed");
  }
  Serial.println();

  //lets try something more interesting and complicated
  file3 = myfs.open("/structuredData/logger.txt", FILE_WRITE);
   for(int32_t i = 0; i < 10; i++) {
    file3.write(mydata.Packet, arraySize);
  }
  file3.close();

  Serial.println();
  Serial.println("2nd Directory contents:");
  printDirectory();
  Serial.println();
  
  file3 = myfs.open("/structuredData/logger.txt");
  for(uint8_t i = 0; i <30; i++){
    //if(eRAM.f_eof(file3)) //break loop on EOF
    //    break;
       int n = file3.read(readdata.Packet, arraySize);
      //Used this in place of a file1.eof() function
   
      //---------Send data to serial
      if (readdata.datastruct.data_0) Serial.print("true");
      if (!readdata.datastruct.data_0) Serial.print("false");
      Serial.print(", ");
      Serial.print(readdata.datastruct.data_1, DEC);
      Serial.print(", ");
      Serial.print(readdata.datastruct.data_2, DEC);
      Serial.print(", ");
      Serial.print(readdata.datastruct.data_3, DEC);  
      Serial.print(", ");
        for (uint8_t j = 0; j < stringLen; j++) {
          Serial.print(readdata.datastruct.data_4[j]);
        }
      Serial.println();
      if((file3.position()+1) > file3.size()) break;
      //if(file3.available() == 0) break;
  }
  
  file3.close();

  file1 = myfs.open("file1.txt", FILE_WRITE);
  file2 = myfs.open("file2.txt", FILE_WRITE);
  file3 = myfs.open("file3.txt", FILE_WRITE);
  file1.println("this is a test");
  file2.println("this is a test");
  file3.println("this is a test");  
  file1.close();
  file2.close();
  file3.close();
  file1 = myfs.open("file10.txt", FILE_WRITE);
  file2 = myfs.open("file20.txt", FILE_WRITE);
  file3 = myfs.open("file30.txt", FILE_WRITE);
  file1.println("this is a test");
  file2.println("this is a test");
  file3.println("this is a test");
  file1.close();
  file2.close();
  file3.close();

  //next test
  //lets make a few files and directories.
  Serial.println();
  file1 = myfs.open("file1.txt", FILE_WRITE);
  file2 = myfs.open("file2.txt", FILE_WRITE);
  file3 = myfs.open("file3.txt", FILE_WRITE);
  file1.println("this is a test");
  file2.println("this is a test");
  file3.println("this is a test");
  file1.close();
  file2.close();
  file3.close();

  myfs.mkdir("test1");
  myfs.mkdir("test2");
  myfs.mkdir("test3");
  printDirectory();
  file1 = myfs.open("/test1/file1.txt", FILE_WRITE);
  file2 = myfs.open("/test2/file2.txt", FILE_WRITE);
  file3 = myfs.open("/test3/file3.txt", FILE_WRITE);
  file1.println("this is a test");
  file2.println("this is a test");
  file3.println("this is a test");
  file1.close();
  file2.close();
  file3.close();


  printDirectory();

  //now lets remove them
/*  if(myfs.remove("/test3/file3") == true) 
          Serial.println("file /test3/file3 removed!");
  if(myfs.rmdir("test3") == true)
          Serial.println("directory /test3 removed!");
  myfs.remove("/test2/file2");
  myfs.rmdir("test2");
*/
  printDirectory();

  Serial.printf("Disk Usuage:\n");
  Serial.printf("Bytes Used: %d, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());

}


void printDirectory() {
  Serial.println("printDirectory\n--------------");
  printDirectory(myfs.open("/"), 0);
  Serial.println();
}

void printDirectory(File dir, int numTabs) {
  //dir.whoami();
  while (true) {
 
    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      //Serial.println("**nomorefiles**");
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }

    if(entry.isDirectory()) {
      Serial.print("DIR\t");
    } else {
      Serial.print("FILE\t");
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println(" / ");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}


void loop() {
}

Code:
printDirectory
--------------
FILE	file1.txt		64
FILE	file10.txt		32
FILE	file2.txt		48
FILE	file20.txt		32
FILE	file3.txt		64
FILE	file30.txt		32
DIR	test1 / 
	FILE	file1.txt		32
DIR	test3 /

Running the exact same code on SPIFlash gives different results:
Code:
printDirectory
--------------
FILE	PRINTOUTPUT1.txt		1256
FILE	PRINTOUTPUT2.txt		1260
FILE	file1.txt		64
FILE	file10.txt		32
FILE	file2.txt		64
FILE	file20.txt		32
FILE	file3.txt		64
FILE	file30.txt		32
FILE	mtpindex.dat		0
DIR	structuredData / 
	FILE	logger.txt		960
DIR	test1 / 
	FILE	file1.txt		32
DIR	test2 / 
	FILE	file2.txt		32
DIR	test3 / 
	FILE	file3.txt		32
Think this pretty much highlights the issue currently with QSPI that I am seeing. The SPIFLash test was done with a propshield but i get the same results with a Winbond breakout board that I am using.
 
First, please allow me to apologize for not keeping up with this thread for the last several days. I've missed or only lightly skimmed the last ~100 messages.

Can anyone give me a quick recap of the remaining QSPI problems and the smallest test code I could use to reproduce them? I'd like to get QSPI working well before packaging up 1.54-beta5 "soon". I do have some time to work on QSPI today and tomorrow morning.

I also haven't had any time to yet to work with MTP. But my hope is for the FS class to eventually replace the various storage classes. So a second question is what else are those storage classes doing that FS would need to provide?

First, just remember you asked this question. MTP for SD Card does not [CORRECTED] suffer from this as it calls back to SDFat-beta through FS .

Not sure I can really explain this without getting myself and everyone confused. MTP works by reading the contents of a directory and storing it on the device in a file mtpindex.dat in the root directory. For the SD Card version it scans the directory by tracking the files handle (0 - xxx number). Think SD when you open a file it returns the index number of the file in the directory. With FS it returns a 0 or 1. There is also a file_.openNextFile(); function which I guess gets the next file - with us we do it by using DIR.
Code:
  void MTPStorage_SD::ScanDir(uint32_t storage, uint32_t i) 
  { Record record = ReadIndexRecord(i);
    if (record.isdir && !record.scanned) {
      OpenFileByIndex(i);
      if (!sd_isOpen(file_)) return;
    
      int sibling = 0;
      while (true) 
      { mtp_lock_storage(true);
        child_=file_.openNextFile();
        mtp_lock_storage(false);
        if(!sd_isOpen(child_)) break;

        Record r;
        r.store = record.store;
        r.parent = i;
        r.sibling = sibling;
        r.isdir = child_.isDirectory();
        r.child = r.isdir ? 0 : child_.size();
        r.scanned = false;
        sd_getName(child_,r.name,64);
        sibling = AppendIndexRecord(r);
        child_.close();
      }
      record.scanned = true;
      record.child = sibling;
      WriteIndexRecord(i, record);
    }
  }

I currently work around this whole issue with a modified printdirectory function:
Code:
  void MTPStorage_RAM::ScanDir(uint32_t storage, uint32_t i) 
  { Record record = ReadIndexRecord(i);
    if (record.isdir && !record.scanned) {
		//need to convert record name to string and add a "/" if not just a /
	if(strcmp(record.name, "/") != 0) {
		char str1[65] = "/";
		strncat(str1, record.name,64);
		printDirectory1(sdp[record.store].open(str1), 0);
	} else {
		printDirectory1(sdp[record.store].open(record.name), 0);
	}

      OpenFileByIndex(i);
	   mtp_lock_storage_ram(true);
        mtp_lock_storage_ram(false);
      if (!file_) return;
      int sibling = 0;
	  
      for(uint16_t rec_count=0; rec_count<entry_cnt; rec_count++) 
      {
        Record r;
		r.store = record.store;
        r.parent = i;
        r.sibling = sibling;
        r.isdir = entries[rec_count].isDir;
        r.child = r.isdir ? 0 : entries[rec_count].size;
        r.scanned = false;
		memset(r.name, 0, sizeof(r.name));
		for(uint8_t j=0;j<entries[rec_count].fnamelen;j++)
				r.name[j] = entries[rec_count].name[j];
        sibling = AppendIndexRecord(r);
    }
      record.scanned = true;
      record.child = sibling;
      WriteIndexRecord(i, record);
    }
  }



void MTPStorage_RAM::printDirectory1(File dir, int numTabs) {
  //dir.whoami();
  entry_cnt = 0;
  while (true) {
    entry_cnt = entry_cnt + 1;
    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      //Serial.println("**nomorefiles**");
      break;
    }
    //for (uint8_t i = 0; i < numTabs; i++) {
    //  Serial.print('\t');
    //}

    if(entry.isDirectory()) {
      //Serial.print("DIR\t");
      entries[entry_cnt].isDir = 1;
    } else {
      //Serial.print("FILE\t");
      entries[entry_cnt].isDir = 0;
    }
    Serial.println(entry.name());
    
    if (entry.isDirectory()) {
      cx = snprintf ( buffer, 64, "%s", entry.name() );
	  entries[entry_cnt].fnamelen = cx;
	  //Serial.println(cx);
      for(int j =0;j<cx;j++) entries[entry_cnt].name[j] = buffer[j];
      //Serial.print(entries[entry_cnt].isDir);
      //Serial.print("  ");Serial.println(entries[entry_cnt].name);
	  entries[entry_cnt].size = 0;
      //printDirectory1(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      //Serial.print("\t\t");
      //Serial.println(entry.size(), DEC);
      cx = snprintf ( buffer, 64, "%s", entry.name() );
		entries[entry_cnt].fnamelen = cx;
		//Serial.print("NAME LEN: ");Serial.println(entries[entry_cnt].fnamelen);
      for(int j =0;j<cx;j++) entries[entry_cnt].name[j] = buffer[j];
      //Serial.print(entries[entry_cnt].isDir);
      //Serial.print(" ");Serial.print(entries[entry_cnt].name);
      entries[entry_cnt].size = entry.size();
      //Serial.print(" "); Serial.println( entries[entry_cnt].size);
    }
    entry.close();
  }
  //Serial.println(entry_cnt);
}
A bit more complicated but it works.
 
Last edited:
Follow on to p#243 - still no clear Failure on FILE write like before - but now enabling the creation of 10 Root directories before any files, doing a DIR again then adding files and another DIR.

Updating Source w/test to post ... output will change to add 'yet more spew' based on the following as it progresses ...

This is done commenting the #define ROOTONLY at top of file and rebuilding.

// COMMENTS - observations inline :: // ODD
Fresh FORMAT and Teensy RESET - shows empty QSPI disk mounted on entry to sketch:
Code:
 RESET Teensy ...
T:\tCode\littleFS\LFSintegrity\LFSintegrity.ino Nov 15 2020 15:13:12
LittleFS Test : File Integrity
QSPI flash begin
Flash ID: EF 40 18
Flash size is 16.00 Mbyte
attempting to mount existing media
success
printDirectory QSPI_DISK
--------------
 0 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes
Bytes Used: 8192, Bytes Total:16777216
 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
?  waited 22910 us
  waited 84 us
  waited 122 us
  waited 26823 us
  waited 99 us
  waited 123 us
  waited 24812 us
  waited 99 us
  waited 120 us
  waited 24364 us
  waited 97 us
  waited 123 us
  waited 23825 us
  waited 99 us
  waited 123 us
  waited 24726 us
  waited 99 us
  waited 123 us
  waited 25155 us
  waited 100 us
  waited 122 us
  waited 24866 us
  waited 98 us
  waited 123 us
  waited 24014 us
  waited 99 us
  waited 123 us
  waited 25305 us
  waited 99 us
  waited 123 us
[  0.03] Awaiting input 0123456789rdchkfvp? loops left 0 > [B]// ODD[/B] - not odd yet - but first 'USB Enter' creates 10 subdirectories
printDirectory QSPI_DISK
--------------DIR	0_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	1_dir / 

 0 dirs with 0 files of Size 0 Bytes     [B]// ODD:[/B] No dir #2
DIR	3_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	4_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	5_dir / 

 0 dirs with 0 files of Size 0 Bytes     [B]// ODD:[/B] No dir #6
DIR	7_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	8_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	9_dir / 

 0 dirs with 0 files of Size 0 Bytes

 8 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes
Bytes Used: 16384, Bytes Total:16777216
[  1.95] Awaiting input 0123456789rdchkfvp? loops left 0 >     [B]// ODD:[/B] Paused here and execute 'DIR' :: Compare 'Bytes Used' above and next below
printDirectory QSPI_DISK
--------------DIR	0_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	2_dir / 

 0 dirs with 0 files of Size 0 Bytes     [B]// ODD:[/B] Now Dir #1 not shown
DIR	3_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	4_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	5_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	7_dir / 

 0 dirs with 0 files of Size 0 Bytes     [B]// ODD:[/B] Again no Dir #6
DIR	8_dir / 

 0 dirs with 0 files of Size 0 Bytes
DIR	9_dir / 

 0 dirs with 0 files of Size 0 Bytes

 8 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes
Bytes Used: 90112, Bytes Total:16777216     [B]// ODD:[/B] Executing the PrintDirectory code now shows 'Bytes Used: 90112' and above was 16384.

[  3.41] Awaiting input 0123456789rdchkfvp? loops left 0 >
d
[  3.41] Awaiting input 0123456789rdchkfvp? loops left 0 >1     [B]// ODD:[/B] Not Odd yet [code starts on file B] - this calls the file create code : Seems to add 2 files to each of 10 directories, and 2 files on the root.
:: /0_dir/B_file.txt   waited 105 us
  waited 97 us
 QSPI_DISK +++ Add ++++ ++ B 
:: /0_dir/C_file.txt   waited 106 us
  waited 109 us
 QSPI_DISK +++ Add ++++ ++ C 
:: /1_dir/D_file.txt   waited 106 us
  waited 121 us
 QSPI_DISK +++ Add ++++ ++ D 
:: /1_dir/E_file.txt   waited 106 us
  waited 133 us
 QSPI_DISK +++ Add ++++ ++ E 
:: /2_dir/F_file.txt   waited 105 us
  waited 144 us
 QSPI_DISK +++ Add ++++ ++ F 
:: /2_dir/G_file.txt   waited 106 us
  waited 155 us
 QSPI_DISK +++ Add ++++ ++ G 
:: /3_dir/H_file.txt   waited 105 us
  waited 167 us
 QSPI_DISK +++ Add ++++ ++ H 
:: /3_dir/I_file.txt   waited 105 us
  waited 179 us
 QSPI_DISK +++ Add ++++ ++ I 
:: /4_dir/J_file.txt   waited 106 us
  waited 191 us
 QSPI_DISK +++ Add ++++ ++ J 
:: /4_dir/K_file.txt   waited 106 us
  waited 204 us
 QSPI_DISK +++ Add ++++ ++ K 
:: /5_dir/L_file.txt   waited 106 us
  waited 214 us
 QSPI_DISK +++ Add ++++ ++ L 
:: /5_dir/M_file.txt   waited 105 us
  waited 225 us
 QSPI_DISK +++ Add ++++ ++ M 
:: /6_dir/N_file.txt   waited 105 us
  waited 237 us
 QSPI_DISK +++ Add ++++ ++ N 
:: /6_dir/O_file.txt   waited 105 us
  waited 249 us
 QSPI_DISK +++ Add ++++ ++ O 
:: /7_dir/P_file.txt   waited 105 us
  waited 260 us
 QSPI_DISK +++ Add ++++ ++ P 
:: /7_dir/Q_file.txt   waited 106 us
  waited 273 us
 QSPI_DISK +++ Add ++++ ++ Q 
:: /8_dir/R_file.txt   waited 105 us
  waited 284 us
 QSPI_DISK +++ Add ++++ ++ R 
:: /8_dir/S_file.txt   waited 106 us
  waited 295 us
 QSPI_DISK +++ Add ++++ ++ S 
:: /9_dir/T_file.txt   waited 105 us
  waited 309 us
 QSPI_DISK +++ Add ++++ ++ T 
:: /9_dir/U_file.txt   waited 105 us
  waited 322 us
 QSPI_DISK +++ Add ++++ ++ U 
:: /V_file.txt   waited 106 us
  waited 331 us
 QSPI_DISK +++ Add ++++ ++ V 
:: /W_file.txt   waited 106 us
  waited 342 us
 QSPI_DISK +++ Add ++++ ++ W      [B]// ODD:[/B] Not Odd yet - created the files and wrote data, file is Opened and read back to assure content - error noted on fail - none noted.
[  4.05] Awaiting input 0123456789rdchkfvp? loops left 0 >     [B]// ODD:[/B] Odd ahead : Should have 22 total files "B-W" created above after this DIR command
printDirectory QSPI_DISK
--------------DIR	0_dir / 
	FILE	B_file.txt		11

 0 dirs with 1 files of Size 11 Bytes     [B]// ODD:[/B] Note File "B" but not "C" in 0_dir
DIR	2_dir / 
	FILE	F_file.txt		51

 0 dirs with 1 files of Size 51 Bytes     [B]// ODD:[/B] No sign of 1_dir [ and files "D", "E"] nor G_file.txt in 2_dir
DIR	3_dir / 
	FILE	H_file.txt		71
	FILE	I_file.txt		81

 0 dirs with 2 files of Size 152 Bytes
DIR	5_dir / 
	FILE	L_file.txt		111

 0 dirs with 1 files of Size 111 Bytes
DIR	7_dir / 
	FILE	P_file.txt		151
	FILE	Q_file.txt		161

 0 dirs with 2 files of Size 312 Bytes
DIR	9_dir / 
	FILE	T_file.txt		191

 0 dirs with 1 files of Size 191 Bytes     [B]// ODD:[/B] Missing _dir 4,6,8 and Files in them [J,K,N,O,R,S] as well as M,U
FILE	V_file.txt		211
FILE	W_file.txt		221

 6 dirs with 2 files of Size 432 Bytes
 Total 10 files of Size 1260 Bytes
Bytes Used: 90112, Bytes Total:16777216

So that shows many issues - then executing '1' for another pass at file create/extend then runs into the failure to read back 1_dir/F_file.txt after it was just written:
Code:
[  4.15] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /0_dir/X_file.txt   waited 106 us
  waited 354 us
 QSPI_DISK +++ Add ++++ ++ X 
:: /0_dir/Y_file.txt   waited 106 us
  waited 366 us
 QSPI_DISK +++ Add ++++ ++ Y 
:: /1_dir/Z_file.txt   waited 106 us
  waited 373 us
  waited 79 us
 QSPI_DISK +++ Add ++++ ++ Z 
:: /1_dir/A_file.txt   waited 105 us
  waited 203 us
 QSPI_DISK +++ Add ++++ ++ A 
:: /1_dir/B_file.txt   waited 106 us
  waited 97 us
 QSPI_DISK +++ Add ++++ ++ B 
:: /1_dir/C_file.txt   waited 105 us
  waited 109 us
 QSPI_DISK +++ Add ++++ ++ C 
:: /1_dir/D_file.txt   waited 157 us
 QSPI_DISK +++ Add ++++ ++ D 
:: /1_dir/E_file.txt   waited 180 us
 QSPI_DISK +++ Add ++++ ++ E 
:: /1_dir/F_file.txt   waited 24495 us
  waited 370 us
  waited 372 us
  waited 265 us
  waited 25353 us
  waited 168 us
[B] QSPI_DISK +++ Add ++++ ++ F Fail File open /1_dir/F_file.txt[/B]

Note: I see I should show prior file size - will create or Extend a given file { causing movement } - and perhaps the expected amount to Add\Extend this pass.
 
@Paul :: Not sure if this is easy enough to understand to debug and repro ... but it does seem consistent here.
<edit - note> : running this same code below on Audio board with build as #define TEST_SPI works perfectly well

CODE ::

I run on a T_4.1 with 16MB QSPI Flash.

The code starts and pauses at a prompt after showing a DIR.
Code has ROOTDIR only enabled, but the code pauses then does another directory while in setup(), so hit enter.

Verbose is on so after each file change with notes on that it will prompt a directory display.

So start, hit Enter - to start with a FRESH format hit 'f'+enter, do a 'd'IR to see.

It has '?' for Help of the commands.

'1' will process one loop - just two files added , showing the ADD and a DIR

reading the output will make clear when DIR doesn't match the files added.

'1' again will make another pair and so on - all on ROOTONLY.

Here is what I saw with that process - missing files in DIR.

Again the verbose 'dir' is only the selected directory. When 'd' is entered the full DIR shows the Total line.

This then shows 'd' and '1' following with how 'hidden' things show up:
T:\tCode\littleFS\LFSintegrity\LFSintegrity.ino Nov 15 2020 17:37:28
LittleFS Test : File Integrity
QSPI flash begin
Flash ID: EF 40 18
Flash size is 16.00 Mbyte
attempting to mount existing media
success
printDirectory QSPI_DISK
--------------
0 dirs with 0 files of Size 0 Bytes
Total 0 files of Size 0 Bytes
Bytes Used: 8192, Bytes Total:16777216
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: RAM Restart : Q/SPI->'myfs.format();'
'v' Verbose All Dir Prints - TOGGLE
'p' Pause after all Dir prints - TOGGLE
'?' Help list
?[ 0.02] Awaiting input 0123456789rdchkfvp? loops left 0 >
printDirectory QSPI_DISK
--------------
0 dirs with 0 files of Size 0 Bytes
Total 0 files of Size 0 Bytes
Bytes Used: 8192, Bytes Total:16777216
[ 0.03] Awaiting input 0123456789rdchkfvp? loops left 0 >
[ 0.05] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /B_file.txt waited 106 us
waited 97 us
QSPI_DISK +++ Add ++++ [was 0 wrote 11] ++ B Verify /B_file.txt bytes read 11 and size 11
FILE B_file.txt 11

0 dirs with 1 files of Size 11 Bytes

:: /C_file.txt waited 106 us
waited 108 us
QSPI_DISK +++ Add ++++ [was 0 wrote 21] ++ C Verify /C_file.txt bytes read 21 and size 21
FILE B_file.txt 11

0 dirs with 1 files of Size 11 Bytes

[ 0.11] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /D_file.txt waited 104 us
waited 121 us
QSPI_DISK +++ Add ++++ [was 0 wrote 31] ++ D Verify /D_file.txt bytes read 31 and size 31
FILE B_file.txt 11
FILE D_file.txt 31

0 dirs with 2 files of Size 42 Bytes

:: /E_file.txt waited 106 us
waited 132 us
QSPI_DISK +++ Add ++++ [was 0 wrote 41] ++ E Verify /E_file.txt bytes read 41 and size 41
FILE B_file.txt 11
FILE D_file.txt 31

0 dirs with 2 files of Size 42 Bytes

[ 0.25] Awaiting input 0123456789rdchkfvp? loops left 0 >
printDirectory QSPI_DISK
--------------FILE B_file.txt 11
FILE D_file.txt 31

0 dirs with 2 files of Size 42 Bytes
Total 2 files of Size 42 Bytes
Bytes Used: 8192, Bytes Total:16777216

[ 12.70] Awaiting input 0123456789rdchkfvp? loops left 0 >
d
[ 12.70] Awaiting input 0123456789rdchkfvp? loops left 0 >
printDirectory QSPI_DISK
--------------FILE B_file.txt 11
FILE D_file.txt 31

0 dirs with 2 files of Size 42 Bytes
Total 2 files of Size 42 Bytes
Bytes Used: 8192, Bytes Total:16777216

[ 13.48] Awaiting input 0123456789rdchkfvp? loops left 0 >
d
[ 13.48] Awaiting input 0123456789rdchkfvp? loops left 0 >1
:: /F_file.txt waited 105 us
waited 144 us
QSPI_DISK +++ Add ++++ [was 0 wrote 51] ++ F Verify /F_file.txt bytes read 51 and size 51
FILE B_file.txt 11
FILE D_file.txt 31
FILE F_file.txt 51

0 dirs with 3 files of Size 93 Bytes

:: /G_file.txt waited 106 us
waited 155 us
QSPI_DISK +++ Add ++++ [was 0 wrote 61] ++ G Verify /G_file.txt bytes read 61 and size 61
FILE B_file.txt 11
FILE D_file.txt 31
FILE F_file.txt 51

0 dirs with 3 files of Size 93 Bytes

[ 13.85] Awaiting input 0123456789rdchkfvp? loops left 0 >
printDirectory QSPI_DISK
--------------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
FILE G_file.txt 61

0 dirs with 6 files of Size 216 Bytes
Total 6 files of Size 216 Bytes
Bytes Used: 8192, Bytes Total:16777216

[ 13.91] Awaiting input 0123456789rdchkfvp? loops left 0 >
d
[ 13.91] Awaiting input 0123456789rdchkfvp? loops left 0 >
[ 18.17] Awaiting input 0123456789rdchkfvp? loops left 0 >
[ 18.18] Awaiting input 0123456789rdchkfvp? loops left 0 >
printDirectory QSPI_DISK
--------------FILE B_file.txt 11
FILE D_file.txt 31
FILE F_file.txt 51
FILE G_file.txt 61

0 dirs with 4 files of Size 154 Bytes
Total 4 files of Size 154 Bytes
Bytes Used: 8192, Bytes Total:16777216

[ 18.19] Awaiting input 0123456789rdchkfvp? loops left 0 >
d
[ 18.19] Awaiting input 0123456789rdchkfvp? loops left 0 >

>Note Blank Enter on prompt only returns to prompt [ when "loops left 0 >" is shown ]
So hit that a couple time and the next directory after files B-G were properly shown now only shows B,D,F,G ?
Hit 'enter' the 'd'+'enter' and it changes?
>> Either the PrintDirectory code is confused - or the return "dir.openNextFile();" is ???

If you continue pass this and create all the files from zero size - when adding to the existing files with more loops - it will show failure to access the files.
 
Last edited:
@Paul - minor UI cleanup (First file after DIR header now on new line) - sketch reposting. Hoping it works for you, show failures quickly, and has Format to restart the test at will.
> Added 'l' to show loop() cycle counts, also bytes read and written to the files. Read always at least double the written as it is verified after any write - and also read again on Delete.

Code:
.
 [ATTACH]22478._xfImport[/ATTACH]
.

GENERAL CODE FLOW:
> File I/O has odd pattern - but not random. So knowing loop() count should return to the same point.
> A single iteration passes loop() multiple times before advancing to next Pass.
> In passes ( though A-Z - rather B-Z,A ) counted with cCnt <3 it Creates or extends files.
> if ( cCnt >= 3 && myfs.exists(szPath) ) the file will be deleted, else if not .exists then it is created.
> and : if ( cCnt >= 5 ) cCnt = 0;

Updated edits:
> 'l' now shows more correct loop count - but user CMD I/O can add a loop cycle! :: Loop Count: 21 (#fileCycle=35), Bytes read 4069, written 3835
> doing that and running bigger numbers to test it fails on 'J' - ENTER '0' on a FAILURE stop and the code now does earlier exit to prevent hang noted below.
> Also after that it is failing earlier and restarting Teensy DIES on first DIR print - had to add line #70 "parseCmd( 'f' );" to force Format and upload that
-> this did not repeat - the prior FORMAT must have left something 'offensive' - fresh format continues to

NOTE: I have not seen any lack of file content integrity so far - the confusion shows in DIR entry reporting and display.
Later - unless this is easier to debug: (Loop Count: 29 (#fileCycle=83) ) From 13 iterations of '1' doing delete of "F" when myfs.open(szPath, FILE_WRITE); on a file missing from DIR that should exist (files [B-E] deleted) trying to delete "F", sees it does not exist to delete, and then fails to open for write.
:: /F_file.txt XXX XXX XXX XXX Fail File open
[ 1.62 M] Awaiting input 0123456789rdchkfvpl? loops left 1 >0
QSPI_DISK +++ Add ++++ [was 0 wrote 1] ++ F V Fail File open /F_file.txt
[ 2.23 M] Awaiting input 0123456789rdchkfvpl? loops left 0 >l
Loop Count: 29 (#fileCycle=83), Bytes read 20568, written 10129
> Once that appears the disk is corrupt - and will lock the Teensy after some added 'enter' passes. Restarting Teensy then giving alternating [11,12,13,14] counts of files with repeat directories, so needs 'f'ormat.
> Noted above enter '0' to break from lower loop to avoid hang.
> Doing that at that point then multiple 'd'irs will give a varying number of files I see : 16, 17, 18. Restart Teensy and the numbers go from 15-20 files in root dir.


Flow is simple for ROOTONLY as all 26 files go there. Fixing that for non-finite run may resolve everything.

After ROOTONLY works for large count: 'h', 'k', or 'c'
> Going not defined ROOTONLY creates the 10 dirs and then cycles through them while cycling the file letters

Command List help/'?':
Code:
 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: RAM Restart : Q/SPI->'myfs.format();'
 'v' Verbose All Dir Prints - TOGGLE
 'p' Pause after all Dir prints - TOGGLE
 'l' Show count of loop()'s, Bytes Read,Written
 '?' Help list
 
Last edited:
@Paul
Was dreaming about this stuff last night so had to check and expand on p#244 and p#245 and check something with my error using "explicit statement which by the way can't find anything with google search on the error. I am digressing now.

RE: Post #244: I just updated my Teensy Core and Little_FS files to the latest as of 6:00 am DST :).
  • On re-running the sketch it seemed to actually work and printed the directory correctly.
  • If I reran the sketch then it would only show a partial list of the files and directories created in root.
  • I did add a format command on the third try but still only showed a partial directory listing.

RE: Post #245:
Think SD when you open a file it returns the index number of the file in the directory. With FS it returns a 0 or 1. There is also a file_.openNextFile(); function which I guess gets the next file - with us we do it by using DIR.
The statement I made in RED is incorrect. The issue really is that there is no file_.openNextFile() in LittleFS as it stands now. As I said its done with DIR.

Ok, sun beginning to come up need more coffee.
 
Back
Top