How to read/write a non filesystem USB storage drive on T4.1

Richard H

New member
Hi

I have searched a bit on this and found a couple of more complex discussions biased towards the MSD rather then USB.
Paul mentions in the MSD topic that direct access may be possible by creating a custom cpp class that inherits from SD.

My aim is to read/write raw bytes/sectors without the need for a file system noting a FAT32 filesystem must be on the MSD for it to be detected using SD. I would not want a FAT32 to be present to detect the USB device. I would not relish trying to code a C++ class that inherits from USBHost_t36 to do this as I am quite a newbie.

Apologies if this is possible already.

Best Regards
Richard
 
Here is an example of doing direct sector reads and writes to a USB thumb drive. It will destroy any file system on the drive!!

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);

//-------------------------------------------------------------------------
#define FILLCHAR 0xaa // Change this to write a different value to sectors.
//-------------------------------------------------------------------------

uint8_t sectorBuffer[512]; // Sector buffer for use with 512 byte R/W
uint8_t mscError = 0;
uint32_t BlockAddress = 10; // Writing and reading from sector 10
uint8_t Blocks = 1;         // Read or write 1 block

// Fill sector buffer with a uint8_t char.
void fillBuff(uint8_t fillChar) {
    for(uint16_t i = 0; i < 512; i++) {
        sectorBuffer[i] = fillChar;
    }
}

// A small hex dump function
void hexDump(const void *ptr, uint32_t len) {
  uint32_t  i = 0, j = 0;
  uint8_t   c=0;
  const uint8_t *p = (const uint8_t *)ptr;

  Serial.printf("BYTE      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
  Serial.printf("---------------------------------------------------------\n");
  for(i = 0; i <= (len-1); i+=16) {
   Serial.printf("%4.4lx      ",i);
   for(j = 0; j < 16; j++) {
      c = p[i+j];
      Serial.printf("%2.2x ",c);
    }
    Serial.printf("  ");
    for(j = 0; j < 16; j++) {
      c = p[i+j];
      if(c > 31 && c < 127)
        Serial.printf("%c",c);
      else
        Serial.printf(".");
    }
    Serial.printf("\n");
  }
}

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

  myusb.begin();
  delay(3000);
  myusb.Task();
  Serial.printf("%cLet's destroy any formatting on a USB thumb drive!!!\n\n",12);

  Serial.printf("Filling sector buffer with 0x%2.2x\n", FILLCHAR); 
  fillBuff(FILLCHAR); //Fill sector buffer with 0xaa
  Serial.println("\nWrite 1 sector to the USB drive (512 bytes)");
  waitforInput();
  // Write one sector
  mscError = myDrive.msWriteBlocks(BlockAddress,Blocks,(uint16_t)512,sectorBuffer);
  Serial.println("\nClearing sector buffer to 0");
  fillBuff(0); // Clear sector buffer
  Serial.println("\nRead that the same sector back into the sector buffer");
  waitforInput();
  // Read one sector
  mscError = myDrive.msReadBlocks(BlockAddress,Blocks,(uint16_t)512,sectorBuffer);
  Serial.println("\nHex Dump the sector buffer\n");
  hexDump(sectorBuffer,512); // Dump the buffer
  Serial.println("\nDone...");

}

void loop() {

}

void waitforInput()
{
  Serial.println("Press any key to continue");
  while (Serial.read() == -1) ;
  while (Serial.read() != -1) ;
}

It first fills a 512 byte buffer with a 'FILLCHAR' (defined in line #11 as 0xaa). Then press any key to write it to the chosen sector (sector 0 in this case). It then clears the sector buffer before reading back the same sector number. Finally it hex dumps the sector.
I have not tried it but it might also work with a USB card reader as well. The two methods, "msReadBlocks()" and "msWriteBlocks()" are found in "MassStorageDriver.cpp".
Remember, any USB drive you use this sketch on will need to be reformatted afterwords..
Hope this is what you were wanting to know...
 
Here is an example of doing direct sector reads and writes to a USB thumb drive. It will destroy any file system on the drive!!
Any chance this was tried with TD 1.59?
Code as above keeps restarting to a CrashReport building IDE 1.8.19 with TD 1.59.
hardware: T_4.1 with a USB drive on USB Host adapter plug
 
Any chance this was tried with TD 1.59?
Opps - powered/programmed the wrong T4.1 on power switching Hub

YES, it works on TD 1.59.

Edited the code to READ/Show {all 0's) first sector to second buffer first and restore it after the test write.
This left the drive filesystem usable.

Odd it faulted - probably from not checking return codes and then continuing?
 
Opps - powered/programmed the wrong T4.1 on power switching Hub

YES, it works on TD 1.59.

Edited the code to READ/Show {all 0's) first sector to second buffer first and restore it after the test write.
This left the drive filesystem usable.

Odd it faulted - probably from not checking return codes and then continuing?
Yes, The USB drive will have to be reformatted as stated. This is what you should see:
Code:
Let's destroy any formatting on a USB thumb drive!!!

Filling sector buffer with 0xaa

Write 1 sector to the USB drive (512 bytes)
Press any key to continue

Clearing sector buffer to 0

Read that the same sector back into the sector buffer
Press any key to continue

Hex Dump the sector buffer

BYTE      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
---------------------------------------------------------
0000      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0010      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0020      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0030      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0040      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0050      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0060      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0070      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0080      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0090      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
00a0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
00b0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
00c0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
00d0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
00e0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
00f0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0100      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0110      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0120      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0130      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0140      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0150      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0160      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0170      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0180      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
0190      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
01a0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
01b0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
01c0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
01d0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
01e0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................
01f0      aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa   ................

Done...
 
Yes, The USB drive will have to be reformatted as stated. This is what you should see:
Yes, that is how it was before edits - once I programmed the right T_4.1 with USB Host and Flash drive connected.
I just added this before to a second buffer to restore later and it did not destroy the drive - but passed the test:
Code:
    mscError = myDrive.msReadBlocks(BlockAddress,Blocks,(uint16_t)512,sectorBufferPrior);
  Serial.println("\nHex Dump the EXISTING sector buffer\n");
  hexDump(sectorBufferPrior,512); // Dump the buffer
That showed All Zero's for the two drives I tested - then after writing 'aa' I put the other buffer back and the drive still worked.
Code:
 mscError = myDrive.msWriteBlocks(BlockAddress,Blocks,(uint16_t)512,sectorBufferPrior);
 
@defragster - So basically you were saving the current contents of sector 10 to another buffer (sectorBufferPrior) before writing the first buffer filled with 0xaa to sector 10. Then you read the back the contents of sector 10 and did the hexdump. Finally you wrote the second buffer back to sector 10 that was filled with the original contents of sector 10. Am I right? That would prevent wiping out the file system. In this case as per post #1 I don't think @Richard H wanted a Fat32 file system on the USB drive...
 
saving the current contents of sector 10 to another buffer (sectorBufferPrior) before writing the first buffer filled with 0xaa to sector 10. Then you read the back the contents of sector 10 and did the hexdump. Finally you wrote the second buffer back to sector 10 that was filled with the original contents of sector 10. Am I right?
Exactly. I wanted to see it work but not trash anything, so I buffered and restored the affected data - and that worked.
Indeed @Richard H doesn't have that concern wanting just raw data space.

So, nice example code that works!
 
USB drives may have sectors which contain 4096 bytes rather than 512. I believe in that case the example code would end up writing random data to bytes 512-4095 and then possibly crash (since it would overrun sectorBuffer significantly) when trying to read back sector 0.
 
@jmarsh Interesting. In my (Windows) low level reader/writer application I have not come across any device (including USB SSD or SATA HDD etc) where writing 512 bytes fails but thank you for pointing this out. I also know CD/DVDs have 2048 bytes/sectors. Maybe I could have an instruction that does a quick probe of the device to find the sector size before attempting any read/write operations? Reading a bit more into things with 4096 byes/sec there is something to do with support for EFI areas on OS emulator forums but thats about it.

Regarding @defragster post, @wwatson is correct in assuming I am not concerned with conserving the original filesystem, but thank you again for thinking about this as it could be a handy little function.
 
The SCSI READ_CAPACITY command returns the sector size (along with the total number of sectors - 1). There's also another catch with that; the basic version of that command is READ_CAPACITY_10 which returns 32-bit values, but some drives (larger than 2TB) may have more than 2^32 512 byte sectors and will return 0xFFFFFFFF, implying you should execute a READ_CAPACITY_16 command which basically does the same thing but uses 64-bit values.
(It's not safe to rely solely on READ_CAPACITY_16 by default since not all devices support it.)
 
Back
Top