LittleFS port to Teensy/SPIFlash

Yes, the meaningful change is to blockisBlank() in two places ( NAND and LFS other) and the call change in formatUnused.

I had a good compare post of the times - forgot to post as I ran off - came back with more info accumulated ... messed up and just deleted ...

<edit>: and of course edits to LFSIntegrity ...

@defragster
Just did the code compare and looks good for NAND. See there are 2 constructors now for blockisBlank in NAND.cpp and that was it for the changes in NAND.cpp. Other than I had some Serial prints uncommented that was it.
 
Yes - two copies - one in prior LFS and one added to the NAND code.

Not all media uses it : FRAM, RAM, PROGRAM. RAM is a NOP - not sure about FRAM to just write may take less time to just write blank on request, without wasting time to read first. As for Program - that is controlled down level in the called code to ignore erase when not needed - and seems hyper efficient/fast.

Would be good to have knowledge of all the format requests (not called by formatUnused but LFS itself) for invalidating a cached LFS Used Traverse list since building that list can be time costly. But that gets to be invasive - and some media 'format' isn't in same class to share a common class variable on the low level using the 'static_erase' I found months back. Working through that would be invasive and still not sure if that is a welcome set of changes to get the job done? Perhaps the formatUnused could just have a way to be void on 'those' media and let them fend for themselves? It almost isn't worth it on NAND with FAST format and large media capacity that takes longer to scan numerous files/dirs they can hold. Though they are better served by the early exit blockIsBlank() { exits are single config->read_size verify in each erase block } that doesn't have to read 256MB to see the media is formatted { they check only 2048 for each 131072 erase block - a 64X speedup }

Question: Is there any other reasonable use case that should be added to test in LFSIntegrity?
> like writes on an interrupt to a file - that could likely re-enter and probably bad form as the time taken is 'unknown/long'. Better to cache data and write in loop()?
> and other common interfaces beyond open, write, close, delete, dir, disk space?
->> Doesn't do any RANDOM seek writes?
 
Ok cool was just looking at this now - so now don't have to. Do have to so some testing with the changes though in MTP and standalone :)

Awesome. Let me know if anything changes - the git.LFSIntegrity should match? We can manage any updates but that helps formatUnused look useful and improves/updates LFSIntegrity.ino.
 
PR prepped to update with latest and LFSIntegrity got pulled into PJRC tree. Copied those files to git.defragster\lfsintegrity so they match now for changes going forward.
 
WOW - 5 weeks since last post ...

@Paul and @mjs513: QSPI 256MB / 2Mb NAND Flash seems to work!
>> Paul this is freshly soldered from last package with the DIY T_4.1 bootloader chip (Argh - PCB already pinned soldering a WSON - it works no burns)
>> Also soldered new 8MB PSRAM to same and it works

Some LFSIntergrity commands to disk - "B":create big file half the size of Media, "b":Verify and Delete big file
Code:
...
:: /X_file.txt  QSPI_NAND +++ Add [sz 0 add 6300] @KB/sec 546.78 {94.18}  ++ X   Verify /X_file.txt 6300B  @KB/sec 527.46 
:: /Y_file.txt  QSPI_NAND +++ Add [sz 0 add 6400] @KB/sec 557.05 {89.71}  ++ Y   Verify /Y_file.txt 6400B  @KB/sec 518.60 
 myfs.formatUnused( 0 ) ...

	 formatUnused :: Done Formatting Low Level in 266725 us.

Start Big write of 130920448 Bytes..... [U]// deleted a lot of dots ....[/U]
Big write /0_bigfile.txt took 47.47 Sec for 130918400 Bytes : file3.size()=130918400
	[B]Big write KBytes per second 2757.89[/B] 

[B]Bytes Used: 134348800, Bytes Total:265289728[/B]

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

 myfs.formatUnused( 0 ) ...

	 formatUnused :: Done Formatting Low Level in 3234789 us.

And the PSRAM for speed compare:
Code:
Start Big write of 4141056 Bytes..................................................
Big write /0_bigfile.txt took  0.96 Sec for 4139008 Bytes : file3.size()=4139008
	[B]Big write KBytes per second 4296.76[/B] 

Bytes Used: 4220928, Bytes Total:8388608

Delete with read verify all #bigfile's
	Verify /0_bigfile.txt bytes 4139008 : ..................................................	GOOD! >>  bytes 4139008
	[B]Big read&compare KBytes per second 2315.14[/B]
 
@defragster
Glad that it worked out of the box. QSPI for that chip was a best guess based on the SPI version and the other QSPI chips.
 
@defragster
Glad that it worked out of the box. QSPI for that chip was a best guess based on the SPI version and the other QSPI chips.

Me too - you did good :) , didn't see it had been tested with that (pre-release?) 2Mb variant Paul got so just hooked it up. It has been on my mind to see it run so requested one.
 
Lots of minor warnings from "cppcheck --enable=all --inconclusive", but these might be an issue:

[lfs.c:1975]: (error, inconclusive) Address of local auto-variable assigned to a function parameter.
[lfs.c:3199]: (error, inconclusive) Address of local auto-variable assigned to a function parameter.
[lfs.c:3320]: (error, inconclusive) Address of local auto-variable assigned to a function parameter.
 
Lots of minor warnings from "cppcheck --enable=all --inconclusive", but these might be an issue:

[lfs.c:1975]: (error, inconclusive) Address of local auto-variable assigned to a function parameter.
Indeed it is:
Code:
int lfs_mkdir(lfs_t *lfs, const char *path) {
    LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path);
    // deorphan if we haven't yet, needed at most once after poweron
    int err = lfs_fs_forceconsistency(lfs);
    if (err) {
        LFS_TRACE("lfs_mkdir -> %d", err);
        return err;
    }

    [B]struct lfs_mlist cwd;[/B]
...
        [B][COLOR="#FF0000"]lfs->mlist = &cwd;[/COLOR][/B]

[lfs.c:3199]: (error, inconclusive) Address of local auto-variable assigned to a function parameter.
Code:
int lfs_remove(lfs_t *lfs, const char *path) {
...
    struct lfs_mlist dir;
...
        [B][COLOR="#FF0000"]lfs->mlist = &dir;[/COLOR][/B]
[lfs.c:3320]: (error, inconclusive) Address of local auto-variable assigned to a function parameter.

Code:
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
...
    struct lfs_mlist prevdir;
...
        [B][COLOR="#FF0000"]lfs->mlist = &prevdir;[/COLOR][/B]
 
Is QSPIFlash in LittleFS on a T4.1 dependent on any of the standard GPIO pins?

I got the 64mb external flash chip (W25Q512JV) working like a boss, using the 1.54 beta #9 and the included example files. I exercised a test sketch hundreds of times to write, read, delete, read directories, and lots more. Then I soldered my T4.1 into a custom PCB that is using a dozen GPIO pins, analog inputs, and I2C and the stand-alone flash sketch now fails to start spidisk. I suspect it is because QSPI is using or dependent on some of the GPIO pins I am using for other I/O, but I can't find a reference (although I was getting close with a reference to pins 35, 36, and 37). I don't have any reason to believe that the chip was damaged or altered when I transferred the T4.1 to the PCB, but that is also a possibility (low likelihood). I suspect I have a GPIO conflict.

Thanks for any direction or advice.

-Mike
 
Is QSPIFlash in LittleFS on a T4.1 dependent on any of the standard GPIO pins?

No, the QSPI pins are unique and routed only to those pads from MCU specific hardware that does the QSPI control. They are valid pins for other use { when not using them as QSPI, except the 'other' CS pin if only one pad set is used }, but they are not common to anything else.

The updated T_4.1 card shown here pjrc.com/store/teensy41.html#pins gives the pin reference for those pads.
> Any software change to function or use of pins #48 to #54 could interfere with QSPI.

I got the 64mb external flash chip (W25Q512JV) working like a boss, using the 1.54 beta #9 and the included example files. I exercised a test sketch hundreds of times to write, read, delete, read directories, and lots more. Then I soldered my T4.1 into a custom PCB that is using a dozen GPIO pins, analog inputs, and I2C and the stand-alone flash sketch now fails to start spidisk. I suspect it is because QSPI is using or dependent on some of the GPIO pins I am using for other I/O, but I can't find a reference (although I was getting close with a reference to pins 35, 36, and 37). I don't have any reason to believe that the chip was damaged or altered when I transferred the T4.1 to the PCB, but that is also a possibility (low likelihood). I suspect I have a GPIO conflict.

Thanks for any direction or advice.

-Mike

Not sure if this is a typo or the problem as it should be QSPI not SPI :: " start spidisk "

If it worked before: only damage, flux uncleaned from pads, added solder or something else directly interfering with the chip would be expected to cause any failure.

It has been tested in some variety of connections with other bus and device use.

Suggest going back to the minimal working sketch/state and confirm function as possible.

Then add minimally to seeing a point of failure and examine or post code so the hardware and software can be considered.
 
Thanks @defragster for the quick reply.

Not sure if this is a typo or the problem as it should be QSPI not SPI :: " start spidisk "
That is a typo. A left over error statement from the original example code. My sketch is using "LittleFS_QSPIFlash myfs". In the library it fails almost immediately in the "LittleFS_QSPIFlash::begin()" function. The flash ID returns FF FF FF and so the chip info returns false.

The sketch I am using is my very stripped down flash test sketch that worked over a hundred times without any other code modifications or library mods, when the Teensy was stand-alone. My SMD soldering skills are usually solid, using 20X magnification, but that 64mb chip (with pins already on the Teensy), doesn't have a lot of room to maneuver, so it is possible something shifted when mounting to the PCB. Unfortunately, after soldering the Teensy down to the PCB, there aren't a lot of options for rework of the flash chip. All the voltages check-out and I have a dozen other components on the board working well when testing with different sketches on the Teensy (I2C, Serial, etc.). I'll keep troubleshooting. As a last resort I might try (very carefully) getting under the Teensy with rework heat on the flash chip.
 
A quick update... I gave my whole board a CRC electronics cleaner bath, including an underbody car wash for the Teensy, followed by compressed air, and the worlds tiniest toothbrush scrub around the flash chip. I reconnected to power and my flash sketch works flawlessly. So, my issue was definitely hardware (solder, flux, poor pcb hygiene) and not related to GPIOs or code. I am now proceeding to rock on.
 
A quick update... I gave my whole board a CRC electronics cleaner bath, including an underbody car wash for the Teensy, followed by compressed air, and the worlds tiniest toothbrush scrub around the flash chip. I reconnected to power and my flash sketch works flawlessly. So, my issue was definitely hardware (solder, flux, poor pcb hygiene) and not related to GPIOs or code. I am now proceeding to rock on.

That is Awesome news - I 90% alcohol toothbrush mine before trusting them - then a quick hairdryer blow dry as much as my hand can stand a few rotations.

Not the first to report error from "flux uncleaned from pads" and then needing better cleaning to work - might have been a loose solder bit ...

The last one I soldered was pre-Pinned and and managed a PSRAM with legs and a WSON FLASH without. And at least another dozen chips on some half dozen boards in various combos that all managed to work. I found a solder paste that I can work with - didn't use that once and on inspection had lots of solder stalagmites until redone with paste to pretty shiny spots.
 
Yep. If anyone else is planning on using the 64mb flash chip (W25Q512JV), I'd highly suggest attaching it on a Teensy board without header pins and add your header pins once you've cleaned and tested it. It is a very tight fit. The chip could be set with rework heat, but there is too much going on the reverse side of the Teensy board for me to chance using heat -- hand soldering seems the way to go. Also, this chip requires a small square of capstan tape on the bottom pad, otherwise it will short the chip pins. Use caution when cleaning (air or alcohol), so you don't dislodge the insulating tape. Besides those caveats, this little 64mb flash chip on the T4.1 is perfect.
 
PR made for LittleFS to reMount RAM disks that survive a Warm Restart

From thread : pjrc.com/threads/67500-Another-PSRAM-option-Lyontek

This :: github.com/PaulStoffregen/LittleFS/pull/12
>> Note PR was merged as this post was saved - so look for this in TD 1.54 Beta 10 and after.

Came about when warm restart testing showed that RAM media was always WIPED with memset on .begin().

When LittleFS_RAM using RAM2:DMAMEM or PSRAM and power is maintained across a Warm Restart those memory areas ( except in unseen worst case interruption perhaps ) will hold their contents on setup() reentry.

Code was changed to attempt mount ( like of the FLASH (MRAM) media ) and if that succeeds then no format is performed.

Some notes from above ref thread - this is before RAM1 was excluded from dcache_flush as it done in the Pull Request linked above.

Thanks, Might have been browser spasm here - was typing a reply and 'focus' was not in the post area ... may have tabbed back and had focus on that check box ... opps.


Tested against RAM2 :: DMAMEM char buf[490000];

Again generally works - except without 'file *' flush the lfs core hasn't updated the DIR entry it seems and file size on 'B'igfile write is not correct and LFSIntegrity catches an error.

LFSIntegrity was not doing ANY FLUSH( file ) - perhaps it should have been - though it is clear when data is not flushed errors are detected.

Using the obvious seeming FLUSH() was a fail ...


>> FIXED ?????
Making a change like this seems to be working with no added code on user part as this is called by the lfs core code as needed, even across a 'Hardware' driven reset with TyComm/Reset:
Code:
class LittleFS_RAM : public LittleFS
{
...
private:
...
	static int static_sync(const struct lfs_config *c) {
		Serial.printf("    arm_dcache_flush_delete: ptr=0x%x, size=%d\n", c->context, c->block_count * c->block_size);
		arm_dcache_flush_delete(c->context, c->block_count * c->block_size );
		return 0;
	}

Here is above code showing the PRINT on creating a BigFile - tested an DMAMEM and here on PSRAM:
Code:
 RAM_DISK +++ Add [sz 0 add 5120] @KB/sec 800.38 {524.81}  ++ I   Verify /I_file.txt 5120B  @KB/sec 2348.62 
:: /J_file.txt     arm_dcache_flush_delete: ptr=0x70000000, size=8388608
    [B]arm_dcache_flush_delete: ptr=0x70000000, size=8388608[/B]
 RAM_DISK +++ Add [sz 0 add 5632] @KB/sec 920.86 {595.41}  ++ J   Verify /J_file.txt 5632B  @KB/sec 2321.52 
:: /A_file.txt     arm_dcache_flush_delete: ptr=0x70000000, size=8388608
    [B]arm_dcache_flush_delete: ptr=0x70000000, size=8388608[/B]
 RAM_DISK +++ Add [sz 0 add 6144] @KB/sec 954.48 {624.77}  ++ A   Verify /A_file.txt 6144B  @KB/sec 2308.04 
[  0.10 M](0.01127 M elap) Awaiting input 0123456789RdwcghkFqvplmusSBbyYxfan+-? loops left 0 >
Start Big write of 4147200 Bytes    arm_dcache_flush_delete: ptr=0x70000000, size=8388608
..................................................    [B]arm_dcache_flush_delete: ptr=0x70000000, size=8388608[/B]

Big write /0_bigfile.txt took  0.97 Sec for 4145152 Bytes : file3.size()=4145152
	Big write KBytes per second 4267.55 

Bytes Used: 4214784, Bytes Total:8388608

NOTE: In the event a sketch NEVER wants to mount and use prior LittleFS_RAM image in setup() after myfs.begin() do a format:
Code:
myfs.quickFormat();

or 

myfs.lowLevelFormat();
 
Looks like LittleFS_Program is only working on Teensy 4.1 but crashes on Teensy 4.0. :(

Won't work here either with RAM that fits or DMAMEM???

Not sure when a T_4.0 may have been tested last?

With 1.9MB free on FLASH it won't run with a 1MB LittleFS_Program either?
 
Back
Top