USBHost_t36 USB Mass Storage Driver Experiments

Thanks for seeing through making it usable!

I am using the SanDisk Ultra - a 32GB micro SDHC card. Seems that is what PJRC.com noted as good on the SD related page - brand makes a difference - and some are 'misbranded' it seems at times. But one seems dead now - and I tossed another cheapo out sometime during T4 Beta as well? I have new ones of some brand - not sure these were new just ones I had around open with no current purpose from old phones or something. Other than that this was the stock example from current downloads. For HDD's and other testing I had played some with alternate buffer sizes - but this was fresh from github.

@BOBILLIER - okay - simple FLASH cards work okay. But nothing HDD or even SSD would work without being on a powered HUB - so I wondered. And working from hub requires that 'HUB' code as noted then it can chain USB to get to a device on a HUB 'transparently'.

TeensyThreads seems nice - I just looked at it for Teensy 4 and learned the loop() is just thread 0 - not sure if it is treated like all other threads. I left a question I didn't see an answer to about that - and I didn't get back to it after I looked a bit. I did suggest a perf 'cycles per thread' used tracker for debug that got put in - I hacked up a slightly diff implementation that made more sense to me but didn't see any reaction to that yet. Using that it looked like in the sample I wrote 10% of the T_4 was consumed in the thread switching - mainly because my threads did very little and then did a .yield() so the switch rate was extreme.

@wwatson - seems I asked a while back about async calls to move data? THough not sure that would help TeensyThreads taskswitch any better unless it was running with DMA?

@defragster

I updated MassStorageHost.cpp and MassStorageDriver.cpp. There were some missing returns in a couple of functions hat the compiler was warning about. And of course I will be testing everything again to make sure I did not mess things up:)

@wwatson - seems I asked a while back about async calls to move data? THough not sure that would help TeensyThreads taskswitch any better unless it was running with DMA?

I can honestly tell you that I have no idea how to do this:(
I know Paul I going to be working on USBHost so I probably will wait till then.
 
I just use one simple USB Key with 16GB directly connect to USB Port (this who place on the top of T3.6 circuit). But like I have powered T3.6 with only 5V, i lost some power through LP38691 circuit. Finally, i just obtain 4.6V for my USB key. I solve this by powering key directly through 5V power supply.

Yes i'm using TeensyThreads library. the 10ms come from the information i have find in the read-me https://github.com/ftrias/TeensyThreads/blob/master/readme.md in "Change" paragraph. I have don't test it to verify if 10ms is true.
To solve my problem with write multi-threading, i have place the open-write-close action to USB Key in the loop() (not in one thread) and just before do it, i lock threading mechanism with one threading.stop() and a threading.start(-1) just after. Like i just save my data every second and like write to key (take between 16 and 40ms) , my threading process isn't very perturbed. And now, all seem working correctly.

wwatson, thank for your library upgrade. But i have test it for my Unmount - mount action and i have always the same problem. I can unmount correctly , but if i try to mount my key again, nothing arrive and T3.6 stay lock. (i have test with and without unplug-plug key action). Do you plan to solve this ? Thanks

I have checked this out. This is a function in FatFS. Hopefully today I will have time to work with it further. As far as MSC is concerned, it only deals with the USB drive connections to USBHost and communications with the drives.
 
@BOBILLIER - I figured out why the USB drive will not remount. Basically f_mount() calls the disk_initialize() function located in uSDFS library file sd_msc.ccp.

Code:
	int MSC_disk_initialize() 
	{	myusb.begin();
		return mscInit();
	}

This was causing the lockup with multiple calls to f_mount(). As a test I commented out mysub.begin() in disk_initialize() and added the following to your sketch:

Code:
#include <diskio.h>
#include <ff.h>
#include <ffconf.h>
#include <uSDFS.h>
#include <USBHost_t36.h>
USBHub hub1(nullptr);
USBHub hub2(nullptr);

[COLOR="#FF0000"]extern USBHost myusb;[/COLOR]


const char *Dev = "2:/"; // USB
FRESULT rc; /* Result code */
FATFS fatfs; /* File system object */
FIL fil; /* File object */
/* Stop with error message */
void die(const char *text, FRESULT rc)
{ Serial.printf("%s: Failed with rc=%s.\r\n", text,FR_ERROR_STRING[rc]); while(1) asm("wfi"); }

void setup() {

while(!Serial);

[COLOR="#FF0000"]myusb.begin();[/COLOR]

// put your setup code here, to run once:
if((rc = f_mount (&fatfs, Dev, 1))) die("Mount",rc); /* Mount/Unmount a logical drive */

Serial.println("USB Mount OK");
}
void loop() {
// put your main code here, to run repeatedly:
while (Serial.available() > 0) {
char Ordre = Serial.read();
switch (Ordre) {
case 'm':
rc = f_mount (&fatfs, Dev, 1);
Serial.println ("Mount USB");
Serial.println(FR_ERROR_STRING[rc]);
break;
case 'u':
rc = f_unmount(Dev);
Serial.println ("Unmount USB");
Serial.println(FR_ERROR_STRING[rc]);
break;
}
}
}

@WMXZ - I am going to try figure a way around this. Any Ideas so I don't screw this up would be great:)

EDIT 2:

Added this to sd_msc.cpp disk_initialize():
Code:
	int MSC_disk_initialize() 
	{	
                [COLOR="#FF0000"]	if(!deviceAvailable())[/COLOR]
			myusb.begin();
		return mscInit();
	}

It seems to work. Going to do more testing
 
Last edited:
@wwatson . Thanks for your suggestion , but not working for me . The program stay lock at the first myusb.begin() in main.
I have changed my USB key and tested again with my program, and now it work as expected. If you unmount, remove key, plug it again and mount, it's fine. But if you unmount key and directly mount it, program stay lock in mount process. To avoid that, i have add test in my program with
Code:
stat = disk_status (2);
. This test return me value (stat) with value below:
1)When i run program with one key, stat = 0 (correct)
2)When i un_mount key, stat = 0 (??)((Why not stat = 1 = Disk not initialized)
3)When i remove key , stat = 1 (Disk not initialized)(Why not stat = 2 = No disk)
4)When i plug key , stat = 1 (Disk not initialized)
5)When i mount key , stat = 0 (correct)

For step 3, is-it like deviceAvailable() was always true and don't fall to false when i remove key.
Finally step 2 and 3 don't return me one expected value (for me), but perhaps it's correct for you.
Thanks for you help
 
@wwatson . Thanks for your suggestion , but not working for me . The program stay lock at the first myusb.begin() in main.
I have changed my USB key and tested again with my program, and now it work as expected. If you unmount, remove key, plug it again and mount, it's fine. But if you unmount key and directly mount it, program stay lock in mount process. To avoid that, i have add test in my program with
Code:
stat = disk_status (2);
. This test return me value (stat) with value below:
1)When i run program with one key, stat = 0 (correct)
2)When i un_mount key, stat = 0 (??)((Why not stat = 1 = Disk not initialized)
3)When i remove key , stat = 1 (Disk not initialized)(Why not stat = 2 = No disk)
4)When i plug key , stat = 1 (Disk not initialized)
5)When i mount key , stat = 0 (correct)

For step 3, is-it like deviceAvailable() was always true and don't fall to false when i remove key.
Finally step 2 and 3 don't return me one expected value (for me), but perhaps it's correct for you.
Thanks for you help

You should not have unplug and plug the the USB key. Did you comment out the myusb.begin() in the uSDFS file sd_msc.cpp which is in the disk_initialize() function like this?

Code:
	int MSC_disk_initialize() 
	{	
		[COLOR="#FF0000"]//myusb.begin();[/COLOR]
		return mscInit();
	}

The sd_msc.cpp file is in the uSDFS utility folder.

Here is the output from your program on my T36 and t$:

Code:
USB Mount OK
Unmount USB
FR_OK
Mount USB
FR_OK

I am working on a better fix for this.
 
@wwatson.
I have tested again with comment myusb.begin() in the uSDFS file sd_msc.cpp. if i do that, disk_status return 1 (not init) although key was plugged and main stay lock. I need add "extern USBHost myusb;" and "myusb.begin();" in my main for starting correctly, like indicate in your previous message. But like previously, i can unmounted correctly, but can't mount again without unplug-plug USB key. Perhaps, it's about key, who aren't working like your. Have you idea about bad disk_status value ?
 
@wwatson
I have just test with another key, and like you i can unmount-mount without unplug-plug key. It's perhaps my first key is USB3 and second is USB2 ...
Your library seem very sensible to key model, because yesterday i have test with another USB2 key, but it's never start (never USB Mount OK).
 
@wwatson
I have just test with another key, and like you i can unmount-mount without unplug-plug key. It's perhaps my first key is USB3 and second is USB2 ...
Your library seem very sensible to key model, because yesterday i have test with another USB2 key, but it's never start (never USB Mount OK).

Glad to here that you have one working. Make sure the USB keys are formatted at least with fat32 formatting.
As far as I know, the T36 and T4 only support USB2 at this point.
I have had some USB keys that flat would not work and some that take up to 20 seconds to initialize.
 
Using MSC to test USB Host on T4 with Looger_RawWrite test and keep having to add this code:
Code:
#include <USBHost_t36.h>
extern USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);

Would be handy to have that in github sources as HDD test requires external HUB.

Tests were on Beta breakout board for T4 and they do work - USB Flash drive and Dongle holding SD and HDD and SSD - but hub needs that code each time.
 
Using MSC to test USB Host on T4 with Looger_RawWrite test and keep having to add this code:
Code:
#include <USBHost_t36.h>
extern USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);

Would be handy to have that in github sources as HDD test requires external HUB.

Tests were on Beta breakout board for T4 and they do work - USB Flash drive and Dongle holding SD and HDD and SSD - but hub needs that code each time.

Would be happy to include that, but which version are you using? in my uSDFS/examples/logger_RawWrite is no #include <USBHost_t36.h>
Maybe I had it in the beginning, but now it is not there.
Could you check the latest repo and make a PR?
Thanks
 
Thanks @WMXZ - Yes it is missing in the :: "...\libraries\uSDFS\examples\logger_RawWrite\logger_RawWrite.ino"

it works for me adding those lines after this as follows:
Code:
// use following lines for early definitions of multiple partition configuration in uSDFS.h
#define MY_VOL_TO_PART
#include "uSDFS.h"
[B]#include <USBHost_t36.h>
extern USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);[/B]

Can't github just now - but if indicated can do that.
 
@All: Has anybody tried using uSDFS and MSC with a fat16 formatted drive?

I formatted a USB stick with fat16 and ran RawWrite.ino and was blown away by the difference in write speeds.

With a fat16 formatted HD:
Code:
Test logger_RawWrite
uSDFS_VER:30_Jun_19_07_17
BUFFSIZE :16384
Dev Type :2:/
File System FS_FAT16
Free Disk Size -1 clusters
Cluster Size 128 sectors
Sector Size 512 bytes

Change drive
A_00001.dat
stat FR_OK 0
 opened FR_OK 0

................................................................
.................................... (4679988 - 14.003455 MB/s)
 (open: 56968 us; close: 12000 us; write: min,max: 3719 37724 us)

A_00002.dat
stat FR_OK 2
 opened FR_OK 0

................................................................
.................................... (4739988 - 13.826196 MB/s)
 (open: 59925 us; close: 20000 us; write: min,max: 3719 39724 us)

With a fat32 formatted HD:
Code:
Test logger_RawWrite
uSDFS_VER:30_Jun_19_07_17
BUFFSIZE :16384
Dev Type :2:/
File System FS_FAT32
Free Disk Size 7607872 clusters
Cluster Size 64 sectors
Sector Size 512 bytes

Change drive
A_00001.dat
stat FR_OK 0
 opened FR_OK 0

................................................................
.................................... (8037987 - 8.153285 MB/s)
 (open: 232964 us; close: 15000 us; write: min,max: 5720 58725 us)

A_00002.dat
stat FR_OK e2c
 opened FR_OK 0

................................................................
.................................... (7388988 - 8.869415 MB/s)
 (open: 207929 us; close: 15000 us; write: min,max: 5720 68725 us)

With a fat16 formatted SD card:
Code:
Test logger_RawWrite
uSDFS_VER:30_Jun_19_07_17
BUFFSIZE :16384
Dev Type :2:/
File System FS_FAT16
Free Disk Size -1 clusters
Cluster Size 128 sectors
Sector Size 512 bytes

Change drive
A_00001.dat
stat FR_OK 0
 opened FR_OK 0

................................................................
.................................... (7456988 - 8.788535 MB/s)
 (open: 86968 us; close: 31000 us; write: min,max: 6719 56724 us)

A_00002.dat
stat FR_OK e0
 opened FR_OK 0

................................................................
.................................... (8514988 - 7.696547 MB/s)
 (open: 98931 us; close: 35000 us; write: min,max: 6722 110724 us)

With a fat32 formatted SD card (8192 buffersize gave best performance):
Code:
Test logger_RawWrite
uSDFS_VER:30_Jun_19_07_17
BUFFSIZE :8192
Dev Type :2:/
File System FS_FAT32
Free Disk Size 1579786 clusters
Cluster Size 16 sectors
Sector Size 512 bytes

Change drive
A_00001.dat
stat FR_OK 0
 opened FR_OK 0

................................................................
.................................... (18658987 - 1.756151 MB/s)
 (open: 380964 us; close: 52999 us; write: min,max: 11855 1795860 us)

A_00002.dat
stat FR_OK 6efcc
 opened FR_OK 0

................................................................
.................................... (15608988 - 2.099303 MB/s)
 (open: 349926 us; close: 23000 us; write: min,max: 11854 1302859 us)

The buffer size sweet spot seems to be 16384 bytes which make some kind of sense since USBHost_t36 is limited to that buffer size. Only with a fat32 formatted SD card did it perform better with a 8192 byte buffer size. That might be dependent on that SD card cluster size.

As a guess I think FatFs is showing a lot latency with the use of a fat32 formatted drive.
Anyway I have done a rewrite of MSC and will start another GitHub branch for it once I am done testing. I used this new version for testing with fat16. I have eliminated most of the extra layers of functions in MassStorageDriver.cpp and moved them to MassStorageHost.cpp and tried to improve where I could.

Right now it would be great to know if any body else has played with a fat16 formatted drive.
 
@All: Has anybody tried using uSDFS and MSC with a fat16 formatted drive?

I formatted a USB stick with fat16 and ran RawWrite.ino and was blown away by the difference in write speeds.

With a fat16 formatted HD:


With a fat32 formatted HD:
...

With a fat16 formatted SD card:
...
With a fat32 formatted SD card (8192 buffersize gave best performance):
...

The buffer size sweet spot seems to be 16384 bytes which make some kind of sense since USBHost_t36 is limited to that buffer size. Only with a fat32 formatted SD card did it perform better with a 8192 byte buffer size. That might be dependent on that SD card cluster size.

As a guess I think FatFs is showing a lot latency with the use of a fat32 formatted drive.
Anyway I have done a rewrite of MSC and will start another GitHub branch for it once I am done testing. I used this new version for testing with fat16. I have eliminated most of the extra layers of functions in MassStorageDriver.cpp and moved them to MassStorageHost.cpp and tried to improve where I could.

Right now it would be great to know if any body else has played with a fat16 formatted drive.

All tests here were likely fat32 of ExFat? with default cluster size.

FAT16 makes the FAT a great deal smaller : a single 512 byte FAT read covers twice as many entries - and each entry covers more bytes on the same drive so more writes before a new cluster to update in the FAT - especially when large drive gets smaller clusters.

Not sure that accounts for all of it - I did a type of Pre-Allocate test and it didn't make that big of a diff IIRC - though it was 'assure contiguous clusters for size "X" perhaps - so still had to grow fat chain and update DIR entry.

Another test would be FAT32 with oversized clusters instead of default.
 
All tests here were likely fat32 of ExFat? with default cluster size.

FAT16 makes the FAT a great deal smaller : a single 512 byte FAT read covers twice as many entries - and each entry covers more bytes on the same drive so more writes before a new cluster to update in the FAT - especially when large drive gets smaller clusters.

Not sure that accounts for all of it - I did a type of Pre-Allocate test and it didn't make that big of a diff IIRC - though it was 'assure contiguous clusters for size "X" perhaps - so still had to grow fat chain and update DIR entry.

Another test would be FAT32 with oversized clusters instead of default.

I have not tried to use ExFat. Guess it's time to find a way of formatting to ExFat without using Windows, if that's possible:)
Thanks...
 
I have not tried to use ExFat. Guess it's time to find a way of formatting to ExFat without using Windows, if that's possible:)
Thanks...

This is the HDD info as used:
Code:
C:\WINDOWS\system32>chkdsk h:
The type of the file system is exFAT.
Volume label is 120GB_Ext.
 117213184 KB total disk space.
    960256 KB in 12 files.
       256 KB in 2 indexes.
         0 KB in bad sectors.
       256 KB in use by the system.
 116252416 KB available on disk.

    131072 bytes in each allocation unit.
    915728 total allocation units on disk.
    908222 allocation units available on disk.

last run left this with write test:
Code:
10/09/2019  12:39 PM        98,304,000 A_00001.dat
10/09/2019  12:39 PM        98,304,000 A_00002.dat
10/09/2019  12:39 PM        98,304,000 A_00003.dat
10/09/2019  12:39 PM        98,304,000 A_00004.dat
10/09/2019  12:39 PM        98,304,000 A_00005.dat
10/09/2019  12:39 PM        98,304,000 A_00006.dat
10/09/2019  12:40 PM        98,304,000 A_00007.dat
10/09/2019  12:40 PM        98,304,000 A_00008.dat
10/09/2019  12:40 PM        98,304,000 A_00009.dat
10/09/2019  12:40 PM        98,304,000 A_00010.dat

Format under windows would be NTFS default - and ExFat is the other option.
 
This is the HDD info as used:
Code:
C:\WINDOWS\system32>chkdsk h:
The type of the file system is exFAT.
Volume label is 120GB_Ext.
 117213184 KB total disk space.
    960256 KB in 12 files.
       256 KB in 2 indexes.
         0 KB in bad sectors.
       256 KB in use by the system.
 116252416 KB available on disk.

    131072 bytes in each allocation unit.
    915728 total allocation units on disk.
    908222 allocation units available on disk.

last run left this with write test:
Code:
10/09/2019  12:39 PM        98,304,000 A_00001.dat
10/09/2019  12:39 PM        98,304,000 A_00002.dat
10/09/2019  12:39 PM        98,304,000 A_00003.dat
10/09/2019  12:39 PM        98,304,000 A_00004.dat
10/09/2019  12:39 PM        98,304,000 A_00005.dat
10/09/2019  12:39 PM        98,304,000 A_00006.dat
10/09/2019  12:40 PM        98,304,000 A_00007.dat
10/09/2019  12:40 PM        98,304,000 A_00008.dat
10/09/2019  12:40 PM        98,304,000 A_00009.dat
10/09/2019  12:40 PM        98,304,000 A_00010.dat

Format under windows would be NTFS default - and ExFat is the other option.

Got one of my USB sticks formatted to ExFat using fdisk in Linux. I am so behind I did not realize that capability was available in Linux. Anyway it was not an SD card formatted with fat16 it was a USB stick. With fat16 it writes ~8 MB/s, with ExFat it writes at ~6 MB/s and with fat32 it writes ~2 MB/s. I still have to test HD's and SD cards with ExFat. I am using logger_RawWrite and logger_RawWrite_FS to test with.
 
@defragster:

A question, what was the fastest write speeds you were getting with the StarTech USB to SATA adapter and an HD formatted with EXFAT and using logger_RawWrite.ino with MSC?

Thanks
 
With the updated MSC and EXFAT I am getting ~18.5 MB/s consistently with no stalls:) I have tried several HD's and the results are the same. The buffer size is 32KB. At this point it seems to be the sweet spot. This is with the T36. I haven't tried with the T4 yet. Really need to get a SSD drive to test with. Will create a new GitHub branch and release the updated MSC for testing.

Wished I had more time to play.
 
With the updated MSC and EXFAT I am getting ~18.5 MB/s consistently with no stalls:) I have tried several HD's and the results are the same. The buffer size is 32KB. At this point it seems to be the sweet spot. This is with the T36. I haven't tried with the T4 yet. Really need to get a SSD drive to test with. Will create a new GitHub branch and release the updated MSC for testing.

Wished I had more time to play.

Like this 32K DWORDS is 128 KByte buffer?

Using what I have installed from Oct 1st libs::
Code:
Test logger_RawWrite
uSDFS_VER:30_Jun_19_07_17
BUFFSIZE :32768
Dev Type :2:/
File System FS_EXFAT
Free Disk Size -1 clusters
Cluster Size 256 sectors
Sector Size 512 bytes

Change drive
A_00001.dat
stat FR_OK 0
 opened FR_OK 0

................................................................
.................................... (7110992 - 18.432308 MB/s)
 (open: 15998 us; close: 99000 us; write: min,max: 6882 12890 us)

And the same with SD card in USB DONGLE:
Code:
File System FS_FAT32
................................................................
.................................... (22447996 - 5.838918 MB/s)

And same on a 64GB ADATA FLASH USB 3.1 drive:
Code:
File System FS_EXFAT
................................................................
.................................... (7296990 - 17.962475 MB/s)
 
Last edited:
Yes, was this without the the stalling between writes? If so then I guess I am up to speed with you.
 
Yes, was this without the the stalling between writes? If so then I guess I am up to speed with you.

Added FLASH drive above too 17.96MB/s

Wasn't watching for stalling - Stalling is accounted for in the speed measure AFAIK. The dots print 1/100 updates or something - so a stalled dot is just a long write.
 
This 32K buffer :: BUFFSIZE :32768

Is actually this in 131,072 bytes :: uint32_t buffer[BUFFSIZE];

just noted - these results on a T4 at 600 MHz

Though the results t 150 MHz are the same - so T_3.6 should be about equal:
Code:
File System FS_EXFAT
................................................................
.................................... (7116938 - 18.416908 MB/s)
 (open: 54025 us; close: 100999 us; write: min,max: 6501 12565 us)
 
Back
Top