Trying to figure out why SD/CardInfo example won't compile

Kalinchuk

Member
Hello, new here. Spent couple hours now trying to figure a way to make this work but got no where. To my understanding SdFile was updated at some point and does not contain the same class members anymore.

Code:
Compilation error: no matching function for call to 'SdFile::openRoot(SdVolume&)'


Code:
/**
 * Copyright (c) 2011-2021 Bill Greiman
 * This file is part of the SdFat library for SD memory cards.
 *
 * MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#ifndef FsFile_h
#define FsFile_h
/**
 * \file
 * \brief FsBaseFile include file.
 */
#include "FsNew.h"
#include "FatLib/FatLib.h"
#include "ExFatLib/ExFatLib.h"
/**
 * \class FsBaseFile
 * \brief FsBaseFile class.
 */
class FsBaseFile {
 public:
  /** Create an instance. */
  FsBaseFile() {}
  /**  Create a file object and open it in the current working directory.
   *
   * \param[in] path A path for a file to be opened.
   *
   * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
   * OR of open flags. see FatFile::open(FatFile*, const char*, uint8_t).
   */
  FsBaseFile(const char* path, oflag_t oflag) {
    open(path, oflag);
  }

  ~FsBaseFile() {close();}
  /** Copy constructor.
   *
   * \param[in] from Object used to initialize this instance.
   */
  FsBaseFile(const FsBaseFile& from);
  /** Copy assignment operator
   * \param[in] from Object used to initialize this instance.
   * \return assigned object.
   */
  FsBaseFile& operator=(const FsBaseFile& from);
  /** The parenthesis operator.
    *
    * \return true if a file is open.
    */
  operator bool() const {return isOpen();}
  /** \return number of bytes available from the current position to EOF
   *   or INT_MAX if more than INT_MAX bytes are available.
   */
  int available() const {
    return m_fFile ? m_fFile->available() :
           m_xFile ? m_xFile->available() : 0;
  }
  /** \return The number of bytes available from the current position
   * to EOF for normal files.  Zero is returned for directory files.
   */
  uint64_t available64() const {
    return m_fFile ? m_fFile->available32() :
           m_xFile ? m_xFile->available64() : 0;
  }
  /** Clear writeError. */
  void clearWriteError() {
    if (m_fFile) m_fFile->clearWriteError();
    if (m_xFile) m_xFile->clearWriteError();
  }
  /** Close a file and force cached data and directory information
   *  to be written to the storage device.
   *
   * \return true for success or false for failure.
   */
  bool close();
  /** Check for contiguous file and return its raw sector range.
   *
   * \param[out] bgnSector the first sector address for the file.
   * \param[out] endSector the last  sector address for the file.
   *
   * Set contiguous flag for FAT16/FAT32 files.
   * Parameters may be nullptr.
   *
   * \return true for success or false for failure.
   */
  bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector) {
    return m_fFile ? m_fFile->contiguousRange(bgnSector, endSector) :
           m_xFile ? m_xFile->contiguousRange(bgnSector, endSector) : false;
  }
  /** \return The current position for a file or directory. */
  uint64_t curPosition() const {
    return m_fFile ? m_fFile->curPosition() :
           m_xFile ? m_xFile->curPosition() : 0;
  }
  /** \return Directory entry index. */
  uint32_t dirIndex() const {
    return m_fFile ? m_fFile->dirIndex() :
           m_xFile ? m_xFile->dirIndex() : 0;
  }
  /** Test for the existence of a file in a directory
   *
   * \param[in] path Path of the file to be tested for.
   *
   * The calling instance must be an open directory file.
   *
   * dirFile.exists("TOFIND.TXT") searches for "TOFIND.TXT" in  the directory
   * dirFile.
   *
   * \return true if the file exists else false.
   */
  bool exists(const char* path) {
    return m_fFile ? m_fFile->exists(path) :
           m_xFile ? m_xFile->exists(path) : false;
  }
  /** get position for streams
   * \param[out] pos struct to receive position
   */
  void fgetpos(fspos_t* pos) const {
    if (m_fFile) m_fFile->fgetpos(pos);
    if (m_xFile) m_xFile->fgetpos(pos);
  }
 /**
   * Get a string from a file.
   *
   * fgets() reads bytes from a file into the array pointed to by \a str, until
   * \a num - 1 bytes are read, or a delimiter is read and transferred to \a str,
   * or end-of-file is encountered. The string is then terminated
   * with a null byte.
   *
   * fgets() deletes CR, '\\r', from the string.  This insures only a '\\n'
   * terminates the string for Windows text files which use CRLF for newline.
   *
   * \param[out] str Pointer to the array where the string is stored.
   * \param[in] num Maximum number of characters to be read
   * (including the final null byte). Usually the length
   * of the array \a str is used.
   * \param[in] delim Optional set of delimiters. The default is "\n".
   *
   * \return For success fgets() returns the length of the string in \a str.
   * If no data is read, fgets() returns zero for EOF or -1 if an error occurred.
   */
  int fgets(char* str, int num, char* delim = nullptr) {
    return m_fFile ? m_fFile->fgets(str, num, delim) :
           m_xFile ? m_xFile->fgets(str, num, delim) : -1;
  }
  /** \return The total number of bytes in a file. */
  uint64_t fileSize() const {
    return m_fFile ? m_fFile->fileSize() :
           m_xFile ? m_xFile->fileSize() : 0;
  }
  /** \return Address of first sector or zero for empty file. */
  uint32_t firstSector() const {
    return m_fFile ? m_fFile->firstSector() :
           m_xFile ? m_xFile->firstSector() : 0;
  }
  /** Ensure that any bytes written to the file are saved to the SD card. */
  void flush() {sync();}
  /** set position for streams
   * \param[in] pos struct with value for new position
   */
  void fsetpos(const fspos_t* pos) {
    if (m_fFile) m_fFile->fsetpos(pos);
    if (m_xFile) m_xFile->fsetpos(pos);
  }
  /** Get a file's access date and time.
   *
   * \param[out] pdate Packed date for directory entry.
   * \param[out] ptime Packed time for directory entry.
   *
   * \return true for success or false for failure.
   */
  bool getAccessDateTime(uint16_t* pdate, uint16_t* ptime) {
    return m_fFile ? m_fFile->getAccessDateTime(pdate, ptime) :
           m_xFile ? m_xFile->getAccessDateTime(pdate, ptime) : false;
  }
  /** Get a file's create date and time.
   *
   * \param[out] pdate Packed date for directory entry.
   * \param[out] ptime Packed time for directory entry.
   *
   * \return true for success or false for failure.
   */
  bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime) {
    return m_fFile ? m_fFile->getCreateDateTime(pdate, ptime) :
           m_xFile ? m_xFile->getCreateDateTime(pdate, ptime) : false;
  }
  /** \return All error bits. */
  uint8_t getError() const {
    return m_fFile ? m_fFile->getError() :
           m_xFile ? m_xFile->getError() : 0XFF;
  }
  /** Get a file's Modify date and time.
   *
   * \param[out] pdate Packed date for directory entry.
   * \param[out] ptime Packed time for directory entry.
   *
   * \return true for success or false for failure.
   */
  bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime) {
    return m_fFile ? m_fFile->getModifyDateTime(pdate, ptime) :
           m_xFile ? m_xFile->getModifyDateTime(pdate, ptime) : false;
  }
  /**
   * Get a file's name followed by a zero byte.
   *
   * \param[out] name An array of characters for the file's name.
   * \param[in] len The size of the array in bytes. The array
   *             must be at least 13 bytes long.  The file's name will be
   *             truncated if the file's name is too long.
   * \return The length of the returned string.
   */
  size_t getName(char* name, size_t len) {
    *name = 0;
    return m_fFile ? m_fFile->getName(name, len) :
           m_xFile ? m_xFile->getName(name, len) : 0;
  }

  /** \return value of writeError */
  bool getWriteError() const {
    return m_fFile ? m_fFile->getWriteError() :
           m_xFile ? m_xFile->getWriteError() : true;
  }
  /**
   * Check for FsBlockDevice busy.
   *
   * \return true if busy else false.
   */
  bool isBusy() {
    return m_fFile ? m_fFile->isBusy() :
           m_xFile ? m_xFile->isBusy() : true;
  }
  /** \return True if the file is contiguous. */
  bool isContiguous() const {
#if USE_FAT_FILE_FLAG_CONTIGUOUS
    return m_fFile ? m_fFile->isContiguous() :
           m_xFile ? m_xFile->isContiguous() : false;
#else  // USE_FAT_FILE_FLAG_CONTIGUOUS
    return m_xFile ? m_xFile->isContiguous() : false;
#endif  // USE_FAT_FILE_FLAG_CONTIGUOUS
  }
  /** \return True if this is a directory else false. */
  bool isDir() const {
    return m_fFile ? m_fFile->isDir() :
           m_xFile ? m_xFile->isDir() : false;
  }
  /** This function reports if the current file is a directory or not.
   * \return true if the file is a directory.
   */
  bool isDirectory() const {return isDir();}
  /** \return True if this is a normal file. */
  bool isFile() const {
    return m_fFile ? m_fFile->isFile() :
           m_xFile ? m_xFile->isFile() : false;
  }
  /** \return True if this is a hidden file else false. */
  bool isHidden() const {
    return m_fFile ? m_fFile->isHidden() :
           m_xFile ? m_xFile->isHidden() : false;
  }
  /** \return True if this is an open file/directory else false. */
  bool isOpen() const {return m_fFile || m_xFile;}
  /** \return True file is readable. */
  bool isReadable() const {
    return m_fFile ? m_fFile->isReadable() :
           m_xFile ? m_xFile->isReadable() : false;
    }
  /** \return True if file is read-only */
  bool isReadOnly() const {
    return m_fFile ? m_fFile->isReadOnly() :
           m_xFile ? m_xFile->isReadOnly() : false;
  }
  /** \return True if this is a subdirectory file else false. */
  bool isSubDir() const {
    return m_fFile ? m_fFile->isSubDir() :
           m_xFile ? m_xFile->isSubDir() : false;
  }
  /** \return True file is writable. */
  bool isWritable() const {
    return m_fFile ? m_fFile->isWritable() :
           m_xFile ? m_xFile->isWritable() : false;
  }
#if ENABLE_ARDUINO_SERIAL
  /** List directory contents.
   *
   * \param[in] flags The inclusive OR of
   *
   * LS_DATE - %Print file modification date
   *
   * LS_SIZE - %Print file size.
   *
   * LS_R - Recursive list of subdirectories.
   */
  bool ls(uint8_t flags) {
    return ls(&Serial, flags);
  }
  /** List directory contents. */
  bool ls() {
    return ls(&Serial);
  }
#endif  // ENABLE_ARDUINO_SERIAL
  /** List directory contents.
   *
   * \param[in] pr Print object.
   *
   * \return true for success or false for failure.
   */
  bool ls(print_t* pr) {
    return m_fFile ? m_fFile->ls(pr) :
           m_xFile ? m_xFile->ls(pr) : false;
  }
  /** List directory contents.
   *
   * \param[in] pr Print object.
   * \param[in] flags The inclusive OR of
   *
   * LS_DATE - %Print file modification date
   *
   * LS_SIZE - %Print file size.
   *
   * LS_R - Recursive list of subdirectories.
   *
   * \return true for success or false for failure.
   */
  bool ls(print_t* pr, uint8_t flags) {
    return m_fFile ? m_fFile->ls(pr, flags) :
           m_xFile ? m_xFile->ls(pr, flags) : false;
  }
  /** Make a new directory.
   *
   * \param[in] dir An open FatFile instance for the directory that will
   *                   contain the new directory.
   *
   * \param[in] path A path with a valid 8.3 DOS name for the new directory.
   *
   * \param[in] pFlag Create missing parent directories if true.
   *
   * \return true for success or false for failure.
   */
  bool mkdir(FsBaseFile* dir, const char* path, bool pFlag = true);
  /** Open a file or directory by name.
   *
   * \param[in] dir An open file instance for the directory containing
   *                    the file to be opened.
   *
   * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
   *
   * \param[in] oflag Values for \a oflag are constructed by a
   *                  bitwise-inclusive OR of flags from the following list
   *
   * O_RDONLY - Open for reading only..
   *
   * O_READ - Same as O_RDONLY.
   *
   * O_WRONLY - Open for writing only.
   *
   * O_WRITE - Same as O_WRONLY.
   *
   * O_RDWR - Open for reading and writing.
   *
   * O_APPEND - If set, the file offset shall be set to the end of the
   * file prior to each write.
   *
   * O_AT_END - Set the initial position at the end of the file.
   *
   * O_CREAT - If the file exists, this flag has no effect except as noted
   * under O_EXCL below. Otherwise, the file shall be created
   *
   * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists.
   *
   * O_TRUNC - If the file exists and is a regular file, and the file is
   * successfully opened and is not read only, its length shall be truncated to 0.
   *
   * WARNING: A given file must not be opened by more than one file object
   * or file corruption may occur.
   *
   * \note Directory files must be opened read only.  Write and truncation is
   * not allowed for directory files.
   *
   * \return true for success or false for failure.
   */
  bool open(FsBaseFile* dir, const char* path, oflag_t oflag = O_RDONLY);
  /** Open a file by index.
   *
   * \param[in] dir An open FsFile instance for the directory.
   *
   * \param[in] index The \a index of the directory entry for the file to be
   * opened.  The value for \a index is (directory file position)/32.
   *
   * \param[in] oflag bitwise-inclusive OR of open flags.
   *            See see FsFile::open(FsFile*, const char*, uint8_t).
   *
   * See open() by path for definition of flags.
   * \return true for success or false for failure.
   */
  bool open(FsBaseFile* dir, uint32_t index, oflag_t oflag);
  /** Open a file or directory by name.
   *
   * \param[in] vol Volume where the file is located.
   *
   * \param[in] path A path for a file to be opened.
   *
   * \param[in] oflag Values for \a oflag are constructed by a
   *                  bitwise-inclusive OR of open flags.
   *
   * \return true for success or false for failure.
   */
  bool open(FsVolume* vol, const char* path, oflag_t oflag);
  /** Open a file or directory by name.
   *
   * \param[in] path A path for a file to be opened.
   *
   * \param[in] oflag Values for \a oflag are constructed by a
   *                  bitwise-inclusive OR of open flags.
   *
   * \return true for success or false for failure.
   */
  bool open(const char* path, oflag_t oflag = O_RDONLY) {
    return FsVolume::m_cwv && open(FsVolume::m_cwv, path, oflag);
  }
  /** Opens the next file or folder in a directory.
   * \param[in] dir directory containing files.
   * \param[in] oflag open flags.
   * \return a file object.
   */
  bool openNext(FsBaseFile* dir, oflag_t oflag = O_RDONLY);
  /** Open a volume's root directory.
   *
   * \param[in] vol The SdFs volume containing the root directory to be opened.
   *
   * \return true for success or false for failure.
   */
  bool openRoot(FsVolume* vol);
  /** \return the current file position. */
  uint64_t position() const {return curPosition();}
  /** Return the next available byte without consuming it.
   *
   * \return The byte if no error and not at eof else -1;
   */
  int peek() {
    return m_fFile ? m_fFile->peek() :
           m_xFile ? m_xFile->peek() : -1;
  }
  /** Allocate contiguous clusters to an empty file.
   *
   * The file must be empty with no clusters allocated.
   *
   * The file will contain uninitialized data for FAT16/FAT32 files.
   * exFAT files will have zero validLength and dataLength will equal
   * the requested length.
   *
   * \param[in] length size of the file in bytes.
   * \return true for success or false for failure.
   */
  bool preAllocate(uint64_t length) {
    return m_fFile ? length < (1ULL << 32) && m_fFile->preAllocate(length) :
           m_xFile ? m_xFile->preAllocate(length) : false;
  }
  /** Print a file's access date and time
   *
   * \param[in] pr Print stream for output.
   *
   * \return true for success or false for failure.
   */
  size_t printAccessDateTime(print_t* pr) {
    return m_fFile ? m_fFile->printAccessDateTime(pr) :
           m_xFile ? m_xFile->printAccessDateTime(pr) : 0;
  }
  /** Print a file's creation date and time
   *
   * \param[in] pr Print stream for output.
   *
   * \return true for success or false for failure.
   */
  size_t printCreateDateTime(print_t* pr) {
    return m_fFile ? m_fFile->printCreateDateTime(pr) :
           m_xFile ? m_xFile->printCreateDateTime(pr) : 0;
  }
  /** Print a number followed by a field terminator.
   * \param[in] value The number to be printed.
   * \param[in] term The field terminator.  Use '\\n' for CR LF.
   * \param[in] prec Number of digits after decimal point.
   * \return The number of bytes written or -1 if an error occurs.
   */
  size_t printField(double value, char term, uint8_t prec = 2) {
    return m_fFile ? m_fFile->printField(value, term, prec) :
           m_xFile ? m_xFile->printField(value, term, prec) : 0;
  }
  /** Print a number followed by a field terminator.
   * \param[in] value The number to be printed.
   * \param[in] term The field terminator.  Use '\\n' for CR LF.
   * \param[in] prec Number of digits after decimal point.
   * \return The number of bytes written or -1 if an error occurs.
   */
  size_t printField(float value, char term, uint8_t prec = 2) {
     return printField(static_cast<double>(value), term, prec);
  }
  /** Print a number followed by a field terminator.
   * \param[in] value The number to be printed.
   * \param[in] term The field terminator.  Use '\\n' for CR LF.
   * \return The number of bytes written or -1 if an error occurs.
   */
  template<typename Type>
  size_t printField(Type value, char term) {
    return m_fFile ? m_fFile->printField(value, term) :
           m_xFile ? m_xFile->printField(value, term) : 0;
  }
  /** Print a file's size.
   *
   * \param[in] pr Print stream for output.
   *
   * \return The number of characters printed is returned
   *         for success and zero is returned for failure.
   */
  size_t printFileSize(print_t* pr) {
    return m_fFile ? m_fFile->printFileSize(pr) :
           m_xFile ? m_xFile->printFileSize(pr) : 0;
  }
  /** Print a file's modify date and time
   *
   * \param[in] pr Print stream for output.
   *
   * \return true for success or false for failure.
   */
  size_t printModifyDateTime(print_t* pr) {
    return m_fFile ? m_fFile->printModifyDateTime(pr) :
           m_xFile ? m_xFile->printModifyDateTime(pr) : 0;
  }
  /** Print a file's name
   *
   * \param[in] pr Print stream for output.
   *
   * \return true for success or false for failure.
   */
  size_t printName(print_t* pr) {
    return m_fFile ? m_fFile->printName(pr) :
           m_xFile ? m_xFile->printName(pr) : 0;
  }
  /** Read the next byte from a file.
   *
   * \return For success return the next byte in the file as an int.
   * If an error occurs or end of file is reached return -1.
   */
  int read() {
    uint8_t b;
    return read(&b, 1) == 1 ? b : -1;
  }
  /** Read data from a file starting at the current position.
   *
   * \param[out] buf Pointer to the location that will receive the data.
   *
   * \param[in] count Maximum number of bytes to read.
   *
   * \return For success read() returns the number of bytes read.
   * A value less than \a count, including zero, will be returned
   * if end of file is reached.
   * If an error occurs, read() returns -1.  Possible errors include
   * read() called before a file has been opened, corrupt file system
   * or an I/O error occurred.
   */
  int read(void* buf, size_t count) {
    return m_fFile ? m_fFile->read(buf, count) :
           m_xFile ? m_xFile->read(buf, count) : -1;
  }
  /** Remove a file.
   *
   * The directory entry and all data for the file are deleted.
   *
   * \note This function should not be used to delete the 8.3 version of a
   * file that has a long name. For example if a file has the long name
   * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
   *
   * \return true for success or false for failure.
   */
  bool remove();
   /** Remove a file.
   *
   * The directory entry and all data for the file are deleted.
   *
   * \param[in] path Path for the file to be removed.
   *
   * Example use: dirFile.remove(filenameToRemove);
   *
   * \note This function should not be used to delete the 8.3 version of a
   * file that has a long name. For example if a file has the long name
   * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
   *
   * \return true for success or false for failure.
   */
  bool remove(const char* path) {
    return m_fFile ? m_fFile->remove(path) :
           m_xFile ? m_xFile->remove(path) : false;
  }
  /** Rename a file or subdirectory.
   *
   * \param[in] newPath New path name for the file/directory.
   *
   * \return true for success or false for failure.
   */
  bool rename(const char* newPath) {
    return m_fFile ? m_fFile->rename(newPath) :
           m_xFile ? m_xFile->rename(newPath) : false;
  }
  /** Rename a file or subdirectory.
   *
   * \param[in] dirFile Directory for the new path.
   * \param[in] newPath New path name for the file/directory.
   *
   * \return true for success or false for failure.
   */
  bool rename(FsBaseFile* dirFile, const char* newPath) {
    return m_fFile ? m_fFile->rename(dirFile->m_fFile, newPath) :
           m_xFile ? m_xFile->rename(dirFile->m_xFile, newPath) : false;
  }
  /** Set the file's current position to zero. */
  void rewind() {
    if (m_fFile) m_fFile->rewind();
    if (m_xFile) m_xFile->rewind();
  }
  /** Rewind a file if it is a directory */
  void rewindDirectory() {
    if (isDir()) rewind();
  }
  /** Remove a directory file.
   *
   * The directory file will be removed only if it is empty and is not the
   * root directory.  rmdir() follows DOS and Windows and ignores the
   * read-only attribute for the directory.
   *
   * \note This function should not be used to delete the 8.3 version of a
   * directory that has a long name. For example if a directory has the
   * long name "New folder" you should not delete the 8.3 name "NEWFOL~1".
   *
   * \return true for success or false for failure.
   */
  bool rmdir();
  /** Seek to a new position in the file, which must be between
   * 0 and the size of the file (inclusive).
   *
   * \param[in] pos the new file position.
   * \return true for success or false for failure.
   */
  bool seek(uint64_t pos) {return seekSet(pos);}
  /** Set the files position to current position + \a pos. See seekSet().
   * \param[in] offset The new position in bytes from the current position.
   * \return true for success or false for failure.
   */
  bool seekCur(int64_t offset) {
    return seekSet(curPosition() + offset);
  }
  /** Set the files position to end-of-file + \a offset. See seekSet().
   * Can't be used for directory files since file size is not defined.
   * \param[in] offset The new position in bytes from end-of-file.
   * \return true for success or false for failure.
   */
  bool seekEnd(int64_t offset = 0) {
    return seekSet(fileSize() + offset);
  }
  /** Sets a file's position.
   *
   * \param[in] pos The new position in bytes from the beginning of the file.
   *
   * \return true for success or false for failure.
   */
  bool seekSet(uint64_t pos) {
    return m_fFile ? pos < (1ULL << 32) && m_fFile->seekSet(pos) :
           m_xFile ? m_xFile->seekSet(pos) : false;
  }
  /** \return the file's size. */
  uint64_t size() const {return fileSize();}
  /** The sync() call causes all modified data and directory fields
   * to be written to the storage device.
   *
   * \return true for success or false for failure.
   */
  bool sync() {
    return m_fFile ? m_fFile->sync() :
           m_xFile ? m_xFile->sync() : false;
  }
  /** Set a file's timestamps in its directory entry.
   *
   * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive
   * OR of flags from the following list
   *
   * T_ACCESS - Set the file's last access date and time.
   *
   * T_CREATE - Set the file's creation date and time.
   *
   * T_WRITE - Set the file's last write/modification date and time.
   *
   * \param[in] year Valid range 1980 - 2107 inclusive.
   *
   * \param[in] month Valid range 1 - 12 inclusive.
   *
   * \param[in] day Valid range 1 - 31 inclusive.
   *
   * \param[in] hour Valid range 0 - 23 inclusive.
   *
   * \param[in] minute Valid range 0 - 59 inclusive.
   *
   * \param[in] second Valid range 0 - 59 inclusive
   *
   * \note It is possible to set an invalid date since there is no check for
   * the number of days in a month.
   *
   * \note
   * Modify and access timestamps may be overwritten if a date time callback
   * function has been set by dateTimeCallback().
   *
   * \return true for success or false for failure.
   */
  bool timestamp(uint8_t flags, uint16_t year, uint8_t month, uint8_t day,
                 uint8_t hour, uint8_t minute, uint8_t second) {
    return m_fFile ?
           m_fFile->timestamp(flags, year, month, day, hour, minute, second) :
           m_xFile ?
           m_xFile->timestamp(flags, year, month, day, hour, minute, second) :
           false;
  }
  /** Truncate a file to the current position.
   *
   * \return true for success or false for failure.
   */
  bool truncate() {
    return m_fFile ? m_fFile->truncate() :
           m_xFile ? m_xFile->truncate() : false;
  }
  /** Truncate a file to a specified length.
   * The current file position will be set to end of file.
   *
   * \param[in] length The desired length for the file.
   *
   * \return true for success or false for failure.
   */
  bool truncate(uint64_t length) {
    return m_fFile ? length < (1ULL << 32) && m_fFile->truncate(length) :
           m_xFile ? m_xFile->truncate(length) : false;
  }
  /** Write a string to a file. Used by the Arduino Print class.
   * \param[in] str Pointer to the string.
   * Use getWriteError to check for errors.
   * \return count of characters written for success or -1 for failure.
   */
  size_t write(const char* str) {
    return write(str, strlen(str));
  }
  /** Write a byte to a file. Required by the Arduino Print class.
   * \param[in] b the byte to be written.
   * Use getWriteError to check for errors.
   * \return 1 for success and 0 for failure.
   */
  size_t write(uint8_t b) {return write(&b, 1);}
  /** Write data to an open file.
   *
   * \note Data is moved to the cache but may not be written to the
   * storage device until sync() is called.
   *
   * \param[in] buf Pointer to the location of the data to be written.
   *
   * \param[in] count Number of bytes to write.
   *
   * \return For success write() returns the number of bytes written, always
   * \a nbyte.  If an error occurs, write() returns zero and writeError is set.
   */
  size_t write(const void* buf, size_t count) {
    return m_fFile ? m_fFile->write(buf, count) :
           m_xFile ? m_xFile->write(buf, count) : 0;
  }

 private:
  newalign_t m_fileMem[FS_ALIGN_DIM(ExFatFile, FatFile)];
  FatFile*   m_fFile = nullptr;
  ExFatFile* m_xFile = nullptr;
};
/**
 * \class FsFile
 * \brief FsBaseFile file with Arduino Stream.
 */
class FsFile : public StreamFile<FsBaseFile, uint64_t> {
 public:
  /** Opens the next file or folder in a directory.
   *
   * \param[in] oflag open flags.
   * \return a FatStream object.
   */
  FsFile openNextFile(oflag_t oflag = O_RDONLY) {
    FsFile tmpFile;
    tmpFile.openNext(this, oflag);
    return tmpFile;
  }
};
#endif  // FsFile_h
 
@Kalinchuk:

What version of Arduino & Teensyduino are you using (in the Arduino IDE, click on "Help" / "About Arduino" & the versions are shown across the top of the popup window) ?? I am running Arduino 1.8.19 + TD 1.58-beta3, & the SD/CardInfo example compiles OK here.

Hope that helps . . . feel free to ask any other questions.

Mark J Culross
KD5RXT
 
@Kalinchuk: Also, may be a private copy of old non-PJRC copy of SdFat in \libraries folder.

That will show in verbose console output in the 'libraries Used or Not Used section'.

The working version is the one installed in the Teensy folder from TeensyDuino
 
The code in msg #1 is part of the SdFat library. It's not meant to be compiled automatically by the Arduino IDE when your program includes either SD.h or SdFat.h.

Maybe you copied all this code into the Arduino IDE window and tried to compile it? Or maybe you have other code in the Arduino IDE and you got this filename from the error (the parts you didn't show us) and you found that file on your hard drive and copied it into your forum message?

I hope you can understand how we're having to make a lot of guesses to help. We can't see what you actually had in the Arduino IDE window. We can't see the whole error info Arduino printed.

So for a completely blind guess, perhaps somewhere in that stuff we can't see is a message about duplicate copies of SdFat? Maybe Arduino is using a copy from a location like {Documents}/Arduino/libraries rather than the Teensy-specific copy at a location like {Arduino}/hardware/teensy/avr/libraries? A copy of SdFat without the requires configuration for Teensy would very likely lead to this sort of error message.
 
@Kalinchuk:

What version of Arduino & Teensyduino are you using (in the Arduino IDE, click on "Help" / "About Arduino" & the versions are shown across the top of the popup window) ?? I am running Arduino 1.8.19 + TD 1.58-beta3, & the SD/CardInfo example compiles OK here.

Hope that helps . . . feel free to ask any other questions.

Mark J Culross
KD5RXT

Arduino 2.0.3 TD 1.57

Also confirmed it is using the teensy SD library (SD 2.0.0) (Actually I temporarily deleted the SD library in teensy and it does compile using the arduino SD library but doesn't actually work. I can comment out the line "root.openRoot(volume);" and it compiles and works but doesn't list the files on sd.

Also, just realized I copied the wrong code

Code:
/*
  SD card test

  This example shows how use the utility libraries on which the'
  SD library is based in order to get info about your SD card.
  Very useful for testing a card when you're not sure whether its working or not.

  The circuit:
    SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
 		Pin 4 used here for consistency with other Arduino examples


  created  28 Mar 2011
  by Limor Fried
  modified 9 Apr 2012
  by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = BUILTIN_SDCARD;

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


  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("Volume type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("Volume size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}
 
Sorry, didn't mean to copy SD.h, had it open trying to figure it out.
No, its compiling using the teensy SD library. At least according to this:

Multiple libraries were found for "SD.h"
Used: /Users/paul/Library/Arduino15/packages/teensy/hardware/avr/1.57.2/libraries/SD
Not used: /Users/paul/Library/Arduino15/libraries/SD
 
@Kalinchuk:

I'm not 100% certain, but I don't think that the following is correct (CS on pin 254 ??):

Code:
const int chipSelect = 254;

Here's the equivalent SD/CardInfo example code from TD1.58b3 (note that it is using CS = 10, so seems to be targeting SD slot on the Teensy Audio Adapter, or the Adafruit SD shields and modules):

Code:
/*
  SD card test 
   
 This example shows how use the utility libraries on which the'
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you're not sure whether its working or not.
 	
 The circuit:
  * SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila, pin 7 on Teensy with audio board
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila, pin 14 on Teensy with audio board
 ** CS - depends on your SD card shield or module - pin 10 on Teensy with audio board
 		Pin 4 used here for consistency with other Arduino examples

 
 created  28 Mar 2011
 by Limor Fried 
 modified 9 Apr 2012
 by Tom Igoe
 */
 // include the SD library:
#include <SD.h>
#include <SPI.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Teensy 3.5 & 3.6 & 4.1 on-board: BUILTIN_SDCARD
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
const int chipSelect = 10;

void setup()
{
  //UNCOMMENT THESE TWO LINES FOR TEENSY AUDIO BOARD:
  //SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
  //SPI.setSCK(14);  // Audio shield has SCK on pin 14
  
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect.
  }


  Serial.print("\nInitializing SD card...");


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
  
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  if (volumesize < 8388608ul) {
    Serial.print("Volume size (bytes): ");
    Serial.println(volumesize * 512);        // SD card blocks are always 512 bytes
  }
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 2;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);

  
  //Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  //root.openRoot(volume);
  
  // list all files in the card with date and size
  //root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {
  
}

Mark J Culross
KD5RXT
 
@Kalinchuk:

I'm not 100% certain, but I don't think that the following is correct (CS on pin 254 ??):

Code:
const int chipSelect = 254;

Here's the equivalent SD/CardInfo example code from TD1.58b3 (note that it is using CS = 10, so seems to be targeting SD slot on the Teensy Audio Adapter, or the Adafruit SD shields and modules):

Code:
/*
  SD card test 
   
 This example shows how use the utility libraries on which the'
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you're not sure whether its working or not.
 	
 The circuit:
  * SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila, pin 7 on Teensy with audio board
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila, pin 14 on Teensy with audio board
 ** CS - depends on your SD card shield or module - pin 10 on Teensy with audio board
 		Pin 4 used here for consistency with other Arduino examples

 
 created  28 Mar 2011
 by Limor Fried 
 modified 9 Apr 2012
 by Tom Igoe
 */
 // include the SD library:
#include <SD.h>
#include <SPI.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Teensy 3.5 & 3.6 & 4.1 on-board: BUILTIN_SDCARD
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
const int chipSelect = 10;

void setup()
{
  //UNCOMMENT THESE TWO LINES FOR TEENSY AUDIO BOARD:
  //SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
  //SPI.setSCK(14);  // Audio shield has SCK on pin 14
  
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect.
  }


  Serial.print("\nInitializing SD card...");


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
  
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  if (volumesize < 8388608ul) {
    Serial.print("Volume size (bytes): ");
    Serial.println(volumesize * 512);        // SD card blocks are always 512 bytes
  }
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 2;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);

  
  //Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  //root.openRoot(volume);
  
  // list all files in the card with date and size
  //root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {
  
}

Mark J Culross
KD5RXT

Yes, I changed it to 254 temporarily(I already edited post to correct it) to see if it would compile using arduino SD library. And just to be clear, I uncommented the lines:
Code:
  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);
  
  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
And that's what is not working.
 
Please show the whole program that is not working, so anyone can just copy it into Arduino and click Verify to reproduce the same error.
 
Please show the whole program that is not working, so anyone can just copy it into Arduino and click Verify to reproduce the same error.

Code:
[Back]

/*
  SD card test

  This example shows how use the utility libraries on which the'
  SD library is based in order to get info about your SD card.
  Very useful for testing a card when you're not sure whether its working or not.

  The circuit:
    SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
 		Pin 4 used here for consistency with other Arduino examples


  created  28 Mar 2011
  by Limor Fried
  modified 9 Apr 2012
  by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = BUILTIN_SDCARD;

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


  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
  return;
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("Volume type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("Volume size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}
 
Oh, now I see where things are going wrong.

Those lines are commented out because "Sd2Card" and "SdVolume" are just compatibility classes to allow programs which depend on some APIs from the ancient Arduino SD library to compile. They're not fully featured replacements for the old SD library.

To make this work, first "root" needs to be type FsFile.

Then the openRoot line needs to be "root.openRoot(SD.sdfs.vol());"

Here is the complete code with those modifications:

Code:
/*
  SD card test

  This example shows how use the utility libraries on which the'
  SD library is based in order to get info about your SD card.
  Very useful for testing a card when you're not sure whether its working or not.

  The circuit:
    SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
     Pin 4 used here for consistency with other Arduino examples


  created  28 Mar 2011
  by Limor Fried
  modified 9 Apr 2012
  by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
FsFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = BUILTIN_SDCARD;

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


  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
  return;
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("Volume type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("Volume size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(SD.sdfs.vol());

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}
 
I have that same erroneous code shown in #10 and I am running Teensyduino 1.58b3.
Presumably this code was installed by TeensyDuino.
Can it be arranged for the corrected version be installed with Teensyduino?
 
Oh, now I see where things are going wrong.

Those lines are commented out because "Sd2Card" and "SdVolume" are just compatibility classes to allow programs which depend on some APIs from the ancient Arduino SD library to compile. They're not fully featured replacements for the old SD library.

To make this work, first "root" needs to be type FsFile.

Then the openRoot line needs to be "root.openRoot(SD.sdfs.vol());"

Here is the complete code with those modifications:
...

Confirming that edited code runs here on T_4.1 with TD 1.58b3.
 
Yes but will it be included in future Teensyduino?

Yes, but with a deprecated warning.

https://github.com/PaulStoffregen/SD/commit/3f44f07339f2d67e7e92913869cf4fd85bbe80fc

To explain a bit further, SdVolume is certainly not the intended public API to access the SD card. It is merely leftover baggage from the ancient Arduino SD library which never had any API to query filesystem size. This example code which opens the low-level stuff has been present in the old Arduino SD library since nearly the beginning of Arduino. The Sd2Card and SdVolume classes we have today in SD.h (which is just a thin wrapper for SdFat) are meant to give compatibility with programs using this old way to query the card size. But programming assumptions about the internal structure of the ancient Arduino SD library into user-level code which just accesses the card for files and folders is definitely not recommended. That's the reason for the deprecated warning.
 
Oh, now I see where things are going wrong.

Those lines are commented out because "Sd2Card" and "SdVolume" are just compatibility classes to allow programs which depend on some APIs from the ancient Arduino SD library to compile. They're not fully featured replacements for the old SD library.

To make this work, first "root" needs to be type FsFile.

Then the openRoot line needs to be "root.openRoot(SD.sdfs.vol());"

Here is the complete code with those modifications:

Code:
/*
  SD card test

  This example shows how use the utility libraries on which the'
  SD library is based in order to get info about your SD card.
  Very useful for testing a card when you're not sure whether its working or not.

  The circuit:
    SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
     Pin 4 used here for consistency with other Arduino examples


  created  28 Mar 2011
  by Limor Fried
  modified 9 Apr 2012
  by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
FsFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = BUILTIN_SDCARD;

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


  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
  return;
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("Volume type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("Volume size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(SD.sdfs.vol());

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}

Awesome, works. Appreciate the quick response!
 
Yes, but with a deprecated warning.

https://github.com/PaulStoffregen/SD/commit/3f44f07339f2d67e7e92913869cf4fd85bbe80fc

To explain a bit further, SdVolume is certainly not the intended public API to access the SD card. It is merely leftover baggage from the ancient Arduino SD library which never had any API to query filesystem size. This example code which opens the low-level stuff has been present in the old Arduino SD library since nearly the beginning of Arduino. The Sd2Card and SdVolume classes we have today in SD.h (which is just a thin wrapper for SdFat) are meant to give compatibility with programs using this old way to query the card size. But programming assumptions about the internal structure of the ancient Arduino SD library into user-level code which just accesses the card for files and folders is definitely not recommended. That's the reason for the deprecated warning.

Then why is it still included with Teensyduino as an example?
 
why is it still included with Teensyduino as an example?

Partly inertia, none of the examples were deleted in the move to SdFat wrapper.

But also partly for testing and maintaining compatibility. My perl script that checks if all examples compile won't be able to tell if we're still successfully compiling code using this old API without this example still in the library. I've seen at least a couple programs online which copied this example code. It's a classic problem with software... widespread usage of old APIs means special code in newer software to maintain compatibility.

Hopefully just by reading this example code anyone can see it's meant to for checking if hardware is working and detecting the type of card. The other examples are focused on showing how to actually access folders and files.
 
Back
Top