git clone git@github.com:mjs513/UsbMscFat.git
cd UsbMscFat
git checkout FS_Integration
cd ..
git clone git@github.com:KurtE/MTP_t4.git
cd MTP_t4
git checkout FS_Integration
#if defined(__IMXRT1062__)
// Quick and dirty combiner class
// that says handle either type of bottom Flash...
// on T4.1
class LittleFS_QSPI : public LittleFS
{
public:
LittleFS_QSPI() { }
bool begin() {
Serial.println("LittleFS_QSPI Try Flash");
if (lfsqflash.begin()) {
plfs = &lfsqflash;
Serial.println("** OK **");
return true;
}
if (lfsqand.begin()) {
Serial.println("LittleFS_QSPI Try Flash");
plfs = &lfsqand;
Serial.println("** OK **");
return true;
}
Serial.println("** FAILED **");
return false;
}
LittleFS_QSPIFlash *QSPIFlash() { return (plfs == &lfsqflash)? &lfsqflash : nullptr;}
LittleFS_QPINAND *QPINAND() { return (plfs == &lfsqand)? &lfsqand : nullptr;}
virtual File open(const char *filename, uint8_t mode = FILE_READ) {
return plfs? plfs->open(filename, mode) : File();
}
virtual bool exists(const char *filepath) {
return plfs? plfs->exists(filepath) : false;
}
virtual bool mkdir(const char *filepath) {
return plfs? plfs->mkdir(filepath) : false;
}
virtual bool rename(const char *oldfilepath, const char *newfilepath) {
return plfs? plfs->rename(oldfilepath, newfilepath) : false;
}
virtual bool remove(const char *filepath) {
return plfs? plfs->remove(filepath) : false;
}
virtual bool rmdir(const char *filepath) {
return plfs? plfs->rmdir(filepath) : 0;
}
virtual uint64_t usedSize() {
return plfs? plfs->usedSize() : 0;
}
virtual uint64_t totalSize() {
return plfs? plfs->totalSize() : 0;
}
private:
LittleFS_QSPIFlash lfsqflash;
LittleFS_QPINAND lfsqand;
LittleFS *plfs = nullptr;
};
#endif
@KurtE - that seems Cool. Would have saved me a skipped heart beat or two when I soldered a fresh Flash to a new T_4.1 and got 'FAIL' when I mistook NOR .vs. NAND because I mislabeled the package I got it from.
Not having to make a hardcoded LFS_thing is a pain and confusing.
Extending that to SPI media would be nice as well ... say if you have a board with 4 of them on.
class FailCallsFS : public LittleFS
{
public:
FailCallsFS() { }
bool begin() {return false;}
virtual File open(const char *filename, uint8_t mode = FILE_READ) { return File(); }
virtual bool exists(const char *filepath) { return false; }
virtual bool mkdir(const char *filepath) { return false; }
virtual bool rename(const char *oldfilepath, const char *newfilepath) { return false; }
virtual bool remove(const char *filepath) { return false; }
virtual bool rmdir(const char *filepath) { return false; }
virtual uint64_t usedSize() { return 0; }
virtual uint64_t totalSize() { return 0; }
};
class LittleFS_QSPI : public LittleFS
{
public:
LittleFS_QSPI() { }
bool begin() {
Serial.println("LittleFS_QSPI Try Flash");
if (lfsqflash.begin()) {
plfs = &lfsqflash;
Serial.println("** OK **");
return true;
}
if (lfsqand.begin()) {
Serial.println("LittleFS_QSPI Try Flash");
plfs = &lfsqand;
Serial.println("** OK **");
return true;
}
plfs = &failsfs;
Serial.println("** FAILED **");
return false;
}
LittleFS_QSPIFlash *QSPIFlash() { return (plfs == &lfsqflash)? &lfsqflash : nullptr;}
LittleFS_QPINAND *QPINAND() { return (plfs == &lfsqand)? &lfsqand : nullptr;}
virtual File open(const char *filename, uint8_t mode = FILE_READ) { return plfs->open(filename, mode); }
virtual bool exists(const char *filepath) { return plfs->exists(filepath); }
virtual bool mkdir(const char *filepath) { return plfs->mkdir(filepath); }
virtual bool rename(const char *oldfilepath, const char *newfilepath) { return plfs->rename(oldfilepath, newfilepath); }
virtual bool remove(const char *filepath) { return plfs->remove(filepath); }
virtual bool rmdir(const char *filepath) { return plfs->rmdir(filepath); }
virtual uint64_t usedSize() { return plfs->usedSize(); }
virtual uint64_t totalSize() { return plfs->totalSize(); }
private:
LittleFS_QSPIFlash lfsqflash;
LittleFS_QPINAND lfsqand;
FailCallsFS failsfs;
LittleFS *plfs = &failsfs;
};
#endif
protected:
bool configured;
bool mounted;
lfs_t lfs;
lfs_config config;
/* LittleFS for Teensy
* Copyright (c) 2020, Paul Stoffregen, paul@pjrc.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice, development funding notice, and this permission
* notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <LittleFS.h>
// Quick and dirty combine classes
class FailCallsFS : public LittleFS
{
public:
FailCallsFS() { }
bool begin() {return false;}
virtual File open(const char *filename, uint8_t mode = FILE_READ) { return File(); }
virtual bool exists(const char *filepath) { return false; }
virtual bool mkdir(const char *filepath) { return false; }
virtual bool rename(const char *oldfilepath, const char *newfilepath) { return false; }
virtual bool remove(const char *filepath) { return false; }
virtual bool rmdir(const char *filepath) { return false; }
virtual uint64_t usedSize() { return 0; }
virtual uint64_t totalSize() { return 0; }
};
// that says handle the three supported SPI memory type chips
// Based on FS, as can not directly call LittleFS specific functions
class LittleFS_SPI : public FS
{
public:
LittleFS_SPI() { }
bool begin(uint8_t cspin, SPIClass &spiport=SPI) {
Serial.println("LittleFS_SPI Try Flash");
if (_lfsflash.begin(cspin, spiport)) {
_plfs = &_lfsflash;
_chipType = CHIP_FLASH;
Serial.println("** OK **");
snprintf(_displayName, sizeof(_displayName), (const char *)F("FLASH_%02u"), cspin);
return true;
}
if (_lfsnand.begin(cspin, spiport)) {
Serial.println("LittleFS_SPI Try NAND");
_plfs = &_lfsnand;
_chipType = CHIP_NAND;
snprintf(_displayName, sizeof(_displayName), (const char *)F("NAND_%02u"), cspin);
Serial.println("** OK **");
return true;
}
if (_lfsfram.begin(cspin, spiport)) {
Serial.println("LittleFS_SPI Try FRAM");
_plfs = &_lfsfram;
_chipType = CHIP_FRAM;
snprintf(_displayName, sizeof(_displayName), (const char *)F("FRAM_%02u"), cspin);
Serial.println("** OK **");
return true;
}
_plfs = &_failsfs;
_chipType = CHIP_NONE;
Serial.println("** FAILED **");
return false;
}
// return functions to get to underlying LittleFS functions
// first generic one
LittleFS * plfs() { return _plfs; }
LittleFS_SPIFlash *SPIFlash() { return (_plfs == &_lfsflash)? &_lfsflash : nullptr;}
LittleFS_SPINAND *SPINAND() { return (_plfs == &_lfsnand)? &_lfsnand : nullptr;}
LittleFS_SPIFram *SPIFram() { return (_plfs == &_lfsfram)? &_lfsfram : nullptr;}
enum {CHIP_NONE=0, CHIP_FLASH=1, CHIP_NAND=2, CHIP_FRAM=3};
uint8_t chipType() { return _chipType; }
const char *displayName() {return _displayName;}
// FS class functions
virtual File open(const char *filename, uint8_t mode = FILE_READ) { return _plfs->open(filename, mode); }
virtual bool exists(const char *filepath) { return _plfs->exists(filepath); }
virtual bool mkdir(const char *filepath) { return _plfs->mkdir(filepath); }
virtual bool rename(const char *oldfilepath, const char *newfilepath) { return _plfs->rename(oldfilepath, newfilepath); }
virtual bool remove(const char *filepath) { return _plfs->remove(filepath); }
virtual bool rmdir(const char *filepath) { return _plfs->rmdir(filepath); }
virtual uint64_t usedSize() { return _plfs->usedSize(); }
virtual uint64_t totalSize() { return _plfs->totalSize(); }
private:
LittleFS_SPIFlash _lfsflash;
LittleFS_SPINAND _lfsnand;
LittleFS_SPIFram _lfsfram;
FailCallsFS _failsfs;
LittleFS * _plfs = &_failsfs;
uint8_t _chipType = CHIP_NONE;
char _displayName[10];
};
#if defined(__IMXRT1062__)
// Based on FS, as can not directly call LittleFS specific functions
// that says handle either type of bottom Flash...
// on T4.1
class LittleFS_QSPI : public FS
{
public:
LittleFS_QSPI() { }
bool begin() {
Serial.println("LittleFS_QSPI Try Flash");
if (_lfsqflash.begin()) {
_plfs = &_lfsqflash;
_chipType = CHIP_FLASH;
Serial.println("** OK **");
return true;
}
if (_lfsqnand.begin()) {
Serial.println("LittleFS_QSPI Try NAND");
_plfs = &_lfsqnand;
_chipType = CHIP_NAND;
Serial.println("** OK **");
return true;
}
_plfs = &_failsfs;
_chipType = CHIP_NONE;
Serial.println("** FAILED **");
return false;
}
// return functions to get to underlying LittleFS functions
// first generic one
LittleFS * plfs() { return _plfs; }
LittleFS_QSPIFlash *QSPIFlash() { return (_plfs == &_lfsqflash)? &_lfsqflash : nullptr;}
LittleFS_QPINAND *QPINAND() { return (_plfs == &_lfsqnand)? &_lfsqnand : nullptr;}
enum {CHIP_NONE=0, CHIP_FLASH=1, CHIP_NAND=2};
uint8_t chipType() { return _chipType; }
const char *displayName() {
switch (_chipType) {
default: return "";
case CHIP_FLASH: return (const char *)F("QFLASH");
case CHIP_NAND: return (const char *)F("QNAND");
}
}
// FS class functions
virtual File open(const char *filename, uint8_t mode = FILE_READ) { return _plfs->open(filename, mode); }
virtual bool exists(const char *filepath) { return _plfs->exists(filepath); }
virtual bool mkdir(const char *filepath) { return _plfs->mkdir(filepath); }
virtual bool rename(const char *oldfilepath, const char *newfilepath) { return _plfs->rename(oldfilepath, newfilepath); }
virtual bool remove(const char *filepath) { return _plfs->remove(filepath); }
virtual bool rmdir(const char *filepath) { return _plfs->rmdir(filepath); }
virtual uint64_t usedSize() { return _plfs->usedSize(); }
virtual uint64_t totalSize() { return _plfs->totalSize(); }
private:
LittleFS_QSPIFlash _lfsqflash;
LittleFS_QPINAND _lfsqnand;
FailCallsFS _failsfs;
LittleFS * _plfs = &_failsfs;
uint8_t _chipType = CHIP_NONE;
};
#endif
File open(const char *filepath, uint8_t mode = FILE_READ) {
oflag_t flags = O_READ;
if (mode == FILE_WRITE) {flags = O_RDWR | O_CREAT | O_AT_END; _cached_usedSize_valid = false;}
else if (mode == FILE_WRITE_BEGIN) {flags = O_RDWR | O_CREAT; _cached_usedSize_valid = false; }
MSCFAT_FILE file = mscfs.open(filepath, flags);
[B][COLOR="#FF0000"] uint32_t now1 = Teensy3Clock.get();
DateTimeFields tm;
breakTime(now1, tm);
if (tm.year < 80 || tm.year > 207)
{
Serial.println("Date out of Range....");
} else {
file.timestamp(T_WRITE, tm.year + 1900, tm.mon + 1,
tm.mday, tm.hour, tm.min, tm.sec);
if(mode == FILE_WRITE_BEGIN) {
file.timestamp(T_CREATE, tm.year + 1900, tm.mon + 1,
tm.mday, tm.hour, tm.min, tm.sec);
}
}[/COLOR][/B]
if (file) return File(new MSCFile(file));
return File();
}
Menu Options:
l - List files on disk
e - Erase files on disk
s - Start Logging data (Restarting logger will append records to existing log)
x - Stop Logging data
d - Dump Log
h - Menu
root@Teensy:/128GEXFATP1/>ls /QPINAND/
Volume Label: QPINAND
Full Path: /QPINAND/
YoureLazyJimmyBarnesJoeBonamassa.wav 102878370 September 26 2021 14:25:22
test1.txt 51 September 26 2021 14:55:41
Free Space: 28442624 bytes
root@Teensy:/128GEXFATP1/>ls 20:UsbMscFat
Volume Label: 8GFAT32
Full Path: 20:UsbMscFat
examples/ <DIR>
extras/ <DIR>
src/ <DIR>
LICENSE 1071 September 06 2021 16:44:24
library.properties 478 September 06 2021 16:44:24
README.md 2770 September 06 2021 16:44:24
keywords.txt 834 September 06 2021 16:44:26
Free Space: 7931068416 bytes
# Autoprobe vendor-specific, communication and PTP devices
ENV{ID_MTP_DEVICE}!="1", ENV{MTP_NO_PROBE}!="1", ENV{COLOR_MEASUREMENT_DEVICE}!="1", ENV{ID_GPHOTO}!="1", ENV{libsane_matched}!="yes", ATTR{bDeviceClass}=="00|02|06|ef|ff", PROGRAM="mtp-probe /sys$env{DEVPATH} $attr{busnum} $attr{devnum}", RESULT=="1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
@wwatson @Paul, @mjs513 @defragster...
Just pushed an update to UsbMscFat Integration branch (https://github.com/mjs513/UsbMscFat/tree/FS_Integration). The update essentially gets the timestamp working. Basically did it the way we did it in LittleFS - timestamp gets called in file open.....
changes highlighted in red.Code:File open(const char *filepath, uint8_t mode = FILE_READ) { oflag_t flags = O_READ; if (mode == FILE_WRITE) {flags = O_RDWR | O_CREAT | O_AT_END; _cached_usedSize_valid = false;} else if (mode == FILE_WRITE_BEGIN) {flags = O_RDWR | O_CREAT; _cached_usedSize_valid = false; } MSCFAT_FILE file = mscfs.open(filepath, flags); [B][COLOR="#FF0000"] uint32_t now1 = Teensy3Clock.get(); DateTimeFields tm; breakTime(now1, tm); if (tm.year < 80 || tm.year > 207) { Serial.println("Date out of Range...."); } else { file.timestamp(T_WRITE, tm.year + 1900, tm.mon + 1, tm.mday, tm.hour, tm.min, tm.sec); if(mode == FILE_WRITE_BEGIN) { file.timestamp(T_CREATE, tm.year + 1900, tm.mon + 1, tm.mday, tm.hour, tm.min, tm.sec); } }[/COLOR][/B] if (file) return File(new MSCFile(file)); return File(); }
I also updated the dataloggerUSB sketch so there are now options to:
the only option not working yet is erase files. But its better than having to upload multiple sketches to see log and file modified date.Code:Menu Options: l - List files on disk e - Erase files on disk s - Start Logging data (Restarting logger will append records to existing log) x - Stop Logging data d - Dump Log h - Menu
Cheers - now I can sleep better.
Before anyone asks - have I done exhaustive testing yet the answer is no but wanted to get the update out there for others to play with as well.
...
"C:\\T_Drive\\Arduino_1.8.16_155\\hardware\\teensy/../tools/teensy_size" "R:\\temp\\arduino_build_listfilesUSB.ino/listfilesUSB.ino.elf"
teensy_size: Memory Usage on Teensy 4.1:
teensy_size: FLASH: code:47516, data:3500, headers:8372 free for files:8067076
teensy_size: RAM1: variables:29376, code:44840, padding:20696 free for local variables:429376
teensy_size: RAM2: variables:5216 free for malloc/new:519072
[B]Using library UsbMscFat at version 1.0.0 in folder: C:\T_Drive\tCode\libraries\UsbMscFat [/B]
Using library USBHost_t36 at version 0.1 in folder: C:\T_Drive\Arduino_1.8.16_155\hardware\teensy\avr\libraries\USBHost_t36
Using library SdFat at version 2.0.5-beta.1 in folder: C:\T_Drive\Arduino_1.8.16_155\hardware\teensy\avr\libraries\SdFat
Using library SPI at version 1.0 in folder: C:\T_Drive\Arduino_1.8.16_155\hardware\teensy\avr\libraries\SPI
Not seeing any updates to leading posts?
IDE 1.8.16 w/ TD 1.56b1
Using latest github app or downloaded ZIP shows
> is something else needed?
Not able to see any USB output or signs of life from the T_4.1? Even adding a print and delay() before first .begin?
Memory Usage on Teensy 4.1:
FLASH: code:48284, data:3436, headers:8692 free for files:8066052
RAM1: variables:29504, code:45608, padding:19928 free for local variables:429248
RAM2: variables:16512 free for malloc/new:507776
Initializing USB MSC drive...initialization done.
T_4.1/
workshop.pdf 8894873 08:03 February 8, 2021
card11a_rev3_web.pdf 377551 23:21 February 9, 2021
card11b_rev3_web.pdf 396325 23:21 February 9, 2021
D435 Obs-slam Links.txt 4879 10:25 January 1, 2021
esp-psram64_.pdf 1344699 23:21 February 9, 2021
esp-psram64_esp-psram64h_datasheet_en.txt 61440 07:55 February 10, 2021
NXP_i2c_UM10204.pdf 1395785 23:21 February 9, 2021
PRINTOUTPUTs2.txt 630 06:04 November 17, 2020
Routed_B.jpg 194564 23:21 February 9, 2021
T4.1-Cardlike0.jpg 220021 13:56 November 16, 2020
teensy41_card.png 320054 23:21 February 9, 2021
Visio-driver.pdf 1472938 13:11 October 27, 2020
VSLAM_and_Navigation_System_of_Unmanned_Ground_Vehicle_Based_on_RGB-D_Camera.pdf 5725283 14:47 December 26, 2020
w25m02gw revd 012219.pdf 1673403 23:21 February 9, 2021
W25N02aKV_Datasheet_20201022_C.pdf 1665621 23:21 February 9, 2021
datalog.txt 515 21:55 September 27, 2021
System Volume Information/
WPSettings.dat 12 09:37 September 27, 2021
IndexerVolumeGuid 76 09:37 September 27, 2021
done!
"C:\\T_Drive\\Arduino_1.8.16_155\\hardware\\teensy/../tools/teensy_size" "R:\\Temp\\arduino_build_680978/listfilesUSB.ino.elf"
Memory Usage on Teensy 4.1:
FLASH: code:47452, data:3404, headers:8532 free for files:8067076
RAM1: variables:29376, code:44776, padding:20760 free for local variables:429376
RAM2: variables:5216 free for malloc/new:519072
Using library UsbMscFat at version 1.0.0 in folder: C:\T_Drive\tCode\libraries\UsbMscFat
Using library USBHost_t36 at version 0.1 in folder: C:\T_Drive\Arduino_1.8.16_155\hardware\teensy\avr\libraries\USBHost_t36
Using library SdFat at version 2.0.5-beta.1 in folder: C:\T_Drive\Arduino_1.8.16_155\hardware\teensy\avr\libraries\SdFat
Using library SPI at version 1.0 in folder: C:\T_Drive\Arduino_1.8.16_155\hardware\teensy\avr\libraries\SPI
C:\T_Drive\Arduino_1.8.16_155\hardware\teensy/../tools/teensy_post_compile -file=listfilesUSB.ino -path=R:\Temp\arduino_build_680978 -tools=C:\T_Drive\Arduino_1.8.16_155\hardware\teensy/../tools -board=TEENSY41 -reboot -port=usb:0/140000/0/6/1/1 -portlabel=[no_device] Bootloader -portprotocol=Teensy
void setup()
{
pinMode( 13, OUTPUT ) ;
digitalWrite( 13, HIGH );
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect.
}
Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
while ( !Serial.available() );
digitalWrite( 13, LOW );
Tim - woke up and saw your comment and wanted to get back to you since I know we are on a time difference here. Heres the zip if you are interested that I downloaded from GIthub. Not sure why you are having problems.
Thanks, still no joy - Nothing prints ...
Tried on TWO T_4.1's - different Flash drives , and another flash drive.
The one used was the write protected one used the other day ...
Just did a third production T_4.1 with two of those USB drives?
IDE Building: MTP Experimental, 600 MHz, Faster
version=1.0.0
version=1.1.0
Arrrrgghhhh ... confusion on my part ... this is NOT MTP
Should still run. If using MTP Disk Serial it takes a good 6 seconds for serial to come line. But you have to wait to open it otherwise it won't work. MTP Disk should come on line fairly quickly - just ran both cases.
Question: Does UsbMscFat support ExFat as well as FAT32?
Seems not as it gives init fail.
For some reason this 64GB Flash only offers ExFat or NTFS, even SD Card Formatter wants to do ExFat
C:\>format i: /FS:FAT32 /V:A64_F32 /Q /X
Insert new disk for drive I:
and press ENTER when ready...
The type of the file system is EXFAT.
The new file system is FAT32.
QuickFormatting 57.8 GB
The volume is too big for FAT32.
Format failed.