Some questions on LittleFS and program memory for the T4

DrM

Well-known member
Following is a complete source code.

The intent is to use LittleFS to save and recall data to and from program memory on a T4.0. The directory listing shows the file is created but that it has zero size.

What I am doing incorrectly?

Thank you



Code:
#include "Arduino.h"

//#include <digitalWriteFast.h>

#include <limits.h>

#include <ADC.h>
#include <ADC_util.h>

#include <EEPROM.h>

#include <LittleFS.h>

LittleFS_Program filesys;
bool filesys_ready = false;

#define DATALENGTH 2048

uint16_t buffer[DATALENGTH];

#define RCVLEN 256
char rcvbuffer[RCVLEN];
uint16_t nrcvbuf = 0;

bool readfromfile( char *name ) {
  File file;
  
  if (!filesys_ready) {
    Serial.println( "Error: filesys not ready" );
    return false;
  }

  if ( !(file = filesys.open( name, FILE_READ )) ) {
    Serial.println( "Error: not able to open for read" );
    return false;
  }

  file.read( (char *) &buffer[0], DATALENGTH*2 );
  file.close();
  return true;
}

bool writetofile( char *name ) {
  File file;
  
  if (!filesys_ready) {
    Serial.println( "Error: filesys not ready" );
    return false;
  }

  if ( !(file = filesys.open( name, FILE_WRITE_BEGIN )) ) {
    Serial.println( "Error: not able to open for write" );
    return false;
  }

  file.write( (char *) &buffer[0], DATALENGTH*2 );

  Serial.print( "saved to ");
  Serial.print( file.name() );
  Serial.print( " ");
  Serial.print( DATALENGTH*2 );
  Serial.print( " ");
  Serial.println( file.size() );

  file.close();
  
  return true;
}

void listfiles() {
  File dir, entry;
  if (filesys_ready) {
    Serial.print("Space Used = ");
    Serial.println(filesys.usedSize());
    Serial.print("Filesystem Size = ");
    Serial.println(filesys.totalSize());
    dir = filesys.open( "/" );
    while( (entry = dir.openNextFile()) ) {
      Serial.print( entry.name() );
      Serial.print( " " );
      Serial.print( entry.size(), DEC );
      Serial.println();
      entry.close();
    }
    dir.close();
  }
  else {
    Serial.println( "Error: filesys not ready" );
  }
}


char *startsWith( char *s, const char *key ) {
  int n = strlen(key);
  if ( !strncmp( s, key, n ) ) {
    return s + n;
  }
  return 0;
}

char *parseUint( char *s, unsigned int *u ) {
  unsigned long int l;
  char *p = s;
  l = strtoul( s, &p, 0 );
  if ( (p > s) && (l <= UINT_MAX) ) {
    *u = (unsigned int) l;
    return p;
  }
  return 0;
}


void setup() {


  if (!filesys.begin( DATALENGTH*2 + 1024 ) ) {
    Serial.println( "not able to setup filesys" );
  }
  else {
    filesys_ready = true;
    Serial.println("filesystem ready");
    listfiles();
  }
    
}


void loop() {

  uint16_t nlen = 0;
  char *pc;
  char c;

  while ( Serial.available() ) {

    c = Serial.read();

    if ( c ) {

      if ( iscntrl( c )  ) {
        nlen = nrcvbuf;
        rcvbuffer[nrcvbuf] = 0;
        nrcvbuf = 0;
        break;
      }

      else if ( nrcvbuf || !isspace(c) ) {
        rcvbuffer[nrcvbuf++] = c;        
      }

      if ( nrcvbuf >= RCVLEN ) {
        Serial.println( (char *)"Error: buffer overflow" );
        nrcvbuf = 0;
      }
    }
    
  }
  
  if ( nlen > 0 ) {
    
    if ( (pc = startsWith( rcvbuffer, "save" )) ) {

       while( pc && isspace(*pc) ) pc++;
       
       writetofile( (char *) pc );
     }

     else if ( (pc = startsWith( rcvbuffer, "recall" )) ) {

       while( pc && isspace(*pc) ) pc++;       

       if ( readfromfile( (char *) pc ) ) {
	 for ( int i = 0; i < DATALENGTH; i++ ) {
	   Serial.println( buffer[i] );
	 }
       }
     }
    
     else if ( (pc = startsWith( rcvbuffer, "quickformat" )) ) {
       filesys.quickFormat();
       listfiles();
     }
    
     else if ( (pc = startsWith( rcvbuffer, "list files" )) ) {
       listfiles();
     }
    
     else if ( (pc = startsWith( rcvbuffer, "remove" )) ) {
       while( pc && isspace(*pc) ) pc++;
       filesys.remove(pc);
       listfiles();
     }
    
     else if ( (pc = startsWith( rcvbuffer, "send" )) ) {    
       for ( int i =0; i < DATALENGTH; i++ ) {
	 Serial.println( buffer[i] );
       }
     }

  }
}
 
Following is a complete source code.

Yes, this is a complete program. I copied it into Arduino and indeed it does compile.

But the nature of this program is it does several different things depending on what text it receives. Without the specific messages you're sending, how am I supposed to run it the same way you did?
 
Command: save temp.txt

Response:
Code:
saved to temp.txt 4096 0

The first number is the number of bytes that were supposed to be written. The last number is the size returned by file.size() immediately after writing the file. As you see, it is zero.
 
At startup it reports

Space Used = 65536
Filesystem Size = 65536


After writing the file, save temp.txt, the list command produces the following. It shows that the file has been created, but the size is 0 and the spaced used is unchanged.

Code:
Space Used = 65536
Filesystem Size = 65536
temp.txt 0
 
So, it seems that the call file.write( pointer, number_of_bytes) creates the file but not write anything to it.
 
Then, I tried "quickformat". The command list files shows that the file has gone away. Save temp.txt, again creates an empty file.

So, I feel confused. Why is write() not writing anything to the file?
 
I just modified the program to load some values into the buffer, for the write() and then to zero the buffer before the read(). With that I can confirm that as far as read is concerned, the data was nt0 stored or read back from the file.
 
Command: save temp.txt

Response:
Code:
saved to temp.txt 4096 0

The first number is the number of bytes that were supposed to be written. The last number is the size returned by file.size() immediately after writing the file. As you see, it is zero.

I kept getting this:


Code:
not able to setup filesys

Until I edited the code to this - replacing '+' with '*':
Code:
  if (!filesys.begin( [B][COLOR="#FF0000"]DATALENGTH * 1024[/COLOR][/B] ) ) {
    Serial.println( "not able to setup filesys" );
  }


Code:
filesystem ready
Space Used = 131072
Filesystem Size = 2097152
saved to temp.txt 4096 4096
 
Hmmm. how interesting. The original code was DATALENGTH * 2 + 1024. The intent was one buffer and another 1K for overhead..
 
And when I set DATALENGTH * 1024, I get the filesys not ready message, probably because it is too big.
 
Hi Paul, I just tried it with 1024*1024, and that works. It seems there is a minimum size that it needs. Can that be added to the documentation?
 
Hmmm. how interesting. The original code was DATALENGTH * 2 + 1024. The intent was one buffer and another 1K for overhead..

Yes, that is what the start code was and failed here.

Forget the chip spec - and never tested for 'smallest usable' - but seems it wasn't asking for enough space and failing on the T_4.1 here.

It takes at least some 'large' amount due to min erase size on flash.

Seems like T_4.0 is 32KB erase and the T_4.1 is 64KB erase size.

So it was starting at smaller size on T_4 perhaps but could not then manage the write for not being able to erase in 5KB.

Code:
 // ...\libraries\LittleFS\src\LittleFS.cpp
{{0xEF, 0x40, 0x16}, 24, 256, [B]32768[/B], 0x52, 4194304, 3000, 1600000, "W25Q32JV*Q/W25Q32FV"},  // Winbond W25Q32JV*Q/W25Q32FV
{{0xEF, 0x40, 0x17}, 24, 256, [B]65536[/B], 0xD8, 8388608, 3000, 2000000, "W25Q64JV*Q/W25Q64FV"},  // Winbond W25Q64JV*Q/W25Q64FV
 
Back
Top