Forum Rule: Always post complete source code & details to reproduce any issue!
Page 17 of 22 FirstFirst ... 7 15 16 17 18 19 ... LastLast
Results 401 to 425 of 548

Thread: USBHost_t36 USB Mass Storage Driver Experiments

  1. #401
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    426
    Quote Originally Posted by KurtE View Post
    @wwatson - I would like to start playing around some as I know these capabilities would be great addition to Teensy world.

    Are the instructions up at: https://forum.pjrc.com/threads/55821...l=1#post231523
    Maybe the best thing to try things out?

    It looks like you had a delta to usbhost_t36? has this already been folded int a Pull Request or do we need to?

    Would be fun to try this stuff out, and maybe see if it can feed through to MTP...
    I have been watching the development of LittleFS and MTP_T4 and at the same time working with SdFat and MSC. The driver part of MSC is now part of USBHost_t36 thanks @Paul. A lot of things have changed from the original MSC. MSC now works with Sdfat.

    The first versions were:
    https://forum.pjrc.com/threads/64784...ght=sdfat+ways

    But as per a conversation with Bill Greiman in a post that I can't find now he did not want to modify SdFat for use with MSC. So what I have come up and still testing is this:
    https://github.com/wwatson4506/UsbMscFat.

    This uses SdFat and FS and does not modify SdFat in any way. It is working with both the latest SdFat and the file abstraction of FS using TD 1.54B6. This is still WIP and I have already found several issues with it that I am working on. Working with hot plugging both USB drives and SD cards and getting volume names. Initially working.

    There are several examples that can be used to test this library and I am working on more of them. All that is needed is TD1.54B6 and UsbMscFat. I know that Paul is also planning to work with MSC so I really am being cautious about how much effort I put into this.

    Hopefully I have not confused you Going back to to a double shift at work now

    Edit: MSC still works with uSDFS.
    Last edited by wwatson; 02-20-2021 at 02:39 AM. Reason: Additional Info

  2. #402
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    @wwatson
    Just downloaded UsbMscFat and so far examples working a couple different devices I tried - 32 thumb drive, SD Card in adapter and a SSD drive. Here some info from one of the examples:
    Code:
    init time: 1341 ms
    
    Drive type: USB Drive.
    msc1 Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X0,0X20,0X21,0X0,0X7,0XFE,0XFF,0XFF,2048,204800000
    2,0X0,0XFE,0XFF,0XFF,0XC,0XFE,0XFF,0XFF,204802048,29634560
    3,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    4,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    
    Scanning FAT, please wait.
    
    Volume is exFAT
    sectorsPerCluster: 256
    clusterCount:      799960
    freeClusterCount:  465956
    fatStartSector:    4096
    dataStartSector:   12288
    
    type any character to start
    and
    Code:
    Type any character to start
    FreeStack: 396520
    Type is exFAT
    Card size: 120.03 GB (GB = 1E9 bytes)
    FILE_SIZE_MB = 32
    BUF_SIZE = 32768 bytes
    Starting write test, please wait.
    
    write speed and latency
    speed,max,min,avg
    KB/Sec,usec,usec,usec
    26214.40,1250,1250,1250
    9595.31,145375,1250,3414
    
    Starting read test, please wait.
    
    read speed and latency
    speed,max,min,avg
    KB/Sec,usec,usec,usec
    Filesize = 32768000.00
    23831.27,1729,1375,1375
    Filesize = 32768000.00
    23831.27,1375,1368,1374
    
    Done

  3. #403
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    426
    Quote Originally Posted by mjs513 View Post
    @wwatson
    Just downloaded UsbMscFat and so far examples working a couple different devices I tried - 32 thumb drive, SD Card in adapter and a SSD drive. Here some info from one of the examples:
    Code:
    init time: 1341 ms
    
    Drive type: USB Drive.
    msc1 Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X0,0X20,0X21,0X0,0X7,0XFE,0XFF,0XFF,2048,204800000
    2,0X0,0XFE,0XFF,0XFF,0XC,0XFE,0XFF,0XFF,204802048,29634560
    3,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    4,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    
    Scanning FAT, please wait.
    
    Volume is exFAT
    sectorsPerCluster: 256
    clusterCount:      799960
    freeClusterCount:  465956
    fatStartSector:    4096
    dataStartSector:   12288
    
    type any character to start
    and
    Code:
    Type any character to start
    FreeStack: 396520
    Type is exFAT
    Card size: 120.03 GB (GB = 1E9 bytes)
    FILE_SIZE_MB = 32
    BUF_SIZE = 32768 bytes
    Starting write test, please wait.
    
    write speed and latency
    speed,max,min,avg
    KB/Sec,usec,usec,usec
    26214.40,1250,1250,1250
    9595.31,145375,1250,3414
    
    Starting read test, please wait.
    
    read speed and latency
    speed,max,min,avg
    KB/Sec,usec,usec,usec
    Filesize = 32768000.00
    23831.27,1729,1375,1375
    Filesize = 32768000.00
    23831.27,1375,1368,1374
    
    Done
    Glad to see that it working. I was hoping that other people could test with there USB drives. 'mscFS.h' is an MSC version of 'SD.h' and 'littleFS.h' setup to use 'USBFat.h' which also includes 'SdFat.h'. This allows SdFat to access a USB drive as a block device. This also allows usage of SdFat with USB drives without having to modify SdFat in any way which is what Bill Greiman requested and gave me examples of how to implement it. What I have is probably not the most efficient way to do it as it is still WIP. Any ideas are very welcome.

    Other than fixing obvious bugs and programming errors I am adding:

    1 - Better error reporting using sense code keys, ASC (additional sense codes) and ASCQ (additional sense code qualifiers). These are working.
    2 - Getting volume names. This is easy with Fat32 formatted drive. Not so much with ExFat formatted drives.
    3 - Hot plugging USB drives and SD cards. This is initially working with SD cards but is just calling the begin() function to see if the SD card is still there.
    - I do not think it is the proper way to do this.

    One other thing I am trying to understand is how to unmount an SD card or a USB drive in SdFat.

  4. #404
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    I have done a little playing here with the MTP-test to add an MSC drive. I turned it off by default as you need to install the libraries mentioned here.

    I also did a Pull Request to change the #define that was in conflict with other libraries: https://github.com/wwatson4506/UsbMscFat/pull/1

    I was able to have AN USB drive plugged in when the program started and it showed up in the Teensy object on the PC. I was then able to drag and drop files into it which appeared to copy to the drive.
    I was able to run it again with that in the drive and double click on the image I copied there and it loaded it up in photoshop

    I am testing with MTP + serial .

    Lots of interesting things to test and see what makes sense with MTP with MSC...

    How do I setup multiple drives? What about partitions? How to handle them coming and going. ...

    But it is fun to see some baby steps

  5. #405
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    426
    Quote Originally Posted by KurtE View Post
    I have done a little playing here with the MTP-test to add an MSC drive. I turned it off by default as you need to install the libraries mentioned here.

    I also did a Pull Request to change the #define that was in conflict with other libraries: https://github.com/wwatson4506/UsbMscFat/pull/1

    I was able to have AN USB drive plugged in when the program started and it showed up in the Teensy object on the PC. I was then able to drag and drop files into it which appeared to copy to the drive.
    I was able to run it again with that in the drive and double click on the image I copied there and it loaded it up in photoshop

    I am testing with MTP + serial .

    Lots of interesting things to test and see what makes sense with MTP with MSC...

    How do I setup multiple drives? What about partitions? How to handle them coming and going. ...

    But it is fun to see some baby steps
    That is awesome I always was wondering how to set USB mass storage devices up with MTP but never had the time to really keep up with the development.

    Multiple drives are just a matter of creating another instance of msController. Obviously you will need USB HUB. If you look at the 'copyFilesUSB.ino' sketch in the examples folder you will see how that is done. This sketch is is very terse but shows how to use SD cards both SDIO and external SPI with MSC. Right now it does not use the the FS file abstraction layer but is what I needed to test UsbMSCFat with SdFat. This is a start to mixing FS and Sdfat API's. I still am trying to fully understand Sdfat and it's inner workings. There is a lot to try and understand

    All of the example sketches in UsbMSCFat I have tried to match with SD and SdFat examples. You will notice that the filenames end in 'USB.ino'

    Again, not knowing what the structure of FS, SD, littleFS and MTP will finally be and what @Paul has in mind I am going to keep fly swatting bugs in UsbMSCFat

    Thanks KurtE

    Edit: Have not played with multiple partitions yet but it is available in SdFat.

  6. #406
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    @KurtE - @wwatson

    Not sure where to post this (kind of crosses - Integration Thread)

    Anyway not sure how this would work but SDFat does have a FatPartition Class that looks like it would allow you address partitions. Not sure if @wwatson has the linkage though - need to get some sleep.

    But looking at it you would need to:
    Code:
    #include <FatPartition.h>
    and then

    create an instance of FilePartion() the guess you would have to init(block device, part #);. FatFile is a friend class so you get access that way.

  7. #407
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    @mjs513 and @wwatson @wmxz @paul - That is why I started playing and why I started that other thread. Sometimes hard to know what is going to happen when you try to integrate several of these sub-systems.
    Or some of the big questions, like do we try to get all of these libraries to optionally support Unicode?

    I see the copy files sketch now which has two msc objects, so I see way to try with two, then see how partitions work...

    Some of the reasons to do this including keep swatting bugs in UsbMSCFat and the like, is by doing so at minimum we can have a working system, and maybe better it gives us a good idea of what things we should try to merge back in to the version of SDFat that ships with Teensyduino.

    Also trying out a few different test programs and the like helps us figure out how we might need to improve the interfaces.

    Example: I keep meaning to take a diversion and maybe have an MTP/MSC/ILI9341 (or better with bigger screen) touch sketch that can maybe be used for a framework.
    That maybe setup for N storage like a T4.1 with SD, MSC, LittleFS on chip...

    On the display have maybe default screen that shows summary of the N storage units, with maybe showing name, total size, free space...
    Maybe simple click to show some of the contents. Maybe options to format drive... And if you choose to format a drive than you want progress bar. So the '.' char passed in to low format may not be sufficient.

    Now suppose someone copies a file from PC to your storage, how to you find out that something changed, as to update your display? What if this sketch also has something that generates new files, like maybe I use the CSI interface and every so often take a picture and store it. How do I tell MTP that the system changed (I added stuff already in my version)... Likewise maybe the screen code allows user to delete stuff, so need to tell MTP about this...

    Likewise maybe there is a configuration file you keep in one of the stores that configures the program, like maybe what picture(s) to use a screensaver or how often to take picture... How does the sketch find out if this file changed?

    ...

    Again it is hard to know where is the best place to post something like this. Sorry I know that a lot of this is off topic.

  8. #408
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    @KurtE
    Was poking around SDFat and not 100% sure it directly supports multiple partitions. Why, Blockdevice* dev I believe has to point to the SDCard but doesn't appear we have access to that. Bill points to card into via sd.card()..... Can't wait to see what you come up with. Going to think about it and look at UsbMscFat.

  9. #409
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    As I asked in the MTP thread:

    My next question to self and others maybe other thread
    is to support multiple MSC drives, I was using the global object (MSC) to add the one MSC object as is in the FilesUSB object.

    Thought I would try the stuff out of copyFilesUSB.ino sketch which is setup for two MSC objects which it has as msc1 and msc2.

    Probably is: MSC global is of the class MSCClass
    which is class MSCClass : public FS

    So works to add to storage.

    But: UsbFs msc1;
    and: class UsbFs : public UsbBase<FsVolume> {

    Which is not based on FS...

    So need to figure out the relationship...

  10. #410
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    First attempt is to substitute MSCClass for UsbFs and it compiles and runs for 1 item...

    Again hard to know if should talk about it here or MTP or...

    But my MTP test code is setup now like:
    Code:
    #if USE_MSC_FAT > 0
    #if defined(__IMXRT1062__) || defined(ARDUINO_TEENSY36)
    #include <mscFS.h>
    USBHost myusb;
    USBHub hub1(myusb);
    USBHub hub2(myusb);
    
    // start off with one controller. 
    msController msDrive[USE_MSC_FAT](myusb);
    MSCClass msc[USE_MSC_FAT];
    Where instead of looking for == 1 I look for > 0 and use that as count of max number to support...
    Will see what happens when I put in the code to see if they exist and add both...

    for the one I just have:
    Code:
      Serial.print("\nInitializing USB MSC drive...");
    
      if (!msc[0].begin(&msDrive[0]))
        { Serial.printf("MSC Storage failed or missing"); Serial.println();
        }
        else
        {
          storage.addFilesystem(msc[0], "MSC");
          uint64_t totalSize = msc[0].totalSize();
          uint64_t usedSize  = msc[0].usedSize();
          Serial.printf("Storage MSC "); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
        return;
      }
    now to loop over count and see what happens. Then next up see if your check to see if
    your function in copy files:
    Code:
    bool driveAvailable(msController *pDrive,UsbFs *mscVol) {
    	if(pDrive->checkConnectedInitialized()) {
    		return false; // No USB Drive connected, give up!
    	}
    	if(!mscVol->fatType()) {  // USB drive present try mount it.
    		if (!mscVol->begin(&msDrive1)) {
    			mscVol->initErrorPrint(&Serial); // Could not mount it print reason.
    			return false;
    		}
    	}
    	return true;
    }
    Will work with the updated class...

  11. #411
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    426
    @mjs513

    Bill points to card into via sd.card().....
    This is a pointer to the SD card object (driver) for a particular SD card. This is found in 'SdFat.h'. The equivalent is found in the UsbMSCFat folder 'UsbFat.h' and would be msc1.usbDrive()->. This allows access to methods in the driver layer. Here is an example of it's usage:

    Code:
    // Get Fat32 volume name.
    bool getFat32VolumeLabel(uint8_t  drvType) {
      uint8_t buf[512];
      uint32_t rootDir = 0;
      
      if(drvType == msDrive) {
        msc1.usbDrive()->readSector(msc1.dataStartSector(),buf);
      }
    
      if(drvType == sdDrive) {
        rootDir =  sd.dataStartSector();
        sd.card()->readSector(sd.dataStartSector(),buf);
      }	 
      Serial.print(F("Volume Name: "));
      for (size_t i = 0; i < 11; i++) {
        Serial.write(buf[i]);
      }
      Serial.println();
      return true;
    }
    I have been working on getting volume names. In this case Fat32 volume names.
    As stated before getting ExFat volume labels is more involved.

  12. #412
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    Morning @KurtE

    Was trying to implement your changes and found you already implement them in the repository example so.... Using just 1 MSC object ran into a couple of problems with some devices:
    1. SD Card using a Lexar adapter: Seems to set a MSC0 drive but doesn't in Windows explorer
    Click image for larger version. 

Name:	Capture.PNG 
Views:	9 
Size:	37.6 KB 
ID:	23793
    Code:
    Storage MSC0 31902400512 3833856
    
    Setup done
    CMD: 1002(OPEN_SESSION)l: 16 T:0 : 1
    RESP:2001(RSP:OK)l: 16 T:0 : 1
    CMD: 1001(GET_DEVICE_INFO)l: 12 T:1
    RESP:2001(RSP:OK)l: 12 T:1
    CMD: 1014(GET_DEVICE_PROP_DESC)l: 16 T:2 : d402
    RESP:2001(RSP:OK)l: 16 T:2 : d402
    CMD: 1004(GET_STORAGE_IDS)l: 12 T:3
    RESP:2001(RSP:OK)l: 12 T:3
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:4 : 1
    RESP:2001(RSP:OK)l: 16 T:4 : 1
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:5 : 2
    RESP:2001(RSP:OK)l: 16 T:5 : 2
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:6 : 3
    RESP:2001(RSP:OK)l: 16 T:6 : 3
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:7 : 4
    RESP:2001(RSP:OK)l: 16 T:7 : 4
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:8 : 5
    RESP:2001(RSP:OK)l: 16 T:8 : 5
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:9 : 6
    RESP:2001(RSP:OK)l: 16 T:9 : 6
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:a : 7
    RESP:2001(RSP:OK)l: 16 T:a : 7
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:b : 8
    RESP:2001(RSP:OK)l: 16 T:b : 8
    CMD: 1005(GET_STORAGE_INFO)l: 16 T:c : 9
    RESP:2001(RSP:OK)l: 16 T:c : 9
    2. SSD recognized in Windows explorer - as mentioned earlier.

    3. Old Microcenter 2GB thumb drive - works no issues

    4. Cruze Fit 32GB Thumb - same thing happens as with the 32GB SD/Lexar combo - does show data in serial monitor:

    Code:
    MTP_test
    sd_addFilesystem: 0 20005d68 RAM1
    RAM Storage 0 RAM1 199936 512
    sd_addFilesystem: 1 20005e30 RAM2
    RAM Storage 1 RAM2 3999744 4096
    sd_addFilesystem: 2 20005ca0 PROGM
    Program Storage 0 PROGM 983040 8192
    sd_addFilesystem: 3 200034e4 QSPI
    QSPI Storage 0 QSPI 16777216 8192
    sd_addFilesystem: 4 200035b8 sflash5
    SPIFlash Storage 0 5 sflash5 67108864 8192
    sd_addFilesystem: 5 20003690 sflash6
    SPIFlash Storage 1 6 sflash6 67108864 8192
    SPIFlash Storage 2 7 prop failed or missing
    Flash ID: EF AA 21
    Flash size is 125.50 Mbyte
    Device ID: 0xEFAA21
    sd_addFilesystem: 6 200063e0 WINBOND1G
    Storage 0 3 WINBOND1G 131596288 9175040
    Flash ID: EF AA 22
    Flash size is 253.00 Mbyte
    Device ID: 0xEFAA22
    sd_addFilesystem: 7 200064d0 WINBOND2G
    Storage 1 4 WINBOND2G 265289728 9306112
    
    Initializing USB MSC drives...
    sd_addFilesystem: 8 200066c4 MSC0
    Storage MSC0 32000016384 10393780224
    
    Setup done
    If I run mscFS SDInfo on the Lexar/SD combo:
    Code:
    Initializing USB MSC drive 1...
    myDrive1 Info:
       connected 1
       initialized 1
       USB Vendor ID: 05dc
      USB Product ID: b051
          HUB Number: 0
            HUB Port: 0
      Device Address: 1
    Removable Device: YES
            VendorID: Lexar   
           ProductID: microSD RDR     
          RevisionID: 0815
             Version: 6
        Sector Count: 62333951
         Sector size: 512
       Disk Capacity: 31914982912 Bytes
    
                           4364 LOG_0816.csv
                         153666 OV7670.bmp
                              0 mtpindex.dat
                           5363 datalog.txt
                             21 test1.txt
                          86201 LOG_0001.csv
                         326837 512-07.jpg
                           4303 D435 Obs-slam Links.txt
    2020-06-26 15:21     121978 LOG_0000-afternno.csv
    2020-06-26 17:03      65318 LOG_00001.csv
    2020-06-27 09:41     183998 LOG_62620.csv
    2020-11-01 09:39      34910 perf.jpg
    2020-11-01 09:39      39057 squirrel_dither.jpg
    2020-11-01 09:40      40582 demo.jpg
    2020-11-02 00:09     289750 num3.wav
    2020-11-02 00:09     260436 num4.wav
    2020-11-02 00:09     276426 num5.wav
    2020-11-02 00:09     260818 num6.wav
    2020-11-02 00:09     300028 num1.wav
    2020-11-02 00:09     266528 num2.wav
    
    Volume type is FAT32
    Cluster Size (bytes): 32768
    Volume size (Kbytes): 31154688
    Volume size (Mbytes): 30424
    
    Initializing USB MSC drive 2...
    initialization failed with code: 40
    Just thought you should know.

  13. #413
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    Quote Originally Posted by wwatson View Post
    @mjs513



    This is a pointer to the SD card object (driver) for a particular SD card. This is found in 'SdFat.h'. The equivalent is found in the UsbMSCFat folder 'UsbFat.h' and would be msc1.usbDrive()->. This allows access to methods in the driver layer. Here is an example of it's usage:

    Code:
    // Get Fat32 volume name.
    bool getFat32VolumeLabel(uint8_t  drvType) {
      uint8_t buf[512];
      uint32_t rootDir = 0;
      
      if(drvType == msDrive) {
        msc1.usbDrive()->readSector(msc1.dataStartSector(),buf);
      }
    
      if(drvType == sdDrive) {
        rootDir =  sd.dataStartSector();
        sd.card()->readSector(sd.dataStartSector(),buf);
      }	 
      Serial.print(F("Volume Name: "));
      for (size_t i = 0; i < 11; i++) {
        Serial.write(buf[i]);
      }
      Serial.println();
      return true;
    }
    I have been working on getting volume names. In this case Fat32 volume names.
    As stated before getting ExFat volume labels is more involved.
    Thanks - the dummy that I am. So with that ran it but I created 4 volumes 3 are FAT32 and 1 is exFAT. This is running the SDInfo without Partition info set up:
    Code:
    SdFat version: 2.0.5-beta.1
    Assuming an SDIO interface.
    
    type any character to start
    init time: 21 ms
    
    Card type: SDXC
    
    Manufacturer ID: 0X3
    OEM ID: SD
    Product: SN128
    Version: 8.0
    Serial number: 0X17DCCFC4
    Manufacturing date: 7/2014
    
    cardSize: 127865.45 MB (MB = 1,000,000 bytes)
    flashEraseSize: 128 blocks
    eraseSingleBlock: true
    
    OCR: 0XC0FF8000
    
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X80,0X20,0X21,0X0,0XC,0XC2,0X22,0X20,2048,524288
    2,0X0,0XC2,0X23,0X20,0XC,0XFE,0XFF,0XFF,526336,65536000
    3,0X0,0XFE,0XFF,0XFF,0XC,0XFE,0XFF,0XFF,66062336,65536000
    4,0X0,0XFE,0XFF,0XFF,0XF,0XFE,0XFF,0XFF,131598336,118138880
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 4
    clusterCount:      129024
    freeClusterCount:  129020
    fatStartSector:    8222
    dataStartSector:   10240
    Here is running through the 4 partitions (partition 4 is exFat):
    Code:
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X80,0X20,0X21,0X0,0XC,0XC2,0X22,0X20,2048,524288
    2,0X0,0XC2,0X23,0X20,0XC,0XFE,0XFF,0XFF,526336,65536000
    3,0X0,0XFE,0XFF,0XFF,0XC,0XFE,0XFF,0XFF,66062336,65536000
    4,0X0,0XFE,0XFF,0XFF,0XF,0XFE,0XFF,0XFF,131598336,118138880
    
    Partion 1
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 4
    clusterCount:      129024
    freeClusterCount:  129020
    fatStartSector:    8222
    dataStartSector:   10240
    ------------------------------- 
     
    Partion 2
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 32
    clusterCount:      2046976
    freeClusterCount:  2046973
    fatStartSector:    527118
    dataStartSector:   559104
    ------------------------------- 
     
    Partion 3
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 32
    clusterCount:      2046976
    freeClusterCount:  2046973
    fatStartSector:    66063118
    dataStartSector:   66095104
    ------------------------------- 
     
    Partion 4
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    --------------------------
    Here is the sketch if you want to play:
    Code:
    /*
     * This program attempts to initialize an SD card and analyze its structure.
     */
    #include "SdFat.h"
    #include "sdios.h"
    /*
      Set DISABLE_CS_PIN to disable a second SPI device.
      For example, with the Ethernet shield, set DISABLE_CS_PIN
      to 10 to disable the Ethernet controller.
    */
    const int8_t DISABLE_CS_PIN = -1;
    /*
      Change the value of SD_CS_PIN if you are using SPI
      and your hardware does not use the default value, SS.
      Common values are:
      Arduino Ethernet shield: pin 4
      Sparkfun SD shield: pin 8
      Adafruit SD shields and modules: pin 10
    */
    // SDCARD_SS_PIN is defined for the built-in SD on some boards.
    #ifndef SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SS;
    #else  // SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
    #endif  // SDCARD_SS_PIN
    
    // Try to select the best SD card configuration.
    #if HAS_SDIO_CLASS
    #define SD_CONFIG SdioConfig(FIFO_SDIO)
    #elif ENABLE_DEDICATED_SPI
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
    #else  // HAS_SDIO_CLASS
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
    #endif  // HAS_SDIO_CLASS
    
    //------------------------------------------------------------------------------
    SdFs sd;
    cid_t m_cid;
    csd_t m_csd;
    uint32_t m_eraseSize;
    uint32_t m_ocr;
    static ArduinoOutStream cout(Serial);
    
    FatPartition Part[4];
    
    //------------------------------------------------------------------------------
    bool cidDmp() {
      cout << F("\nManufacturer ID: ");
      cout << uppercase << showbase << hex << int(m_cid.mid) << dec << endl;
      cout << F("OEM ID: ") << m_cid.oid[0] << m_cid.oid[1] << endl;
      cout << F("Product: ");
      for (uint8_t i = 0; i < 5; i++) {
        cout << m_cid.pnm[i];
      }
      cout << F("\nVersion: ");
      cout << int(m_cid.prv_n) << '.' << int(m_cid.prv_m) << endl;
      cout << F("Serial number: ") << hex << m_cid.psn << dec << endl;
      cout << F("Manufacturing date: ");
      cout << int(m_cid.mdt_month) << '/';
      cout << (2000 + m_cid.mdt_year_low + 10 * m_cid.mdt_year_high) << endl;
      cout << endl;
      return true;
    }
    //------------------------------------------------------------------------------
    void clearSerialInput() {
      uint32_t m = micros();
      do {
        if (Serial.read() >= 0) {
          m = micros();
        }
      } while (micros() - m < 10000);
    }
    //------------------------------------------------------------------------------
    bool csdDmp() {
      bool eraseSingleBlock;
      if (m_csd.v1.csd_ver == 0) {
        eraseSingleBlock = m_csd.v1.erase_blk_en;
        m_eraseSize = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low;
      } else if (m_csd.v2.csd_ver == 1) {
        eraseSingleBlock = m_csd.v2.erase_blk_en;
        m_eraseSize = (m_csd.v2.sector_size_high << 1) | m_csd.v2.sector_size_low;
      } else {
        cout << F("m_csd version error\n");
        return false;
      }
      m_eraseSize++;
      cout << F("cardSize: ") << 0.000512 * sdCardCapacity(&m_csd);
      cout << F(" MB (MB = 1,000,000 bytes)\n");
    
      cout << F("flashEraseSize: ") << int(m_eraseSize) << F(" blocks\n");
      cout << F("eraseSingleBlock: ");
      if (eraseSingleBlock) {
        cout << F("true\n");
      } else {
        cout << F("false\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void errorPrint() {
      if (sd.sdErrorCode()) {
        cout << F("SD errorCode: ") << hex << showbase;
        printSdErrorSymbol(&Serial, sd.sdErrorCode());
        cout << F(" = ") << int(sd.sdErrorCode()) << endl;
        cout << F("SD errorData = ") << int(sd.sdErrorData()) << endl;
      }
    }
    //------------------------------------------------------------------------------
    bool mbrDmp() {
      MbrSector_t mbr;
      bool valid = true;
      if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
        cout << F("\nread MBR failed.\n");
        errorPrint();
        return false;
      }
      cout << F("\nSD Partition Table\n");
      cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");
      for (uint8_t ip = 1; ip < 5; ip++) {
        MbrPart_t *pt = &mbr.part[ip - 1];
        if ((pt->boot != 0 && pt->boot != 0X80) ||
            getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
          valid = false;
        }
        cout << int(ip) << ',' << uppercase << showbase << hex;
        cout << int(pt->boot) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->beginCHS[i]) << ',';
        }
        cout << int(pt->type) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->endCHS[i]) << ',';
        }
        cout << dec << getLe32(pt->relativeSectors) << ',';
        cout << getLe32(pt->totalSectors) << endl;
      }
      if (!valid) {
        cout << F("\nMBR not valid, assuming Super Floppy format.\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void dmpVol(uint8_t i) {
      cout << F("\nScanning FAT, please wait.\n");
      uint32_t freeClusterCount = Part[i].freeClusterCount();
      if (Part[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(Part[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(Part[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << Part[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << Part[i].fatStartSector() << endl;
      cout << F("dataStartSector:   ") << Part[i].dataStartSector() << endl;
      if (Part[i+1].dataStartSector() % m_eraseSize) {
        cout << F("Data area is not aligned on flash erase boundary!\n");
        cout << F("Download and use formatter from www.sdcard.org!\n");
      }
    }
    //------------------------------------------------------------------------------
    void printCardType() {
    
      cout << F("\nCard type: ");
    
      switch (sd.card()->type()) {
        case SD_CARD_TYPE_SD1:
          cout << F("SD1\n");
          break;
    
        case SD_CARD_TYPE_SD2:
          cout << F("SD2\n");
          break;
    
        case SD_CARD_TYPE_SDHC:
          if (sdCardCapacity(&m_csd) < 70000000) {
            cout << F("SDHC\n");
          } else {
            cout << F("SDXC\n");
          }
          break;
    
        default:
          cout << F("Unknown\n");
      }
    }
    //------------------------------------------------------------------------------
    void printConfig(SdSpiConfig config) {
      if (DISABLE_CS_PIN < 0) {
        cout << F(
               "\nAssuming the SD is the only SPI device.\n"
               "Edit DISABLE_CS_PIN to disable an SPI device.\n");
      } else {
        cout << F("\nDisabling SPI device on pin ");
        cout << int(DISABLE_CS_PIN) << endl;
        pinMode(DISABLE_CS_PIN, OUTPUT);
        digitalWrite(DISABLE_CS_PIN, HIGH);
      }
      cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
      cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
    }
    //------------------------------------------------------------------------------
    void printConfig(SdioConfig config) {
      (void)config;
      cout << F("Assuming an SDIO interface.\n");
    }
    //-----------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      // Wait for USB Serial
      while (!Serial) {
        SysCall::yield();
      }
      cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
      printConfig(SD_CONFIG);
    
    }
    //------------------------------------------------------------------------------
    void loop() {
      // Read any existing Serial data.
      clearSerialInput();
    
      // F stores strings in flash to save RAM
      cout << F("\ntype any character to start\n");
      while (!Serial.available()) {
        SysCall::yield();
      }
      uint32_t t = millis();
      if (!sd.cardBegin(SD_CONFIG)) {
        cout << F(
               "\nSD initialization failed.\n"
               "Do not reformat the card!\n"
               "Is the card correctly inserted?\n"
               "Is there a wiring/soldering problem?\n");
        if (isSpi(SD_CONFIG)) {
          cout << F(
               "Is SD_CS_PIN set to the correct value?\n"
               "Does another SPI device need to be disabled?\n"
               );
        }
        errorPrint();
        return;
      }
      t = millis() - t;
      cout << F("init time: ") << t << " ms" << endl;
    
      if (!sd.card()->readCID(&m_cid) ||
          !sd.card()->readCSD(&m_csd) ||
          !sd.card()->readOCR(&m_ocr)) {
        cout << F("readInfo failed\n");
        errorPrint();
        return;
      }
      printCardType();
      cidDmp();
      csdDmp();
      cout << F("\nOCR: ") << uppercase << showbase;
      cout << hex << m_ocr << dec << endl;
      if (!mbrDmp()) {
        return;
      }
      if (!sd.volumeBegin()) {
        cout << F("\nvolumeBegin failed. Is the card formatted?\n");
        errorPrint();
        return;
      }
      for(uint8_t i = 0; i <4; i++){
        cout << F("\nPartion ") << (int) i+1 << F("\n");
        Part[i].init(sd.card(), (int) i+1);
        dmpVol(i);
        cout << F("------------------------------- \n ");
      }
    }

  14. #414
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    426
    Quote Originally Posted by mjs513 View Post
    Thanks - the dummy that I am. So with that ran it but I created 4 volumes 3 are FAT32 and 1 is exFAT. This is running the SDInfo without Partition info set up:
    Code:
    SdFat version: 2.0.5-beta.1
    Assuming an SDIO interface.
    
    type any character to start
    init time: 21 ms
    
    Card type: SDXC
    
    Manufacturer ID: 0X3
    OEM ID: SD
    Product: SN128
    Version: 8.0
    Serial number: 0X17DCCFC4
    Manufacturing date: 7/2014
    
    cardSize: 127865.45 MB (MB = 1,000,000 bytes)
    flashEraseSize: 128 blocks
    eraseSingleBlock: true
    
    OCR: 0XC0FF8000
    
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X80,0X20,0X21,0X0,0XC,0XC2,0X22,0X20,2048,524288
    2,0X0,0XC2,0X23,0X20,0XC,0XFE,0XFF,0XFF,526336,65536000
    3,0X0,0XFE,0XFF,0XFF,0XC,0XFE,0XFF,0XFF,66062336,65536000
    4,0X0,0XFE,0XFF,0XFF,0XF,0XFE,0XFF,0XFF,131598336,118138880
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 4
    clusterCount:      129024
    freeClusterCount:  129020
    fatStartSector:    8222
    dataStartSector:   10240
    Here is running through the 4 partitions (partition 4 is exFat):
    Code:
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X80,0X20,0X21,0X0,0XC,0XC2,0X22,0X20,2048,524288
    2,0X0,0XC2,0X23,0X20,0XC,0XFE,0XFF,0XFF,526336,65536000
    3,0X0,0XFE,0XFF,0XFF,0XC,0XFE,0XFF,0XFF,66062336,65536000
    4,0X0,0XFE,0XFF,0XFF,0XF,0XFE,0XFF,0XFF,131598336,118138880
    
    Partion 1
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 4
    clusterCount:      129024
    freeClusterCount:  129020
    fatStartSector:    8222
    dataStartSector:   10240
    ------------------------------- 
     
    Partion 2
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 32
    clusterCount:      2046976
    freeClusterCount:  2046973
    fatStartSector:    527118
    dataStartSector:   559104
    ------------------------------- 
     
    Partion 3
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 32
    clusterCount:      2046976
    freeClusterCount:  2046973
    fatStartSector:    66063118
    dataStartSector:   66095104
    ------------------------------- 
     
    Partion 4
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    --------------------------
    Here is the sketch if you want to play:
    Code:
    /*
     * This program attempts to initialize an SD card and analyze its structure.
     */
    #include "SdFat.h"
    #include "sdios.h"
    /*
      Set DISABLE_CS_PIN to disable a second SPI device.
      For example, with the Ethernet shield, set DISABLE_CS_PIN
      to 10 to disable the Ethernet controller.
    */
    const int8_t DISABLE_CS_PIN = -1;
    /*
      Change the value of SD_CS_PIN if you are using SPI
      and your hardware does not use the default value, SS.
      Common values are:
      Arduino Ethernet shield: pin 4
      Sparkfun SD shield: pin 8
      Adafruit SD shields and modules: pin 10
    */
    // SDCARD_SS_PIN is defined for the built-in SD on some boards.
    #ifndef SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SS;
    #else  // SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
    #endif  // SDCARD_SS_PIN
    
    // Try to select the best SD card configuration.
    #if HAS_SDIO_CLASS
    #define SD_CONFIG SdioConfig(FIFO_SDIO)
    #elif ENABLE_DEDICATED_SPI
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
    #else  // HAS_SDIO_CLASS
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
    #endif  // HAS_SDIO_CLASS
    
    //------------------------------------------------------------------------------
    SdFs sd;
    cid_t m_cid;
    csd_t m_csd;
    uint32_t m_eraseSize;
    uint32_t m_ocr;
    static ArduinoOutStream cout(Serial);
    
    FatPartition Part[4];
    
    //------------------------------------------------------------------------------
    bool cidDmp() {
      cout << F("\nManufacturer ID: ");
      cout << uppercase << showbase << hex << int(m_cid.mid) << dec << endl;
      cout << F("OEM ID: ") << m_cid.oid[0] << m_cid.oid[1] << endl;
      cout << F("Product: ");
      for (uint8_t i = 0; i < 5; i++) {
        cout << m_cid.pnm[i];
      }
      cout << F("\nVersion: ");
      cout << int(m_cid.prv_n) << '.' << int(m_cid.prv_m) << endl;
      cout << F("Serial number: ") << hex << m_cid.psn << dec << endl;
      cout << F("Manufacturing date: ");
      cout << int(m_cid.mdt_month) << '/';
      cout << (2000 + m_cid.mdt_year_low + 10 * m_cid.mdt_year_high) << endl;
      cout << endl;
      return true;
    }
    //------------------------------------------------------------------------------
    void clearSerialInput() {
      uint32_t m = micros();
      do {
        if (Serial.read() >= 0) {
          m = micros();
        }
      } while (micros() - m < 10000);
    }
    //------------------------------------------------------------------------------
    bool csdDmp() {
      bool eraseSingleBlock;
      if (m_csd.v1.csd_ver == 0) {
        eraseSingleBlock = m_csd.v1.erase_blk_en;
        m_eraseSize = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low;
      } else if (m_csd.v2.csd_ver == 1) {
        eraseSingleBlock = m_csd.v2.erase_blk_en;
        m_eraseSize = (m_csd.v2.sector_size_high << 1) | m_csd.v2.sector_size_low;
      } else {
        cout << F("m_csd version error\n");
        return false;
      }
      m_eraseSize++;
      cout << F("cardSize: ") << 0.000512 * sdCardCapacity(&m_csd);
      cout << F(" MB (MB = 1,000,000 bytes)\n");
    
      cout << F("flashEraseSize: ") << int(m_eraseSize) << F(" blocks\n");
      cout << F("eraseSingleBlock: ");
      if (eraseSingleBlock) {
        cout << F("true\n");
      } else {
        cout << F("false\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void errorPrint() {
      if (sd.sdErrorCode()) {
        cout << F("SD errorCode: ") << hex << showbase;
        printSdErrorSymbol(&Serial, sd.sdErrorCode());
        cout << F(" = ") << int(sd.sdErrorCode()) << endl;
        cout << F("SD errorData = ") << int(sd.sdErrorData()) << endl;
      }
    }
    //------------------------------------------------------------------------------
    bool mbrDmp() {
      MbrSector_t mbr;
      bool valid = true;
      if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
        cout << F("\nread MBR failed.\n");
        errorPrint();
        return false;
      }
      cout << F("\nSD Partition Table\n");
      cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");
      for (uint8_t ip = 1; ip < 5; ip++) {
        MbrPart_t *pt = &mbr.part[ip - 1];
        if ((pt->boot != 0 && pt->boot != 0X80) ||
            getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
          valid = false;
        }
        cout << int(ip) << ',' << uppercase << showbase << hex;
        cout << int(pt->boot) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->beginCHS[i]) << ',';
        }
        cout << int(pt->type) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->endCHS[i]) << ',';
        }
        cout << dec << getLe32(pt->relativeSectors) << ',';
        cout << getLe32(pt->totalSectors) << endl;
      }
      if (!valid) {
        cout << F("\nMBR not valid, assuming Super Floppy format.\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void dmpVol(uint8_t i) {
      cout << F("\nScanning FAT, please wait.\n");
      uint32_t freeClusterCount = Part[i].freeClusterCount();
      if (Part[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(Part[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(Part[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << Part[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << Part[i].fatStartSector() << endl;
      cout << F("dataStartSector:   ") << Part[i].dataStartSector() << endl;
      if (Part[i+1].dataStartSector() % m_eraseSize) {
        cout << F("Data area is not aligned on flash erase boundary!\n");
        cout << F("Download and use formatter from www.sdcard.org!\n");
      }
    }
    //------------------------------------------------------------------------------
    void printCardType() {
    
      cout << F("\nCard type: ");
    
      switch (sd.card()->type()) {
        case SD_CARD_TYPE_SD1:
          cout << F("SD1\n");
          break;
    
        case SD_CARD_TYPE_SD2:
          cout << F("SD2\n");
          break;
    
        case SD_CARD_TYPE_SDHC:
          if (sdCardCapacity(&m_csd) < 70000000) {
            cout << F("SDHC\n");
          } else {
            cout << F("SDXC\n");
          }
          break;
    
        default:
          cout << F("Unknown\n");
      }
    }
    //------------------------------------------------------------------------------
    void printConfig(SdSpiConfig config) {
      if (DISABLE_CS_PIN < 0) {
        cout << F(
               "\nAssuming the SD is the only SPI device.\n"
               "Edit DISABLE_CS_PIN to disable an SPI device.\n");
      } else {
        cout << F("\nDisabling SPI device on pin ");
        cout << int(DISABLE_CS_PIN) << endl;
        pinMode(DISABLE_CS_PIN, OUTPUT);
        digitalWrite(DISABLE_CS_PIN, HIGH);
      }
      cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
      cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
    }
    //------------------------------------------------------------------------------
    void printConfig(SdioConfig config) {
      (void)config;
      cout << F("Assuming an SDIO interface.\n");
    }
    //-----------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      // Wait for USB Serial
      while (!Serial) {
        SysCall::yield();
      }
      cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
      printConfig(SD_CONFIG);
    
    }
    //------------------------------------------------------------------------------
    void loop() {
      // Read any existing Serial data.
      clearSerialInput();
    
      // F stores strings in flash to save RAM
      cout << F("\ntype any character to start\n");
      while (!Serial.available()) {
        SysCall::yield();
      }
      uint32_t t = millis();
      if (!sd.cardBegin(SD_CONFIG)) {
        cout << F(
               "\nSD initialization failed.\n"
               "Do not reformat the card!\n"
               "Is the card correctly inserted?\n"
               "Is there a wiring/soldering problem?\n");
        if (isSpi(SD_CONFIG)) {
          cout << F(
               "Is SD_CS_PIN set to the correct value?\n"
               "Does another SPI device need to be disabled?\n"
               );
        }
        errorPrint();
        return;
      }
      t = millis() - t;
      cout << F("init time: ") << t << " ms" << endl;
    
      if (!sd.card()->readCID(&m_cid) ||
          !sd.card()->readCSD(&m_csd) ||
          !sd.card()->readOCR(&m_ocr)) {
        cout << F("readInfo failed\n");
        errorPrint();
        return;
      }
      printCardType();
      cidDmp();
      csdDmp();
      cout << F("\nOCR: ") << uppercase << showbase;
      cout << hex << m_ocr << dec << endl;
      if (!mbrDmp()) {
        return;
      }
      if (!sd.volumeBegin()) {
        cout << F("\nvolumeBegin failed. Is the card formatted?\n");
        errorPrint();
        return;
      }
      for(uint8_t i = 0; i <4; i++){
        cout << F("\nPartion ") << (int) i+1 << F("\n");
        Part[i].init(sd.card(), (int) i+1);
        dmpVol(i);
        cout << F("------------------------------- \n ");
      }
    }
    Thanks @mjs513 - I most certainly want to play

    I just finished up the last of my honey do's and got my wife off to work. You guys amaze me with how fast you can figure out this stuff and program.

    Anyway, I have a little bit of time to play before dinner and zzzzz's.

    Thanks again
    Last edited by wwatson; 02-21-2021 at 10:24 PM. Reason: You know:)

  15. #415
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    426
    @mjs13 - I modified the sketch to show info about the ExFat partition. ExFat is treated differently than Fat32. With the sketch you provided partition 4 was showing this:
    Code:
    Partition 4
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    --------------------------
    Which is is not being recognized by:
    Code:
    FatPartition Part[4];
    For ExFat partitions you need to use:
    Code:
    ExFatPartition ExPart[4];
    Also:
    Code:
    dataStartSector()
    Is not used with ExFat This I discovered when I was trying get the volume name from an ExFat formatted volume. ExFat works differently than Fat32 in a lot of ways.

    I modified the sketch (shown in red):
    Code:
    /*
     * This program attempts to initialize an SD card and analyze its structure.
     */
    #include "SdFat.h"
    #include "sdios.h"
    /*
      Set DISABLE_CS_PIN to disable a second SPI device.
      For example, with the Ethernet shield, set DISABLE_CS_PIN
      to 10 to disable the Ethernet controller.
    */
    const int8_t DISABLE_CS_PIN = -1;
    /*
      Change the value of SD_CS_PIN if you are using SPI
      and your hardware does not use the default value, SS.
      Common values are:
      Arduino Ethernet shield: pin 4
      Sparkfun SD shield: pin 8
      Adafruit SD shields and modules: pin 10
    */
    // SDCARD_SS_PIN is defined for the built-in SD on some boards.
    #ifndef SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SS;
    #else  // SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
    #endif  // SDCARD_SS_PIN
    
    // Try to select the best SD card configuration.
    #if HAS_SDIO_CLASS
    #define SD_CONFIG SdioConfig(FIFO_SDIO)
    #elif ENABLE_DEDICATED_SPI
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
    #else  // HAS_SDIO_CLASS
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
    #endif  // HAS_SDIO_CLASS
    
    //------------------------------------------------------------------------------
    SdFs sd;
    cid_t m_cid;
    csd_t m_csd;
    uint32_t m_eraseSize;
    uint32_t m_ocr;
    static ArduinoOutStream cout(Serial);
    
    FatPartition Part[4];
    ExFatPartition ExPart[4];
    
    //------------------------------------------------------------------------------
    bool cidDmp() {
      cout << F("\nManufacturer ID: ");
      cout << uppercase << showbase << hex << int(m_cid.mid) << dec << endl;
      cout << F("OEM ID: ") << m_cid.oid[0] << m_cid.oid[1] << endl;
      cout << F("Product: ");
      for (uint8_t i = 0; i < 5; i++) {
        cout << m_cid.pnm[i];
      }
      cout << F("\nVersion: ");
      cout << int(m_cid.prv_n) << '.' << int(m_cid.prv_m) << endl;
      cout << F("Serial number: ") << hex << m_cid.psn << dec << endl;
      cout << F("Manufacturing date: ");
      cout << int(m_cid.mdt_month) << '/';
      cout << (2000 + m_cid.mdt_year_low + 10 * m_cid.mdt_year_high) << endl;
      cout << endl;
      return true;
    }
    //------------------------------------------------------------------------------
    void clearSerialInput() {
      uint32_t m = micros();
      do {
        if (Serial.read() >= 0) {
          m = micros();
        }
      } while (micros() - m < 10000);
    }
    //------------------------------------------------------------------------------
    bool csdDmp() {
      bool eraseSingleBlock;
      if (m_csd.v1.csd_ver == 0) {
        eraseSingleBlock = m_csd.v1.erase_blk_en;
        m_eraseSize = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low;
      } else if (m_csd.v2.csd_ver == 1) {
        eraseSingleBlock = m_csd.v2.erase_blk_en;
        m_eraseSize = (m_csd.v2.sector_size_high << 1) | m_csd.v2.sector_size_low;
      } else {
        cout << F("m_csd version error\n");
        return false;
      }
      m_eraseSize++;
      cout << F("cardSize: ") << 0.000512 * sdCardCapacity(&m_csd);
      cout << F(" MB (MB = 1,000,000 bytes)\n");
    
      cout << F("flashEraseSize: ") << int(m_eraseSize) << F(" blocks\n");
      cout << F("eraseSingleBlock: ");
      if (eraseSingleBlock) {
        cout << F("true\n");
      } else {
        cout << F("false\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void errorPrint() {
      if (sd.sdErrorCode()) {
        cout << F("SD errorCode: ") << hex << showbase;
        printSdErrorSymbol(&Serial, sd.sdErrorCode());
        cout << F(" = ") << int(sd.sdErrorCode()) << endl;
        cout << F("SD errorData = ") << int(sd.sdErrorData()) << endl;
      }
    }
    //------------------------------------------------------------------------------
    bool mbrDmp() {
      MbrSector_t mbr;
      bool valid = true;
      if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
        cout << F("\nread MBR failed.\n");
        errorPrint();
        return false;
      }
      cout << F("\nSD Partition Table\n");
      cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");
      for (uint8_t ip = 1; ip < 5; ip++) {
        MbrPart_t *pt = &mbr.part[ip - 1];
        if ((pt->boot != 0 && pt->boot != 0X80) ||
            getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
          valid = false;
        }
        cout << int(ip) << ',' << uppercase << showbase << hex;
        cout << int(pt->boot) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->beginCHS[i]) << ',';
        }
        cout << int(pt->type) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->endCHS[i]) << ',';
        }
        cout << dec << getLe32(pt->relativeSectors) << ',';
        cout << getLe32(pt->totalSectors) << endl;
      }
      if (!valid) {
        cout << F("\nMBR not valid, assuming Super Floppy format.\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void dmpVol(uint8_t i) {
      cout << F("\nScanning FAT, please wait.\n");
      uint32_t freeClusterCount = Part[i].freeClusterCount();
      if (Part[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(Part[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(Part[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << Part[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << Part[i].fatStartSector() << endl;
      cout << F("dataStartSector:   ") << Part[i].dataStartSector() << endl;
      if (Part[i+1].dataStartSector() % m_eraseSize) {
        cout << F("Data area is not aligned on flash erase boundary!\n");
        cout << F("Download and use formatter from www.sdcard.org!\n");
      }
    }
    //------------------------------------------------------------------------------
    void dmpExVol(uint8_t i) {
      cout << F("\nScanning FAT, please wait.\n");
      uint32_t freeClusterCount = Part[i].freeClusterCount();
      if (ExPart[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(ExPart[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(ExPart[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << ExPart[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << ExPart[i].fatStartSector() << endl;
    //  cout << F("dataStartSector:   ") << ExPart[i].dataStartSector() << endl;
    //  if (ExPart[i+1].dataStartSector() % m_eraseSize) {
    //    cout << F("Data area is not aligned on flash erase boundary!\n");
    //    cout << F("Download and use formatter from www.sdcard.org!\n");
    //  }
    }
    //------------------------------------------------------------------------------
    void printCardType() {
    
      cout << F("\nCard type: ");
    
      switch (sd.card()->type()) {
        case SD_CARD_TYPE_SD1:
          cout << F("SD1\n");
          break;
    
        case SD_CARD_TYPE_SD2:
          cout << F("SD2\n");
          break;
    
        case SD_CARD_TYPE_SDHC:
          if (sdCardCapacity(&m_csd) < 70000000) {
            cout << F("SDHC\n");
          } else {
            cout << F("SDXC\n");
          }
          break;
    
        default:
          cout << F("Unknown\n");
      }
    }
    //------------------------------------------------------------------------------
    void printConfig(SdSpiConfig config) {
      if (DISABLE_CS_PIN < 0) {
        cout << F(
               "\nAssuming the SD is the only SPI device.\n"
               "Edit DISABLE_CS_PIN to disable an SPI device.\n");
      } else {
        cout << F("\nDisabling SPI device on pin ");
        cout << int(DISABLE_CS_PIN) << endl;
        pinMode(DISABLE_CS_PIN, OUTPUT);
        digitalWrite(DISABLE_CS_PIN, HIGH);
      }
      cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
      cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
    }
    //------------------------------------------------------------------------------
    void printConfig(SdioConfig config) {
      (void)config;
      cout << F("Assuming an SDIO interface.\n");
    }
    //-----------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      // Wait for USB Serial
      while (!Serial) {
        SysCall::yield();
      }
      cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
      printConfig(SD_CONFIG);
    
    }
    //------------------------------------------------------------------------------
    void loop() {
      // Read any existing Serial data.
      clearSerialInput();
    
      // F stores strings in flash to save RAM
      cout << F("\ntype any character to start\n");
      while (!Serial.available()) {
        SysCall::yield();
      }
      uint32_t t = millis();
      if (!sd.cardBegin(SD_CONFIG)) {
        cout << F(
               "\nSD initialization failed.\n"
               "Do not reformat the card!\n"
               "Is the card correctly inserted?\n"
               "Is there a wiring/soldering problem?\n");
        if (isSpi(SD_CONFIG)) {
          cout << F(
               "Is SD_CS_PIN set to the correct value?\n"
               "Does another SPI device need to be disabled?\n"
               );
        }
        errorPrint();
        return;
      }
      t = millis() - t;
      cout << F("init time: ") << t << " ms" << endl;
    
      if (!sd.card()->readCID(&m_cid) ||
          !sd.card()->readCSD(&m_csd) ||
          !sd.card()->readOCR(&m_ocr)) {
        cout << F("readInfo failed\n");
        errorPrint();
        return;
      }
      printCardType();
      cidDmp();
      csdDmp();
      cout << F("\nOCR: ") << uppercase << showbase;
      cout << hex << m_ocr << dec << endl;
      if (!mbrDmp()) {
        return;
      }
      if (!sd.volumeBegin()) {
        cout << F("\nvolumeBegin failed. Is the card formatted?\n");
        errorPrint();
        return;
      }
      for(uint8_t i = 0; i <4; i++){
        cout << F("\nPartion ") << (int) i+1 << F("\n");
        if(i == 3) {
    		ExPart[i].init(sd.card(), (int) i+1);
    		dmpExVol(i);
    	} else {
    		Part[i].init(sd.card(), (int) i+1);
    		dmpVol(i);
    	}
        cout << F("------------------------------- \n ");
      }
    }
    Shows this for partition 4:
    Code:
    Partion 4
    
    Scanning FAT, please wait.
    
    Volume is exFAT
    sectorsPerCluster: 64
    clusterCount:      222722
    freeClusterCount:  4294967295
    fatStartSector:    46835840
    -------------------------------
    :
    Last edited by wwatson; 02-21-2021 at 11:57 PM. Reason: Typo's

  16. #416
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    @wwatson
    Thanks for the changes will play more with it tomorrow. May try to do a list files but intent really was to see if and how to get access via sdfat. But the use of sd.card was the key

  17. #417
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    426
    Quote Originally Posted by mjs513 View Post
    @wwatson
    Thanks for the changes will play more with it tomorrow. May try to do a list files but intent really was to see if and how to get access via sdfat. But the use of sd.card was the key
    You are welcome. I want to do the same with MSC and UbFat.During the week I do not have much time to play with this but with taxes being done next weekend is MINE

  18. #418
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    Taxes - yep - already did mine.

    Anyway get the volume directory was relative easy.
    Code:
    SdFat version: 2.0.5-beta.1
    Assuming an SDIO interface.
    
    type any character to start
    init time: 22 ms
    
    Card type: SDXC
    
    Manufacturer ID: 0X3
    OEM ID: SD
    Product: SN128
    Version: 8.0
    Serial number: 0X17DCCFC4
    Manufacturing date: 7/2014
    
    cardSize: 127865.45 MB (MB = 1,000,000 bytes)
    flashEraseSize: 128 blocks
    eraseSingleBlock: true
    
    OCR: 0XC0FF8000
    
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X80,0X20,0X21,0X0,0XC,0XC2,0X22,0X20,2048,524288
    2,0X0,0XC2,0X23,0X20,0XC,0XFE,0XFF,0XFF,526336,65536000
    3,0X0,0XFE,0XFF,0XFF,0XC,0XFE,0XFF,0XFF,66062336,65536000
    4,0X0,0XFE,0XFF,0XFF,0XF,0XFE,0XFF,0XFF,131598336,118138880
    swampy.pdf
    The-Design-and-Implementation-of-a-Robust-AHRS-for-Implementation-on-a-Quadrotor.pdf
    
    Partion 1
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 4
    clusterCount:      129024
    freeClusterCount:  124192
    fatStartSector:    8222
    dataStartSector:   10240
    
    Volume Directory:      
    swampy.pdf
    The-Design-and-Implementation-of-a-Robust-AHRS-for-Implementation-on-a-Quadrotor.pdf
    ------------------------------- 
     
    Partion 2
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 32
    clusterCount:      2046976
    freeClusterCount:  2046882
    fatStartSector:    527118
    dataStartSector:   559104
    
    Volume Directory:      
    Visio-driver.pdf
    ------------------------------- 
     
    Partion 3
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 32
    clusterCount:      2046976
    freeClusterCount:  2046622
    fatStartSector:    66063118
    dataStartSector:   66095104
    
    Volume Directory:      
    VSLAM_and_Navigation_System_of_Unmanned_Ground_Vehicle_Based_on_RGB-D_Camera.pdf
    ------------------------------- 
     
    Partion 4
    
    Scanning exFAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 1
    clusterCount:      0
    freeClusterCount:  4294967290
    fatStartSector:    0
    
    Volume Directory:      
    ------------------------------- 
     
    type any character to start
    Still having problems with that exFat directory.

    Code:
    /*
     * This program attempts to initialize an SD card and analyze its structure.
     */
    #include "SdFat.h"
    #include "sdios.h"
    /*
      Set DISABLE_CS_PIN to disable a second SPI device.
      For example, with the Ethernet shield, set DISABLE_CS_PIN
      to 10 to disable the Ethernet controller.
    */
    const int8_t DISABLE_CS_PIN = -1;
    /*
      Change the value of SD_CS_PIN if you are using SPI
      and your hardware does not use the default value, SS.
      Common values are:
      Arduino Ethernet shield: pin 4
      Sparkfun SD shield: pin 8
      Adafruit SD shields and modules: pin 10
    */
    // SDCARD_SS_PIN is defined for the built-in SD on some boards.
    #ifndef SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SS;
    #else  // SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
    #endif  // SDCARD_SS_PIN
    
    // Try to select the best SD card configuration.
    #if HAS_SDIO_CLASS
    #define SD_CONFIG SdioConfig(FIFO_SDIO)
    #elif ENABLE_DEDICATED_SPI
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
    #else  // HAS_SDIO_CLASS
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
    #endif  // HAS_SDIO_CLASS
    
    //------------------------------------------------------------------------------
    SdFs sd;
    cid_t m_cid;
    csd_t m_csd;
    uint32_t m_eraseSize;
    uint32_t m_ocr;
    static ArduinoOutStream cout(Serial);
    
    FatPartition Part[4];
    ExFatPartition ExPart[4];
    FatVolume partVol;
    ExFatVolume expartVol;
    
    //------------------------------------------------------------------------------
    bool cidDmp() {
      cout << F("\nManufacturer ID: ");
      cout << uppercase << showbase << hex << int(m_cid.mid) << dec << endl;
      cout << F("OEM ID: ") << m_cid.oid[0] << m_cid.oid[1] << endl;
      cout << F("Product: ");
      for (uint8_t i = 0; i < 5; i++) {
        cout << m_cid.pnm[i];
      }
      cout << F("\nVersion: ");
      cout << int(m_cid.prv_n) << '.' << int(m_cid.prv_m) << endl;
      cout << F("Serial number: ") << hex << m_cid.psn << dec << endl;
      cout << F("Manufacturing date: ");
      cout << int(m_cid.mdt_month) << '/';
      cout << (2000 + m_cid.mdt_year_low + 10 * m_cid.mdt_year_high) << endl;
      cout << endl;
      return true;
    }
    //------------------------------------------------------------------------------
    void clearSerialInput() {
      uint32_t m = micros();
      do {
        if (Serial.read() >= 0) {
          m = micros();
        }
      } while (micros() - m < 10000);
    }
    //------------------------------------------------------------------------------
    bool csdDmp() {
      bool eraseSingleBlock;
      if (m_csd.v1.csd_ver == 0) {
        eraseSingleBlock = m_csd.v1.erase_blk_en;
        m_eraseSize = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low;
      } else if (m_csd.v2.csd_ver == 1) {
        eraseSingleBlock = m_csd.v2.erase_blk_en;
        m_eraseSize = (m_csd.v2.sector_size_high << 1) | m_csd.v2.sector_size_low;
      } else {
        cout << F("m_csd version error\n");
        return false;
      }
      m_eraseSize++;
      cout << F("cardSize: ") << 0.000512 * sdCardCapacity(&m_csd);
      cout << F(" MB (MB = 1,000,000 bytes)\n");
    
      cout << F("flashEraseSize: ") << int(m_eraseSize) << F(" blocks\n");
      cout << F("eraseSingleBlock: ");
      if (eraseSingleBlock) {
        cout << F("true\n");
      } else {
        cout << F("false\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void errorPrint() {
      if (sd.sdErrorCode()) {
        cout << F("SD errorCode: ") << hex << showbase;
        printSdErrorSymbol(&Serial, sd.sdErrorCode());
        cout << F(" = ") << int(sd.sdErrorCode()) << endl;
        cout << F("SD errorData = ") << int(sd.sdErrorData()) << endl;
      }
    }
    //------------------------------------------------------------------------------
    bool mbrDmp() {
      MbrSector_t mbr;
      bool valid = true;
      if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
        cout << F("\nread MBR failed.\n");
        errorPrint();
        return false;
      }
      cout << F("\nSD Partition Table\n");
      cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");
      for (uint8_t ip = 1; ip < 5; ip++) {
        MbrPart_t *pt = &mbr.part[ip - 1];
        if ((pt->boot != 0 && pt->boot != 0X80) ||
            getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
          valid = false;
        }
        cout << int(ip) << ',' << uppercase << showbase << hex;
        cout << int(pt->boot) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->beginCHS[i]) << ',';
        }
        cout << int(pt->type) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->endCHS[i]) << ',';
        }
        cout << dec << getLe32(pt->relativeSectors) << ',';
        cout << getLe32(pt->totalSectors) << endl;
      }
      if (!valid) {
        cout << F("\nMBR not valid, assuming Super Floppy format.\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void dmpVol(uint8_t i) {
      cout << F("\nScanning FAT, please wait.\n");
      uint32_t freeClusterCount = Part[i].freeClusterCount();
      if (Part[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(Part[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(Part[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << Part[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << Part[i].fatStartSector() << endl;
      cout << F("dataStartSector:   ") << Part[i].dataStartSector() << endl;
      if (Part[i].dataStartSector() % m_eraseSize) {
        cout << F("Data area is not aligned on flash erase boundary!\n");
        cout << F("Download and use formatter from www.sdcard.org!\n");
      }
    
      cout << F("\nVolume Directory:      ") <<endl;
      partVol.begin(sd.card(), true, i+1);
      partVol.chvol();
      partVol.ls("/", LS_R);
      
      
    }
    //------------------------------------------------------------------------------
    void dmpExVol(uint8_t i) {
      cout << F("\nScanning exFAT, please wait.\n");
      uint32_t freeClusterCount = ExPart[i].freeClusterCount();
      if (Part[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(ExPart[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(ExPart[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << ExPart[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << ExPart[i].fatStartSector() << endl;
    //  cout << F("dataStartSector:   ") << ExPart[i].dataStartSector() << endl;
    //  if (ExPart[i+1].dataStartSector() % m_eraseSize) {
    //    cout << F("Data area is not aligned on flash erase boundary!\n");
    //    cout << F("Download and use formatter from www.sdcard.org!\n");
    //  }
      cout << F("\nVolume Directory:      ") <<endl;
      expartVol.begin(sd.card(), true, i+1);
      expartVol.chvol();
      expartVol.ls("/", LS_R);
    
    }
    //------------------------------------------------------------------------------
    void printCardType() {
    
      cout << F("\nCard type: ");
    
      switch (sd.card()->type()) {
        case SD_CARD_TYPE_SD1:
          cout << F("SD1\n");
          break;
    
        case SD_CARD_TYPE_SD2:
          cout << F("SD2\n");
          break;
    
        case SD_CARD_TYPE_SDHC:
          if (sdCardCapacity(&m_csd) < 70000000) {
            cout << F("SDHC\n");
          } else {
            cout << F("SDXC\n");
          }
          break;
    
        default:
          cout << F("Unknown\n");
      }
    }
    //------------------------------------------------------------------------------
    void printConfig(SdSpiConfig config) {
      if (DISABLE_CS_PIN < 0) {
        cout << F(
               "\nAssuming the SD is the only SPI device.\n"
               "Edit DISABLE_CS_PIN to disable an SPI device.\n");
      } else {
        cout << F("\nDisabling SPI device on pin ");
        cout << int(DISABLE_CS_PIN) << endl;
        pinMode(DISABLE_CS_PIN, OUTPUT);
        digitalWrite(DISABLE_CS_PIN, HIGH);
      }
      cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
      cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
    }
    //------------------------------------------------------------------------------
    void printConfig(SdioConfig config) {
      (void)config;
      cout << F("Assuming an SDIO interface.\n");
    }
    //-----------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      // Wait for USB Serial
      while (!Serial) {
        SysCall::yield();
      }
      cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
      printConfig(SD_CONFIG);
    
    }
    //------------------------------------------------------------------------------
    void loop() {
      // Read any existing Serial data.
      clearSerialInput();
    
      // F stores strings in flash to save RAM
      cout << F("\ntype any character to start\n");
      while (!Serial.available()) {
        SysCall::yield();
      }
      uint32_t t = millis();
      if (!sd.cardBegin(SD_CONFIG)) {
        cout << F(
               "\nSD initialization failed.\n"
               "Do not reformat the card!\n"
               "Is the card correctly inserted?\n"
               "Is there a wiring/soldering problem?\n");
        if (isSpi(SD_CONFIG)) {
          cout << F(
               "Is SD_CS_PIN set to the correct value?\n"
               "Does another SPI device need to be disabled?\n"
               );
        }
        errorPrint();
        return;
      }
      t = millis() - t;
      cout << F("init time: ") << t << " ms" << endl;
    
      if (!sd.card()->readCID(&m_cid) ||
          !sd.card()->readCSD(&m_csd) ||
          !sd.card()->readOCR(&m_ocr)) {
        cout << F("readInfo failed\n");
        errorPrint();
        return;
      }
      printCardType();
      cidDmp();
      csdDmp();
      cout << F("\nOCR: ") << uppercase << showbase;
      cout << hex << m_ocr << dec << endl;
      if (!mbrDmp()) {
        return;
      }
      if (!sd.volumeBegin()) {
        cout << F("\nvolumeBegin failed. Is the card formatted?\n");
        errorPrint();
        return;
      }
      sd.ls("/", LS_R);
      
      for(uint8_t i = 0; i <4; i++){
        cout << F("\nPartion ") << (int) i+1 << F("\n");
        if(i == 3) {
        ExPart[i].init(sd.card(), (int) i+1);
        dmpExVol(i);
      } else {
        Part[i].init(sd.card(), (int) i+1);
        dmpVol(i);
      }
        cout << F("------------------------------- \n ");
      }
    }
    Last edited by mjs513; 02-22-2021 at 11:07 AM. Reason: Corrected sketch and output

  19. #419
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    @mjs513 @wwatson - looks like you are having some fun. Now to figure out how to integrate this with MTP I was happy yesterday to be able to plug in USB drive and it shows up and unplug it and it goes away...
    Now probably need to figure out how volumes fit in.

  20. #420
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    @...

    @mjs513 - tried you sketch above with a few cards. And it looks like it dumps lots of interesting info...

    Tried reformat 32gb SD to exFat. As you mentioned not able to read that data (yet)...

    Side question, wondering how hard it is to get the Volume Label? Will play around some.

    If we can get it also wondering if we should pass that on through to MTP... Currently is is always passing null string:
    writestring(""); // volume identifier

    Now back to more playing!

  21. #421
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    For the fun of it, I thought I would see if I could get it to read an ExFat one...

    I think this one sort of works for it. Probably a real hack, but...

    When you are dumping out the top partition table, I keep the type values:
    Code:
    uint8_t partition_types[4];
    ...
        cout << int(pt->type) << ',';
        ////////////////////////////
        partition_types[ip-1] = pt->type;
    And then when you decide to dump each partition I do:
    Code:
      for (uint8_t i = 0; i < 4; i++) {
        cout << F("\nPartion ") << (int) i + 1 << F("\n");
        ////////////////////////////
        if (partition_types[i] == 7) {
          ExPart[i].init(sd.card(), (int) i + 1);
          dmpExVol(i);
        } else {
          Part[i].init(sd.card(), (int) i + 1);
          dmpVol(i);
        }
        cout << F("------------------------------- \n ");
      }
    As I believe Fat types are like:
    Code:
    6=Fat16
    7=ExFat
    C=Fat32
    Probably others, I think B is an old Fat32...
    Edit: Some of this data from: https://www.win.tue.nl/~aeb/partitio...n_types-1.html

    Here is a ExFat card I setup:
    Code:
    init time: 8 ms
    
    Card type: SDHC
    
    Manufacturer ID: 0X1B
    OEM ID: SM
    Product: GB2MW
    Version: 3.0
    Serial number: 0X275361AC
    Manufacturing date: 7/2011
    
    cardSize: 32026.66 MB (MB = 1,000,000 bytes)
    flashEraseSize: 128 blocks
    eraseSingleBlock: true
    
    OCR: 0XC0FF8000
    
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X0,0X82,0X3,0X0,0X7,0XFE,0XFF,0XFF,8192,62543872
    2,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    3,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    4,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    2021-02-22 06:44        32768 System Volume Information/
      2021-02-22 06:44           12 WPSettings.dat
      2021-02-22 06:44           76 IndexerVolumeGuid
    2021-01-24 06:23       393481 T4.1-Cardlike.jpg
    2021-01-13 17:56       340510 T4-Cardlike.jpg
    2010-03-22 07:11      3373255 DSC03355.JPG
                               21 test1.txt
                                0 mtpindex.dat
    
    Partion 1
    
    Scanning exFAT, please wait.
    
    Volume is FAT64
    sectorsPerCluster: 64
    clusterCount:      977088
    freeClusterCount:  976950
    fatStartSector:    10240
    
    Volume Directory:      
    2021-02-22 06:44        32768 System Volume Information/
      2021-02-22 06:44           12 WPSettings.dat
      2021-02-22 06:44           76 IndexerVolumeGuid
    2021-01-24 06:23       393481 T4.1-Cardlike.jpg
    2021-01-13 17:56       340510 T4-Cardlike.jpg
    2010-03-22 07:11      3373255 DSC03355.JPG
                               21 test1.txt
                                0 mtpindex.dat
    ------------------------------- 
     
    Partion 2
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    
    Volume Directory:      
    ------------------------------- 
     
    Partion 3
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    
    Volume Directory:      
    ------------------------------- 
     
    Partion 4
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    
    Volume Directory:      
    ------------------------------- 
     
    type any character to start
    and a simple Fat16...
    Code:
    init time: 61 ms
    
    Card type: SD2
    
    Manufacturer ID: 0X3
    OEM ID: SD
    Product: SU01G
    Version: 8.0
    Serial number: 0X750B2400
    Manufacturing date: 1/2007
    
    cardSize: 1015.81 MB (MB = 1,000,000 bytes)
    flashEraseSize: 32 blocks
    eraseSingleBlock: true
    
    OCR: 0X80FF8000
    
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X0,0X3,0X3D,0X0,0X6,0X4,0XC4,0XD8,249,1983751
    2,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    3,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    4,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    2021-02-21 11:37          0 System Volume Information/
      2021-02-21 11:37         12 WPSettings.dat
      2021-02-21 11:37         76 IndexerVolumeGuid
    2021-01-24 06:23     393481 T4.1-Cardlike.jpg
                             21 test1.txt
                              0 mtpindex.dat
    
    Partion 1
    
    Scanning FAT, please wait.
    
    Volume is FAT16
    sectorsPerCluster: 32
    clusterCount:      61976
    freeClusterCount:  61945
    fatStartSector:    250
    dataStartSector:   768
    
    Volume Directory:      
    2021-02-21 11:37          0 System Volume Information/
      2021-02-21 11:37         12 WPSettings.dat
      2021-02-21 11:37         76 IndexerVolumeGuid
    2021-01-24 06:23     393481 T4.1-Cardlike.jpg
                             21 test1.txt
                              0 mtpindex.dat
    ------------------------------- 
     
    Partion 2
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    
    Volume Directory:      
    ------------------------------- 
     
    Partion 3
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    
    Volume Directory:      
    ------------------------------- 
     
    Partion 4
    
    Scanning FAT, please wait.
    
    Volume is FAT0
    sectorsPerCluster: 0
    clusterCount:      4294967295
    freeClusterCount:  4294967295
    fatStartSector:    0
    dataStartSector:   0
    
    Volume Directory:      
    ------------------------------- 
     
    type any character to start

    Code:
    /*
       This program attempts to initialize an SD card and analyze its structure.
    */
    #include "SdFat.h"
    #include "sdios.h"
    /*
      Set DISABLE_CS_PIN to disable a second SPI device.
      For example, with the Ethernet shield, set DISABLE_CS_PIN
      to 10 to disable the Ethernet controller.
    */
    const int8_t DISABLE_CS_PIN = -1;
    /*
      Change the value of SD_CS_PIN if you are using SPI
      and your hardware does not use the default value, SS.
      Common values are:
      Arduino Ethernet shield: pin 4
      Sparkfun SD shield: pin 8
      Adafruit SD shields and modules: pin 10
    */
    // SDCARD_SS_PIN is defined for the built-in SD on some boards.
    #ifndef SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SS;
    #else  // SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
    #endif  // SDCARD_SS_PIN
    
    // Try to select the best SD card configuration.
    #if HAS_SDIO_CLASS
    #define SD_CONFIG SdioConfig(FIFO_SDIO)
    #elif ENABLE_DEDICATED_SPI
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
    #else  // HAS_SDIO_CLASS
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
    #endif  // HAS_SDIO_CLASS
    
    //------------------------------------------------------------------------------
    SdFs sd;
    cid_t m_cid;
    csd_t m_csd;
    uint32_t m_eraseSize;
    uint32_t m_ocr;
    static ArduinoOutStream cout(Serial);
    uint8_t partition_types[4];
    FatPartition Part[4];
    ExFatPartition ExPart[4];
    FatVolume partVol;
    ExFatVolume expartVol;
    
    //------------------------------------------------------------------------------
    bool cidDmp() {
      cout << F("\nManufacturer ID: ");
      cout << uppercase << showbase << hex << int(m_cid.mid) << dec << endl;
      cout << F("OEM ID: ") << m_cid.oid[0] << m_cid.oid[1] << endl;
      cout << F("Product: ");
      for (uint8_t i = 0; i < 5; i++) {
        cout << m_cid.pnm[i];
      }
      cout << F("\nVersion: ");
      cout << int(m_cid.prv_n) << '.' << int(m_cid.prv_m) << endl;
      cout << F("Serial number: ") << hex << m_cid.psn << dec << endl;
      cout << F("Manufacturing date: ");
      cout << int(m_cid.mdt_month) << '/';
      cout << (2000 + m_cid.mdt_year_low + 10 * m_cid.mdt_year_high) << endl;
      cout << endl;
      return true;
    }
    //------------------------------------------------------------------------------
    void clearSerialInput() {
      uint32_t m = micros();
      do {
        if (Serial.read() >= 0) {
          m = micros();
        }
      } while (micros() - m < 10000);
    }
    //------------------------------------------------------------------------------
    bool csdDmp() {
      bool eraseSingleBlock;
      if (m_csd.v1.csd_ver == 0) {
        eraseSingleBlock = m_csd.v1.erase_blk_en;
        m_eraseSize = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low;
      } else if (m_csd.v2.csd_ver == 1) {
        eraseSingleBlock = m_csd.v2.erase_blk_en;
        m_eraseSize = (m_csd.v2.sector_size_high << 1) | m_csd.v2.sector_size_low;
      } else {
        cout << F("m_csd version error\n");
        return false;
      }
      m_eraseSize++;
      cout << F("cardSize: ") << 0.000512 * sdCardCapacity(&m_csd);
      cout << F(" MB (MB = 1,000,000 bytes)\n");
    
      cout << F("flashEraseSize: ") << int(m_eraseSize) << F(" blocks\n");
      cout << F("eraseSingleBlock: ");
      if (eraseSingleBlock) {
        cout << F("true\n");
      } else {
        cout << F("false\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void errorPrint() {
      if (sd.sdErrorCode()) {
        cout << F("SD errorCode: ") << hex << showbase;
        printSdErrorSymbol(&Serial, sd.sdErrorCode());
        cout << F(" = ") << int(sd.sdErrorCode()) << endl;
        cout << F("SD errorData = ") << int(sd.sdErrorData()) << endl;
      }
    }
    //------------------------------------------------------------------------------
    bool mbrDmp() {
      MbrSector_t mbr;
      bool valid = true;
      if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
        cout << F("\nread MBR failed.\n");
        errorPrint();
        return false;
      }
      cout << F("\nSD Partition Table\n");
      cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");
      for (uint8_t ip = 1; ip < 5; ip++) {
        MbrPart_t *pt = &mbr.part[ip - 1];
        if ((pt->boot != 0 && pt->boot != 0X80) ||
            getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
          valid = false;
        }
        cout << int(ip) << ',' << uppercase << showbase << hex;
        cout << int(pt->boot) << ',';
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->beginCHS[i]) << ',';
        }
        cout << int(pt->type) << ',';
        ////////////////////////////
        partition_types[ip-1] = pt->type;
        for (int i = 0; i < 3; i++ ) {
          cout << int(pt->endCHS[i]) << ',';
        }
        cout << dec << getLe32(pt->relativeSectors) << ',';
        cout << getLe32(pt->totalSectors) << endl;
      }
      if (!valid) {
        cout << F("\nMBR not valid, assuming Super Floppy format.\n");
      }
      return true;
    }
    //------------------------------------------------------------------------------
    void dmpVol(uint8_t i) {
      cout << F("\nScanning FAT, please wait.\n");
      uint32_t freeClusterCount = Part[i].freeClusterCount();
      if (Part[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(Part[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(Part[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << Part[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << Part[i].fatStartSector() << endl;
      cout << F("dataStartSector:   ") << Part[i].dataStartSector() << endl;
      if (Part[i].dataStartSector() % m_eraseSize) {
        cout << F("Data area is not aligned on flash erase boundary!\n");
        cout << F("Download and use formatter from www.sdcard.org!\n");
      }
    
      cout << F("\nVolume Directory:      ") << endl;
      partVol.begin(sd.card(), true, i + 1);
      partVol.chvol();
      partVol.ls("/", LS_R | LS_DATE | LS_SIZE | LS_A);
    
    
    }
    //------------------------------------------------------------------------------
    void dmpExVol(uint8_t i) {
      cout << F("\nScanning exFAT, please wait.\n");
      uint32_t freeClusterCount = ExPart[i].freeClusterCount();
      if (Part[i].fatType() <= 32) {
        cout << F("\nVolume is FAT") << int(ExPart[i].fatType()) << endl;
      } else {
        cout << F("\nVolume is exFAT\n");
      }
      cout << F("sectorsPerCluster: ") << int(ExPart[i].sectorsPerCluster()) << endl;
      cout << F("clusterCount:      ") << ExPart[i].clusterCount() << endl;
      cout << F("freeClusterCount:  ") << freeClusterCount << endl;
      cout << F("fatStartSector:    ") << ExPart[i].fatStartSector() << endl;
      //  cout << F("dataStartSector:   ") << ExPart[i].dataStartSector() << endl;
      //  if (ExPart[i+1].dataStartSector() % m_eraseSize) {
      //    cout << F("Data area is not aligned on flash erase boundary!\n");
      //    cout << F("Download and use formatter from www.sdcard.org!\n");
      //  }
      cout << F("\nVolume Directory:      ") << endl;
      expartVol.begin(sd.card(), true, i + 1);
      expartVol.chvol();
      expartVol.ls("/", LS_R | LS_DATE | LS_SIZE | LS_A);
    
    }
    //------------------------------------------------------------------------------
    void printCardType() {
    
      cout << F("\nCard type: ");
    
      switch (sd.card()->type()) {
        case SD_CARD_TYPE_SD1:
          cout << F("SD1\n");
          break;
    
        case SD_CARD_TYPE_SD2:
          cout << F("SD2\n");
          break;
    
        case SD_CARD_TYPE_SDHC:
          if (sdCardCapacity(&m_csd) < 70000000) {
            cout << F("SDHC\n");
          } else {
            cout << F("SDXC\n");
          }
          break;
    
        default:
          cout << F("Unknown\n");
      }
    }
    //------------------------------------------------------------------------------
    void printConfig(SdSpiConfig config) {
      if (DISABLE_CS_PIN < 0) {
        cout << F(
               "\nAssuming the SD is the only SPI device.\n"
               "Edit DISABLE_CS_PIN to disable an SPI device.\n");
      } else {
        cout << F("\nDisabling SPI device on pin ");
        cout << int(DISABLE_CS_PIN) << endl;
        pinMode(DISABLE_CS_PIN, OUTPUT);
        digitalWrite(DISABLE_CS_PIN, HIGH);
      }
      cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
      cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
    }
    //------------------------------------------------------------------------------
    void printConfig(SdioConfig config) {
      (void)config;
      cout << F("Assuming an SDIO interface.\n");
    }
    //-----------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      // Wait for USB Serial
      while (!Serial) {
        SysCall::yield();
      }
      cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
      printConfig(SD_CONFIG);
    
    }
    //------------------------------------------------------------------------------
    void loop() {
      // Read any existing Serial data.
      clearSerialInput();
    
      // F stores strings in flash to save RAM
      cout << F("\ntype any character to start\n");
      while (!Serial.available()) {
        SysCall::yield();
      }
      uint32_t t = millis();
      if (!sd.cardBegin(SD_CONFIG)) {
        cout << F(
               "\nSD initialization failed.\n"
               "Do not reformat the card!\n"
               "Is the card correctly inserted?\n"
               "Is there a wiring/soldering problem?\n");
        if (isSpi(SD_CONFIG)) {
          cout << F(
                 "Is SD_CS_PIN set to the correct value?\n"
                 "Does another SPI device need to be disabled?\n"
               );
        }
        errorPrint();
        return;
      }
      t = millis() - t;
      cout << F("init time: ") << t << " ms" << endl;
    
      if (!sd.card()->readCID(&m_cid) ||
          !sd.card()->readCSD(&m_csd) ||
          !sd.card()->readOCR(&m_ocr)) {
        cout << F("readInfo failed\n");
        errorPrint();
        return;
      }
      printCardType();
      cidDmp();
      csdDmp();
      cout << F("\nOCR: ") << uppercase << showbase;
      cout << hex << m_ocr << dec << endl;
      if (!mbrDmp()) {
        return;
      }
      if (!sd.volumeBegin()) {
        cout << F("\nvolumeBegin failed. Is the card formatted?\n");
        errorPrint();
        return;
      }
      sd.ls("/", LS_R | LS_DATE | LS_SIZE | LS_A);
    
      for (uint8_t i = 0; i < 4; i++) {
        cout << F("\nPartion ") << (int) i + 1 << F("\n");
        ////////////////////////////
        if (partition_types[i] == 7) {
          ExPart[i].init(sd.card(), (int) i + 1);
          dmpExVol(i);
        } else {
          Part[i].init(sd.card(), (int) i + 1);
          dmpVol(i);
        }
        cout << F("------------------------------- \n ");
      }
    }
    Again I know a real hack!
    Last edited by KurtE; 02-22-2021 at 03:40 PM.

  22. #422
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    @KurtE
    Sorry for the delay in responding. Was busy playing and watching more snow fall

    Any tried to modify formatter but haven't broken the code on that one and wound up messing up my partitions on the sd card

    Anyway did try the Buffered print example but modified to write on either fat or extFAT. Can confirm that it can be done - will post that one shortly

    But I do see you used @wwatson's modified version to get to exfat. Going to try and play with that a bit more as well. Not a real hack - but only way to do it since SD cards really weren't meant to have partitions

  23. #423
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    @KurtE - @wwatson
    Decided to play around with the BufferedPrint example to see what it takes to write and read files from the partitions. Did manage to create 3 partitions that I can test with;
    Code:
    SD Partition Table
    part,boot,bgnCHS[3],type,endCHS[3],start,length
    1,0X80,0X0,0X1,0X10,0XC,0X3,0XE0,0XFF,2048,524288
    2,0X0,0XC2,0X23,0X20,0XC,0XFE,0XFF,0XFF,526336,16564224
    3,0X0,0XFE,0XFF,0XFF,0X7,0XFE,0XFF,0XFF,17092608,232642560
    4,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
    Partition 1: Is a FAT32 (actually name is system-boot)
    Partition 2: Another FAT32
    Partition 3: exFAT

    Interesting thing to note is that when you start the sd.card() you have to make sure you start it with whatever the first volume is formatted as otherwise it mess with the partitions that aren;t the same. In my case I had to set it up so SDFat sd was specified as part the extended fat defines:
    Code:
    // Test and benchmark of the fast bufferedPrint class.
    //
    // Mainly for AVR but may improve print performance with other CPUs.
    #include "SdFat.h"
    #include "BufferedPrint.h"
    
    // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
    // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
    #define SD_FAT_TYPE 2  // I tested with 1 and 2
    
    // SDCARD_SS_PIN is defined for the built-in SD on some boards.
    #ifndef SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SS;
    #else  // SDCARD_SS_PIN
    // Assume built-in SD is used.
    const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
    #endif  // SDCARD_SS_PIN
    
    // Try to select the best SD card configuration.
    #if HAS_SDIO_CLASS
    #define SD_CONFIG SdioConfig(FIFO_SDIO)
    #elif ENABLE_DEDICATED_SPI
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI)
    #else  // HAS_SDIO_CLASS
    #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI)
    #endif  // HAS_SDIO_CLASS
    
    #if SD_FAT_TYPE == 0
    SdFat sd;
    typedef File file_t;
    #elif SD_FAT_TYPE == 1
    SdFat32 sd;
    typedef File32 file_t;
    FatVolume partVol;
    #elif SD_FAT_TYPE == 2
    //SdExFat sd;
    SdFat sd;  //if 1st partition is Fat32 have to start the SD card as FAT32 then use exVol to write to extended volume
    typedef ExFile file_t;
    ExFatVolume partVol;
    #elif SD_FAT_TYPE == 3
    SdFs sd;
    typedef FsFile file_t;
    FatVolume partVol;
    #else  // SD_FAT_TYPE
    #error Invalid SD_FAT_TYPE
    #endif  // SD_FAT_TYPE
    
    // number of lines to print
    const uint16_t N_PRINT = 20000;
    //------------------------------------------------------------------------------
    void benchmark() {
      file_t file;
      BufferedPrint<file_t, 64> bp;
      // do write test
      Serial.println();
      for (int test = 0; test < 6; test++) {
        char fileName[13] = "bench0.txt";
        fileName[5] = '0' + test;
        // open or create file - truncate existing file.
        if (!file.open(fileName, O_RDWR | O_CREAT | O_TRUNC)) {
          sd.errorHalt(&Serial, F("open failed"));
        }
        if (test & 1) {
          bp.begin(&file);
        }
        uint32_t t = millis();
        switch(test) {
        case 0:
          Serial.println(F("Test of println(uint16_t)"));
          for (uint16_t i = 0; i < N_PRINT; i++) {
            file.println(i);
          }
          break;
    
        case 1:
          Serial.println(F("Test of printField(uint16_t, char)"));
          for (uint16_t i = 0; i < N_PRINT; i++) {
            bp.printField(i, '\n');
          }
          break;
    
        case 2:
          Serial.println(F("Test of println(uint32_t)"));
          for (uint16_t i = 0; i < N_PRINT; i++) {
            file.println(12345678UL + i);
          }
          break;
    
        case 3:
          Serial.println(F("Test of printField(uint32_t, char)"));
          for (uint16_t i = 0; i < N_PRINT; i++) {
            bp.printField(12345678UL + i, '\n');
          }
          break;
    
        case 4:
          Serial.println(F("Test of println(double)"));
          for (uint16_t i = 0; i < N_PRINT; i++) {
            file.println((double)0.01*i);
          }
          break;
    
        case 5:
          Serial.println(F("Test of printField(double, char)"));
          for (uint16_t i = 0; i < N_PRINT; i++) {
            bp.printField((double)0.01*i, '\n');
          }
          break;
    
        }
        if (test & 1) {
          bp.sync();
        }
        if (file.getWriteError()) {
          sd.errorHalt(&Serial, F("write failed"));
        }
        double s = file.fileSize();
        file.close();
        t = millis() - t;
        Serial.print(F("Time "));
        Serial.print(0.001*t, 3);
        Serial.println(F(" sec"));
        Serial.print(F("File size "));
        Serial.print(0.001*s);
        Serial.println(F(" KB"));
        Serial.print(F("Write "));
        Serial.print(s/t);
        Serial.println(F(" KB/sec"));
        Serial.println();
      }
    }
    //------------------------------------------------------------------------------
    void testMemberFunctions() {
      BufferedPrint<Print, 32> bp(&Serial);
      char c = 'c';    // char
    //#define BASIC_TYPES
    #ifdef BASIC_TYPES
      signed char sc = -1;   // signed 8-bit
      unsigned char uc = 1;  // unsiged 8-bit
      signed short ss = -2;  // signed 16-bit
      unsigned short us = 2; // unsigned 16-bit
      signed long sl = -4;   // signed 32-bit
      unsigned long ul = 4;  // unsigned 32-bit
    #else  // BASIC_TYPES
      int8_t sc = -1;  // signed 8-bit
      uint8_t uc = 1;  // unsiged 8-bit
      int16_t ss = -2; // signed 16-bit
      uint16_t us = 2; // unsigned 16-bit
      int32_t sl = -4; // signed 32-bit
      uint32_t ul = 4; // unsigned 32-bit
    #endif  // BASIC_TYPES
      float f = -1.234;
      double d = -5.678;
      bp.println();
      bp.println("Test print()");
      bp.print(c);
      bp.println();
      bp.print("string");
      bp.println();
      bp.print(F("flash"));
      bp.println();
      bp.print(sc);
      bp.println();
      bp.print(uc);
      bp.println();
      bp.print(ss);
      bp.println();
      bp.print(us);
      bp.println();
      bp.print(sl);
      bp.println();
      bp.print(ul);
      bp.println();
      bp.print(f);
      bp.println();
      bp.print(d);
      bp.println();
      bp.println();
    
      bp.println("Test println()");
      bp.println(c);
      bp.println("string");
      bp.println(F("flash"));
      bp.println(sc);
      bp.println(uc);
      bp.println(ss);
      bp.println(us);
      bp.println(sl);
      bp.println(ul);
      bp.println(f);
      bp.println(d);
      bp.println();
    
      bp.println("Test printField()");
      bp.printField(c, ',');
      bp.printField("string", ',');
      bp.printField(F("flash"), ',');
      bp.printField(sc, ',');
      bp.printField(uc, ',');
      bp.printField(ss, ',');
      bp.printField(us, ',');
      bp.printField(sl, ',');
      bp.printField(ul, ',');
      bp.printField(f, ',');
      bp.printField(d, '\n');
    
      bp.sync();
    }
    //------------------------------------------------------------------------------
    void setup() {
      Serial.begin(9600);
      while (!Serial) {}
      Serial.println("Type any character to begin.");
      while(!Serial.available()) {}
      if (!sd.begin(SD_CONFIG)) {
        sd.initErrorHalt(&Serial);
      }
      
      Serial.println("\nVolume Directory:      ");
      
      if(!partVol.begin(sd.card(), true, 3)){   // for me part 1 and 2 are FAT32 and 3 is extFAT 
        sd.errorHalt("Volume did not start");//change part accordingly
      }
      partVol.chvol();
      partVol.ls("/", LS_SIZE);
      
      Serial.println();
      Serial.println(F("Test member funcions:"));
      testMemberFunctions();
      Serial.println();
      Serial.println(F("Benchmark performance for uint16_t, uint32_t, and double:"));
      benchmark();
    
        partVol.ls("/", LS_SIZE);
    
      Serial.println("Done");
    }
    //------------------------------------------------------------------------------
    void loop() {
    }
    I think I got all the changes hightlighted in red. If I then do the sdinfo modified to do volumes, it looks like it worked (checked the 3 volumes in explorer)
    Code:
    Partion 1
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 1
    clusterCount:      516190
    freeClusterCount:  514313
    fatStartSector:    2080
    dataStartSector:   10146
    Data area is not aligned on flash erase boundary!
    Download and use formatter from www.sdcard.org!
    
    Volume Directory:      
        128890 bench0.txt
        128890 bench1.txt
        200000 bench2.txt
        200000 bench3.txt
        149000 bench4.txt
        149000 bench5.txt
    ------------------------------- 
     
    Partion 2
    
    Scanning FAT, please wait.
    
    Volume is FAT32
    sectorsPerCluster: 8
    clusterCount:      2066432
    freeClusterCount:  2066192
    fatStartSector:    526814
    dataStartSector:   559104
    
    Volume Directory:      
        128890 bench0.txt
        128890 bench1.txt
        200000 bench2.txt
        200000 bench3.txt
        149000 bench4.txt
        149000 bench5.txt
    ------------------------------- 
     
    Partion 3
    
    Scanning exFAT, please wait.
    
    Volume is FAT64
    sectorsPerCluster: 256
    clusterCount:      908720
    freeClusterCount:  908704
    fatStartSector:    17094656
    
    Volume Directory:      
    bench0.txt
    bench1.txt
    bench2.txt
    bench3.txt
    bench4.txt
    bench5.txt
    -------------------------------
    How to get this info incorporated into FS and MTP and MSC do not know. But at least we now know that it can be done.

  24. #424
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,017
    @mjs513 - Not a problem... Hope not too much snow! Here it is raining and upper 40s...

    Will play more, but may want to switch gears to see about partitions on USB disks, which is probably more interesting.

    Also sort of question to myself and ... Would be nice to get the volume labels... Especially toward MTP,

    wondering if there is a method... SO far I have not seen one with SDFat stuff. I have seen mention of hacks.
    There appear to be to ways maybe Volume name is stored: As part of the structure:
    Code:
    const uint8_t EXTENDED_BOOT_SIGNATURE = 0X29;
    typedef struct biosParameterBlockFat16 {
      uint8_t  bytesPerSector[2];
      uint8_t  sectorsPerCluster;
      uint8_t  reservedSectorCount[2];
      uint8_t  fatCount;
      uint8_t  rootDirEntryCount[2];
      uint8_t  totalSectors16[2];
      uint8_t  mediaType;
      uint8_t  sectorsPerFat16[2];
      uint8_t  sectorsPerTrtack[2];
      uint8_t  headCount[2];
      uint8_t  hidddenSectors[4];
      uint8_t  totalSectors32[4];
    
      uint8_t  physicalDriveNumber;
      uint8_t  extReserved;
      uint8_t  extSignature;
      uint8_t  volumeSerialNumber[4];
      uint8_t  volumeLabel[11];
      uint8_t  volumeType[8];
    } BpbFat16_t;
    Note: there are other structures for fat32 ... and I don't see any code that uses this structure anywhere in the code...

    Or the Root directory probably first directory entry may contain volume id... But we don't see it as: the nextfile like code calls:
    Code:
    static inline bool isFileOrSubdir(const DirFat_t* dir) {
      return (dir->attributes & FAT_ATTRIB_LABEL) == 0;
    }
    And it specifically does not allow the label to come through...
    Might be nice to have a new method that allows this?

    Or maybe add a special flag to the call: openNextFile
    which says sure return that one...

    But now back to playing

  25. #425
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,972
    @KurtE
    Been searching the code and the help system as well but to no avail. Nothing I have found seems to return the volume name. Think @wwatson mentioned in an earlier post that he was doing something to get the vol name.

    As you said what would be more interesting is getting partitions working for USBdrives, thumb or SSD or HDD, which was really the final state for this stuff.

Posting Permissions

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