LittleFS port to Teensy/SPIFlash

Was just posting when crosspost email came in. Will do a sync here. Just gave them a look and they seem like they should build.

It does build - not even a warning :)

First run the loopCnt was not decrementing again (noted below) ???? It has something to do with 'a'uto formatUnused being sent in ??? Seems to get cleared up after hitting '0' Enter ???? Gave it a glance and not seeing it - it happens when I start a '#' of iterations and then while running interject 'a'uto because I forgot it. Minor bug, '0' seems to resolve it, or perhaps entering 'a' when paused at prompt.

... What I was posting:
Left that running on the MRAM - The ROHM FeRam.

LFSintegrity.INO for some reason running 'k' for thousand iterations stopped decrementing - same with 'h'undred after that was seen ( done while running) ????

Did a '0' to stop, then a couple of single digits and then the 'h' worked and stopped?

So that resulted in a really long running set of MRAM iterations with NO PROBLEMS!

Code:
 0 dirs with 0 files of Size 0 Bytes
FILE	A_file.txt		800
FILE	B_file.txt		440
FILE	C_file.txt		480
FILE	D_file.txt		520
FILE	E_file.txt		560
FILE	F_file.txt		600
FILE	G_file.txt		640
FILE	H_file.txt		680

 8 dirs with 9 files of Size 47728 Bytes
 Total 40 files of Size 103758 Bytes
Bytes Used: 123392, Bytes Total:131072


	 Loop Count: 162 (#fileCycle=541462), Bytes read 71820190, written 34670470, #Files=40
	 Free Space Warn COUNT =75854

The "#define MAXFILL 2048" leads to skipping file create or extend when reported size left is not more than 2048 bytes. That is enough to prevent failed Err=-28 on write, but led to 75,854 of those writes and instead a file delete typically.

So that is good and in the process 34,670,470 Bytes were written to the 128KB drive, and in verification confirmations 71,820,190 Bytes were read back - while doing the 'occasional' formatUnused(20, res).

As indicated this run is on ROOT and 8 subdirectories and at this paused point this is the case:: "Bytes Used: 123392, Bytes Total:131072"

Bottom line - MRAM and LittleFS in general seems stable with normal operation - including reFormatting during use.

And the $4 FeRAM works as well as the $12 MRAM for 128KB of static, but not fast, storage.

I dropped the 50ns delays to 10 and it worked but no faster, same with the two 250's dropped to 50ns. So they seem okay if they assure function. Still 500 to 600 KB/Sec - into 700's with larger files.

Note: Turning on 'a'uto formatUnused with //ROOTONLY seems to keep the unformatted mess down, but doing ROOTONLY to make bigger files doesn't get called often enough to prevent dirty Blocks.
 
LittleFS and W25N01G (SPI version)

Well - couldn't help myself. So kludged together a version that is beginning to show some life but...
Code:
LittleFS Test
Flash ID: EF AA 21
Flash size is 128.00 Mbyte
Status of reg 0xa0: 
(HEX: ) 0x00, (Binary: )0

0
Status of reg 0xb0: 
(HEX: ) 0x18, (Binary: )11000

attempting to mount existing media
success
started
MAKE DIRECTORY
block (1), block_size(2048), addr(2048)
2048
printDirectory
--------------
FILE	temp_test.txt		57

Disk Usuage:
Bytes Used: 4096, Bytes Total:134217728
Not going to post - still alot to do.

EDIT: just by way of a note - it doesn't like directories - gets very upset.
 
Last edited:
Wonder if the DIR doing inplace updates is getting screwed?

To some degree a dir entry AFAIK is re-used as long as free space in the block is unused. That may involve further bit clearing in the prior portion to indicate the later section is the current part?

That may not be fully or wholly correct - but if it does think adding 0's can invalidate an entry - IIRC it was noted the NAND's don't allow rewrites.

Perhaps setting this ENTRY in the class to 1 :: config.block_cycles = 400;

For RAM and MRAM that can be 1,000 as those items do not WEAR out. For NOR flash it says how long it spins on a block before moving it. In the case of NAND perhaps 1 will say it cannot be reused - but must move on each cycle?

Check the .MD files for notes on that - maybe it is even in the world of GITHUB comments for NAND usage?
 
Wonder if the DIR doing inplace updates is getting screwed?

To some degree a dir entry AFAIK is re-used as long as free space in the block is unused. That may involve further bit clearing in the prior portion to indicate the later section is the current part?

That may not be fully or wholly correct - but if it does think adding 0's can invalidate an entry - IIRC it was noted the NAND's don't allow rewrites.

Perhaps setting this ENTRY in the class to 1 :: config.block_cycles = 400;

For RAM and MRAM that can be 1,000 as those items do not WEAR out. For NOR flash it says how long it spins on a block before moving it. In the case of NAND perhaps 1 will say it cannot be reused - but must move on each cycle?

Check the .MD files for notes on that - maybe it is even in the world of GITHUB comments for NAND usage?

When I get some ambition I will go through the Github notes again. The other thing I noted is that you can only write to same page a max of 4 times before ECC errors kick in - easy to clear by just erasing the block. This looks like a hard requirement that even was noted by Winbond. So basically don't expect to write to same file many times with small array. Each write should be a minimum of 512bytes so it fills up the whole page.
 
When I get some ambition I will go through the Github notes again. The other thing I noted is that you can only write to same page a max of 4 times before ECC errors kick in - easy to clear by just erasing the block. This looks like a hard requirement that even was noted by Winbond. So basically don't expect to write to same file many times with small array. Each write should be a minimum of 512bytes so it fills up the whole page.

A quick test then would be :: config.block_cycles = 4; // maybe 3? The reason I pointed to MD docs was because I'm not sure if this is 1 or zero based.

If not config.block_cycles = 1; to see if it fixes DIR updates

Again that is AFAIK - but worst case it will cause block underuse and moving on - not any harm apart from wear - that may be needed given the nature of NAND physics.

Not in the MD files :(

Here is what is in lfs.h: - so it may be ZERO based where a block is (re)used Only once when Zero? Which may be one time too many for DIR meta data blocks?
Code:
    // Number of erase cycles before littlefs evicts metadata logs and moves 
    // the metadata to another block. Suggested values are in the
    // range 100-1000, with large values having better performance at the cost
    // of less consistent wear distribution.
    //
    // [B]Set to -1 to disable block-level wear-leveling[/B].
    int32_t block_cycles;

UPDATE from lfs.c:
Code:
    // [B][COLOR="#FF0000"]block_cycles = 0 is no longer supported.[/COLOR][/B]
    //
    // block_cycles is the number of erase cycles before littlefs evicts
    // metadata logs as a part of wear leveling. Suggested values are in the
    // range of 100-1000, or set block_cycles to -1 to disable block-level
    // wear-leveling.

UPDATE #2 from lfc.c : Dirs get special handing ???
Code:
    // increment revision count
    dir->rev += 1;
    // If our revision count == n * block_cycles, we should force a relocation,
    // this is how littlefs wear-levels at the metadata-pair level. Note that we
    // actually use (block_cycles+1)|1, this is to avoid two corner cases:
    // 1. block_cycles = 1, which would prevent relocations from terminating
    // 2. block_cycles = 2n, which, due to aliasing, would only ever relocate
    //    one metadata block in the pair, effectively making this useless
 
@defragster
Thanks for checking on block_cycles definitions. Did try to adjust the block_cycles but still didn't work. However with that said, in trying to write a file over 256 bytes I did manage to track the problem down - again a silly typo. So now:
Code:
LittleFS Test
Flash ID: EF AA 21
Flash size is 128.00 Mbyte
Status of reg 0xa0: 
(HEX: ) 0x00, (Binary: )0

0
Status of reg 0xb0: 
(HEX: ) 0x18, (Binary: )11000

attempting to mount existing media
success
started
MAKE files
printDirectory
--------------
DIR	structureData1 / 
	FILE	temp_test.txt		19
FILE	temp_test.txt		19
FILE	temp_test1.txt		38
FILE	temp_test2.txt		38
FILE	temp_test3.txt		1024

--------------
27, 18
Uncorrectable ECC in a single page (addr, code): b3000, 2
printDirectory
--------------
DIR	structureData1 / 
	FILE	temp_test.txt		38
FILE	temp_test.txt		19
FILE	temp_test1.txt		57
FILE	temp_test2.txt		57
FILE	temp_test3.txt		1536

Disk Usuage:
Bytes Used: 10240, Bytes Total:2097152
Test for SOME DATA TO TEST

If you want to give it a try I am attaching the library I created - just put it in your libraries folder. Oh - haven't been able to test lowlevelFormat or quickFormat. Its one of those C++ things and using inheritance I think. Guess now to do some clean up.
 

Attachments

  • LittleFS_NAND.zip
    12.1 KB · Views: 57
That seems boring :)

More trouble unpacking and setting it up than to see it run - thanks for including the sample sketch.

Looks like a 'ZERO' is printing again - see the clipped output below missing the last many lines.
Here it is after a couple of TyComm RESETs and a Power Off restart - the data extends run to run:
Code:
LittleFS Test
Flash ID: EF AA 21
Flash size is 128.00 Mbyte
Status of reg 0xa0: 
(HEX: ) 0x00, (Binary: )0

0
Status of reg 0xb0: 
(HEX: ) 0x18, (Binary: )11000

attempting to mount existing media
success
started
MAKE files
printDirectory
--------------
DIR	structureData1 / 
	FILE	temp_test.txt		76
FILE	temp_test1.txt		76
FILE	temp_test2.txt		76
FILE	temp_test3.txt		2048

--------------
27, 18
printDirectory
--------------
DIR	structureData1 / 
	FILE	temp_test.txt		95
FILE	temp_test1.txt		95
FILE	temp_test2.txt		95
FILE	temp_test3.txt		2560

Disk Usuage:
Bytes Used: 12288, Bytes Total:2097152
Test for SOME DATA TO TEST
 
@defragster
Yeah - after I got it working was kind of, ok what next moment.
Oh - that zero is just a debug statement in the sketch or I had in the lib while debugging. Next version will have them removed. But at least its working now at 75Mhz.

Probably would have saved you some time if you did a deviceErase first. Oh, by the way you will notice that the total chip size is way off. Know what the problem is but not how to fix it yet
 
@defragster
Yeah - after I got it working was kind of, ok what next moment.
Oh - that zero is just a debug statement in the sketch or I had in the lib while debugging. Next version will have them removed. But at least its working now at 75Mhz.

Probably would have saved you some time if you did a deviceErase first. Oh, by the way you will notice that the total chip size is way off. Know what the problem is but not how to fix it yet

Yes, Awesome progress to see it working - and 75MHz will be better for SPI transfer!

Just noticed this this is SPI only : LittleFS_SPINAND - don't have a way to use my two QSPI Teeny 4.1's with 1Gb NAND :( ... LittleFS_QSPINAND
{ so don't quit now you are almost half done :) }

Did you get one of those soldered for T_4.1 QSPI to test?

I did not notice the wrong Media size - good luck with that.
 
@mjs513 @defragster - great work. Maybe soon will order some of these chips.
All the GOOD credit to @mjs513!

There is the one on the memory board in 1Mb that works with the sample ... and the 2Mb one too

It seems the working one 1Mb is : #define chipSelect 3
As known_chips[] :: {{0xEF, 0xAA, 0x21}, 24, 2048, 131072, 134217728, 2000, 15000}, //Winbond W25N01G
Code:
LittleFS Test
Flash ID: EF AA 21
Flash size is 128.00 Mbyte
Status of reg 0xa0: 
(HEX: ) 0x00, (Binary: )0


As #define chipSelect 4 fails with no entry in known_chips[]:
Code:
Flash ID: EF AA 22
Error starting spidisk

Question: Do all the SPI/QSPI chips respond to the same commands for getting that JEDEC 'Flash ID'?
 
Actually I believe I obviously have some of these. Both on the Test board.

Plus I believe I have one of the 1G ones soldered on the FlexSPI setups on T4.1... For some reason I was thinking you might be playing with the FSRAM...
 
Actually I believe I obviously have some of these. Both on the Test board.

Plus I believe I have one of the 1G ones soldered on the FlexSPI setups on T4.1... For some reason I was thinking you might be playing with the FSRAM...

I wondered - thought that NAND was an old thing ... now the FSRAM is the old thing and the NAND is new again.
 
@defragster - @KurtE
Ah don't give me credit too soon - running into some issues on some of the test cases that I am not happy with - have to do some rereading and testing again. Works for the example I gave. At least its a start. But when I ran the 100's from LFSIntegrity it fails. Like I said still have some debugging to do before its ready for prime time.

Seems 0x9F is the standard command for FLASH/FRAMs to get the JEDEC, at least for the chips I have been playing with. Only diff may be in the output format. Ran into that with the NANDs and FeRAM (8Mbit).

Been using the test board on for SPI devel of the NAND 1G/2G chips so far. Eventually will get around to playing with the 1G on QSPI which I have soldered directly on a T4.1. Need to resolve issues with SPI version first. Think its a problem converting addresses from LittleFS to addresses I am using in the functions.
 
@mjs513 - that is 128 MB so depending on file size modifier #defines it could fill in hundreds and start wrapping/reusing space.

In prior version there was a way to print the LFS_Traverse memory map - that would give an idea of where the used files are.

I could put those back in as debug? But that seems like it could make the code hard to read being part of the class and intermixed? That and the format list print were nice. Though not sure how big and how many blocks there are - that could be a long list.

Have you tried the formatUnused()? Would be interesting to see what it does - I suppose I could edit your sample and watch, but wasn't sure how far away from LFSintegrity.INO sketch update being published. You could do a branch I suppose?
 
@mjs513 any progress or troubles with NAND FLASH in LFSinegrity?

Great timing on the question. Just figured out what the root issue was in getting the driver to work properly with the NAND. Boiled down to a couple of typos on my part so now my updated test case and your LFSIntegrity seems to be working. As an example:
Code:
Big write /0_bigfile.txt took 72.75 Sec for 67086336 Bytes : file3.size()=67086336
	Big write KBytes per second 922.14 

Bytes Used: 67086336, Bytes Total:134217728
Have some clean up to do with all the debug stuff I put in then I will post the updates. But probably won't be until late this afternoon - have more shoveling to do. What use to take me a few hours to do now takes me 3 days and a lot of aches and pains.

EDIT: attaching updated lib and example. Looks like just needs a bunch of clean up before I move on to QSPI version :)
 

Attachments

  • LittleFS_NAND.zip
    12.5 KB · Views: 58
Last edited:
Sounds great - I will have to start playing again once I complete the current round of diversions.
 
...
EDIT: attaching updated lib and example. Looks like just needs a bunch of clean up before I move on to QSPI version :)

Is this on my end ?
Code:
"T:\\TEMP\\arduino_build_littlefs_teensy_test1a.ino\\sketch\\littlefs_teensy_test1a.ino.cpp.o"
T:\tCode\libraries\LittleFS_NAND\examples\littlefs_teensy_test1a\littlefs_teensy_test1a.ino: In function 'void printDirectory(File, int)':
T:\tCode\libraries\LittleFS_NAND\examples\littlefs_teensy_test1a\littlefs_teensy_test1a.ino:167:7: error: 'fTot' was not declared in this scope
       fTot += fCnt;
       ^
T:\tCode\libraries\LittleFS_NAND\examples\littlefs_teensy_test1a\littlefs_teensy_test1a.ino:168:7: error: 'totSize1' was not declared in this scope
       totSize1 += fSize;
       ^
Using library LittleFS_NAND at version 1.0.0 in folder: T:\tCode\libraries\LittleFS_NAND
 
@defragster
Nope - my end - during cleanup I deleted too much. Add this at global:
Code:
uint64_t fTot, totSize1;
 
@defragster - @KurtE
Well incorporated the QSPI stuff into the lib for LittleFS and not working and not sure why. Have to play some more tomorrow with with it. It does start most of the time so something is off. Keep getting corrupted dir pair from littleFS. Remember had that problem before.

Just out of curiosity - what flashBaseAddress should I be using?
 
Just got back and saw the simple global declare - and it works.

Odd it doesn't work reliably for NAND when integrated :( Seems if it works once then it should just work - unless the startup.begin() is tripping on something?

Nice it reports corruption - in my testing that is not something I've ever seen.

The Dirs are PAIRED - one is updated in advance of the other so there are always two copies before there can be NONE ... in some fashion to allow a power fail to have a pointer to either old or new that works. That sounds like it is trying to edit a prior set block bit and failing when it tries to update an existing entry ??? Then when it checks - the two entries are not marked as expected ... Maybe it is a cache flush issue where an expected write didn't get done?
 
I only see baseaddr used by :: LittleFS_Program()

The other ones have it hard coded to the device in the addressing commands?

Can you branch the littleFS in defragster? I'll look to go do that - then we can see the code.
 
@mjs513 : Got bored waiting for LFSintegrity.ino to run on NAND's :) - did a quit edit to write 2MB file from loop(). 'B' adds files '0-8' as repeated, and 'b' removes those files with read back verify. Then does a DIR, blank enter also dies a DIR.
A couple iterations and restarts and new upload and all reports well, but Probably still using unformatted Flash?

Also the T_4.x Time Set through Bootloader has been decoded - and @luni made a program to do it and it works : github.com/luni64/TeensySharp/discussions/5
> so code below prints Teensy Time - that isn't updated by TyCommander.

It is ODD though - never noticed before? It should be writing 2048 bytes One Thousand times and yet the file size is not 2048000? Will have to check that???
Code:
Sun Dec 20 02:44:57 2020

Start Big write of [B][U]2048000 [/U][/B]Bytes........................
Big write /0_2MBfile.txt took  2.26 Sec for [B][COLOR="#FF0000"]2045952 [/COLOR][/B]Bytes : file3.size()=[B]2045952[/B]
	Big write KBytes per second 904.11 

Bytes Used: 9043968, Bytes Total:134217728
printDirectory
--------------
FILE	0_2MBfile.txt		[B]2045952[/B]
FILE	bigfile.txt  		6164480
DIR	structureData1 / 
	FILE	temp_test.txt		190

 0 dirs with 1 files of Size 190 Bytes
FILE	temp_test1.txt		190
FILE	temp_test2.txt		190
FILE	temp_test3.txt		10240

 1 dirs with 5 files of Size 8221052 Bytes

Sun Dec 20 03:00:07 2020

Delete with read verify all #bigfile's
	Verify /0_2MBfile.txt bytes [B]2045952 [/B]: ..................................................	GOOD! >>  bytes [B]2045952[/B]
	Big read&compare KBytes per second 1429.25

Code:
#include <LittleFS_NAND.h>
#include <stdarg.h>
uint64_t fTot, totSize1;

extern "C" void debug_print(const char *format, ...)
{
  va_list args;

  va_start(args, format);
  for (; *format != 0; format++) { // no-frills stand-alone printf
    if (*format == '%') {
      ++format;
      if (*format == '%') goto out;
      if (*format == '-') format++; // ignore size
      while (*format >= '0' && *format <= '9') format++; // ignore size
      if (*format == 'l') format++; // ignore long
      if (*format == '\0') break;
      if (*format == 's') {
        debug_print((char *)va_arg(args, int));
      } else if (*format == 'd') {
        Serial.print(va_arg(args, int));
      } else if (*format == 'u') {
        Serial.print(va_arg(args, unsigned int));
      } else if (*format == 'x' || *format == 'X') {
        Serial.print(va_arg(args, int), HEX);
      } else if (*format == 'c' ) {
        Serial.print((char)va_arg(args, int));
      } else if (*format == 'p' ) { Serial.print(va_arg(args, int), HEX);}
    } else {
out:
      if (*format == '\n') Serial.print('\r');
      Serial.print(*format);
    }
  }
  va_end(args);
}
//LittleFS_QSPIFlash myfs;
//LittleFS_Program myfs;
//LittleFS_SPIFlash myfs;
//LittleFS_SPIFram myfs;
LittleFS_SPINAND myfs;
#define chipSelect 3

File file, file1, file3;


#include <ctime>


void setup() {
  //pinMode(13, OUTPUT);
  pinMode(chipSelect, OUTPUT);
  digitalWrite(chipSelect, HIGH);
  while (!Serial) ; // wait

  delay(1000);
  Serial.println("LittleFS Test"); delay(5);
  //if (!myfs.begin()) {
  myfs.begin(chipSelect);
  if (!myfs.begin(chipSelect)) {
    Serial.println("Error starting spidisk");
    while (1) ;
  }

  Serial.printf("TotalSize (Bytes): %d\n", myfs.totalSize());
  //myfs.deviceErase();

  delay(1000);
  Serial.println("started");
  //printDirectory();
  delay(10);
  Serial.println("MAKE files");
  myfs.mkdir("structureData1");
  printDirectory();
  file = myfs.open("structureData1/temp_test.txt", FILE_WRITE);
  delay(10);
  file.println("SOME DATA TO TEST");
  file.close();
  file = myfs.open("temp_test1.txt", FILE_WRITE);
  delay(10);
  file.println("SOME DATA TO TEST");
  file.close();
  file = myfs.open("temp_test2.txt", FILE_WRITE);
  delay(10);
  file.println("SOME DATA TO TEST");
  file.close();

  uint8_t buffer[] = "Test for SOME DATA TO TEST";
  Serial.println("--------------");
  file = myfs.open("temp_test3.txt", FILE_WRITE);
  uint16_t writeSize = sizeof(buffer);
  uint16_t write2Buffer = 512 / writeSize;
  //Serial.printf("%d, %d\n", writeSize, write2Buffer);

  uint8_t tempBuffer[512];
  memset(tempBuffer, 0xFF, 512);
  for (uint16_t j = 0; j < write2Buffer; j++) {
    for (uint16_t i = 0; i < writeSize; i++) {
      tempBuffer[j * writeSize + i] = buffer[i];
    }
  }
  for (uint16_t j = 0; j < 2; j++)
    file.write(tempBuffer, sizeof(tempBuffer));
  delay(10);

  //file.println("SOME DATA TO TEST");
  file.close();
  //file = myfs.open("temp_test3.txt", FILE_WRITE);
  //delay(10);
  //file.write(buffer, sizeof(buffer));
  //file.close();



  delay(100);
  printDirectory();
  delay(10);

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

  uint8_t buf[2048];
  memset(buf, 0, 2048);
  file = myfs.open("temp_test3.txt", FILE_READ);
  file.read(buf, 2048);
  for (uint16_t i = 0; i < 15; i++) {
    for (uint16_t j = 0; j < sizeof(buffer); j++) {
      Serial.printf("%c", buf[j + sizeof(buffer)*i]);
    } Serial.println();
  }
  file.close();
//Serial.println("Running Big File");
  bigFile();
  time_t t = rtc_get();
  Serial.print(std::ctime(&t));

  //myfs.rename("file10", "file10.txt");
  //myfs.rename("file20", "file20.txt");
  //printDirectory();

}

void bigFile() {
  char someData[2048];
  memset( someData, 'z', 2048 );
  file = myfs.open("bigfile.txt  ", FILE_WRITE);
  file.write(someData, sizeof(someData));

  for (uint16_t j = 0; j < 300; j++)
    file.write(someData, sizeof(someData));
  file.close();
  printDirectory();
}

void loop() {
  if ( Serial.available() ) {
    char rr;
    rr = Serial.read();
    if (rr == 'B') bigFile2MB(1);
    if (rr == 'b') bigFile2MB(0);
    printDirectory();
  time_t t = rtc_get();
  Serial.print(std::ctime(&t));
  }
}

void printDirectory() {

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


void printDirectory(File dir, int numTabs) {
  //dir.whoami();
  uint64_t fSize = 0;
  uint32_t dCnt = 0, fCnt = 0;
  if ( 0 == dir ) {
    Serial.printf( "\t>>>\t>>>>> No Dir\n" );
    return;
  }
  while (true) {
    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      Serial.printf("\n %u dirs with %u files of Size %u Bytes\n", dCnt, fCnt, fSize);
      fTot += fCnt;
      totSize1 += fSize;
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }

    if (entry.isDirectory()) {
      Serial.print("DIR\t");
      dCnt++;
    } else {
      Serial.print("FILE\t");
      fCnt++;
      fSize += entry.size();
    }
    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();
    //Serial.flush();
  }
}

void bigFile2MB( int doThis ) {
  char myFile[] = "/0_2MBfile.txt";
  char fileID = '0' - 1;

  if ( 0 == doThis ) {  // delete File
    Serial.printf( "\nDelete with read verify all #bigfile's\n");
    do {
      fileID++;
      myFile[1] = fileID;
      if ( myfs.exists(myFile) && bigVerify( myFile, fileID) ) {
        //filecount--;
        myfs.remove(myFile);
      }
      else break; // no more of these
    } while ( 1 );
  }
  else {  // FILL DISK
    lfs_ssize_t resW = 1;
    char someData[2048];
    uint32_t xx, toWrite;
    toWrite = 2048 * 1000;
    if ( toWrite > (65535 + (myfs.totalSize() - myfs.usedSize()) ) ) {
      Serial.print( "Disk too full! DO :: q or F");
      return;
    }
    xx = toWrite;
    Serial.printf( "\nStart Big write of %u Bytes", xx);
    uint32_t timeMe = micros();
    file3 = nullptr;
    do {
      if ( file3 ) file3.close();
      fileID++;
      myFile[1] = fileID;
      file3 = myfs.open(myFile, FILE_WRITE);
    } while ( fileID < '9' && file3.size() > 0);
    if ( fileID == '9' ) {
      Serial.print( "Disk has 9 FILES 0-8! DO :: b or q or F");
      return;
    }
    memset( someData, fileID, 2048 );
    int hh = 0;
    while ( toWrite > 2048 && resW > 0 ) {
      resW = file3.write( someData , 2048 );
      hh++;
      if ( !(hh % 40) ) Serial.print('.');
      toWrite -= 2048;
    }
    xx -= toWrite;
    file3.close();
    timeMe = micros() - timeMe;
    file3 = myfs.open(myFile, FILE_WRITE);
    if ( file3.size() > 0 ) {
      //filecount++;
      Serial.printf( "\nBig write %s took %5.2f Sec for %lu Bytes : file3.size()=%llu", myFile , timeMe / 1000000.0, xx, file3.size() );
    }
    if ( file3 != 0 ) file3.close();
    Serial.printf( "\n\tBig write KBytes per second %5.2f \n", xx / (timeMe / 1000.0) );
    Serial.printf("\nBytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());
    if ( resW < 0 ) {
      Serial.printf( "\nBig write ERR# %i 0x%X \n", resW, resW );
      //errsLFS++;
      myfs.remove(myFile);
    }
  }
}

bool bigVerify( char szPath[], char chNow ) {
  uint32_t timeMe = micros();
  file3 = myfs.open(szPath);
  if ( 0 == file3 ) {
    return false;
  }
  char mm;
  uint32_t ii = 0;
  uint32_t kk = file3.size() / 50;
  Serial.printf( "\tVerify %s bytes %llu : ", szPath, file3.size() );
  while ( file3.available() ) {
    file3.read( &mm , 1 );
    //rdCnt++;
    ii++;
    if ( !(ii % kk) ) Serial.print('.');
    if ( chNow != mm ) {
      Serial.printf( "<Bad Byte!  %c! = %c [0x%X] @%u\n", chNow, mm, mm, ii );
      //parseCmd( '0' );
      //errsLFS++;
      //checkInput( 1 );
      break;
    }
  }
  if (ii != file3.size()) {
    Serial.printf( "\n\tRead Count fail! :: read %u != f.size %llu\n", ii, file3.size() );
    //parseCmd( '0' );
    //errsLFS++;
    //checkInput( 1 );  // PAUSE on CmdLine
  }
  else
    Serial.printf( "\tGOOD! >>  bytes %lu", ii );
  file3.close();
  timeMe = micros() - timeMe;
  Serial.printf( "\n\tBig read&compare KBytes per second %5.2f \n", ii / (timeMe / 1000.0) );
  if ( 0 == ii ) return false;
  return true;
}
 
Back
Top