Forum Rule: Always post complete source code & details to reproduce any issue!
Page 35 of 38 FirstFirst ... 25 33 34 35 36 37 ... LastLast
Results 851 to 875 of 941

Thread: LittleFS port to Teensy/SPIFlash

  1. #851
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    I have an ADC sketch running on a T_4.0 and I rebuilt that to work.

    Tested the ASCIITable to build and run on T_4

    The LittleFS_Program sketch certainly should not use any of the _RAM code changed - but note p#848 that fails as well.

    Also fails on T_MMod

    I can build and upload that NVRAM test sketch to both : T_4.0 and T_MMod though ...

  2. #852
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Opened IDE 1.8.13 with TD 1.54 b7 and it builds and runs with 1MB :: LittleFS_Program myfs;

    I'll install 1.54 b9 over that IDE 1.8.13 and see ...

  3. #853
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    TD 1.54 Beta 9 installed over IDE 1.8.13 beta 7 {working in poist #852}:

    Same sketch EPROM DISK of 1MB :: #define TEST_PROG with if (!myfs.begin(1024 * 1024 * 1)) {

    FAILS to start the T_4.0 after upload w/TeensyLoader - USB device OFFLINE - removed from Ports:
    Code:
    17:45:46.375 (loader):  gauge old value = 91
    17:45:46.375 (loader): flash, block=92, bs=1024, auto=1
    17:45:46.375 (loader):  gauge old value = 92
    17:45:46.380 (loader): sending reboot
    17:45:46.380 (loader): begin wait_until_offline
    17:45:46.392 (ports 5): WM_DEVICECHANGE DBT_DEVICEREMOVECOMPLETE
    17:45:46.393 (ports 5): remove: loc=usb:0/140000/0/6/1/4
    17:45:46.393 (ports 5): usb_remove: usb:0/140000/0/6/1/4
    17:45:46.393 (ports 5): nothing new, skipping HID & Ports enum
    17:45:46.448 (loader): offline, waited 1
    17:45:46.448 (loader): end operation, total time = 0.903 seconds
    17:45:46.450 (loader): set background IMG_REBOOT_OK
    17:45:46.451 (loader): redraw timer set, image 14 to show for 1200 ms
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.498 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:45:46.591 (ports 5): WM_DEVICECHANGE DBT_DEVNODES_CHANGED
    17:45:46.591 (ports 5): nothing new, skipping HID & Ports enum
    17:45:47.676 (loader): redraw, image 9
    17:45:48.008 (ports 5): purge, name=hid#vid_16c0&pid_0478 (Teensy 4.0) Bootloader, loc=usb:0/140000/0/6/1/4, age=1.615 sec
    17:46:14.137 (loader): file changed
    17:46:14.157 (loader): File "LFSintegrity.ino.hex". 95232 bytes, 5% used
    17:46:14.200 (post_compile 7): Begin, version=1.54-beta9, high-res time
    17:46:14.202 (loader): remote connection 1540 opened
    17:46:14.202 (loader): remote cmd from 1540: "comment: Teensyduino 1.54-beta9 - WINDOWS (teensy_post_compile)"
    17:46:14.202 (loader): remote cmd from 1540: "status"
    17:46:14.203 (post_compile 7): Sending command: comment: Teensyduino 1.54-beta9 - WINDOWS (teensy_post_compile)
    17:46:14.203 (loader): remote cmd from 1540: "dir:C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\"
    17:46:14.203 (loader): remote cmd from 1540: "file:LFSintegrity.ino.hex"
    17:46:14.204 (post_compile 7): Status: 1, 1, 0, 2, 0, 0, C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\, LFSintegrity.ino.hex
    17:46:14.204 (post_compile 7): Sending command: dir:C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\
    17:46:14.204 (post_compile 7): Sending command: file:LFSintegrity.ino.hex
    17:46:14.220 (loader): File "LFSintegrity.ino.hex". 95232 bytes, 5% used
    17:46:14.227 (loader): remote cmd from 1540: "status"
    17:46:14.228 (post_compile 7): Status: 1, 1, 0, 2, 0, 0, C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\, LFSintegrity.ino.hex
    17:46:14.228 (post_compile 7): Disconnect
    17:46:14.249 (loader): remote connection 1540 closed
    17:46:14.516 (loader): remote connection 1460 opened
    17:46:14.516 (loader): remote cmd from 1460: "comment: Teensyduino 1.54-beta9 - WINDOWS (teensy_post_compile)"
    17:46:14.516 (loader): remote cmd from 1460: "status"
    17:46:14.516 (loader): remote cmd from 1460: "dir:C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\"
    17:46:14.516 (loader): remote cmd from 1460: "file:LFSintegrity.ino.hex"
    17:46:14.520 (post_compile 8): Begin, version=1.54-beta9, high-res time
    17:46:14.522 (post_compile 8): Sending command: comment: Teensyduino 1.54-beta9 - WINDOWS (teensy_post_compile)
    17:46:14.523 (post_compile 8): Status: 1, 1, 0, 2, 0, 0, C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\, LFSintegrity.ino.hex
    17:46:14.523 (post_compile 8): Sending command: dir:C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\
    17:46:14.523 (post_compile 8): Sending command: file:LFSintegrity.ino.hex
    17:46:14.532 (loader): File "LFSintegrity.ino.hex". 95232 bytes, 5% used
    17:46:14.548 (loader): remote cmd from 1460: "status"
    17:46:14.549 (post_compile 8): Status: 1, 1, 0, 2, 0, 0, C:\Users\Tim\AppData\Local\Temp\arduino_build_8985\, LFSintegrity.ino.hex
    17:46:14.549 (post_compile 8): Disconnect
    17:46:14.563 (loader): remote connection 1460 closed
    17:46:14.563 (loader): remote connection 1460 opened
    17:46:14.564 (post_compile 9): Running teensy_reboot: "T:\arduino-1.8.13_t54\hardware\teensy\..\tools\teensy_reboot.exe" teensy_reboot.exe "-board=TEENSY40" "-port=usb:0/140000/0/6/1/4" "-portlabel=(null)" "-portprotocol=(null)"
    17:46:14.579 (loader): remote connection 1468 opened
    17:46:14.579 (reboot 10): Begin, version=1.54-beta9, high-res time
    17:46:14.579 (reboot 10): location = usb:0/140000/0/6/1/4
    17:46:14.579 (reboot 10): portlabel = (null)
    17:46:14.579 (reboot 10): portprotocol = (null)
    17:46:14.579 (reboot 10): LoadLibrary cfgmgr32 ok
    17:46:14.579 (reboot 10): LoadLibrary ntdll ok
    17:46:14.582 (reboot 10): nothing new, skipping HID & Ports enum
    17:46:14.584 (reboot 10): Disconnect
    17:46:14.595 (loader): remote connection 1468 closed
    17:46:14.595 (loader): remote connection 1460 closed
    17:46:18.485 (ports 5): WM_DEVICECHANGE DBT_DEVICEARRIVAL
    17:46:18.486 (ports 5): found_usb_device, id=\\?\usb#vid_16c0&pid_0478#00096263#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    17:46:18.486 (ports 5): found_usb_device, loc=usb:0/140000/0/6/1/4    Port_#0004.Hub_#0011
    17:46:18.486 (ports 5): found_usb_device, hwid=USB\VID_16C0&PID_0478&REV_0105
    17:46:18.486 (ports 5): found_usb_device, devinst=00000018
    17:46:18.486 (ports 5): add: loc=usb:0/140000/0/6/1/4, class=HID, vid=16C0, pid=0478, ver=0105, serial=00096263, dev=\\?\usb#vid_16c0&pid_0478#00096263#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    17:46:18.486 (ports 5): hiddev_from_devinst_list: iface=0
    17:46:18.487 (ports 5): found_usb_device complete
    17:46:18.489 (ports 5): hid, found devinst=00000019
    17:46:18.489 (ports 5): hid, path=\\?\hid#vid_16c0&pid_0478#8&36efacb3&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
    17:46:18.489 (ports 5): hid,  opened handle
    17:46:18.489 (ports 5):  devinst=00000019, location=usb:0/140000/0/6/1/4
    17:46:18.489 (ports 5):  vid=16C0, pid=0478, ver=0105, usepage=FF9C, use=0024
    17:46:18.489 (ports 5):  devpath=\\?\hid#vid_16c0&pid_0478#8&36efacb3&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
    17:46:18.489 (ports 5): usb_add: usb:0/140000/0/6/1/4  hid#vid_16c0&pid_0478 (Teensy 4.0) Bootloader
    17:46:18.501 (ports 5): WM_DEVICECHANGE DBT_DEVNODES_CHANGED
    17:46:18.502 (ports 5): nothing new, skipping HID & Ports enum
    17:46:18.673 (ports 5): WM_DEVICECHANGE DBT_DEVNODES_CHANGED
    17:46:18.673 (ports 5): nothing new, skipping HID & Ports enum
    17:46:18.679 (loader): Device came online, code_size = 2031616
    17:46:18.679 (loader): Board is: Teensy 4.0 (IMXRT1062), version 1.05
    17:46:18.694 (loader): File "LFSintegrity.ino.hex". 95232 bytes, 5% used
    17:46:18.694 (loader): set background IMG_ONLINE
    17:46:18.710 (loader): File "LFSintegrity.ino.hex". 95232 bytes, 5% used
    17:46:18.710 (loader): elf appears to be for Teensy 4.0 (IMXRT1062) (2031616 bytes)
    17:46:18.710 (loader): elf binary data matches hex file
    17:46:18.710 (loader): elf file is for Teensy 4.0 (IMXRT1062)
    17:46:18.710 (loader): begin operation
    17:46:18.737 (loader): flash, block=0, bs=1024, auto=1
    17:46:18.737 (loader):  gauge old value = 0
    ...
    17:46:19.413 (loader): flash, block=91, bs=1024, auto=1
    17:46:19.418 (loader):  gauge old value = 91
    17:46:19.418 (loader): flash, block=92, bs=1024, auto=1
    17:46:19.418 (loader):  gauge old value = 92
    17:46:19.423 (loader): sending reboot
    17:46:19.423 (loader): begin wait_until_offline
    17:46:19.434 (ports 5): WM_DEVICECHANGE DBT_DEVICEREMOVECOMPLETE
    17:46:19.435 (ports 5): remove: loc=usb:0/140000/0/6/1/4
    17:46:19.435 (ports 5): usb_remove: usb:0/140000/0/6/1/4
    17:46:19.435 (ports 5): nothing new, skipping HID & Ports enum
    17:46:19.484 (loader): offline, waited 1
    17:46:19.484 (loader): end operation, total time = 0.774 seconds
    17:46:19.484 (loader): set background IMG_REBOOT_OK
    17:46:19.484 (loader): redraw timer set, image 14 to show for 1200 ms
    17:46:19.484 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.484 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.484 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.484 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.484 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.500 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.500 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.500 (loader): HID/win32:  vid:046D pid:C52B ver:1211
    17:46:19.747 (ports 5): WM_DEVICECHANGE DBT_DEVNODES_CHANGED
    17:46:19.747 (ports 5): nothing new, skipping HID & Ports enum
    17:46:20.690 (loader): redraw, image 9
    17:46:21.074 (ports 5): purge, name=hid#vid_16c0&pid_0478 (Teensy 4.0) Bootloader, loc=usb:0/140000/0/6/1/4, age=1.639 sec
    17:46:32.925 (loader): Verbose Info event

  4. #854
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Installed TD Beta 8 over Beta 9 on IDE 1.8.13 and LFSIntegrity.ino works on T_4.0:
    Code:
    17:54:31.698 (loader): redraw, image 9
    17:54:40.819 (serialmon 6): Begin, version=1.54-beta8, high-res time
    17:54:40.819 (serialmon 6): listening for location: usb:0/140000/0/6/1/4
    17:54:40.819 (serialmon 6): LoadLibrary cfgmgr32 ok
    17:54:40.819 (serialmon 6): LoadLibrary ntdll ok
    17:54:40.822 (serialmon 6): callback 0024
    17:54:40.822 (serialmon 6): callback 0081
    17:54:40.825 (serialmon 6): callback 0083
    17:54:40.825 (serialmon 6): hWnd = 1316154
    17:54:40.825 (serialmon 6): loop stdin, ready=262143
    17:54:40.827 (serialmon 6): found_usb_device, id=\\?\usb#vid_16c0&pid_0483#6150110#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    17:54:40.827 (serialmon 6): found_usb_device, loc=usb:0/140000/0/6/1/4    Port_#0004.Hub_#0011
    17:54:40.827 (serialmon 6): found_usb_device, hwid=USB\VID_16C0&PID_0483&REV_0279
    17:54:40.827 (serialmon 6): found_usb_device, devinst=00000004
    17:54:40.827 (serialmon 6): add: loc=usb:0/140000/0/6/1/4, class=USB, vid=16C0, pid=0483, ver=0279, serial=6150110, dev=\\?\usb#vid_16c0&pid_0483#6150110#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    17:54:40.827 (serialmon 6):   comport_from_devinst_list attempt
    17:54:40.827 (serialmon 6):   found Ports in classguid_list at index=1
    17:54:40.827 (serialmon 6):   port COM19 found from devnode
    17:54:40.827 (serialmon 6): found_usb_device complete
    17:54:40.828 (serialmon 6): usb_add: usb:0/140000/0/6/1/4
    17:54:40.828 (serialmon 6): translate "COM19" -> "\\.\COM19"
    17:54:40.879 (serialmon 6): GetDefaultCommConfig success
    17:54:40.918 (serialmon 6): SetDefaultCommConfig success
    17:54:40.918 (serialmon 6): Opened \\.\COM19 Serial
    17:54:40.920 (ports 5): callback 001A
    17:54:41.006 (loader): remote connection 1440 opened
    17:55:32.031 (loader): Verbose Info event

  5. #855
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,760
    Just tried Teensy Micromod with my test sketch:
    1. Hangs with 1.54bet9 on 1.8.15
    but
    2. Works with 1.54beta8 with IDE1.8.14
    3. T4.0 works as well with beta8

  6. #856
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,760
    @PaulStoffregen - @defragster

    Don't think its an issue with LittleFS believe its something that changed in the core between 1.54beta8 and beta9. Why do I say this - I went back to previous commits - back to feb 23, 2021 with the same results it hangs the Teensy 4.0. Think @defragster is implying the same thing in post #854
    Installed TD Beta 8 over Beta 9 on IDE 1.8.13 and LFSIntegrity.ino works on T_4.0:
    @KurtE mentioned that if the core changed memory alignment (don't remember if you reverted that one or not) it might be the delta between T4 and t4.1?

  7. #857
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,760
    @PaulStoffregen - @defragster - @KurtE

    Not sure you reverted the 1k boundaries completely from the core for the 1062. This is still in imxrt1052.ld
    Code:
    	.text.csf : {
    		FILL(0xFF)
    		. = ALIGN(1024);

  8. #858
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    11,795
    @all - Sorry head in different ...

    Mike and I have been chatting as part of Hexapod stuff...

    I wondered about maybe core changes to align memory to some alignments in flash...
    And wondered if maybe something along that line.

    I assume some of the obvious things have been checked, like that it is properly getting the size of the Flash for the 3 boards (T4, 4.1 and MM)...

    And the starting location is OK...
    EEPROM?

    Again sorry I know random stuff

    Edit: Will try in the morning... Hands shot for today!

  9. #859
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,760
    Rabbit holes ….

    Late for me to start playing but want to hook up a spi flash and see if there is a further problem or just the use of dmamem. Tim forgot if you tested with program mem. Eyes are crossed now.

  10. #860
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    11,795
    Which sketch? Does it have spi flash ram? Does the 4.1 have psram… which would turn into dammed usage without?

  11. #861
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Quote Originally Posted by KurtE View Post
    Which sketch? Does it have spi flash ram? Does the 4.1 have psram… which would turn into dammed usage without?
    post #853 - lfsintegrity using RAM1 or RAM2 - DMAMEM ( dammed ) - or EEPROM Program memory : didn't see it work ...

  12. #862
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Typed the text below before I checked that I am running 1.54b9 with *.LD's from 1.54b8!
    >> I had that thought and copied from the IDE 1.5.13 reinstall ... but apparently left before I built from that setup ... and then didn't restore the LD's

    ------------------- ALL GOOD USING THE TD 1.54b8 : imxrt1062.ld with :: IDE 1.8.15 and TeensyDuino 1.54 Beta 9
    Got out a Beta T_4.0 Ran a sketch from 6 Nov 2020 - that was already on it and then rebuilt and ran fine

    Put the same sketch on another T_4.0 that failed earlier and now it works. It does both RAM and SPI FLASH- but without Flash connected to stopped there.

    Then put an older local copy of LFSIntegrity on that worked RAM and PROG on the Beta T_4 - and then that sketch on the other T-4.0 also working now????

    This is current system IDE 1.8.15 and TeensyDuino 1.54 Beta 9 - running as before from TSET CmdLine builds from SublimeText editor - using TyCommnader for upload and SerMon.


    No Idea what changed - or how it was wrong and match what Paul and Mike found ... now is working fine?

  13. #863
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    28,478
    Looks like the 1K memory align change in the linker script exposed a bug in the startup code where we need a memory barrier between configuring the stack pointer and calling the memory copy function.

    Committed a fix on github
    https://github.com/PaulStoffregen/co...b0d864b035c2ed

    1K memory align is necessary for (future) support of encrypting flash memory.

  14. #864
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,760
    Quote Originally Posted by PaulStoffregen View Post
    Looks like the 1K memory align change in the linker script exposed a bug in the startup code where we need a memory barrier between configuring the stack pointer and calling the memory copy function.

    Committed a fix on github
    https://github.com/PaulStoffregen/co...b0d864b035c2ed

    1K memory align is necessary for (future) support of encrypting flash memory.
    Good morning all

    Just gave the fix a quick try on the MM and the 4.0. The worked like a charm.

    No hangs my little test sketch from post https://forum.pjrc.com/threads/67500...l=1#post281478.

    That looks like it got, ok have to go and make some coffee - just work up.

  15. #865
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    11,795
    Glad you found it! I wonder if it was like the Uncanny eyes code that tried to estimate how much memory we used so walked from top of memory to stack pointer finding out where memory changed. And I think it was Frank who mentioned I needed to not get that close to top of memory.... But that was awhile ago before this change

  16. #866
    I've got an issue when using LittleFS on a T4.1 with an external flash chip, while running under a separate thread. It hangs the thread randomly, where the code works just fine when compiled without threads. I also see that if I substantially increase the setMicroTimer the condition improves, but does not go away. This wasn't an issue when using the same (similar) code with an SD card.

    Are there any known issues using LittleFS or external Flash with threading?

  17. #867
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Quote Originally Posted by TeensyDigital View Post
    I've got an issue when using LittleFS on a T4.1 with an external flash chip, while running under a separate thread. It hangs the thread randomly, where the code works just fine when compiled without threads. I also see that if I substantially increase the setMicroTimer the condition improves, but does not go away. This wasn't an issue when using the same (similar) code with an SD card.

    Are there any known issues using LittleFS or external Flash with threading?
    Not sure any use with threading was tested. SD card I/o uses interrupts or DMA perhaps and can complete its process without being on an active thread.

    LittleFS code is all direct action where it uses the user thread for completion. If the thread is parked that ongoing operation will be frozen and that will leave the operation incomplete and the Flash in an unknown state.

  18. #868
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,760
    Quote Originally Posted by TeensyDigital View Post
    I've got an issue when using LittleFS on a T4.1 with an external flash chip, while running under a separate thread. It hangs the thread randomly, where the code works just fine when compiled without threads. I also see that if I substantially increase the setMicroTimer the condition improves, but does not go away. This wasn't an issue when using the same (similar) code with an SD card.

    Are there any known issues using LittleFS or external Flash with threading?
    As @defragster mentioned - LittleFS wasn't tested with Teensythreads. The SD card operates differently than a flash chip.

    Can you post the code so we can either test or see if there is anything obvious. Without that I can run an example and it works but may not work in your situation.

  19. #869
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Installed 1.54b10 and it works initially on T_4.0

    Seeing odd DMAMEM char buf[490000]; behavior - doing 'R'estart to test static RAM and hanging on restart?
    Saw it on beta 10 announce post ... but this diff now?
    Quote Originally Posted by defragster View Post
    Installed td 1.54 b10 on Win 10 over IDE 1.8.15 - Install good and no problems w/LittleFS LFSIntegrity onto T_4.0.

    Ramdisk note - Primary RAM / RAM1 is always zeroed on any restart to won't persist.
    Does work with DMAMEM / RAM2 : using LFSIntegrity {DMAMEM char buf[490000];} found an anomaly filling half of disk with a 'B'igfile then 'R'estart and 'b'igfile delete does a forever delete. using 256 byte blocks for file of size 223232 leaves something about the long file chain file unwritten. Will add .flush to see if it triggers safe use. Other I/O after 'B' is safe so not a lfs problem. Will move to T_4.1 PSRAM and try similar.
    >> .flush() didn't fix ?
    Not sure if it is added .flush leaving the RAM in odd worse state than just bad 'B'igfile ... looking some more.

  20. #870
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Took out .flush that was not there before - can't even write the Bigfile just now?

    It hangs and keeps hanging on restart until power off ... like DMAMEM adjustment changed how it works ????

    DMAMEM char buf[490000];
    that leaves room in RAM2:
    teensy_size: Memory Usage on Teensy 4.1:
    teensy_size: FLASH: code:78264, data:9752, headers:8236 free for files:8030212
    teensy_size: RAM1: variables:21184, code:72536, padding:25768 free for local variables:404800
    teensy_size: RAM2: variables:502400 free for malloc/new:21888

  21. #871
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    Switched to PSRAM ramdrive - 'B'igfile won't complete there either? It hangs after some portion of the write.

    Button and TyComm/Reset has it start and dies early in setup() - next line would be ramdisk .begin()

    Note just Bigfile - dies on first file write in a single iteration too ... Then hangs on restart after disk mounted - with debug on ...
    Code:
    printDirectory RAM_DISK
    --------------
    
     0 dirs with 0 files of Size 0 Bytes
     Total 0 files of Size 0 Bytes
    Bytes Used: 4096, Bytes Total:8388608
    :: /B_file.txt   dies here ... then restart follows
    T:\arduino-1.8.15\hardware\teensy\avr\libraries\LittleFS\examples\LFSintegrity\LFSintegrity.ino Jun 18 2021 23:31:25
    LittleFS Test : File Integrity
    configure 
    mounted atfer format
    Mounts and returns to setup then dies doing:
    >> filecount = printDirectoryFilecount( myfs.open("/") ); // Set base value of filecount for disk
    Last edited by defragster; 06-19-2021 at 07:01 AM.

  22. #872
    Quote Originally Posted by mjs513 View Post
    Can you post the code so we can either test or see if there is anything obvious. Without that I can run an example and it works but may not work in your situation.
    My code is too large/complex to post (thousands of lines, a dozen sensors, four thread loops, etc). I’m heading out of town, but I’ll try and isolate it on Monday and post.

    That said, when I couldn’t get the littleFS flash to work in threads, I reverted that section of my code to my old SD card solution. To my surprise it had the same strange behavior and also hung the thread. So, I went back a few revs to my last known good sketch on a known good board and it also didn’t work. This was all on 1.54b9. So, I ditched the 1.54 beta and went back to the GA IDE and all my SD routines in a thread worked great again. So, I suspect there is something in the beta that is breaking both SD and LittleFS in threads (both work fine without threads), in my specific situation.

    Again, I’ll work to isolate a subset/sample and post next Monday.

    Thanks,
    Mike

  23. #873
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,435
    @TeensyDigital - TD 1.54 Beta 10 was released with a change in startup that Paul saw cause troubles.

    Though something new and bad affecting the LittleFS sketch in use with Beta 10.

    @Paul /@all - I cannot now get the LFSIntegrity to write a complete file and not hang. I reverted the _RAM code in listtleFS.h for static RAM - always Zeros and no _sync doing dcache_flush - and still it is failing the write without hang on PSRAM?

    Using a T_4.1 with twin PSRAMS but only using 8MB - was seeing the same with DMAMEM RAM2 on T_4.1 and on T_4.0:

    Odd it was doing better on first post in Beta 10 thread ...now a total fail. Before and after removing the just added RAM code.

    DOING: 'B' - starts BIG write and does not complete
    or
    DOING '1' - a single loop write to one small file and it hangs.

    Something is corrupting the FS on RAM? With the STATIC RAM reversion and always ZERO on start it will restart okay, if not reverted it hangs on starting as the image is broken.

    past times for Zzzz's ...

    Current edits to LFSIntegrity as installed are the top: ROOTONLY, _RAM select and sizing, and (optional for smaller DMAMEM) fewer subdirs of 16 are only changes to test:

    Code:
    //#include <LittleFS.h>
    #include <LittleFS_NAND.h>
    
    #define HALFCUT  // HALFCUT defined to fill half the disk
    #define ROOTONLY // NORMAL is NOT DEFINED!
    #define NUMDIRS 32  // When not ROOTONLY must be 1 or more
    #define MYPSRAM 8	// compile time PSRAM size
    #define MYBLKSIZE 2048 // 2048
    //#define SHOW_YIELD_CNT  1 // uncommented shows calls to Yield per second
    
    #define TEST_RAM
    //#define TEST_SPI
    //#define TEST_QSPI
    //#define TEST_SPI_NAND
    //#define TEST_QSPI_NAND
    //#define TEST_PROG
    //#define TEST_MRAM
    
    IntervalTimer clocked10ms;
    uint32_t yCalls = 0;
    uint32_t yCallsMax = 0;
    uint32_t yCallsLast = 0;
    uint32_t yCallsIdx = 0;
    uint32_t yCallsSum = 0;
    #ifdef SHOW_YIELD_CNT
    void yield() {
    	yCalls++;
    }
    #endif
    void clock_isr() {
    	yCallsIdx++;
    	if ( yCallsIdx >= 100 ) {
    		if (yCallsSum > 0 )
    			Serial.printf( "\n yps=%lu [mx=%lu]\t", yCallsSum, yCallsMax * 100);
    		yCallsIdx = 0;
    		yCallsSum = 0;
    		yCallsMax = 0;
    	}
    	yCallsSum += yCalls - yCallsLast;
    	if ( yCalls - yCallsLast > yCallsMax ) yCallsMax = yCalls - yCallsLast;
    	yCallsLast = yCalls;
    }
    
    // Set for SPI usage
    //const int FlashChipSelect = 10; // AUDIO BOARD
    const int FlashChipSelect = 4; // PJRC Mem board 64MB on #5, #6 : NAND 1Gb on #3, 2GB on #4
    //const int FlashChipSelect = 5; // PJRC Mem board 64MB on #5, #6 : NAND 1Gb on #3, 2GB on #4
    //const int FlashChipSelect = 6; // digital pin for flash chip CS pin
    
    
    #ifdef TEST_RAM
    LittleFS_RAM myfs;
    // RUNTIME :: extern "C" uint8_t external_psram_size;
    EXTMEM char buf[MYPSRAM * 1024 * 1024];	// USE DMAMEM for more memory than ITCM allows - or remove
    //DMAMEM char buf[490000];	// USE DMAMEM for more memory than ITCM allows - or remove
    //char buf[390000];	// USE DMAMEM for more memory than ITCM allows - or remove
    char szDiskMem[] = "RAM_DISK";
    #elif defined(TEST_SPI)
    //const int FlashChipSelect = 10; // Arduino 101 built-in SPI Flash
    #define FORMATSPI
    //#define FORMATSPI2
    LittleFS_SPIFlash myfs;
    char szDiskMem[] = "SPI_DISK";
    #elif defined(TEST_MRAM)
    //const int FlashChipSelect = 10; // Arduino 101 built-in SPI Flash
    LittleFS_SPIFram myfs;
    char szDiskMem[] = "FRAM_DISK";
    #elif defined(TEST_PROG)
    LittleFS_Program myfs;
    char szDiskMem[] = "PRO_DISK";
    #elif defined(TEST_QSPI_NAND)
    char szDiskMem[] = "QSPI_NAND";
    LittleFS_QPINAND myfs;
    #elif defined(TEST_SPI_NAND)
    char szDiskMem[] = "SPI_NAND";
    LittleFS_SPINAND myfs;
    #else // TEST_QSPI
    LittleFS_QSPIFlash myfs;
    char szDiskMem[] = "QSPI_DISK";
    
    #endif
    
    File file3;
    
    uint32_t DELSTART = 3; // originally was 3 + higher bias more to writes and larger files - lower odd
    #define SUBADD 512	// bytes added each pass (*times file number)
    #define BIGADD 1024	// bytes added each pass - bigger will quickly consume more space
    #define MAXNUM 16	// ALPHA A-Z is 26, less for fewer files
    #define MAXFILL 2048 // 66000	// ZERO to disable :: Prevent iterations from over filling - require this much free
    #define DELDELAY 0 	// delay before DEL files : delayMicroseconds
    #define ADDDELAY 0 	// delay on ADD FILE : delayMicroseconds
    
    const uint32_t lowOffset = 'a' - 'A';
    const uint32_t lowShift = 13;
    uint32_t errsLFS = 0;
    uint32_t warnLFS = 0;
    uint32_t lCnt = 0;
    uint32_t LoopCnt = 0;
    uint64_t rdCnt = 0;
    uint64_t wrCnt = 0;
    int filecount = 0;
    
    void setup() {
    	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_RAM2)
    	if (!myfs.begin(buf, sizeof(buf), MYBLKSIZE )) {
    #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
    #elif defined(TEST_MRAM)
    	if (!myfs.begin( FlashChipSelect )) {
    #elif defined(TEST_SPI_NAND)
    	if (!myfs.begin( FlashChipSelect )) {
    #elif defined(TEST_PROG)
    	if (!myfs.begin(1024 * 1024 * 6)) {
    #else
    	if (!myfs.begin()) {
    #endif
    		Serial.printf("Error starting %s\n", szDiskMem);
    		checkInput( 1 );
    	}
    	// parseCmd( 'F' ); // ENABLE this if disk won't allow startup
    	filecount = printDirectoryFilecount( myfs.open("/") );  // Set base value of filecount for disk
    	printDirectory();
    	parseCmd( '?' );
    #ifndef ROOTONLY // make subdirs if !ROOTONLY
    	makeRootDirs();
    #endif
    	checkInput( 1 );
    	filecount = printDirectoryFilecount( myfs.open("/") );  // Set base value of filecount for disk
    	printDirectory();
    #ifdef SHOW_YIELD_CNT
    	clocked10ms.begin(clock_isr, 10000);
    #endif
    	while ( 1 ) {
    		loopX(); // Avoid end of loop() yield so the clock_isr() isn't noisy when used.
    #ifndef SHOW_YIELD_CNT
    		yield(); // simulate normal exec
    #endif
    	}
    }
    
    void makeRootDirs() {
    	char szDir[16];
    	for ( uint32_t ii = 1; ii <= NUMDIRS; ii++ ) {
    		sprintf( szDir, "/%lu_dir", ii );
    		myfs.mkdir( szDir );
    	}
    }
    
    int loopLimit = 0; // -1 continuous, otherwise # to count down to 0
    bool pauseDir = false;  // Start Pause on each off
    bool showDir =  false;  // false Start Dir on each off
    bool bDirVerify =  false;  // false Start Dir on each off
    bool bWriteVerify = true;  // Verify on Write Toggle
    bool bAutoFormat =  false;  // false Auto formatUnused() off
    bool bCheckFormat =  false;  // false CheckFormat
    bool bCheckUsed =  false;  // false CheckUsed
    uint32_t res = 0; // for formatUnused
    void loop() { }
    void loopX() {
    	char szDir[16];
    	LoopCnt++;
    	uint32_t chStep;
    	if ( loopLimit != 0 ) {
    #ifdef ROOTONLY // ii=1-NUMDIRS are subdirs. #0 is Root
    		for ( uint32_t ii = 0; ii < 1 && ( loopLimit != 0 ); ii++ )
    #else
    		for ( uint32_t ii = 0; ii < NUMDIRS && ( loopLimit != 0 ); ii++ )
    #endif
    		{
    			if ( ii == 0 )
    				sprintf( szDir, "/" );
    			else
    				sprintf( szDir, "/%lu_dir", ii );
    			chStep = fileCycle(szDir);
    			if ( bAutoFormat && !(lCnt % 5) ) res = loopAutoFormat( 20, res );
    //			if ( bAutoFormat && !(lCnt % 20) ) res = loopAutoFormat( 6, res );
    			while ( chStep != fileCycle(szDir) && ( loopLimit != 0 ) ) {
    				if ( bAutoFormat && !(lCnt % 5) ) res = loopAutoFormat( 12, res ); // how often and how many depends on media and sizes
    				//if ( bAutoFormat && !(lCnt % 20) ) res = loopAutoFormat( 6, res );
    				checkInput( 0 ); // user input can 0 loopLimit
    			}
    		}
    		checkInput( 0 );
    		if ( loopLimit > 0 ) // -1 means continuous
    			loopLimit--;
    	}
    	else
    		checkInput( 1 );
    }
    uint32_t loopAutoFormat( uint32_t cnt, uint32_t myres ) {
    	uint32_t retres;
    	retres = myfs.formatUnused( cnt, myres );
    	Serial.printf("\t fmtU @ %lu - %lu \n", myres, retres );
    	return retres;
    
    }
    
    char szInputs[] = "0123456789RdwcghkFqvplmusSBbyYxfan+-?";
    uint32_t lastTime;
    void checkInput( int step ) { // prompt for input without user input with step != 0
    	uint32_t nowTime = micros();
    
    	char retVal = 0, temp;
    	char *pTemp;
    	if ( step != 0 ) {
    		nowTime -= lastTime;
    		Serial.printf( "[%6.2f M](%6.5f M elap) Awaiting input %s loops left %d >", millis() / 60000.0, nowTime / 60000000.0, szInputs, loopLimit );
    	}
    	else {
    		if ( !Serial.available() ) return;
    		nowTime -= lastTime;
    		Serial.printf( "[%6.2f M](%6.2f elap) Awaiting input %s loops left %d >", millis() / 60000.0, nowTime / 60000000.0, szInputs, loopLimit );
    		//Serial.printf( "[%6.2f] Awaiting input %s loops left %d >", millis() / 60000.0, 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 );
    		}
    	}
    	Serial.print( '\n' );
    	if ( '?' == retVal ) checkInput( 1 ); // recurse on '?' to allow command show and response
    	return;
    }
    void parseCmd( char chIn ) { // pass chIn == '?' for help
    	uint32_t timeMe;
    		char szNone[]="";
    	switch (chIn ) {
    	case '?':
    		Serial.printf( "%s\n", " 0, 1-9 '#' passes continue loop before Pause\n\
     'a' Auto formatUnused() during iterations - TOGGLE\n\
     'R' Restart Teensy\n\
     'd' Directory of LittleFS\n\
     'w' WIPE Directory of LittleFS\n\
     'b' big file delete\n\
     'B' BIG FILE MAKE\n\
     'S' FILE 2MB MAKE\n\
     's' FILE 2MB delete\n\
     'c' Continuous Loop\n\
     'g' run speedBench()\n\
     'h' Hundred loops\n\
     'k' Thousand loops\n\
     'F' LittleFS_ Low Level Format Disk \n\
     'f' LittleFS::formatUnused( ALL ) : DATA PRESERVED \n\
     'q' LittleFS_ Quick Format Disk \n\
     'v' Verbose All Dir Prints - TOGGLE\n\
     'p' Pause after all Dir prints - TOGGLE\n\
     'l' Show count of loop()'s, Bytes Read,Written\n\
     'm' Make ROOT dirs (needed after q/F format !ROOTONLY)\n\
     'u' Update Filecount\n\
     'x' Directory filecount verify - TOGGLE\n\
     'n' No verify on Write- TOGGLE\n\
     '+' more add to delete cycles\n\
     '-' fewer add to delete cycles\n\
     'y' reclaim 1 block :: myfs.formatUnused( 1 )\n\
     'Y' reclaim 15 blocks :: myfs.formatUnused( 15 )\n\
     '?' Help list" );
    		break;
    	case 'R':
    		Serial.print(" RESTART Teensy ...");
    		delay(100);
    		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';
    		if ( chIn != '0' )	// Preserve elapsed time on Error or STOP command
    			lastTime = micros();
    		break;
    	case 'b':
    		bigFile( 0 ); // delete
    		chIn = 0;
    		break;
    	case 'B':
    		lastTime = micros();
    		bigFile( 1 ); // CREATE
    		chIn = 0;
    		break;
    	case 's':
    		bigFile2MB( 0 ); // CREATE
    		chIn = 0;
    		break;
    	case 'S':
    		lastTime = micros();
    		bigFile2MB( 1 ); // CREATE
    		chIn = 0;
    		break;
    	case 'c':
    		loopLimit = -1;
    		break;
    	case 'g':
    		lastTime = micros();
    		speedBench();
    		chIn = 0;
    		break;
    	case 'd':
    		Serial.print( " d\n" );
    		lastTime = micros();
    		printDirectory();
    		Serial.print( '\n' );
    		parseCmd( 'l' );
    		checkInput( 1 );
    		chIn = 0;
    		break;
    	case 'w':
    		Serial.println("\nWipe All Files and DIRS:");
    		deleteAllDirectory(myfs.open("/"), szNone );
    		errsLFS = 0; // No Errors on new Format
    		warnLFS = 0; // No warning on new Format
    		chIn = 0;
    		parseCmd( 'u' );
    		break;
    	case 'h':
    		loopLimit = 100;
    		lastTime = micros();
    		break;
    	case 'k':
    		loopLimit = 1000;
    		lastTime = micros();
    		break;
    	case 'F': // Low Level format
    		Serial.print( "\nFormatting Low Level:\n\t" );
    		lastTime = micros();
    		timeMe = micros();
    		myfs.lowLevelFormat('.');
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n Done Formatting Low Level in %lu us.\n", timeMe );
    		errsLFS = 0; // No Errors on new Format
    		warnLFS = 0; // No warning on new Format
    		bCheckFormat  = false;
    		parseCmd( 'u' );
    		break;
    	case 'q': // quick format
    		lastTime = micros();
    		myfs.quickFormat();
    		errsLFS = 0; // No Errors on new Format
    		parseCmd( 'u' );
    		break;
    	case 'v': // verbose dir
    		showDir = !showDir;
    		showDir ? Serial.print(" Verbose on: ") : Serial.print(" Verbose off: ");
    		chIn = 0;
    		break;
    	case 'p': // pause on dirs
    		pauseDir = !pauseDir;
    		pauseDir ? Serial.print(" Pause on: ") : Serial.print(" Pause off: ");
    		chIn = 0;
    		break;
    	case 'x': // dir filecount Verify
    		bDirVerify = !bDirVerify;
    		bDirVerify ? Serial.print(" FileCnt on: ") : Serial.print(" FileCnt off: ");
    		lastTime = micros();
    		dirVerify();
    		chIn = 0;
    		break;
    	case 'n': // No Verify on write
    		bWriteVerify = !bWriteVerify;
    		bWriteVerify ? Serial.print(" Write Verify on: ") : Serial.print(" Write Verify off: ");
    		chIn = 0;
    		break;
    	case 'a': // Auto myfs.formatUnused() during iterations
    		bAutoFormat = !bAutoFormat;
    		bAutoFormat ? Serial.print(" \nAuto formatUnused() On: ") : Serial.print(" \nAuto formatUnused() Off: ");
    		chIn = 0;
    		break;
    	case 'y': // Reclaim 1 unused format
    		lastTime = micros();
    		Serial.printf( "\n myfs.formatUnused( 1 ) ...\n" );
    		timeMe = micros();
    		res = myfs.formatUnused( 1, res );
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n\t formatUnused :: Done Formatting Low Level in %lu us (last %lu).\n", timeMe, res );
    		chIn = 0;
    		break;
    	case 'Y': // Reclaim 15 unused format
    		lastTime = micros();
    		Serial.printf( "\n myfs.formatUnused( 15 ) ...\n" );
    		timeMe = micros();
    		res = myfs.formatUnused( 15, res );
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n\t formatUnused :: Done Formatting Low Level in %lu us (last %lu).\n", timeMe, res );
    		chIn = 0;
    		break;
    	case 'f': // Reclaim all unused format
    		lastTime = micros();
    		Serial.printf( "\n myfs.formatUnused( 0 ) ...\n" );
    		timeMe = micros();
    		myfs.formatUnused( 0, 0 );
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n\t formatUnused :: Done Formatting Low Level in %lu us.\n", timeMe );
    		chIn = 0;
    		break;
    	case 'l': // Show Loop Count
    		Serial.printf("\n\t Loop Count: %u (#fileCycle=%u), Bytes read %llu, written %llu, #Files=%u\n", LoopCnt, lCnt, rdCnt, wrCnt, filecount );
    		if ( 0 != errsLFS )
    			Serial.printf("\t ERROR COUNT =%u\n", errsLFS );
    		if ( 0 != warnLFS )
    			Serial.printf("\t Free Space Warn COUNT =%u\n", warnLFS );
    		dirVerify();
    		chIn = 0;
    		break;
    	case 'm':
    		Serial.printf("m \n\t Making Root Dirs\n" );
    		makeRootDirs();
    		parseCmd( 'd' );
    		chIn = 0;
    		break;
    	case 'u': // Show Loop Count
    		filecount = printDirectoryFilecount( myfs.open("/") );
    		Serial.printf("u \n\t Updated filecount %u\n", filecount );
    		chIn = 0;
    		break;
    	case '+': // increase add cycles
    		DELSTART++;
    		Serial.printf("+\n Deletes start after %u cycles ", DELSTART);
    		chIn = 0;
    		break;
    	case '-': // decrease add cycles
    		DELSTART--;
    		if ( DELSTART < 1 ) DELSTART = 1;
    		Serial.printf("-\n Deletes start after %u cycles ", DELSTART);
    		chIn = 0;
    		break;
    	default:
    		Serial.println( chIn ); // never see without unhandled char in szInputs[]
    		break;
    	}
    	if ( 0 != chIn ) Serial.print( chIn );
    }
    
    uint32_t fTot, totSize;
    void printDirectory() {
    	fTot = 0, totSize = 0;
    	Serial.printf("printDirectory %s\n--------------\n", szDiskMem);
    	printDirectory(myfs.open("/"), 0);
    	Serial.printf(" %Total %u files of Size %u Bytes\n", fTot, totSize);
    	Serial.printf("Bytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());
    }
    
    void deleteAllDirectory(File dir, char *fullPath ) {
    	char myPath[ 256 ] = "";
    	while (true) {
    		File entry =  dir.openNextFile();
    		if (! entry) {
    			// no more files
    			break;
    		}
    		if (entry.isDirectory()) {
    			strcpy( myPath, fullPath);
    			strcat( myPath, entry.name());
    			strcat( myPath, "/");
    			deleteAllDirectory(entry, myPath);
    			entry.close();
    			if ( !myfs.remove( myPath ) )
    				Serial.print( "  Fail remove DIR>\t");
    			else
    				Serial.print( "  Removed DIR>\t");
    			Serial.println( myPath );
    
    		} else {
    			strcpy( myPath, fullPath);
    			strcat( myPath, entry.name());
    			entry.close();
    			if ( !myfs.remove( myPath ) )
    				Serial.print( "\tFail remove>\t");
    			else
    				Serial.print( "\tRemoved>\t");
    			Serial.println( myPath );
    		}
    	}
    }
    
    int printDirectoryFilecount(File dir) {
    	unsigned int filecnt = 0;
    	while (true) {
    		File entry =  dir.openNextFile();
    		if (! entry) {
    			// no more files
    			break;
    		}
    		if (entry.isDirectory()) {
    			filecnt += printDirectoryFilecount(entry);
    		} else {
    			filecnt++;
    		}
    		entry.close();
    	}
    	return filecnt;
    }
    
    void printDirectory(File dir, int numTabs) {
    	//dir.whoami();
    	uint32_t fSize = 0, 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;
    			totSize += 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();
    	}
    }
    
    uint32_t cCnt = 0;
    uint32_t fileCycle(const char *dir) {
    	static char szFile[] = "_file.txt";
    	char szPath[150];
    	int ii;
    	lCnt++;
    	byte nNum = lCnt % MAXNUM;
    	char chNow = 'A' + lCnt % MAXNUM;
    	lfs_ssize_t resW = 1;
    	uint32_t timeMeAll = micros();
    
    	if ( dir[1] == 0 )	// catch root
    		sprintf( szPath, "/%c%s", chNow, szFile );
    	else
    		sprintf( szPath, "%s/%c%s", dir, chNow, szFile );
    	if ( cCnt >= DELSTART && myfs.exists(szPath) ) { // DELETE ALL KNOWN FILES
    		if ( nNum == 1 ) {
    			Serial.print( "\n == == ==   DELETE PASS START  == == == = \n");
    			if ( showDir ) {
    				printDirectory();
    				Serial.print( " == == ==   DELETE PASS START  == == == = \n");
    			}
    			delayMicroseconds(DELDELAY);
    		}
    	}
    	Serial.printf( ":: %s ", szPath );
    	if ( cCnt >= DELSTART && myfs.exists(szPath) ) { // DELETE ALL KNOWN FILES
    		readVerify( szPath, chNow );
    		myfs.remove(szPath);
    		filecount--;
    		Serial.printf(" %s ----DEL----", szDiskMem);
    		Serial.printf(" -- %c", chNow);
    		if ( showDir ) {
    			Serial.print("\n");
    			printDirectory(myfs.open(dir), 1);
    		}
    		if ( pauseDir ) checkInput( 1 );
    		Serial.println();
    	}
    	else {
    		if ( bWriteVerify && myfs.totalSize() - myfs.usedSize() < MAXFILL ) {
    			warnLFS++;
    			Serial.printf( "\tXXX\tXXX\tXXX\tXXX\tSIZE WARNING { MAXFILL } \n" );
    			cCnt = DELSTART;
    			return cCnt;	// EARLY EXIT
    		}
    		if ( nNum == 0 ) {
    			nNum = 10;
    			cCnt++;
    			if ( cCnt >= DELSTART + 2 ) cCnt = 0;
    		}
    		file3 = myfs.open(szPath, FILE_WRITE);
    		if ( 0 == file3 ) {
    			Serial.printf( "\tXXX\tXXX\tXXX\tXXX\tFail File open {mkdir?}\n" );
    			delayMicroseconds(300000);
    			checkInput( 1 );	// PAUSE on CmdLine
    		}
    		else {
    			delayMicroseconds(ADDDELAY);
    			char mm = chNow + lowOffset;
    			uint32_t jj = file3.size() + 1;
    			uint32_t timeMe = micros();
    			for ( ii = 0; ii < (nNum * SUBADD + BIGADD ) && resW > 0; ii++ ) {
    				if ( 0 == ((ii + jj) / lowShift) % 2 )
    					resW = file3.write( &mm , 1 );
    				else
    					resW = file3.write( &chNow , 1 );
    				wrCnt++;
    				// if ( lCnt%100 == 50 ) mm='x'; // GENERATE ERROR to detect on DELETE read verify
    			}
    			file3.close();
    			timeMe = micros() - timeMe;
    			timeMeAll = micros() - timeMeAll;
    			Serial.printf(" %s +++ Add [sz %u add %u] @KB/sec %5.2f {%5.2f} ", szDiskMem, jj - 1, ii, ii / (timeMe / 1000.0), ii / (timeMeAll / 1000.0) );
    			if (resW < 0) {
    				Serial.printf( "\n\twrite fail ERR# %i 0x%X \n", resW, resW );
    				parseCmd( '0' );
    				errsLFS++;
    				checkInput( 1 );	// PAUSE on CmdLine
    			}
    			else if ( jj == 1 ) filecount++; // File Added
    			Serial.printf(" ++ %c ", chNow);
    			if ( bWriteVerify )
    				readVerify( szPath, chNow );
    			else
    				Serial.print('\n');
    			if ( showDir ) {
    				Serial.print('\n');
    				printDirectory(myfs.open(dir), 1);
    			}
    		}
    		if ( pauseDir ) checkInput( 1 );
    		//Serial.print("\n");
    		delayMicroseconds(ADDDELAY);
    	}
    	checkInput( 0 ); // user stop request?
    	if ( bDirVerify ) dirVerify();
    	return cCnt;
    }
    
    void dirVerify() {
    	uint32_t timeMe = micros();
    	Serial.printf("\tdirV...");
    	if ( filecount != printDirectoryFilecount( myfs.open("/") ) ) {
    		Serial.printf( "\tFilecount mismatch %u != %u\n", filecount, printDirectoryFilecount( myfs.open("/") ) );
    		parseCmd( '0' );
    		errsLFS++;
    		checkInput( 1 );	// PAUSE on CmdLine
    	}
    	timeMe = micros() - timeMe;
    	Serial.printf("%lu_us\t", timeMe);
    }
    
    void readVerify( char szPath[], char chNow ) {
    	uint32_t timeMe = micros();
    	file3 = myfs.open(szPath);
    	if ( 0 == file3 ) {
    		Serial.printf( "\tV\t Fail File open %s\n", szPath );
    		parseCmd( '0' );
    		errsLFS++;
    		checkInput( 1 );
    	}
    	char mm;
    	char chNow2 = chNow + lowOffset;
    	uint32_t ii = 0;
    	while ( file3.available() ) {
    		file3.read( &mm , 1 );
    		rdCnt++;
    		//Serial.print( mm ); // show chars as read
    		ii++;
    		if ( 0 == (ii / lowShift) % 2 ) {
    			if ( chNow2 != mm ) {
    				Serial.printf( "<Bad Byte!  %c! = %c [0x%X] @%u\n", chNow2, mm, mm, ii );
    				parseCmd( '0' );
    				errsLFS++;
    				checkInput( 1 );
    				break;
    			}
    		}
    		else {
    			if ( chNow != mm ) {
    				Serial.printf( "<Bad Byte!  %c! = %c [0x%X] @%u\n", chNow, mm, mm, ii );
    				parseCmd( '0' );
    				errsLFS++;
    				checkInput( 1 );
    				break;
    			}
    		}
    	}
    	Serial.printf( "  Verify %s %uB ", szPath, ii );
    	if (ii != file3.size()) {
    		Serial.printf( "\n\tRead Count fail! :: read %u != f.size %llu", ii, file3.size() );
    		parseCmd( '0' );
    		errsLFS++;
    		checkInput( 1 );	// PAUSE on CmdLine
    	}
    	file3.close();
    	timeMe = micros() - timeMe;
    	Serial.printf( " @KB/sec %5.2f \n", ii / (timeMe / 1000.0) );
    }
    
    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;
    }
    
    
    void bigFile( int doThis ) {
    	char myFile[] = "/0_bigfile.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 = (myfs.totalSize()) - myfs.usedSize();
    		if ( toWrite < 65535 ) {
    			Serial.print( "Disk too full! DO :: b or q or F");
    			return;
    		}
    		toWrite -= 40960; // allow for slack space :: WORKS on FLASH?
    #ifdef HALFCUT
    		toWrite /= 2; // cutting to this works on LittleFS_RAM myfs - except reported file3.size()=2054847098 OR now 0
    #endif
    		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 halves 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);
    		}
    	}
    }
    
    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);
    		}
    	}
    }
    
    #include <sdios.h>
    ArduinoOutStream cout(Serial);
    File file;
    
    // File size in bytes.
    const uint32_t FILE_SIZE = 16 * 1024;
    
    // Set SKIP_FIRST_LATENCY true if the first read/write to the SD can
    // be avoid by writing a file header or reading the first record.
    const bool SKIP_FIRST_LATENCY = true;
    
    // Size of read/write.
    const size_t BUF_SIZE = 2048;
    
    // Write pass count.
    const uint8_t WRITE_COUNT = 5;
    
    // Read pass count.
    const uint8_t READ_COUNT = 5;
    
    //Block size for qspi
    #define MYBLKSIZE 2048 // 2048
    
    // Insure 4-byte alignment.
    uint32_t buf32[(BUF_SIZE + 3) / 4];
    uint8_t* bufA32 = (uint8_t*)buf32;
    
    //Number of random reads
    #define randomReads 1
    
    void speedBench() {
    	File file;
    	float s;
    	uint32_t t;
    	uint32_t maxLatency;
    	uint32_t minLatency;
    	uint32_t totalLatency;
    	bool skipLatency;
    
    	myfs.remove("bench.dat");
    	//for(uint8_t cnt=0; cnt < 10; cnt++) {
    
    	// fill buf with known data
    	if (BUF_SIZE > 1) {
    		for (size_t i = 0; i < (BUF_SIZE - 2); i++) {
    			bufA32[i] = 'A' + (i % 26);
    		}
    		bufA32[BUF_SIZE - 2] = '\r';
    	}
    	bufA32[BUF_SIZE - 1] = '\n';
    
    	Serial.printf("%s Disk Stats:", szDiskMem );
    	Serial.printf("Bytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());
    	Serial.printf("%s Benchmark:\n", szDiskMem );
    	cout << F("FILE_SIZE = ") << FILE_SIZE << endl;
    	cout << F("BUF_SIZE = ") << BUF_SIZE << F(" bytes\n");
    	cout << F("Starting write test, please wait.") << endl << endl;
    
    	// do write test
    	uint32_t n = FILE_SIZE / BUF_SIZE;
    	cout << F("write speed and latency") << endl;
    	cout << F("speed,max,min,avg") << endl;
    	cout << F("KB/Sec,usec,usec,usec") << endl;
    
    	// open or create file - truncate existing file.
    	file = myfs.open("bench.dat", FILE_WRITE);
    
    	for (uint8_t nTest = 0; nTest < WRITE_COUNT; nTest++) {
    		file.seek(0);
    
    		maxLatency = 0;
    		minLatency = 9999999;
    		totalLatency = 0;
    		skipLatency = SKIP_FIRST_LATENCY;
    		t = millis();
    
    		for (uint32_t i = 0; i < n; i++) {
    			uint32_t m = micros();
    			if (file.write(bufA32, BUF_SIZE) != BUF_SIZE) {
    				Serial.println("write failed");
    			}
    			m = micros() - m;
    			totalLatency += m;
    			if (skipLatency) {
    				// Wait until first write to SD, not just a copy to the cache.
    				skipLatency = file.position() < 512;
    			} else {
    				if (maxLatency < m) {
    					maxLatency = m;
    				}
    				if (minLatency > m) {
    					minLatency = m;
    				}
    			}
    		}
    
    		t = millis() - t;
    		s = file.size();
    		cout << s / t << ',' << maxLatency << ',' << minLatency;
    		cout << ',' << totalLatency / n << endl;
    	}
    	cout << endl << F("Starting sequential read test, please wait.") << endl;
    	cout << endl << F("read speed and latency") << endl;
    	cout << F("speed,max,min,avg") << endl;
    	cout << F("KB/Sec,usec,usec,usec") << endl;
    
    	// do read test
    	for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
    		file.seek(0);
    		maxLatency = 0;
    		minLatency = 9999999;
    		totalLatency = 0;
    		skipLatency = SKIP_FIRST_LATENCY;
    		t = micros();
    		for (uint32_t i = 0; i < n; i++) {
    			bufA32[BUF_SIZE - 1] = 0;
    			uint32_t m = micros();
    			int32_t nr = file.read(bufA32, BUF_SIZE);
    			if (nr != BUF_SIZE) {
    				Serial.println("read failed");
    			}
    			m = micros() - m;
    			totalLatency += m;
    			if (bufA32[BUF_SIZE - 1] != '\n') {
    				Serial.println("data check error");
    			}
    			if (skipLatency) {
    				skipLatency = false;
    			} else {
    				if (maxLatency < m) {
    					maxLatency = m;
    				}
    				if (minLatency > m) {
    					minLatency = m;
    				}
    			}
    		}
    
    		s = file.size();
    
    		t = micros() - t;
    		cout << s * 1000 / t << ',' << maxLatency << ',' << minLatency;
    		cout << ',' << totalLatency / n << endl;
    	}
    
    	cout << endl << F("Done") << endl;
    
    	cout << endl << F("Starting random read test, please wait.") << endl;
    
    	Serial.printf("Number of random reads: %d\n", randomReads);
    	Serial.printf("Number of blocks: %d\n", n);
    
    	cout << endl << F("read speed and latency") << endl;
    	cout << F("speed,max,min,avg") << endl;
    
    	// do read test
    	for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
    		file.seek(0);
    		maxLatency = 0;
    		minLatency = 0;
    		totalLatency = 0;
    		skipLatency = SKIP_FIRST_LATENCY;
    		t = micros();
    		for (uint32_t i = 0; i < randomReads; i++) {
    			bufA32[BUF_SIZE - 1] = 0;
    			uint32_t m = micros();
    			uint32_t block_pos = random(0, (n - 1));
    			uint32_t random_pos = block_pos * MYBLKSIZE;
    			cout << "Position (bytes), Block: " << random_pos << ", ";
    			cout << block_pos << endl;
    			uint32_t startCNT = ARM_DWT_CYCCNT;
    			file.seek(random_pos);
    			int32_t nr = file.read(bufA32, BUF_SIZE);
    			uint32_t endCNT = ARM_DWT_CYCCNT;
    			cout << F("Read Time (ARM Cycle Delta): ") << endCNT - startCNT << endl;
    			if (nr != BUF_SIZE) {
    				Serial.println("read failed");
    			}
    			m = micros() - m;
    			totalLatency += m;
    			if (bufA32[BUF_SIZE - 1] != '\n') {
    				Serial.println("data check error");
    			}
    			if (skipLatency) {
    				skipLatency = false;
    			} else {
    				if (maxLatency < m) {
    					maxLatency = m;
    				}
    				if (minLatency > m) {
    					minLatency = m;
    				}
    			}
    		}
    
    		s = file.size();
    
    
    		t = micros() - t;
    		cout << F("KB/Sec,usec,usec,usec") << endl;
    		cout << s * 1000 / t << ',' << maxLatency << ',' << minLatency;
    		cout << ',' << totalLatency / n << endl;
    	}
    	cout << endl << F("Done") << endl;
    
    
    	file.close();
    	myfs.remove("bench.dat");
    
    }

  24. #874
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,760
    Quote Originally Posted by defragster View Post
    @TeensyDigital - TD 1.54 Beta 10 was released with a change in startup that Paul saw cause troubles.

    Though something new and bad affecting the LittleFS sketch in use with Beta 10.

    @Paul /@all - I cannot now get the LFSIntegrity to write a complete file and not hang. I reverted the _RAM code in listtleFS.h for static RAM - always Zeros and no _sync doing dcache_flush - and still it is failing the write without hang on PSRAM?

    Using a T_4.1 with twin PSRAMS but only using 8MB - was seeing the same with DMAMEM RAM2 on T_4.1 and on T_4.0:

    Odd it was doing better on first post in Beta 10 thread ...now a total fail. Before and after removing the just added RAM code.

    DOING: 'B' - starts BIG write and does not complete
    or
    DOING '1' - a single loop write to one small file and it hangs.

    Something is corrupting the FS on RAM? With the STATIC RAM reversion and always ZERO on start it will restart okay, if not reverted it hangs on starting as the image is broken.

    past times for Zzzz's ...

    Current edits to LFSIntegrity as installed are the top: ROOTONLY, _RAM select and sizing, and (optional for smaller DMAMEM) fewer subdirs of 16 are only changes to test:

    Code:
    //#include <LittleFS.h>
    #include <LittleFS_NAND.h>
    
    #define HALFCUT  // HALFCUT defined to fill half the disk
    #define ROOTONLY // NORMAL is NOT DEFINED!
    #define NUMDIRS 32  // When not ROOTONLY must be 1 or more
    #define MYPSRAM 8	// compile time PSRAM size
    #define MYBLKSIZE 2048 // 2048
    //#define SHOW_YIELD_CNT  1 // uncommented shows calls to Yield per second
    
    #define TEST_RAM
    //#define TEST_SPI
    //#define TEST_QSPI
    //#define TEST_SPI_NAND
    //#define TEST_QSPI_NAND
    //#define TEST_PROG
    //#define TEST_MRAM
    
    IntervalTimer clocked10ms;
    uint32_t yCalls = 0;
    uint32_t yCallsMax = 0;
    uint32_t yCallsLast = 0;
    uint32_t yCallsIdx = 0;
    uint32_t yCallsSum = 0;
    #ifdef SHOW_YIELD_CNT
    void yield() {
    	yCalls++;
    }
    #endif
    void clock_isr() {
    	yCallsIdx++;
    	if ( yCallsIdx >= 100 ) {
    		if (yCallsSum > 0 )
    			Serial.printf( "\n yps=%lu [mx=%lu]\t", yCallsSum, yCallsMax * 100);
    		yCallsIdx = 0;
    		yCallsSum = 0;
    		yCallsMax = 0;
    	}
    	yCallsSum += yCalls - yCallsLast;
    	if ( yCalls - yCallsLast > yCallsMax ) yCallsMax = yCalls - yCallsLast;
    	yCallsLast = yCalls;
    }
    
    // Set for SPI usage
    //const int FlashChipSelect = 10; // AUDIO BOARD
    const int FlashChipSelect = 4; // PJRC Mem board 64MB on #5, #6 : NAND 1Gb on #3, 2GB on #4
    //const int FlashChipSelect = 5; // PJRC Mem board 64MB on #5, #6 : NAND 1Gb on #3, 2GB on #4
    //const int FlashChipSelect = 6; // digital pin for flash chip CS pin
    
    
    #ifdef TEST_RAM
    LittleFS_RAM myfs;
    // RUNTIME :: extern "C" uint8_t external_psram_size;
    EXTMEM char buf[MYPSRAM * 1024 * 1024];	// USE DMAMEM for more memory than ITCM allows - or remove
    //DMAMEM char buf[490000];	// USE DMAMEM for more memory than ITCM allows - or remove
    //char buf[390000];	// USE DMAMEM for more memory than ITCM allows - or remove
    char szDiskMem[] = "RAM_DISK";
    #elif defined(TEST_SPI)
    //const int FlashChipSelect = 10; // Arduino 101 built-in SPI Flash
    #define FORMATSPI
    //#define FORMATSPI2
    LittleFS_SPIFlash myfs;
    char szDiskMem[] = "SPI_DISK";
    #elif defined(TEST_MRAM)
    //const int FlashChipSelect = 10; // Arduino 101 built-in SPI Flash
    LittleFS_SPIFram myfs;
    char szDiskMem[] = "FRAM_DISK";
    #elif defined(TEST_PROG)
    LittleFS_Program myfs;
    char szDiskMem[] = "PRO_DISK";
    #elif defined(TEST_QSPI_NAND)
    char szDiskMem[] = "QSPI_NAND";
    LittleFS_QPINAND myfs;
    #elif defined(TEST_SPI_NAND)
    char szDiskMem[] = "SPI_NAND";
    LittleFS_SPINAND myfs;
    #else // TEST_QSPI
    LittleFS_QSPIFlash myfs;
    char szDiskMem[] = "QSPI_DISK";
    
    #endif
    
    File file3;
    
    uint32_t DELSTART = 3; // originally was 3 + higher bias more to writes and larger files - lower odd
    #define SUBADD 512	// bytes added each pass (*times file number)
    #define BIGADD 1024	// bytes added each pass - bigger will quickly consume more space
    #define MAXNUM 16	// ALPHA A-Z is 26, less for fewer files
    #define MAXFILL 2048 // 66000	// ZERO to disable :: Prevent iterations from over filling - require this much free
    #define DELDELAY 0 	// delay before DEL files : delayMicroseconds
    #define ADDDELAY 0 	// delay on ADD FILE : delayMicroseconds
    
    const uint32_t lowOffset = 'a' - 'A';
    const uint32_t lowShift = 13;
    uint32_t errsLFS = 0;
    uint32_t warnLFS = 0;
    uint32_t lCnt = 0;
    uint32_t LoopCnt = 0;
    uint64_t rdCnt = 0;
    uint64_t wrCnt = 0;
    int filecount = 0;
    
    void setup() {
    	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_RAM2)
    	if (!myfs.begin(buf, sizeof(buf), MYBLKSIZE )) {
    #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
    #elif defined(TEST_MRAM)
    	if (!myfs.begin( FlashChipSelect )) {
    #elif defined(TEST_SPI_NAND)
    	if (!myfs.begin( FlashChipSelect )) {
    #elif defined(TEST_PROG)
    	if (!myfs.begin(1024 * 1024 * 6)) {
    #else
    	if (!myfs.begin()) {
    #endif
    		Serial.printf("Error starting %s\n", szDiskMem);
    		checkInput( 1 );
    	}
    	// parseCmd( 'F' ); // ENABLE this if disk won't allow startup
    	filecount = printDirectoryFilecount( myfs.open("/") );  // Set base value of filecount for disk
    	printDirectory();
    	parseCmd( '?' );
    #ifndef ROOTONLY // make subdirs if !ROOTONLY
    	makeRootDirs();
    #endif
    	checkInput( 1 );
    	filecount = printDirectoryFilecount( myfs.open("/") );  // Set base value of filecount for disk
    	printDirectory();
    #ifdef SHOW_YIELD_CNT
    	clocked10ms.begin(clock_isr, 10000);
    #endif
    	while ( 1 ) {
    		loopX(); // Avoid end of loop() yield so the clock_isr() isn't noisy when used.
    #ifndef SHOW_YIELD_CNT
    		yield(); // simulate normal exec
    #endif
    	}
    }
    
    void makeRootDirs() {
    	char szDir[16];
    	for ( uint32_t ii = 1; ii <= NUMDIRS; ii++ ) {
    		sprintf( szDir, "/%lu_dir", ii );
    		myfs.mkdir( szDir );
    	}
    }
    
    int loopLimit = 0; // -1 continuous, otherwise # to count down to 0
    bool pauseDir = false;  // Start Pause on each off
    bool showDir =  false;  // false Start Dir on each off
    bool bDirVerify =  false;  // false Start Dir on each off
    bool bWriteVerify = true;  // Verify on Write Toggle
    bool bAutoFormat =  false;  // false Auto formatUnused() off
    bool bCheckFormat =  false;  // false CheckFormat
    bool bCheckUsed =  false;  // false CheckUsed
    uint32_t res = 0; // for formatUnused
    void loop() { }
    void loopX() {
    	char szDir[16];
    	LoopCnt++;
    	uint32_t chStep;
    	if ( loopLimit != 0 ) {
    #ifdef ROOTONLY // ii=1-NUMDIRS are subdirs. #0 is Root
    		for ( uint32_t ii = 0; ii < 1 && ( loopLimit != 0 ); ii++ )
    #else
    		for ( uint32_t ii = 0; ii < NUMDIRS && ( loopLimit != 0 ); ii++ )
    #endif
    		{
    			if ( ii == 0 )
    				sprintf( szDir, "/" );
    			else
    				sprintf( szDir, "/%lu_dir", ii );
    			chStep = fileCycle(szDir);
    			if ( bAutoFormat && !(lCnt % 5) ) res = loopAutoFormat( 20, res );
    //			if ( bAutoFormat && !(lCnt % 20) ) res = loopAutoFormat( 6, res );
    			while ( chStep != fileCycle(szDir) && ( loopLimit != 0 ) ) {
    				if ( bAutoFormat && !(lCnt % 5) ) res = loopAutoFormat( 12, res ); // how often and how many depends on media and sizes
    				//if ( bAutoFormat && !(lCnt % 20) ) res = loopAutoFormat( 6, res );
    				checkInput( 0 ); // user input can 0 loopLimit
    			}
    		}
    		checkInput( 0 );
    		if ( loopLimit > 0 ) // -1 means continuous
    			loopLimit--;
    	}
    	else
    		checkInput( 1 );
    }
    uint32_t loopAutoFormat( uint32_t cnt, uint32_t myres ) {
    	uint32_t retres;
    	retres = myfs.formatUnused( cnt, myres );
    	Serial.printf("\t fmtU @ %lu - %lu \n", myres, retres );
    	return retres;
    
    }
    
    char szInputs[] = "0123456789RdwcghkFqvplmusSBbyYxfan+-?";
    uint32_t lastTime;
    void checkInput( int step ) { // prompt for input without user input with step != 0
    	uint32_t nowTime = micros();
    
    	char retVal = 0, temp;
    	char *pTemp;
    	if ( step != 0 ) {
    		nowTime -= lastTime;
    		Serial.printf( "[%6.2f M](%6.5f M elap) Awaiting input %s loops left %d >", millis() / 60000.0, nowTime / 60000000.0, szInputs, loopLimit );
    	}
    	else {
    		if ( !Serial.available() ) return;
    		nowTime -= lastTime;
    		Serial.printf( "[%6.2f M](%6.2f elap) Awaiting input %s loops left %d >", millis() / 60000.0, nowTime / 60000000.0, szInputs, loopLimit );
    		//Serial.printf( "[%6.2f] Awaiting input %s loops left %d >", millis() / 60000.0, 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 );
    		}
    	}
    	Serial.print( '\n' );
    	if ( '?' == retVal ) checkInput( 1 ); // recurse on '?' to allow command show and response
    	return;
    }
    void parseCmd( char chIn ) { // pass chIn == '?' for help
    	uint32_t timeMe;
    		char szNone[]="";
    	switch (chIn ) {
    	case '?':
    		Serial.printf( "%s\n", " 0, 1-9 '#' passes continue loop before Pause\n\
     'a' Auto formatUnused() during iterations - TOGGLE\n\
     'R' Restart Teensy\n\
     'd' Directory of LittleFS\n\
     'w' WIPE Directory of LittleFS\n\
     'b' big file delete\n\
     'B' BIG FILE MAKE\n\
     'S' FILE 2MB MAKE\n\
     's' FILE 2MB delete\n\
     'c' Continuous Loop\n\
     'g' run speedBench()\n\
     'h' Hundred loops\n\
     'k' Thousand loops\n\
     'F' LittleFS_ Low Level Format Disk \n\
     'f' LittleFS::formatUnused( ALL ) : DATA PRESERVED \n\
     'q' LittleFS_ Quick Format Disk \n\
     'v' Verbose All Dir Prints - TOGGLE\n\
     'p' Pause after all Dir prints - TOGGLE\n\
     'l' Show count of loop()'s, Bytes Read,Written\n\
     'm' Make ROOT dirs (needed after q/F format !ROOTONLY)\n\
     'u' Update Filecount\n\
     'x' Directory filecount verify - TOGGLE\n\
     'n' No verify on Write- TOGGLE\n\
     '+' more add to delete cycles\n\
     '-' fewer add to delete cycles\n\
     'y' reclaim 1 block :: myfs.formatUnused( 1 )\n\
     'Y' reclaim 15 blocks :: myfs.formatUnused( 15 )\n\
     '?' Help list" );
    		break;
    	case 'R':
    		Serial.print(" RESTART Teensy ...");
    		delay(100);
    		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';
    		if ( chIn != '0' )	// Preserve elapsed time on Error or STOP command
    			lastTime = micros();
    		break;
    	case 'b':
    		bigFile( 0 ); // delete
    		chIn = 0;
    		break;
    	case 'B':
    		lastTime = micros();
    		bigFile( 1 ); // CREATE
    		chIn = 0;
    		break;
    	case 's':
    		bigFile2MB( 0 ); // CREATE
    		chIn = 0;
    		break;
    	case 'S':
    		lastTime = micros();
    		bigFile2MB( 1 ); // CREATE
    		chIn = 0;
    		break;
    	case 'c':
    		loopLimit = -1;
    		break;
    	case 'g':
    		lastTime = micros();
    		speedBench();
    		chIn = 0;
    		break;
    	case 'd':
    		Serial.print( " d\n" );
    		lastTime = micros();
    		printDirectory();
    		Serial.print( '\n' );
    		parseCmd( 'l' );
    		checkInput( 1 );
    		chIn = 0;
    		break;
    	case 'w':
    		Serial.println("\nWipe All Files and DIRS:");
    		deleteAllDirectory(myfs.open("/"), szNone );
    		errsLFS = 0; // No Errors on new Format
    		warnLFS = 0; // No warning on new Format
    		chIn = 0;
    		parseCmd( 'u' );
    		break;
    	case 'h':
    		loopLimit = 100;
    		lastTime = micros();
    		break;
    	case 'k':
    		loopLimit = 1000;
    		lastTime = micros();
    		break;
    	case 'F': // Low Level format
    		Serial.print( "\nFormatting Low Level:\n\t" );
    		lastTime = micros();
    		timeMe = micros();
    		myfs.lowLevelFormat('.');
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n Done Formatting Low Level in %lu us.\n", timeMe );
    		errsLFS = 0; // No Errors on new Format
    		warnLFS = 0; // No warning on new Format
    		bCheckFormat  = false;
    		parseCmd( 'u' );
    		break;
    	case 'q': // quick format
    		lastTime = micros();
    		myfs.quickFormat();
    		errsLFS = 0; // No Errors on new Format
    		parseCmd( 'u' );
    		break;
    	case 'v': // verbose dir
    		showDir = !showDir;
    		showDir ? Serial.print(" Verbose on: ") : Serial.print(" Verbose off: ");
    		chIn = 0;
    		break;
    	case 'p': // pause on dirs
    		pauseDir = !pauseDir;
    		pauseDir ? Serial.print(" Pause on: ") : Serial.print(" Pause off: ");
    		chIn = 0;
    		break;
    	case 'x': // dir filecount Verify
    		bDirVerify = !bDirVerify;
    		bDirVerify ? Serial.print(" FileCnt on: ") : Serial.print(" FileCnt off: ");
    		lastTime = micros();
    		dirVerify();
    		chIn = 0;
    		break;
    	case 'n': // No Verify on write
    		bWriteVerify = !bWriteVerify;
    		bWriteVerify ? Serial.print(" Write Verify on: ") : Serial.print(" Write Verify off: ");
    		chIn = 0;
    		break;
    	case 'a': // Auto myfs.formatUnused() during iterations
    		bAutoFormat = !bAutoFormat;
    		bAutoFormat ? Serial.print(" \nAuto formatUnused() On: ") : Serial.print(" \nAuto formatUnused() Off: ");
    		chIn = 0;
    		break;
    	case 'y': // Reclaim 1 unused format
    		lastTime = micros();
    		Serial.printf( "\n myfs.formatUnused( 1 ) ...\n" );
    		timeMe = micros();
    		res = myfs.formatUnused( 1, res );
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n\t formatUnused :: Done Formatting Low Level in %lu us (last %lu).\n", timeMe, res );
    		chIn = 0;
    		break;
    	case 'Y': // Reclaim 15 unused format
    		lastTime = micros();
    		Serial.printf( "\n myfs.formatUnused( 15 ) ...\n" );
    		timeMe = micros();
    		res = myfs.formatUnused( 15, res );
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n\t formatUnused :: Done Formatting Low Level in %lu us (last %lu).\n", timeMe, res );
    		chIn = 0;
    		break;
    	case 'f': // Reclaim all unused format
    		lastTime = micros();
    		Serial.printf( "\n myfs.formatUnused( 0 ) ...\n" );
    		timeMe = micros();
    		myfs.formatUnused( 0, 0 );
    		timeMe = micros() - timeMe;
    		Serial.printf( "\n\t formatUnused :: Done Formatting Low Level in %lu us.\n", timeMe );
    		chIn = 0;
    		break;
    	case 'l': // Show Loop Count
    		Serial.printf("\n\t Loop Count: %u (#fileCycle=%u), Bytes read %llu, written %llu, #Files=%u\n", LoopCnt, lCnt, rdCnt, wrCnt, filecount );
    		if ( 0 != errsLFS )
    			Serial.printf("\t ERROR COUNT =%u\n", errsLFS );
    		if ( 0 != warnLFS )
    			Serial.printf("\t Free Space Warn COUNT =%u\n", warnLFS );
    		dirVerify();
    		chIn = 0;
    		break;
    	case 'm':
    		Serial.printf("m \n\t Making Root Dirs\n" );
    		makeRootDirs();
    		parseCmd( 'd' );
    		chIn = 0;
    		break;
    	case 'u': // Show Loop Count
    		filecount = printDirectoryFilecount( myfs.open("/") );
    		Serial.printf("u \n\t Updated filecount %u\n", filecount );
    		chIn = 0;
    		break;
    	case '+': // increase add cycles
    		DELSTART++;
    		Serial.printf("+\n Deletes start after %u cycles ", DELSTART);
    		chIn = 0;
    		break;
    	case '-': // decrease add cycles
    		DELSTART--;
    		if ( DELSTART < 1 ) DELSTART = 1;
    		Serial.printf("-\n Deletes start after %u cycles ", DELSTART);
    		chIn = 0;
    		break;
    	default:
    		Serial.println( chIn ); // never see without unhandled char in szInputs[]
    		break;
    	}
    	if ( 0 != chIn ) Serial.print( chIn );
    }
    
    uint32_t fTot, totSize;
    void printDirectory() {
    	fTot = 0, totSize = 0;
    	Serial.printf("printDirectory %s\n--------------\n", szDiskMem);
    	printDirectory(myfs.open("/"), 0);
    	Serial.printf(" %Total %u files of Size %u Bytes\n", fTot, totSize);
    	Serial.printf("Bytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());
    }
    
    void deleteAllDirectory(File dir, char *fullPath ) {
    	char myPath[ 256 ] = "";
    	while (true) {
    		File entry =  dir.openNextFile();
    		if (! entry) {
    			// no more files
    			break;
    		}
    		if (entry.isDirectory()) {
    			strcpy( myPath, fullPath);
    			strcat( myPath, entry.name());
    			strcat( myPath, "/");
    			deleteAllDirectory(entry, myPath);
    			entry.close();
    			if ( !myfs.remove( myPath ) )
    				Serial.print( "  Fail remove DIR>\t");
    			else
    				Serial.print( "  Removed DIR>\t");
    			Serial.println( myPath );
    
    		} else {
    			strcpy( myPath, fullPath);
    			strcat( myPath, entry.name());
    			entry.close();
    			if ( !myfs.remove( myPath ) )
    				Serial.print( "\tFail remove>\t");
    			else
    				Serial.print( "\tRemoved>\t");
    			Serial.println( myPath );
    		}
    	}
    }
    
    int printDirectoryFilecount(File dir) {
    	unsigned int filecnt = 0;
    	while (true) {
    		File entry =  dir.openNextFile();
    		if (! entry) {
    			// no more files
    			break;
    		}
    		if (entry.isDirectory()) {
    			filecnt += printDirectoryFilecount(entry);
    		} else {
    			filecnt++;
    		}
    		entry.close();
    	}
    	return filecnt;
    }
    
    void printDirectory(File dir, int numTabs) {
    	//dir.whoami();
    	uint32_t fSize = 0, 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;
    			totSize += 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();
    	}
    }
    
    uint32_t cCnt = 0;
    uint32_t fileCycle(const char *dir) {
    	static char szFile[] = "_file.txt";
    	char szPath[150];
    	int ii;
    	lCnt++;
    	byte nNum = lCnt % MAXNUM;
    	char chNow = 'A' + lCnt % MAXNUM;
    	lfs_ssize_t resW = 1;
    	uint32_t timeMeAll = micros();
    
    	if ( dir[1] == 0 )	// catch root
    		sprintf( szPath, "/%c%s", chNow, szFile );
    	else
    		sprintf( szPath, "%s/%c%s", dir, chNow, szFile );
    	if ( cCnt >= DELSTART && myfs.exists(szPath) ) { // DELETE ALL KNOWN FILES
    		if ( nNum == 1 ) {
    			Serial.print( "\n == == ==   DELETE PASS START  == == == = \n");
    			if ( showDir ) {
    				printDirectory();
    				Serial.print( " == == ==   DELETE PASS START  == == == = \n");
    			}
    			delayMicroseconds(DELDELAY);
    		}
    	}
    	Serial.printf( ":: %s ", szPath );
    	if ( cCnt >= DELSTART && myfs.exists(szPath) ) { // DELETE ALL KNOWN FILES
    		readVerify( szPath, chNow );
    		myfs.remove(szPath);
    		filecount--;
    		Serial.printf(" %s ----DEL----", szDiskMem);
    		Serial.printf(" -- %c", chNow);
    		if ( showDir ) {
    			Serial.print("\n");
    			printDirectory(myfs.open(dir), 1);
    		}
    		if ( pauseDir ) checkInput( 1 );
    		Serial.println();
    	}
    	else {
    		if ( bWriteVerify && myfs.totalSize() - myfs.usedSize() < MAXFILL ) {
    			warnLFS++;
    			Serial.printf( "\tXXX\tXXX\tXXX\tXXX\tSIZE WARNING { MAXFILL } \n" );
    			cCnt = DELSTART;
    			return cCnt;	// EARLY EXIT
    		}
    		if ( nNum == 0 ) {
    			nNum = 10;
    			cCnt++;
    			if ( cCnt >= DELSTART + 2 ) cCnt = 0;
    		}
    		file3 = myfs.open(szPath, FILE_WRITE);
    		if ( 0 == file3 ) {
    			Serial.printf( "\tXXX\tXXX\tXXX\tXXX\tFail File open {mkdir?}\n" );
    			delayMicroseconds(300000);
    			checkInput( 1 );	// PAUSE on CmdLine
    		}
    		else {
    			delayMicroseconds(ADDDELAY);
    			char mm = chNow + lowOffset;
    			uint32_t jj = file3.size() + 1;
    			uint32_t timeMe = micros();
    			for ( ii = 0; ii < (nNum * SUBADD + BIGADD ) && resW > 0; ii++ ) {
    				if ( 0 == ((ii + jj) / lowShift) % 2 )
    					resW = file3.write( &mm , 1 );
    				else
    					resW = file3.write( &chNow , 1 );
    				wrCnt++;
    				// if ( lCnt%100 == 50 ) mm='x'; // GENERATE ERROR to detect on DELETE read verify
    			}
    			file3.close();
    			timeMe = micros() - timeMe;
    			timeMeAll = micros() - timeMeAll;
    			Serial.printf(" %s +++ Add [sz %u add %u] @KB/sec %5.2f {%5.2f} ", szDiskMem, jj - 1, ii, ii / (timeMe / 1000.0), ii / (timeMeAll / 1000.0) );
    			if (resW < 0) {
    				Serial.printf( "\n\twrite fail ERR# %i 0x%X \n", resW, resW );
    				parseCmd( '0' );
    				errsLFS++;
    				checkInput( 1 );	// PAUSE on CmdLine
    			}
    			else if ( jj == 1 ) filecount++; // File Added
    			Serial.printf(" ++ %c ", chNow);
    			if ( bWriteVerify )
    				readVerify( szPath, chNow );
    			else
    				Serial.print('\n');
    			if ( showDir ) {
    				Serial.print('\n');
    				printDirectory(myfs.open(dir), 1);
    			}
    		}
    		if ( pauseDir ) checkInput( 1 );
    		//Serial.print("\n");
    		delayMicroseconds(ADDDELAY);
    	}
    	checkInput( 0 ); // user stop request?
    	if ( bDirVerify ) dirVerify();
    	return cCnt;
    }
    
    void dirVerify() {
    	uint32_t timeMe = micros();
    	Serial.printf("\tdirV...");
    	if ( filecount != printDirectoryFilecount( myfs.open("/") ) ) {
    		Serial.printf( "\tFilecount mismatch %u != %u\n", filecount, printDirectoryFilecount( myfs.open("/") ) );
    		parseCmd( '0' );
    		errsLFS++;
    		checkInput( 1 );	// PAUSE on CmdLine
    	}
    	timeMe = micros() - timeMe;
    	Serial.printf("%lu_us\t", timeMe);
    }
    
    void readVerify( char szPath[], char chNow ) {
    	uint32_t timeMe = micros();
    	file3 = myfs.open(szPath);
    	if ( 0 == file3 ) {
    		Serial.printf( "\tV\t Fail File open %s\n", szPath );
    		parseCmd( '0' );
    		errsLFS++;
    		checkInput( 1 );
    	}
    	char mm;
    	char chNow2 = chNow + lowOffset;
    	uint32_t ii = 0;
    	while ( file3.available() ) {
    		file3.read( &mm , 1 );
    		rdCnt++;
    		//Serial.print( mm ); // show chars as read
    		ii++;
    		if ( 0 == (ii / lowShift) % 2 ) {
    			if ( chNow2 != mm ) {
    				Serial.printf( "<Bad Byte!  %c! = %c [0x%X] @%u\n", chNow2, mm, mm, ii );
    				parseCmd( '0' );
    				errsLFS++;
    				checkInput( 1 );
    				break;
    			}
    		}
    		else {
    			if ( chNow != mm ) {
    				Serial.printf( "<Bad Byte!  %c! = %c [0x%X] @%u\n", chNow, mm, mm, ii );
    				parseCmd( '0' );
    				errsLFS++;
    				checkInput( 1 );
    				break;
    			}
    		}
    	}
    	Serial.printf( "  Verify %s %uB ", szPath, ii );
    	if (ii != file3.size()) {
    		Serial.printf( "\n\tRead Count fail! :: read %u != f.size %llu", ii, file3.size() );
    		parseCmd( '0' );
    		errsLFS++;
    		checkInput( 1 );	// PAUSE on CmdLine
    	}
    	file3.close();
    	timeMe = micros() - timeMe;
    	Serial.printf( " @KB/sec %5.2f \n", ii / (timeMe / 1000.0) );
    }
    
    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;
    }
    
    
    void bigFile( int doThis ) {
    	char myFile[] = "/0_bigfile.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 = (myfs.totalSize()) - myfs.usedSize();
    		if ( toWrite < 65535 ) {
    			Serial.print( "Disk too full! DO :: b or q or F");
    			return;
    		}
    		toWrite -= 40960; // allow for slack space :: WORKS on FLASH?
    #ifdef HALFCUT
    		toWrite /= 2; // cutting to this works on LittleFS_RAM myfs - except reported file3.size()=2054847098 OR now 0
    #endif
    		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 halves 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);
    		}
    	}
    }
    
    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);
    		}
    	}
    }
    
    #include <sdios.h>
    ArduinoOutStream cout(Serial);
    File file;
    
    // File size in bytes.
    const uint32_t FILE_SIZE = 16 * 1024;
    
    // Set SKIP_FIRST_LATENCY true if the first read/write to the SD can
    // be avoid by writing a file header or reading the first record.
    const bool SKIP_FIRST_LATENCY = true;
    
    // Size of read/write.
    const size_t BUF_SIZE = 2048;
    
    // Write pass count.
    const uint8_t WRITE_COUNT = 5;
    
    // Read pass count.
    const uint8_t READ_COUNT = 5;
    
    //Block size for qspi
    #define MYBLKSIZE 2048 // 2048
    
    // Insure 4-byte alignment.
    uint32_t buf32[(BUF_SIZE + 3) / 4];
    uint8_t* bufA32 = (uint8_t*)buf32;
    
    //Number of random reads
    #define randomReads 1
    
    void speedBench() {
    	File file;
    	float s;
    	uint32_t t;
    	uint32_t maxLatency;
    	uint32_t minLatency;
    	uint32_t totalLatency;
    	bool skipLatency;
    
    	myfs.remove("bench.dat");
    	//for(uint8_t cnt=0; cnt < 10; cnt++) {
    
    	// fill buf with known data
    	if (BUF_SIZE > 1) {
    		for (size_t i = 0; i < (BUF_SIZE - 2); i++) {
    			bufA32[i] = 'A' + (i % 26);
    		}
    		bufA32[BUF_SIZE - 2] = '\r';
    	}
    	bufA32[BUF_SIZE - 1] = '\n';
    
    	Serial.printf("%s Disk Stats:", szDiskMem );
    	Serial.printf("Bytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());
    	Serial.printf("%s Benchmark:\n", szDiskMem );
    	cout << F("FILE_SIZE = ") << FILE_SIZE << endl;
    	cout << F("BUF_SIZE = ") << BUF_SIZE << F(" bytes\n");
    	cout << F("Starting write test, please wait.") << endl << endl;
    
    	// do write test
    	uint32_t n = FILE_SIZE / BUF_SIZE;
    	cout << F("write speed and latency") << endl;
    	cout << F("speed,max,min,avg") << endl;
    	cout << F("KB/Sec,usec,usec,usec") << endl;
    
    	// open or create file - truncate existing file.
    	file = myfs.open("bench.dat", FILE_WRITE);
    
    	for (uint8_t nTest = 0; nTest < WRITE_COUNT; nTest++) {
    		file.seek(0);
    
    		maxLatency = 0;
    		minLatency = 9999999;
    		totalLatency = 0;
    		skipLatency = SKIP_FIRST_LATENCY;
    		t = millis();
    
    		for (uint32_t i = 0; i < n; i++) {
    			uint32_t m = micros();
    			if (file.write(bufA32, BUF_SIZE) != BUF_SIZE) {
    				Serial.println("write failed");
    			}
    			m = micros() - m;
    			totalLatency += m;
    			if (skipLatency) {
    				// Wait until first write to SD, not just a copy to the cache.
    				skipLatency = file.position() < 512;
    			} else {
    				if (maxLatency < m) {
    					maxLatency = m;
    				}
    				if (minLatency > m) {
    					minLatency = m;
    				}
    			}
    		}
    
    		t = millis() - t;
    		s = file.size();
    		cout << s / t << ',' << maxLatency << ',' << minLatency;
    		cout << ',' << totalLatency / n << endl;
    	}
    	cout << endl << F("Starting sequential read test, please wait.") << endl;
    	cout << endl << F("read speed and latency") << endl;
    	cout << F("speed,max,min,avg") << endl;
    	cout << F("KB/Sec,usec,usec,usec") << endl;
    
    	// do read test
    	for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
    		file.seek(0);
    		maxLatency = 0;
    		minLatency = 9999999;
    		totalLatency = 0;
    		skipLatency = SKIP_FIRST_LATENCY;
    		t = micros();
    		for (uint32_t i = 0; i < n; i++) {
    			bufA32[BUF_SIZE - 1] = 0;
    			uint32_t m = micros();
    			int32_t nr = file.read(bufA32, BUF_SIZE);
    			if (nr != BUF_SIZE) {
    				Serial.println("read failed");
    			}
    			m = micros() - m;
    			totalLatency += m;
    			if (bufA32[BUF_SIZE - 1] != '\n') {
    				Serial.println("data check error");
    			}
    			if (skipLatency) {
    				skipLatency = false;
    			} else {
    				if (maxLatency < m) {
    					maxLatency = m;
    				}
    				if (minLatency > m) {
    					minLatency = m;
    				}
    			}
    		}
    
    		s = file.size();
    
    		t = micros() - t;
    		cout << s * 1000 / t << ',' << maxLatency << ',' << minLatency;
    		cout << ',' << totalLatency / n << endl;
    	}
    
    	cout << endl << F("Done") << endl;
    
    	cout << endl << F("Starting random read test, please wait.") << endl;
    
    	Serial.printf("Number of random reads: %d\n", randomReads);
    	Serial.printf("Number of blocks: %d\n", n);
    
    	cout << endl << F("read speed and latency") << endl;
    	cout << F("speed,max,min,avg") << endl;
    
    	// do read test
    	for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
    		file.seek(0);
    		maxLatency = 0;
    		minLatency = 0;
    		totalLatency = 0;
    		skipLatency = SKIP_FIRST_LATENCY;
    		t = micros();
    		for (uint32_t i = 0; i < randomReads; i++) {
    			bufA32[BUF_SIZE - 1] = 0;
    			uint32_t m = micros();
    			uint32_t block_pos = random(0, (n - 1));
    			uint32_t random_pos = block_pos * MYBLKSIZE;
    			cout << "Position (bytes), Block: " << random_pos << ", ";
    			cout << block_pos << endl;
    			uint32_t startCNT = ARM_DWT_CYCCNT;
    			file.seek(random_pos);
    			int32_t nr = file.read(bufA32, BUF_SIZE);
    			uint32_t endCNT = ARM_DWT_CYCCNT;
    			cout << F("Read Time (ARM Cycle Delta): ") << endCNT - startCNT << endl;
    			if (nr != BUF_SIZE) {
    				Serial.println("read failed");
    			}
    			m = micros() - m;
    			totalLatency += m;
    			if (bufA32[BUF_SIZE - 1] != '\n') {
    				Serial.println("data check error");
    			}
    			if (skipLatency) {
    				skipLatency = false;
    			} else {
    				if (maxLatency < m) {
    					maxLatency = m;
    				}
    				if (minLatency > m) {
    					minLatency = m;
    				}
    			}
    		}
    
    		s = file.size();
    
    
    		t = micros() - t;
    		cout << F("KB/Sec,usec,usec,usec") << endl;
    		cout << s * 1000 / t << ',' << maxLatency << ',' << minLatency;
    		cout << ',' << totalLatency / n << endl;
    	}
    	cout << endl << F("Done") << endl;
    
    
    	file.close();
    	myfs.remove("bench.dat");
    
    }
    @defragster - @Paul - @all

    Downloaded the beta10 and installed over 1.54beta9. Loaded up the LFSIntegrity sketch in previous post and ran it on both a T4.1 and Teensy MicroMod. Then for using:
    DOING: 'B' - starts BIG write
    or
    DOING '1' - a single loop write to one small file
    Tested EXTMEM, DMAMEM, RAM1 and in all cases did I see any hangs. I did it a few times between power recycling. Did "Restart" as well for all 3 regions and then used 1 and B again, no hangs.

  25. #875
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    28,478
    I also could not reproduce the problem using 1.54-beta10 and running on a Teensy 4.1 with 1 PSRAM and 1 Flash chip soldered to the bottom side.

    Quote Originally Posted by defragster View Post
    DOING: 'B' - starts BIG write and does not complete
    When I run it here, it prints this:

    Code:
    Big write /1_bigfile.txt took  0.50 Sec for 2074624 Bytes : file3.size()=2074624
    	Big write KBytes per second 4157.79 
    
    Bytes Used: 6277120, Bytes Total:8388608
    
    printDirectory RAM_DISK
    --------------
    FILE	0_bigfile.txt		4169728
    FILE	1_bigfile.txt		2074624
    FILE	B_file.txt		1536
    FILE	C_file.txt		2048
    
     0 dirs with 4 files of Size 6247936 Bytes
     Total 4 files of Size 6247936 Bytes
    Bytes Used: 6277120, Bytes Total:8388608
    [  0.11 M](0.00896 M elap) Awaiting input 0123456789RdwcghkFqvplmusSBbyYxfan+-? loops left 0 >

    or
    DOING '1' - a single loop write to one small file and it hangs.
    I get this result here:

    Code:
    :: /B_file.txt  RAM_DISK +++ Add [sz 1536 add 1536] @KB/sec 327.02 {81.21}  ++ B   Verify /B_file.txt 3072B  @KB/sec 2357.64 
    :: /C_file.txt  RAM_DISK +++ Add [sz 2048 add 2048] @KB/sec 487.04 {110.97}  ++ C   Verify /C_file.txt 4096B  @KB/sec 2386.95 
    [  1.12 M](0.00067 M elap) Awaiting input 0123456789RdwcghkFqvplmusSBbyYxfan+-? loops left 0 >
    Ran it several times, could not get it to hang.

    I ran the exact from from msg #873. Didn't edit the defines or many changes in any way.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •