Teensy 3.6/4.0/4.1, USBHost_t36, Reading and Writing Files

TargetSound

New member
Dear Forum,

For Teensy 3.6/4.0/4.1 I would like to use USBHost_t36.h to read and write files on a USB mass storage device. This concerns both
binary files as well as ASCII files (line by line). Does anyone have a suggestion, or better still a code example, for the simplest
possibility (file: verify existence, open, read, write, close)?

Many greetings, Alexander
 
Well to start I would look at the USBHost_t36 Storage examples especially the ListFiles example.

One thing to note is that because of changes to the Library the examples were not update. So in the examples where you see:
Code:
  Serial.print("\nInitializing USB MSC drive...");

  // future USBFilesystem will begin automatically
  // begin(USBDrive) is a temporary feature
  if (!firstPartition.begin(&myDrive)) {
    Serial.println("initialization failed!");
    return;
  }
should be changed to:
Code:
  Serial.print("\nWaiting for partition to...");

  while (!firstPartition) {
    myusb.Task();
}

@KurtE has a PR in that fixes all the examples.

The one nice think is that once you have it set up to address the USB drive accessing files for reading/writing works the same way as if you were using a SD card. So if you are not familar with using a SD Card I would like at the examples in the SD Library included in the Teensyduino library.
 
USBHost_t36 supports USB drives, that have Fat file systems (Fat32, Fat16, exFat)

The library does have some examples that may be slightly broken in the current beta release of Teensyduino, which is a little different than the
current released version of Teensyduino. But the main differences is that the older code had to do it's own enumeration of drives to File systems
and the current beta version does this for you.

One example lists the files on the first partition that is enumerated on a drive:
Code:
 This example code is in the public domain.

 */
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);

// Setup MSC for the number of USB Drives you are using. (Two for this example)
// Mutiple  USB drives can be used. Hot plugging is supported. There is a slight
// delay after a USB MSC device is plugged in. This is waiting for initialization
// but after it is initialized ther should be no delay.
USBDrive myDrive(myusb);
USBFilesystem firstPartition(myusb);

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();

  Serial.print("\nWaiting for partition to...");

  while (!firstPartition) {
    myusb.Task();
  }
  Serial.println("initialization done.");

  File root = firstPartition.open("/");

  printDirectory(root, 0);

  Serial.println("done!");
}

void loop()
{
  // nothing happens after setup finishes.
}

void printDirectory(File dir, int numSpaces) {
  while(true) {
    File entry = dir.openNextFile();
    if (! entry) {
      //Serial.println("** no more files **");
      break;
    }
    printSpaces(numSpaces);
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numSpaces+2);
    } else {
      // files have sizes, directories do not
      printSpaces(48 - numSpaces - strlen(entry.name()));
      Serial.print("  ");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

void printSpaces(int num) {
  for (int i=0; i < num; i++) {
    Serial.print(" ");
  }
}
The USBDrive myDrive(myusb) - Object handles one drive being plugged in. We have support for both Master Boot Record (MBR) as well as some GUID Partition Table(GPT) type disks.

The line: USBFilesystem firstPartition(myusb); - adds support for one partition to be used. If you think that there may likely be multiple partitions, that you wish to support, add more of these lines to the code, with different names.

The USBFilesystem objects are like our SD objects in that they are subclasses of the Teensy core FS object base class. So, you can do all of the normal things with them, of enumerating directories and open files and the like. Once you have a file open, you can do all of the normal File things like read and write.
 
Hello,

I still have one question: What is the limit of the buffer length for each write and read access?

Many greetings, Alexander
 
Hello,

I still have one question: What is the limit of the buffer length for each write and read access?

Many greetings, Alexander

When I was first developing MSC I was testing buffer sizes vs. transfer speeds. Here is a copy file sketch that I used for testing. I have modified it to work with the latest changes to USBHost_t36. As you stated above it's fairly easy to update.

Any way to answer your question about buffer sizes, here is a sketch for testing:
Code:
/*
  MSC Drive read/write copy file
 
 This example code is in the public domain.
 */
 
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

// Setup MSC for the number of USB Drives you are using. (Two for this example)
// Mutiple  USB drives can be used. Hot plugging is supported. There is a slight
// delay after a USB MSC device is plugged in. This is waiting for initialization
// but after it is initialized ther should be no delay.
USBDrive myDrive(myusb);
USBFilesystem firstPartition(myusb);

File myFile;
File myFile1;

//************************************************
// Size of read/write buffer. Start with 4096.
// Have tried 4096, 8192, 16384, 32768 and 65536.
// Usually settle on 16384 
// 
//************************************************
const size_t BUF_SIZE = 4096;

// File size in MB where MB = 1,024,000 bytes.
const uint32_t FILE_SIZE_MB = 32;
// File size in bytes.
const uint32_t FILE_SIZE = 1024000UL*FILE_SIZE_MB;
FASTRUN uint8_t* buf[BUF_SIZE];
uint32_t t;
uint32_t flSize = 0;
float MBs = 1.0f;

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();

  Serial.print("\nInitializing USB MSC drive...");
  if (!firstPartition.begin(&myDrive)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  Serial.print("\nTesting Write, Copy and Read. BUF_SIZE = ");
  Serial.println(BUF_SIZE);
  
//  File root = firstPartition.open("/");
//  printDirectory(root, 0);

  // fill buf with known data
  if (BUF_SIZE > 1) {
    for (size_t i = 0; i < (BUF_SIZE - 2); i++) {
      buf[i] = (uint8_t *)('A' + (i % 26));
    }
    buf[BUF_SIZE-2] = (uint8_t *)'\r';
  }
  buf[BUF_SIZE-1] = (uint8_t *)'\n';
  
  uint32_t n = FILE_SIZE/BUF_SIZE;

  if(firstPartition.exists("test.txt"))
	firstPartition.remove("test.txt");

  // open the file. 
  myFile = firstPartition.open("test.txt", FILE_WRITE_BEGIN);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("\nWriting to test.txt...");
  t = millis();
  for (uint32_t i = 0; i < n; i++) {
    if (myFile.write(buf, BUF_SIZE) != BUF_SIZE) {
      Serial.printf("Write Failed: Stopping Here...");
      while(1);
    }
  }
  t = millis() - t;
  flSize = myFile.size();
  MBs = flSize / t;
  Serial.printf("Wrote %lu bytes %f seconds. Speed : %f MB/s\n",flSize, (1.0 * t)/1000.0f, MBs / 1000.0f);
  // close the file:
  myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("Error opening test.txt: Write Failed: Stoppiing Here...");
    while(1);
  }
  // re-open the file for reading:
  myFile = firstPartition.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
	if(firstPartition.exists("copy.txt"))
		firstPartition.remove("copy.txt");
    // open the second file for writing. 
    myFile1 = firstPartition.open("copy.txt", FILE_WRITE_BEGIN);
    // if the file opened okay, write to it:
    if (myFile1) {
      Serial.printf("Copying test.txt to copy.txt...");
	  t = millis();
      while(myFile.read(buf, BUF_SIZE) == BUF_SIZE) {
        if (myFile1.write(buf, BUF_SIZE) != BUF_SIZE) {
          Serial.printf("Write Failed: Stoppiing Here...");
          while(1);
        }
      }
    }
    t = millis() - t;
    flSize = myFile.size();
    MBs = flSize / t;
    Serial.printf("Copied %lu bytes %f seconds. Speed : %f MB/s\n",flSize, (1.0 * t)/1000.0f, MBs/1000.0f);
    // close the files:
    myFile.close();
    myFile1.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  // re-open the second file for reading:
  myFile1 = firstPartition.open("copy.txt");
  if (myFile1) {
    Serial.println("copy.txt:");
    // open the file for a read. 
    myFile1 = firstPartition.open("copy.txt");
    // if the file opened okay, write to it:
    if (myFile1) {
      Serial.printf("Reading File: copy.txt...");
	  t = millis();
      while(myFile1.read(buf, BUF_SIZE) == BUF_SIZE);
    }
    t = millis() - t;
    flSize = myFile1.size();
    MBs = flSize / t;
    Serial.printf("Read %lu bytes %f seconds. Speed : %f MB/s\n",flSize, (1.0 * t)/1000.0f, MBs/1000.0f);
    // close the files:
    myFile1.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("Error opening copy.txt");
  }
  Serial.printf("Done..\n");
}

void loop()
{
	// nothing happens after setup
}

void printDirectory(File dir, int numSpaces) {
   while(true) {
     File entry = dir.openNextFile();
     if (! entry) {
       //Serial.println("** no more files **");
       break;
     }
     printSpaces(numSpaces);
     Serial.print(entry.name());
     if (entry.isDirectory()) {
       Serial.println("/");
       printDirectory(entry, numSpaces+2);
     } else {
       // files have sizes, directories do not
       printSpaces(48 - numSpaces - strlen(entry.name()));
       Serial.print("  ");
       Serial.println(entry.size(), DEC);
     }
     entry.close();
   }
}

void printSpaces(int num) {
  for (int i=0; i < num; i++) {
    Serial.print(" ");
  }
}

Hopefully my time calculations are correct:) If you uncomment lines 63 and 64 you will get a directory listing.

Here is some results from one of my 128Gig thumb drives:
Code:
Initializing USB MSC drive...initialization done.

Testing Write, Copy and Read. BUF_SIZE = 4096

Writing to test.txt...Wrote 32768000 bytes 12.043000 seconds. Speed : 2.720000 MB/s
test.txt:
Copying test.txt to copy.txt...Copied 32768000 bytes 19.549000 seconds. Speed : 1.676000 MB/s
copy.txt:                                                                          
Reading File: copy.txt...Read 32768000 bytes 4.998000 seconds. Speed : 6.556000 MB/s
Done..                                                                             
                                                                                   
Initializing USB MSC drive...initialization done.

Testing Write, Copy and Read. BUF_SIZE = 8192

Writing to test.txt...Wrote 32768000 bytes 10.931000 seconds. Speed : 2.997000 MB/s
test.txt:                                                                          
Copying test.txt to copy.txt...Copied 32768000 bytes 11.638000 seconds. Speed : 2.815000 MB/s
copy.txt:                                                                          
Reading File: copy.txt...Read 32768000 bytes 3.000000 seconds. Speed : 10.922000 MB/s
Done..

Initializing USB MSC drive...initialization done.

Testing Write, Copy and Read. BUF_SIZE = 16384

Writing to test.txt...Wrote 32768000 bytes 8.092000 seconds. Speed : 4.049000 MB/s
test.txt:
Copying test.txt to copy.txt...Copied 32768000 bytes 7.696000 seconds. Speed : 4.257000 MB/s
copy.txt:
Reading File: copy.txt...Read 32768000 bytes 2.235000 seconds. Speed : 14.661000 MB/s
Done..

Initializing USB MSC drive...initialization done.

Testing Write, Copy and Read. BUF_SIZE = 32768

Writing to test.txt...Wrote 32768000 bytes 7.842000 seconds. Speed : 4.178000 MB/s
test.txt:
Copying test.txt to copy.txt...Copied 32768000 bytes 6.943000 seconds. Speed : 4.719000 MB/s
copy.txt:
Reading File: copy.txt...Read 32768000 bytes 1.744000 seconds. Speed : 18.788000 MB/s
Done..

Initializing USB MSC drive...initialization done.

Testing Write, Copy and Read. BUF_SIZE = 65536

Writing to test.txt...Wrote 32768000 bytes 7.704000 seconds. Speed : 4.253000 MB/s
test.txt:
Copying test.txt to copy.txt...Copied 32768000 bytes 6.566000 seconds. Speed : 4.990000 MB/s
copy.txt:
Reading File: copy.txt...Read 32768000 bytes 1.513000 seconds. Speed : 21.657000 MB/s
Done..

Once you get past 16384 buffer size there is not much improvement to the write and copy speeds. I may be wrong but I think that is the buffer size used by the USB host driver as well.

I should probably go through my original examples and update them for use with the latest USBHost_t36 library....

EDIT: You can change the buffer size at line #32 in the sketch.
EDIT2: Also you will find several examples of using some of the common file operations in this sketch such as open, close, read, write, exists and remove.
 
Last edited:
What things did you have to adjust to get this to work? I keep getting errors related to msController and I don't understand it.

With the information you've given us there is not much we can do to help you... Please read the Forum Rule above. What operating system are you using?
What version of Arduino and Teensyduino are you using? What are the errors you are seeing? What sketch are you using? I assume it's the one posted above. What Teensy model are you using?

With that information we might be able to help you:)
 
With the information you've given us there is not much we can do to help you... Please read the Forum Rule above. What operating system are you using?
What version of Arduino and Teensyduino are you using? What are the errors you are seeing? What sketch are you using? I assume it's the one posted above. What Teensy model are you using?

With that information we might be able to help you:)

Sorry let me back up. I am using a teensy 4.1, I am using Arduino 1.8.19, I am using teensyduino 1.57. windows 10 computer. I am using the sketch here: https://github.com/wwatson4506/UsbMscFat/blob/UsbMscFat/examples/ReadWriteUSB/ReadWriteUSB.ino

TargetSound had mentioned that they were able to use that sketch and adjust a few things to get it to work perfectly. I am wondering what things they changed to get it to work. When I run that sketch, ReadWriteUSB, with the necessary libraries, I get an error saying:

C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\UsbMscFat\src/USBmscInfo.h:39:36: error: 'msController' has not been declared
void printMscAscError(print_t* pr, msController *pDrive);


I don't make any changes to the sketch at all.

My goal is to figure out how to create and write a txt file to an external usb drive that I plug in to the USB host on the board. I know how to do it with the onboard sd card, and was hoping this was similar.
 
Sorry let me back up. I am using a teensy 4.1, I am using Arduino 1.8.19, I am using teensyduino 1.57. windows 10 computer. I am using the sketch here: https://github.com/wwatson4506/UsbMscFat/blob/UsbMscFat/examples/ReadWriteUSB/ReadWriteUSB.ino

TargetSound had mentioned that they were able to use that sketch and adjust a few things to get it to work perfectly. I am wondering what things they changed to get it to work. When I run that sketch, ReadWriteUSB, with the necessary libraries, I get an error saying:

C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\UsbMscFat\src/USBmscInfo.h:39:36: error: 'msController' has not been declared
void printMscAscError(print_t* pr, msController *pDrive);


I don't make any changes to the sketch at all.

My goal is to figure out how to create and write a txt file to an external usb drive that I plug in to the USB host on the board. I know how to do it with the onboard sd card, and was hoping this was similar.

Did you see this notice for that repository:
Code:
UsbMscFat Library
NOTE: This Library is OUTDATED !!!
Please Use the examples in the latest USBHost_t36 stable library for the Teensy. Teensyduino 1.57 up 1.58B3. Arduino 1.8.19.

That is an outdated repository. It won't work. Try this instead:
Code:
/*
  MSC USB Drive read/write
 
 This example shows how to read and write data to and from an 
 MSC USB drive file 	

 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 modified 17 Nov 2020
 by Warren Watson
 
 This example code is in the public domain.
 	 
 */
 
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

// Setup MSC for the number of USB Drives you are using. (Two for this example)
// Mutiple  USB drives can be used. Hot plugging is supported. There is a slight
// delay after a USB MSC device is plugged in. This is waiting for initialization
// but after it is initialized ther should be no delay.
USBDrive myDrive(myusb);
USBFilesystem firstPartition(myusb);

File myFile;

void setup()
{

 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();
  myusb.Task();
  Serial.print("\nInitializing USB MSC drive...");

  if (!firstPartition.begin(&myDrive)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. 
  myFile = firstPartition.open("test.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
	// close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  // re-open the file for reading:
  myFile = firstPartition.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
    
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
    	Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop()
{
	// nothing happens after setup
}

I should probably archive that repo:)
Good luck...
 
Did you see this notice for that repository:
Code:
UsbMscFat Library
NOTE: This Library is OUTDATED !!!
Please Use the examples in the latest USBHost_t36 stable library for the Teensy. Teensyduino 1.57 up 1.58B3. Arduino 1.8.19.

That is an outdated repository. It won't work. Try this instead:
Code:
/*
  MSC USB Drive read/write
 
 This example shows how to read and write data to and from an 
 MSC USB drive file 	

 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 modified 17 Nov 2020
 by Warren Watson
 
 This example code is in the public domain.
 	 
 */
 
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

// Setup MSC for the number of USB Drives you are using. (Two for this example)
// Mutiple  USB drives can be used. Hot plugging is supported. There is a slight
// delay after a USB MSC device is plugged in. This is waiting for initialization
// but after it is initialized ther should be no delay.
USBDrive myDrive(myusb);
USBFilesystem firstPartition(myusb);

File myFile;

void setup()
{

 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();
  myusb.Task();
  Serial.print("\nInitializing USB MSC drive...");

  if (!firstPartition.begin(&myDrive)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. 
  myFile = firstPartition.open("test.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
	// close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  // re-open the file for reading:
  myFile = firstPartition.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
    
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
    	Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop()
{
	// nothing happens after setup
}

I should probably archive that repo:)
Good luck...

thanks! That looks like exactly what I am trying to do. Although I am getting another error now:


ListFiles: In function 'void setup()':
ListFiles:50: error: 'class USBFilesystem' has no member named 'begin'
if (!firstPartition.begin(&myDrive)) {
^
'class USBFilesystem' has no member named 'begin'

maybe my USBHost_t36.h is outdated.....
 
@tstarr - There have been changes made to USBHost_t3 library. I would suggest that you upgrade Teensyduino to 1.58 Beta3. Here is tthe link:
https://forum.pjrc.com/threads/71693-Teensyduino-1-58-Beta-3

This is the latest version which I am using as well and the listFiles sketch does work...

I have the latest beta 3 installed in the 2.0.3 IDE, and unfortunately, I'm getting the same error listed in the last post. This is when trying to run the updated code you posted at https://forum.pjrc.com/threads/7164...-Writing-Files?p=320567&viewfull=1#post320567.
 
Last edited:
@jellish - @tstarr - Can you give us the full error, including anything Arduino is saying about duplicate libraries and the full paths of the libraries it actually used?

When you get this error (or any compile error) in Arduino, you should see a "Copy Error Messages" button. Please click it, so you copy all the error info. Then here on the forum, click the "#" button (last button on the right hand side) and when you see the cursor is between the two "code" tags, press CTRL-V (or Command-V is using MacOS) to paste all the error info. The code tags preserve formatting.

copy.png

code.png
 
I don’t know if this is still relevant.
But I hade luck with this simple code (to Write a file). I dont use "firstPartition.begin"

Code:
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);

// Instances for one drive
USBDrive myDrive(myusb);

// Instances for accessing the files on the drive
USBFilesystem myFilesystem(myusb);
File myFile;

void WriteFile()
{
  myFile = myFilesystem.open("test.txt", FILE_WRITE);
  myFile.println("testing 1, 2, 3.");
  myFile.close();

  return;
}
void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for Arduino Serial Monitor to connect.
  }
  myusb.begin();
  Serial.println("\nWaiting for Drive to initialize...");

  // Wait for the drive to start.
  while (!myFilesystem) {
    myusb.Task();
  }

  Serial.println("Done initialize, Start Writing");

  delay(100);
  WriteFile();
  Serial.println("Done");
}

void loop(void) {

}

I use Arduino IDE 2.1.0 with Teensy 0.59.2
 
Last edited:
Back
Top