LittleFS port to Teensy/SPIFlash

@Paul: Not rushing to abuse the PCB FLASH makes sense - T_4.0 doesn't have pads - but it has less usable Flash - though could replace size limited EEPROM abuse for (semi)static data, but for one time startup config or whatever that might be - then static external SPI chip would be as good - if a bit more ugly work.

@KurtE mentioned perhaps hand wiring an SPI Flash to bottom 'out of order pads' to get SPI2 (?) - not sure if he progressed on that yet ...

<edit>: as hit post I saw a 'lightbulb' in yes/no: The user can reserve space and you will LittleFS there - and I/O will work and persist ... until the Teensy is re-programmed.
 
Speaking of those other ways, has anyone tried connecting a flash chip to SPI1 or SPI2? In theory it should work if you use something like this:

Code:
  myflash.begin(36, SPI2);
Yes and NO...

On a T4.1 I tried:
Code:
  pinMode(7,OUTPUT);
  digitalWriteFast(7, LOW);
  SPI2.setMOSI(50);
  SPI2.setMISO(54);
  SPI2.setSCK(49);
  SPI2.begin();
  if (!myfs.begin(51, SPI2)) {
Before you had the FLEXSPI2 stuff and it failed to read bottom chips. Again mentioned previously, but Why?
The way the FlexSPI2 pins have LPSPI1 pins that don't really match up to same logical positions. So wrong pins on chip for SCK...
More in the posting: https://forum.pjrc.com/threads/58033-LittleFS-port-to-Teensy-SPIFlash?p=258701&viewfull=1#post258701

However I did use my extended T4.1 and jumpered from T4.1 pins to propshield memory location pins and that works.
 
Speaking of those other ways, has anyone tried connecting a flash chip to SPI1 or SPI2? In theory it should work if you use something like this:

Code:
  myflash.begin(36, SPI2);
This works for SPI1:
Code:
  SPI1.setMOSI(26);
  SPI1.setMISO(39);
  SPI1.setSCK(27);
  if(!myfs.begin(38, SPI1))
just doing
Code:
  if(!myfs.begin(38, SPI1))
does not work.
 
This works for SPI1:
Code:
  SPI1.setMOSI(26);
  SPI1.setMISO(39);
  SPI1.setSCK(27);
  if(!myfs.begin(38, SPI1))
just doing
Code:
  if(!myfs.begin(38, SPI1))
does not work.

Makes sense... Currently the default MISO pin for SPI1 is pin 1 (like T4). The other two calls are not needed as 26 and 27 are the only pins.

Note: Again I wish we could update the T4.1 card with 39 with the alternate color... I totally understand that it may be awhile before new cards are ordered, but at least would be nice to have updated stuff up on website.
 
Makes sense... Currently the default MISO pin for SPI1 is pin 1 (like T4). The other two calls are not needed as 26 and 27 are the only pins.

Note: Again I wish we could update the T4.1 card with 39 with the alternate color... I totally understand that it may be awhile before new cards are ordered, but at least would be nice to have updated stuff up on website.

Thought I tried 1 first but ddin't work - must have had my wiring messed up. So any way moved MISO to pin1 and re-ran the test just to check and yes it using:
Code:
if(!myfs.begin(38, SPI1))
worked without an issue.
 
Morning all
Just finished updating 2 of my example sketches that I had used for SPIFFS. First it the Buddabrot example that uses a ILI9488 display, ext_mem for framebuffer and QSPIFlash to store BMP's. The second is a playback sketch that will read the BMPs from QSPIFlash and display them on the ILF9488.

Cheers.
 

Attachments

  • Buddabrot_LittleFS_9488.zip
    8.1 KB · Views: 59
These are from Arduino's SD library API. Documentation is here:

https://www.arduino.cc/en/Reference/SDopen

While we may add some other stuff Arduino doesn't have, a major goal of mine is to keep compatibility with Arduino's API.

Paul - I totally agree that is a great goal. But wondering about the details and maybe if we can allow additional capabilities to go through.

That is if I look at the SDFat library (or Adafruit version of SD library) I see defines for
FILE_READ and FILE_WRITE which are not the simple:
Code:
#define FILE_READ  0
#define FILE_WRITE 1

That is they have defines like:
Code:
#ifndef FILE_READ
#define FILE_READ O_RDONLY
#endif  // FILE_READ
/** Arduino SD.h style flag for open at EOF for read/write with create. */
#ifndef FILE_WRITE
#define FILE_WRITE (O_RDWR | O_CREAT | O_AT_END)
Which @mjs513 showed earlier as:
Code:
#else  // USE_FCNTL_H
#define O_RDONLY  0X00  ///< Open for reading only.
#define O_WRONLY  0X01  ///< Open for writing only.
#define O_RDWR    0X02  ///< Open for reading and writing.
#define O_AT_END  0X04  ///< Open at EOF.
#define O_APPEND  0X08  ///< Set append mode.
#define O_CREAT   0x10  ///< Create file if it does not exist.
#define O_TRUNC   0x20  ///< Truncate file to zero length.
#define O_EXCL    0x40  ///< Fail if the file exists.
#define O_SYNC    0x80  ///< Synchronized write I/O operations.
Which I see in #116 @mjs513 added to his FS.H
Code:
#define FILE_RDWR    0X02  ///< Open for reading and writing.
#define FILE_AT_END  0X04  ///< Open at EOF.
#define FILE_APPEND  0X08  ///< Set append mode.
#define FILE_CREATE   0x10  ///< Create file if it does not exist.
#define FILE_TRUNC   0x20  ///< Truncate file to zero length.
#define FILE_EXCL    0x40  ///< Fail if the file exists.
#define FILE_SYNC    0x80  ///< Synchronized write I/O operations.

So question is should we adapt to these and if so, should the lfs code defines be changed to match:
Code:
    // open flags
    LFS_O_RDONLY = 1,         // Open a file as read only
    LFS_O_WRONLY = 2,         // Open a file as write only
    LFS_O_RDWR   = 3,         // Open a file as read and write
    LFS_O_CREAT  = 0x0100,    // Create a file if it does not exist
    LFS_O_EXCL   = 0x0200,    // Fail if a file already exists
    LFS_O_TRUNC  = 0x0400,    // Truncate the existing file to zero size
    LFS_O_APPEND = 0x0800,    // Move to end of file on every write

Or slight variation of this, should the LFS_O_... be converted to the same as SD library O_...
And then the only ones in SD.h match up to:

Code:
#define FILE_READ  0 // O_RDONLY
#define FILE_WRITE 0x16 // O_RDWR | O_CREAT | O_AT_END

And allow our wrappers to hopefully just pass these through to the two File systems who hopefully know what to do with them?
By the different Bits?

Which would hopefully then allow you to do: File f2 = myfs.open("TEST.txt", O_RDWR | O_CREAT | O_TRUC);
To open a file create it if it does not exist otherwise truncate it if it does exist...
 
Which would hopefully then allow you to do: File f2 = myfs.open("TEST.txt", O_RDWR | O_CREAT | O_TRUC);
To open a file create it if it does not exist otherwise truncate it if it does exist..

Paul - kind of agree with @KurtE on this one. I am now working on modifying MTP Responder to work with LittleFS and running into simple issues like:
Code:
D:\Users\Merli\Documents\Arduino\libraries\MTP_t4-LittleFS\src/Storage.h:156:52: error: 'O_RDONLY' was not declared in this scope
   void OpenFileByIndex(uint32_t i, uint32_t mode = O_RDONLY) ;
which would now require added work if we have a consistent set of modes in the LittleFS lib while at the same time maintaining backward compatibility with the Arduino SD Lib
 
@KurtE
One problem with the USE_FCNTL_H definition is that they are 16 bit
while this for LittleFS may be no issue it is not compatible to FS.h interface where mode is declared as uint8_t
So,
Ether Paul changes FS.h mode to 16 bit to be compatible also to SdFat-beta which internally allows use of FCNTL_H
Or we drop FCNTL_H modes and stick solely to Arduino 8 bit
If Little FS goes 16 bit and FS.h stays 8 bit then we create only confusion
 
@KurtE
One problem with the USE_FCNTL_H definition is that they are 16 bit
while this for LittleFS may be no issue it is not compatible to FS.h interface where mode is declared as uint8_t
So,
Ether Paul changes FS.h mode to 16 bit to be compatible also to SdFat-beta which internally allows use of FCNTL_H
Or we drop FCNTL_H modes and stick solely to Arduino 8 bit
If Little FS goes 16 bit and FS.h stays 8 bit then we create only confusion

Internally I believe LittleFS is 16 bit(actually 32 bits)... At least they had you pass in, things like: lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);

where:
Code:
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
        const char *path, int flags);

But anyway the flags mentioned in previous post the FCNTL ones look like they fit in a byte. Only the Little FS ones don't currently fit...
Code:
// open flags
    LFS_O_RDONLY = 1,         // Open a file as read only
    LFS_O_WRONLY = 2,         // Open a file as write only
    LFS_O_RDWR   = 3,         // Open a file as read and write
    LFS_O_CREAT  = 0x0100,    // Create a file if it does not exist
    LFS_O_EXCL   = 0x0200,    // Fail if a file already exists
    LFS_O_TRUNC  = 0x0400,    // Truncate the existing file to zero size
    LFS_O_APPEND = 0x0800,    // Move to end of file on every write
Question is could we simply modify the LFS ones to match the FCNTL ones?
 
I found this in include/sys/default_fcntl.h
Code:
#define	_SYS__DEFAULT_FCNTL_H_
#include <_ansi.h>
#include <sys/cdefs.h>
#define	_FOPEN		(-1)	/* from sys/file.h, kernel use only */
#define	_FREAD		0x0001	/* read enabled */
#define	_FWRITE		0x0002	/* write enabled */
#define	_FAPPEND	0x0008	/* append (writes guaranteed at the end) */
#define	_FMARK		0x0010	/* internal; mark during gc() */
#define	_FDEFER		0x0020	/* internal; defer for next gc pass */
#define	_FASYNC		0x0040	/* signal pgrp when data ready */
#define	_FSHLOCK	0x0080	/* BSD flock() shared lock present */
#define	_FEXLOCK	0x0100	/* BSD flock() exclusive lock present */
#define	_FCREAT		0x0200	/* open with file create */
#define	_FTRUNC		0x0400	/* open with truncation */
#define	_FEXCL		0x0800	/* error on open if file exists */
#define	_FNBIO		0x1000	/* non blocking I/O (sys5 style) */
#define	_FSYNC		0x2000	/* do all writes synchronously */
#define	_FNONBLOCK	0x4000	/* non blocking I/O (POSIX style) */
#define	_FNDELAY	_FNONBLOCK	/* non blocking I/O (4.2 style) */
#define	_FNOCTTY	0x8000	/* don't assign a ctty on this open */
at least a symbol brought me there
 
And allow our wrappers to hopefully just pass these through to the two File systems who hopefully know what to do with them?
By the different Bits?

Which would hopefully then allow you to do: File f2 = myfs.open("TEST.txt", O_RDWR | O_CREAT | O_TRUC);
To open a file create it if it does not exist otherwise truncate it if it does exist...

If we support this, which is still an open question at this point, I would want it to look something like this:

File f2 = myfs.open("TEST.txt", FILE_OPEN_NATIVE(O_RDWR | O_CREAT | O_TRUC));

or

File f2 = myfs.open("TEST.txt", FILE_OPEN_NATIVE(LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC));

Perhaps "native" isn't the right word? Maybe a word which communicates you're tying your code to 1 specific filesystem?

Anyway, if we support such a thing, FILE_OPEN_NATIVE() would directly pass the low 7, 15 or 31 bits as-is to the filesystem's actual open function. Arduino's API uses an 8 bit number, but I don't see any harm in expanding it to 16 or 32 bits.

While today it's hard to imagine supporting another filesystem-providing library beyond SdFat and LittleFS, perhaps someday we'll have network filesystems or maybe even support for Linux ext4, Mac HFS, Windows NTFS, etc? Public APIs should be designed to perform well now but at least with some sort of vision for possible future software we can't fully anticipate today.
 
Expanding on the files on root create / add / remove in LittleFS

Sketch below creates 10 directories on root, then in some haphazard fashion revisits the directories (including root) creating files with A-Z in the name.
> creates 10 sub dirs with 26 files each and 26 more on the root.
> Current params create files only a couple hundred up toward 1K when there is space - for 286 files - enough to get multiple megabytes - only run in RAM so far.

There are #define's at top to control SPEW delays and also resultant file sizes in some fashion.

Very SPEW heavy:: >> Just added to loop(): on exit if (Serial.available()) it will clear that and WAIT until the NEXT Serial.available() before RESUME - it will finish current func() first - be patient.

In some turn of events it will Create the file A-Z in a some directory, write more to the files, delete the files and repeat.
> The files are filled with the LETTER in the file name 'A-Z', and before removing a file it is read and all characters are verified to be that 'letter'
> That assures some integrity, but not complete. But with files getting extended a way to better assure hasn't yet been added.
> As long as data read from file is as expected ( accepting truncated files ) - it just runs as long as it is left alone

No I/O error detect was there - and on no space writes failed, but I added detect of write fail which looks like this when RAMDISK too small:
:: /7_dir/Y_file.txt printDirectory RAM_DISK --Add---- ++Y write fail -28
<edit> found -28 - reasonable for this case :: LFS_ERR_NOSPC = -28, // No space left on device

@Paul - this seems to be a problem? - On (too small 40KB) RAM disk ( in DMAMEM ) a write failure is expected at times and never hurt before
That ran for a while and as expected - now it STOPPED and this error was presented:
Code:
FILE	Z_file.txt		0

:: /7_dir/M_file.txt printDirectory [COLOR="#FF0000"][B]RAM_DISK --Add---- ++M write fail -84[/B][/COLOR]
:: /7_dir/N_file.txt
<edit> found -84 :: LFS_ERR_CORRUPT = -84, // Corrupted

It quit there? This is the first the sketch doesn't just run as long as it is ignored? The disk was only 40KB and may have been too much too small to allow even FS meta data storage update on failure? Perhaps it got wedged not having enough reserve space to update when it saw it was out of room. I doubled the RAM to 80KB and it has not repeated the error -84 yet.

The code - with KurtE's #ifdef to define the disk type - ONLY tried on RAM:
Code:
#include <LittleFS.h>

#define TEST_RAM
//#define TEST_SPI
//#define TEST_QSPI

#ifdef TEST_RAM
LittleFS_RAM myfs;
DMAMEM char buf[400000];	// USE DMAMEM for more memory than ITCM allows - or remove DMAMEM
char szDiskMem[] = "RAM_DISK";
#elif defined(TEST_SPI)
LittleFS_SPIFlash myfs;
char szDiskMem[] = "SPI_DISK";
#else
LittleFS_QSPIFlash myfs;
char szDiskMem[] = "QSPI_DISK";
#endif

File file3;

#define SUBADD 10	// bytes added each pass (*times file number)
#define BIGADD 1	// bytes added each pass - bigger will quickly consume more space
#define MAXNUM 26	// ALPHA A-Z is 26, less for fewer files
#define DELDELAY 100 	// delay before DEL files
#define ADDDELAY 10 	// delay on ADD FILE

uint8_t offsetPr[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 };

void setup() {
	pinMode(13, OUTPUT);
	digitalWrite(13, HIGH);
	while (!Serial) ; // wait
	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
	Serial.println("LittleFS Test : File Integrity"); delay(5);

	if (!myfs.begin(buf, sizeof(buf))) {
		Serial.printf("Error starting %s\n", szDiskMem);
		while (1) ;
	}

	printDirectory();
	char szDir[16];
	for ( int ii = 0; ii < 10; ii++ ) {
		sprintf( szDir, "/%c_dir", '0' + ii );
		myfs.mkdir( szDir );
	}
	printDirectory();
	delay(2000);
}

void loop() {
	//fileCycle( "/" );
	char szDir[16];
	uint32_t chStep;
	for ( int ii = 0; ii < 11; ii++ ) {
		if ( ii == 10 )
			sprintf( szDir, "/" );
		else
			sprintf( szDir, "/%c_dir", '0' + ii );
		chStep = fileCycle(szDir);
		while ( chStep != fileCycle(szDir) );
	}
	if ( Serial.available() ) {
		while ( Serial.available() ) Serial.read();
		while ( !Serial.available() );
		while ( Serial.available() ) Serial.read();
	}
}



void printDirectory() {
	Serial.printf("printDirectory %s\n--------------", szDiskMem);
	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");
			delayMicroseconds( 8 );
		} 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();
	}
}


uint32_t lCnt = 0;
uint32_t cCnt = 0;
uint32_t fileCycle(const char *dir) {
	static char szFile[] = "_file.txt";
	char szPath[150];
	int numTabs = 0;
	digitalToggleFast(13);
	int ii;
	lCnt++;
	byte nNum = lCnt % MAXNUM;
	char chNow = 'A' + lCnt % MAXNUM;
	lfs_ssize_t res = 1;

	if ( dir[1] == 0 )	// catch root
		sprintf( szPath, "/%c%s", chNow, szFile );
	else
		sprintf( szPath, "%s/%c%s", dir, chNow, szFile );
	Serial.printf( ":: %s ", szPath );
	if ( cCnt >= 3 && myfs.exists(szPath) ) { // DELETE ALL KNOWN FILES
		if ( nNum == 1 ) {
			Serial.print( "======   DELETE PASS START  =======\n");
			printDirectory();
			Serial.print( "======   DELETE PASS START  =======\n");
			delay(DELDELAY);
		}
		file3 = myfs.open(szPath);
		ii = 0;
		char mm;
		while ( file3.available() ) {
			file3.read( &mm , 1 );
			if ( chNow != mm ) {
				Serial.printf( "Bad Byte!  %c != %c\n", chNow, mm );
				while (1);
			}
		}
		file3.close();
		myfs.remove(szPath);
		Serial.printf("printDirectory %s ----DEL-------", szDiskMem);
		Serial.printf(" --%c \n", chNow);
		// printDirectory(myfs.open(dir), numTabs); // MUCH SPEW - turn on to see DIR after each delete
		Serial.println();
	}
	else {
		if ( nNum == 0 ) {
			nNum = 10;
			cCnt++;
			if ( cCnt >= 5 ) cCnt = 0;
		}
		file3 = myfs.open(szPath, FILE_WRITE);
		delay(ADDDELAY);
		char mm = chNow;
		for ( ii = 0; ii < (nNum * SUBADD + BIGADD ) && res > 0; ii++ ) {
			res = file3.write( &mm , 1 );
			// if ( lCnt%1000 == 500 ) mm='x'; // GENERATE ERROR to detect on DELETE read verify
		}
		file3.close();
		Serial.printf("printDirectory %s --Add----", szDiskMem);
		Serial.printf(" ++%c ", chNow);
		//printDirectory(myfs.open(dir), numTabs); // MUCH SPEW - turn on to see DIR after each ADD
		if (res < 0) Serial.printf( "write fail %i", res );
		Serial.print("\n");
		delay(ADDDELAY);
	}
	return cCnt;
}
 
Last edited:
If we support this, which is still an open question at this point, I would want it to look something like this:

File f2 = myfs.open("TEST.txt", FILE_OPEN_NATIVE(O_RDWR | O_CREAT | O_TRUC));

or

File f2 = myfs.open("TEST.txt", FILE_OPEN_NATIVE(LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC));

Perhaps "native" isn't the right word? Maybe a word which communicates you're tying your code to 1 specific filesystem?

Anyway, if we support such a thing, FILE_OPEN_NATIVE() would directly pass the low 7, 15 or 31 bits as-is to the filesystem's actual open function. Arduino's API uses an 8 bit number, but I don't see any harm in expanding it to 16 or 32 bits.

While today it's hard to imagine supporting another filesystem-providing library beyond SdFat and LittleFS, perhaps someday we'll have network filesystems or maybe even support for Linux ext4, Mac HFS, Windows NTFS, etc? Public APIs should be designed to perform well now but at least with some sort of vision for possible future software we can't fully anticipate today.
Hi Paul,

Yes I see there are two very possible solutions to this.

a) as you mentioned, use NATIVE or some other function to map... Which may be a valid thing we should do.

b) What I was trying to say also is/was, is there any reason they can not be the same. That is are there any systems out there that use LittleFS who relies on the fact that LFS_O_RDWR is different than O_RDWR? And which bit is which?
If not Could we not simply convert the LFS_O_... to have the same values as O_...
At least for the ones that I think anyone might care about:
Code:
else  // USE_FCNTL_H
#define O_RDONLY  0X00  ///< Open for reading only.
#define O_WRONLY  0X01  ///< Open for writing only.
#define O_RDWR    0X02  ///< Open for reading and writing.
#define O_AT_END  0X04  ///< Open at EOF.
#define O_APPEND  0X08  ///< Set append mode.
#define O_CREAT   0x10  ///< Create file if it does not exist.
#define O_TRUNC   0x20  ///< Truncate file to zero length.
#define O_EXCL    0x40  ///< Fail if the file exists.
#define O_SYNC    0x80  ///< Synchronized write I/O operations.
Not that all have to be supported. Like O_SYNC not sure if that is anything or not that makes sense here. Not sure about O_APPEND (how it different from WRITE AT_END...

As for expanding to word/int... We can for extensions or if there are some FS specific settings... But I think it would be great if for all of the typical usage cases they were the same.
 
Yes, for these 2 filesystems it does look like the open flag bits could be reassigned so the common features end up being the same numbers. But is that a wise move? Is something like FILE_OPEN_NATIVE() even a wise plan? These are very hard questions.

The long term issue with this sort of API comes up years later after people have written lots of code which depends on consistent definition of the flags. If we later add more filesystems that can't implement binary compatible flags, then all that code breaks if used with the new filesystem.
 
@Paul - yep I hear you, it is always hard to know what is the best way to go for compatibility. At this point I have no idea of what is right...

But if you base things on being compatible with Arduino. I downloaded the current Arduino SD library (https://github.com/arduino-libraries/SD)
And they have in SD.h
Code:
#define FILE_READ O_READ
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND)
And in sdfat.h they have:
Code:
uint8_t const O_READ = 0X01;
/** open() oflag - same as O_READ */
uint8_t const O_RDONLY = O_READ;
/** open() oflag for write */
uint8_t const O_WRITE = 0X02;
/** open() oflag - same as O_WRITE */
uint8_t const O_WRONLY = O_WRITE;
/** open() oflag for reading and writing */
uint8_t const O_RDWR = (O_READ | O_WRITE);
/** open() oflag mask for access modes */
uint8_t const O_ACCMODE = (O_READ | O_WRITE);
/** The file offset shall be set to the end of the file prior to each write. */
uint8_t const O_APPEND = 0X04;
/** synchronous writes - call sync() after each write */
uint8_t const O_SYNC = 0X08;
/** create the file if nonexistent */
uint8_t const O_CREAT = 0X10;
/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
uint8_t const O_EXCL = 0X20;
/** truncate the file to zero length */
uint8_t const O_TRUNC = 0X40;

So that may be one possibility. As for new systems in the future, I can see where some flags may error out. Example if you have a FS for CDROM, open for write will fail. As for if each FS should use the same #defines... That might be nice for common features. Sort of like having 10 different TFT drivers that all use 565 color format, and each has their own defines for things like: ILI9341_RED, versus ILI9488_RED, versus ST7735_RED...

But obviously the choice is yours. Will help as we can.
 
@Paul - getting some strange results with QSPIFlash.

Every time I run printDirectory I get a different set of results. Example:

1st load of sketch:
Code:
printDirectory
--------------
FILE	9px_0001.bmp		307254
FILE	9px_0002.bmp		307254
FILE	9px_0003.bmp		307254
FILE	PRINTOUTPUT1.txt		3768
FILE	PRINTOUTPUT2.txt		3780
FILE	file10		144
FILE	file1		176
FILE	file20		128
FILE	file2		224
FILE	file30		112
FILE	file3		224
DIR	structureData / 
FILE	test1.dat		4

turn power on and off and wait a few seconds:
Code:
printDirectory
--------------
FILE	9px_0001.bmp		307254
FILE	9px_0002.bmp		307254
FILE	9px_0003.bmp		307254
FILE	PRINTOUTPUT2.txt		3780
FILE	file10		144
FILE	file20		128
FILE	file2		224
FILE	file30		112
FILE	file3		224
DIR	structureData / 
DIR	structuredData / 
	FILE	logger.txt		4320
FILE	test1.dat		4

3rd power cycle will get same results as the second power cycle.

If I reload the sketch after the 3rd power cycle:
Code:
printDirectory
--------------
FILE	9px_0001.bmp		307254
FILE	9px_0002.bmp		307254
FILE	9px_0003.bmp		307254
FILE	PRINTOUTPUT2.txt		3780
FILE	file10		144
FILE	file20		128
FILE	file2		224
FILE	file30		112
FILE	file3		224
DIR	structureData / 

DIR	structuredData / 
	FILE	logger.txt		4320
FILE	test1.dat		4
It seems to arbitrarily lose files. Above was a decent run but there is a file missing in structureData Directory that is not printing, suppose to look like
Code:
DIR	structureData / 
	FILE	temp_test.txt		285
 
getting some strange results with QSPIFlash.

Yup, me too. QSPIFlash is definitely not right yet. I will work on it again later this week. These test cases should really help! :)



But if you base things on being compatible with Arduino. I downloaded the current Arduino SD library (https://github.com/arduino-libraries/SD)
And they have in SD.h
Code:
#define FILE_READ O_READ
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND)

Aren't those the settings for the very old copy of SdFat they're bundling?

Indeed I had the wrong flags until just last night (or technically early this morning). Fixed only several hours ago.


So that may be one possibility. As for new systems in the future, I can see where some flags may error out. Example if you have a FS for CDROM, open for write will fail. As for if each FS should use the same #defines... That might be nice for common features. Sort of like having 10 different TFT drivers that all use 565 color format, and each has their own defines for things like: ILI9341_RED, versus ILI9488_RED, versus ST7735_RED...

Indeed this is the exact purpose of FILE_READ and FILE_WRITE, to have defined constants that work the exactly same way on every filesystem. The reason they will do that is because each library's public API will internally use whatever flags that filesystem needs.

My main hope is to encourage people to use FILE_WRITE and FILE_READ (though FILE_READ is usually not written in code since it's the default) rather than the filesystem-specific flags.

Just imagine if Adafruit had created a universal API early on for color names in GFX and kept names like ILI9341_RED and ST7735_RED private.
 
Sketch posted #139 above ran fine on RAM overnight - and still running.

I'll have it PAUSE on start waiting for input.

Perhaps allow input for 'r'estart Teensy, and 'd'irectory, and 1-9 for passes through loop to run before Pause?

As noted the only error return code reported is failed file write. Are there any other critical ones?

just does: open, write, read, file remove - in addition to the standard 'printDirectory'

Do we have stand alone SPI and QSPI Flash formatters? I could bring in the 'SPI EraseEverything' code to execute in the initial pause if not - is there a similar 'sketch' for QSPI I could link in? usage would be 'f'ormat and that would be followed by an auto 'r'estart to have normal startup to empty 'media' - except RAM could just to 'r'estart.

When I have it working as such for SPI - I can post and it might be useful for QSPI?

Anyone glance at the code and have ideas for alterations that might help catch/force errors?

Got a task to do - then will be back ...
 
Yup, me too. QSPIFlash is definitely not right yet. I will work on it again later this week. These test cases should really help! :)

Thanks Paul.

Just to let you know that I now have MTP Responder hacked up to work with LittleFS. Tested so far with QSPIFlash and SPIFlash. Right now until the QSPIFlash is updated files names showing up are a bit screwy - it better on SPIFlash. Need to do a bit more hacking though before ready for prime time.

Copying files to the PC seem to work. Only thing I really tested so far.

Since there is no rename function in the API, moving and renaming files aren't supported. Do you think you can add eventually?
 
Updated MultiDir File 'create / extend / remove' now with USB cmdline UI. '?' Help shows this:
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
Awaiting input 0123456789rdchkfvp? loops left 0
>> It will process multiple commands on a line left to right, ending with '?' will keep it from executing right away with recurse to help.

It starts showing a 'dir' - so for any disk it powers up after begin and shows what is there, then pauses for input - it won't run until given 1-9,c,h,k.
After first input it makes the default 10 dirs [0-9]_dir - then shows 'dir' and pauses.
-One loop may involve iterations A-Z, user input is monitored between iterations.
-Not every loop does the same thing!
-Toggle of 'v or p' shows single step progress - slow but useful?

Added code for SPI FLASH FORMAT then it does a Restart. Restart alone good for RAMDISK. Don't have stand alone QSPI format at hand?

Updated #ifdef for myfs.begin() on SPI [and KurtE SPI2] and QSPI that was missing. Tested on T_4.0 w/Audio card SPI Flash.

Have not tested on QSPI yet. If directory integrity is a question perhaps start blank media and CMD: vp1
> Enables Verbose DIR on each change, Enables Pause to UI after each DIR print, run one loop.
> At some point watching the DIR output doing Restart should return to the SAME directory image.

Code:
#include <LittleFS.h>

//#define TEST_RAM
#define TEST_SPI
//#define TEST_QSPI

#ifdef TEST_RAM
LittleFS_RAM myfs;
DMAMEM char buf[400000];	// USE DMAMEM for more memory than ITCM allows - or remove
char szDiskMem[] = "RAM_DISK";
#elif defined(TEST_SPI)
const int FlashChipSelect = 6; // digital pin for flash chip CS pin
//const int FlashChipSelect = 21; // Arduino 101 built-in SPI Flash
#define FORMATSPI
//#define FORMATSPI2
LittleFS_SPIFlash myfs;
char szDiskMem[] = "SPI_DISK";
#else
LittleFS_QSPIFlash myfs;
char szDiskMem[] = "QSPI_DISK";
#endif

File file3;

#define SUBADD 10	// bytes added each pass (*times file number)
#define BIGADD 1	// bytes added each pass - bigger will quickly consume more space
#define MAXNUM 26	// ALPHA A-Z is 26, less for fewer files
#define DELDELAY 100 	// delay before DEL files
#define ADDDELAY 10 	// delay on ADD FILE

uint8_t offsetPr[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 };

void setup() {
	pinMode(13, OUTPUT);
	digitalWrite(13, HIGH);
	while (!Serial) ; // wait
	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
	Serial.println("LittleFS Test : File Integrity"); delay(5);

#ifdef TEST_RAM
	if (!myfs.begin(buf, sizeof(buf))) {
#elif defined(TEST_SPI)
#ifdef FORMATSPI
	if (!myfs.begin( FlashChipSelect )) {
#elif defined(FORMATSPI2)
	pinMode(FlashChipSelect, OUTPUT);
	digitalWriteFast(FlashChipSelect, LOW);
	SPI2.setMOSI(50);
	SPI2.setMISO(54);
	SPI2.setSCK(49);
	SPI2.begin();
	if (!myfs.begin(51, SPI2)) {
#endif
#else
	if (!myfs.begin()) {
#endif
		Serial.printf("Error starting %s\n", szDiskMem);
		checkInput( 1 );
	}

	printDirectory();
	parseCmd( '?' );
	char szDir[16];
	for ( int ii = 0; ii < 10; ii++ ) {
		sprintf( szDir, "/%c_dir", '0' + ii );
		myfs.mkdir( szDir );
	}
	checkInput( 1 );
	printDirectory();
}

int loopLimit = 0; // -1 continuous, otherwise # to count down to 0
bool pauseDir = false;
bool showDir = false;
void loop() {
	char szDir[16];
	uint32_t chStep;
	if ( loopLimit != 0 ) {
		if ( loopLimit > 0 )
			loopLimit--;
		for ( int ii = 0; ii < 11; ii++ ) {
			if ( ii == 10 )
				sprintf( szDir, "/" );
			else
				sprintf( szDir, "/%c_dir", '0' + ii );
			chStep = fileCycle(szDir);
			while ( chStep != fileCycle(szDir) ) checkInput( 0 );
		}
		checkInput( 0 );
	}
	else
		checkInput( 1 );
}

char szInputs[] = "0123456789rdchkfvp?";
void checkInput( int step ) { // prompt for input without user input with step != 0
	char retVal = 0, temp;
	char *pTemp;
	if ( step != 0 ) {
		Serial.printf( "Awaiting input %s loops left %d\n", szInputs, loopLimit );
	}
	else {
		if ( !Serial.available() ) return;
		Serial.printf( "Awaiting input %s loops left %d\n", szInputs, loopLimit );
		while ( Serial.available() ) {
			temp = Serial.read( );
			if ( (pTemp = strchr(szInputs, temp)) ) {
				retVal = pTemp[0];
				parseCmd( retVal );
			}
		}
	}
	while ( !Serial.available() );
	while ( Serial.available() ) {
		temp = Serial.read();
		if ( (pTemp = strchr(szInputs, temp)) ) {
			retVal = pTemp[0];
			parseCmd( retVal );
		}
	}
	if ( '?' == retVal ) checkInput( 1 ); // recurse on '?' to allow command show and response
	return;
}
void parseCmd( char chIn ) { // pass chIn == '?' for help
	switch (chIn ) {
	case '?':
		Serial.printf( "%s\n", " 0, 1-9 '#' passes continue loop before Pause\n\
 'r' Restart Teensy\n\
 'd' Directory of LittleFS\n\
 'c' Continuous Loop\n\
 'h' Hundred loops\n\
 'k' Thousand loops\n\
 'f' Format then Restart : 'SPI EraseEverything'\n\
 'v' Verbose All Dir Prints - TOGGLE\n\
 'p' Pause after all Dir prints - TOGGLE\n\
 '?' Help list" );
		break;
	case 'r':
		SCB_AIRCR = 0x05FA0004;
		break;
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
		loopLimit = chIn - '0';
		break;
	case 'c':
		loopLimit = -1;
		break;
	case 'd':
		printDirectory();
		checkInput( 1 );
		break;
	case 'h':
		loopLimit = 100;
		break;
	case 'k':
		loopLimit = 1000;
		break;
	case 'f': // format
#ifdef TEST_RAM
		parseCmd( 'r' );
#elif defined(TEST_SPI)
		FormatSPI();
		parseCmd( 'r' );
#else
		Serial.println( "TBD format QSPI_DISK" );
#endif
		break;
	case 'v': // verbose dir
		showDir = !showDir;
		showDir ? Serial.print(" Verbose on\n") : Serial.print(" Verbose off\n");
		break;
	case 'p': // pause on dirs
		pauseDir = !pauseDir;
		pauseDir ? Serial.print(" Pause on\n") : Serial.print(" Pause off\n");
		break;
	default:
		Serial.println( chIn ); // never see without unhandled char in szInputs[]
		break;
	}
}

#include <SerialFlash.h>
#include <SPI.h>

SerialFlashFile file;

const unsigned long testIncrement = 4096;

void FormatSPI() {
	//uncomment these if using Teensy audio shield
	//SPI.setSCK(14);  // Audio shield has SCK on pin 14
	//SPI.setMOSI(7);  // Audio shield has MOSI on pin 7

	//uncomment these if you have other SPI chips connected
	//to keep them disabled while using only SerialFlash
	//pinMode(4, INPUT_PULLUP);
	//pinMode(10, INPUT_PULLUP);

	Serial.begin(9600);

	// wait up to 10 seconds for Arduino Serial Monitor
	unsigned long startMillis = millis();
	while (!Serial && (millis() - startMillis < 10000)) ;
	delay(100);

	if (!SerialFlash.begin(FlashChipSelect)) {
		while (1) {
			Serial.println("Unable to access SPI Flash chip");
			delay(1000);
		}
	}
	unsigned char id[5];
	SerialFlash.readID(id);
	unsigned long size = SerialFlash.capacity(id);

	if (size > 0) {
		Serial.print("Flash Memory has ");
		Serial.print(size);
		Serial.println(" bytes.");
		Serial.println("Erasing ALL Flash Memory: ");
		// Estimate the (lengthy) wait time.
		Serial.print("  estimated wait: ");
		int seconds = (float)size / eraseBytesPerSecond(id) + 0.5;
		Serial.print(seconds);
		Serial.println(" seconds.");
		Serial.println("  Yes, full chip erase is SLOW!");
		SerialFlash.eraseAll();
		unsigned long dotMillis = millis();
		unsigned char dotcount = 0;
		while (SerialFlash.ready() == false) {
			if (millis() - dotMillis > 1000) {
				dotMillis = dotMillis + 1000;
				Serial.print(".");
				dotcount = dotcount + 1;
				if (dotcount >= 60) {
					Serial.println();
					dotcount = 0;
				}
			}
		}
		if (dotcount > 0) Serial.println();
		Serial.println("Erase completed");
		unsigned long elapsed = millis() - startMillis;
		Serial.print("  actual wait: ");
		Serial.print(elapsed / 1000ul);
		Serial.println(" seconds.");
	}
}

float eraseBytesPerSecond(const unsigned char *id) {
	if (id[0] == 0x20) return 152000.0; // Micron
	if (id[0] == 0x01) return 500000.0; // Spansion
	if (id[0] == 0xEF) return 419430.0; // Winbond
	if (id[0] == 0xC2) return 279620.0; // Macronix
	return 320000.0; // guess?
}

void printDirectory() {
	Serial.printf("printDirectory %s\n--------------", szDiskMem);
	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");
			delayMicroseconds( 8 );
		} 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();
	}
}


uint32_t lCnt = 0;
uint32_t cCnt = 0;
uint32_t fileCycle(const char *dir) {
	static char szFile[] = "_file.txt";
	char szPath[150];
	digitalToggleFast(13);
	int ii;
	lCnt++;
	byte nNum = lCnt % MAXNUM;
	char chNow = 'A' + lCnt % MAXNUM;
	lfs_ssize_t res = 1;

	if ( dir[1] == 0 )	// catch root
		sprintf( szPath, "/%c%s", chNow, szFile );
	else
		sprintf( szPath, "%s/%c%s", dir, chNow, szFile );
	Serial.printf( ":: %s ", szPath );
	if ( cCnt >= 3 && myfs.exists(szPath) ) { // DELETE ALL KNOWN FILES
		if ( nNum == 1 ) {
			Serial.print( " == == ==   DELETE PASS START  == == == = \n");
			printDirectory();
			Serial.print( " == == ==   DELETE PASS START  == == == = \n");
			delay(DELDELAY);
		}
		file3 = myfs.open(szPath);
		ii = 0;
		char mm;
		while ( file3.available() ) {
			file3.read( &mm , 1 );
			if ( chNow != mm ) {
				Serial.printf( "Bad Byte!  %c! = %c\n", chNow, mm );
				while (1);
			}
		}
		file3.close();
		myfs.remove(szPath);
		Serial.printf("printDirectory %s ----DEL------ -", szDiskMem);
		Serial.printf(" -- %c\n", chNow);
		if ( showDir ) {
			Serial.print("\n");
			printDirectory(myfs.open(dir), 1);
		}
		if ( pauseDir ) checkInput( 1 );
		Serial.println();
	}
	else {
		if ( nNum == 0 ) {
			nNum = 10;
			cCnt++;
			if ( cCnt >= 5 ) cCnt = 0;
		}
		file3 = myfs.open(szPath, FILE_WRITE);
		delay(ADDDELAY);
		char mm = chNow;
		for ( ii = 0; ii < (nNum * SUBADD + BIGADD ) && res > 0; ii++ ) {
			res = file3.write( &mm , 1 );
			// if ( lCnt%1000 == 500 ) mm='x'; // GENERATE ERROR to detect on DELETE read verify
		}
		file3.close();
		Serial.printf("printDirectory %s --Add----", szDiskMem);
		Serial.printf(" ++ %c ", chNow);
		if ( showDir ) {
			Serial.print("\n");
			printDirectory(myfs.open(dir), 1);
		}
		if ( pauseDir ) checkInput( 1 );
		if (res < 0) Serial.printf( "write fail %i", res );
		Serial.print("\n");
		delay(ADDDELAY);
	}
	return cCnt;
}

Created what seems a fun CMD line input processor
checkInput( 0 ) - returns if no USB .available()
checkInput( 1 ) - Pauses for input
That calls parseCmd() with found known character choice.
parseCmd( '?' ) can also be called with any valid command as if the user entered it
 
Did two runs on SPI Flash - 'f' Formatted, clear TyComm SerMon, restart, 'h' to run one hundred loops, before copy the output hit 'd' for current directory. Took about 45 minutes between saving off the 2.7MB files from TyCommander.

At the end of 100 passes the state of the directories, that started EMPTY!, are identical in the end. So the process is HapHazard - but repeatable given same start and no errors and enough room.

Need to put Time on the prompt line for ref. >> Done will update.

Excel shows 5944 bytes in Root files and 49,888 bytes in the subfolders - files are small as shown below:
Code:
printDirectory SPI_DISK --Add---- ++ Q 
Awaiting input 0123456789rdchkfvp? loops left 0
printDirectory SPI_DISK
--------------DIR	0_dir / 
	FILE	A_file.txt		101
	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
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	FILE	J_file.txt		91
	FILE	K_file.txt		101
	FILE	L_file.txt		111
	FILE	M_file.txt		121
	FILE	N_file.txt		131
	FILE	O_file.txt		141
	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		422
	FILE	W_file.txt		442
	FILE	X_file.txt		231
	FILE	Y_file.txt		241
	FILE	Z_file.txt		251
DIR	1_dir / 
	FILE	A_file.txt		101
	FILE	B_file.txt		22
	FILE	C_file.txt		42
	FILE	D_file.txt		31
	FILE	E_file.txt		41
	FILE	F_file.txt		102
	FILE	G_file.txt		122
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	FILE	J_file.txt		182
	FILE	K_file.txt		202
	FILE	L_file.txt		111
	FILE	M_file.txt		121
	FILE	N_file.txt		262
	FILE	O_file.txt		282
	FILE	P_file.txt		151
	FILE	Q_file.txt		161
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		191
	FILE	U_file.txt		201
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		462
	FILE	Y_file.txt		482
	FILE	Z_file.txt		251
DIR	2_dir / 
	FILE	A_file.txt		101
	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
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	FILE	J_file.txt		91
	FILE	K_file.txt		101
	FILE	L_file.txt		111
	FILE	M_file.txt		121
	FILE	N_file.txt		131
	FILE	O_file.txt		141
	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
DIR	3_dir / 
	FILE	A_file.txt		101
	FILE	B_file.txt		22
	FILE	C_file.txt		42
	FILE	D_file.txt		31
	FILE	E_file.txt		41
	FILE	F_file.txt		102
	FILE	G_file.txt		122
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	FILE	J_file.txt		182
	FILE	K_file.txt		202
	FILE	L_file.txt		111
	FILE	M_file.txt		121
	FILE	N_file.txt		262
	FILE	O_file.txt		282
	FILE	P_file.txt		151
	FILE	Q_file.txt		161
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		191
	FILE	U_file.txt		201
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		231
	FILE	Y_file.txt		241
	FILE	Z_file.txt		251
DIR	4_dir / 
	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		302
	FILE	Q_file.txt		322
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		382
	FILE	U_file.txt		402
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		462
	FILE	Y_file.txt		482
	FILE	Z_file.txt		251
DIR	5_dir / 
	FILE	A_file.txt		101
	FILE	B_file.txt		11
	FILE	C_file.txt		21
	FILE	D_file.txt		31
	FILE	E_file.txt		41
	FILE	F_file.txt		102
	FILE	G_file.txt		122
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	FILE	J_file.txt		182
	FILE	K_file.txt		202
	FILE	L_file.txt		111
	FILE	M_file.txt		121
	FILE	N_file.txt		262
	FILE	O_file.txt		282
	FILE	P_file.txt		151
	FILE	Q_file.txt		161
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		191
	FILE	U_file.txt		201
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		231
	FILE	Y_file.txt		241
	FILE	Z_file.txt		251
DIR	6_dir / 
	FILE	A_file.txt		101
	FILE	B_file.txt		22
	FILE	C_file.txt		42
	FILE	D_file.txt		31
	FILE	E_file.txt		41
	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		302
	FILE	Q_file.txt		322
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		382
	FILE	U_file.txt		402
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		462
	FILE	Y_file.txt		482
	FILE	Z_file.txt		251
DIR	7_dir / 
	FILE	A_file.txt		101
	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
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	FILE	J_file.txt		182
	FILE	K_file.txt		202
	FILE	L_file.txt		111
	FILE	M_file.txt		121
	FILE	N_file.txt		262
	FILE	O_file.txt		282
	FILE	P_file.txt		151
	FILE	Q_file.txt		161
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		191
	FILE	U_file.txt		201
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		231
	FILE	Y_file.txt		241
	FILE	Z_file.txt		251
DIR	8_dir / 
	FILE	A_file.txt		101
	FILE	B_file.txt		22
	FILE	C_file.txt		42
	FILE	D_file.txt		31
	FILE	E_file.txt		41
	FILE	F_file.txt		102
	FILE	G_file.txt		122
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	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		302
	FILE	Q_file.txt		322
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		382
	FILE	U_file.txt		402
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		462
	FILE	Y_file.txt		482
	FILE	Z_file.txt		251
DIR	9_dir / 
	FILE	A_file.txt		101
	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
	FILE	H_file.txt		71
	FILE	I_file.txt		81
	FILE	J_file.txt		91
	FILE	K_file.txt		101
	FILE	L_file.txt		111
	FILE	M_file.txt		121
	FILE	N_file.txt		262
	FILE	O_file.txt		282
	FILE	P_file.txt		151
	FILE	Q_file.txt		161
	FILE	R_file.txt		342
	FILE	S_file.txt		362
	FILE	T_file.txt		191
	FILE	U_file.txt		201
	FILE	V_file.txt		422
	FILE	W_file.txt		442
	FILE	X_file.txt		231
	FILE	Y_file.txt		241
	FILE	Z_file.txt		251
FILE	A_file.txt		101
FILE	B_file.txt		22
FILE	C_file.txt		42
FILE	D_file.txt		31
FILE	E_file.txt		41
FILE	F_file.txt		102
FILE	G_file.txt		122
FILE	H_file.txt		71
FILE	I_file.txt		81
FILE	J_file.txt		182
FILE	K_file.txt		202
FILE	L_file.txt		111
FILE	M_file.txt		121
FILE	N_file.txt		262
FILE	O_file.txt		282
FILE	P_file.txt		302
FILE	Q_file.txt		322
FILE	R_file.txt		342
FILE	S_file.txt		362
FILE	T_file.txt		382
FILE	U_file.txt		402
FILE	V_file.txt		422
FILE	W_file.txt		442
FILE	X_file.txt		462
FILE	Y_file.txt		482
FILE	Z_file.txt		251

Awaiting input 0123456789rdchkfvp? loops left 0
Awaiting input 0123456789rdchkfvp? loops left 0

ON TO QSPI! Drive formatted with 'test.ino' from extmem\spiffs and setup edited to NOT SPIFFS INIT the drive!

First run of '5' loops Died with BAD DATA READ! I left a while(1) that was to be checkInput( 1 ) that does a stop waiting for input - where a 'd' DIR would be possible.

Code:
 == == ==   DELETE PASS START  == == == = 
  waited 27229 us
  waited 361 us
  waited 361 us
  waited 320 us
  waited 107 us
printDirectory QSPI_DISK ----DEL------ - -- B

:: /1_dir/C_file.txt   waited 80 us
printDirectory QSPI_DISK ----DEL------ - -- C

:: /1_dir/D_file.txt   waited 80 us
printDirectory QSPI_DISK ----DEL------ - -- D

:: /1_dir/E_file.txt   waited 80 us
printDirectory QSPI_DISK ----DEL------ - -- E

:: /1_dir/F_file.txt   waited 81 us
printDirectory QSPI_DISK ----DEL------ - -- F

:: /1_dir/G_file.txt   waited 80 us
printDirectory QSPI_DISK ----DEL------ - -- G

[B][COLOR="#FF0000"]:: /1_dir/H_file.txt Bad Byte!  H! = �[/COLOR][/B]

Some cleanup to do ... more soon
 
Back
Top