SDRaw Class Reference

A class to control an SD Card. More...

#include <SFBSDRaw.h>


Public Types

enum  State {
  NOT_BEGUN = 0,
  UNINITTED,
  RESET_FAILED,
  CRC_ON_FAILED,
  TYPE_CHECK_FAILED,
  OP_COND_FAILED,
  READ_OCR_FAILED,
  CONFIG_FAILED,
  ACTIVE,
  INACTIVE_READ,
  INACTIVE_WRITE,
  ERROR_READ_SINGLE_BLOCK,
  ERROR_READ_REGISTER,
  ERROR_READ_TIMEOUT_DATA,
  ERROR_READ_CRC_DATA,
  ERROR_BAD_CSD_VERSION,
  ERROR_WRITE_TIMEOUT_DATA,
  ERROR_WRITE_SINGLE_BLOCK
}
 State codes of an SDRaw host controller. More...

Public Member Functions

void begin (u8 face)
 Begin using an SDRaw object to control an SD card connected to face.
void begin (u8 face, u8 CSPin, u8 clkPin, u8 MOSIpin, u8 MISOpin)
 Begin using an SDRaw object to control an SD card.
bool end ()
 Deconfigure an SDRaw object.
u32 getState ()
 Get the current State of this SDRaw object.
u32 getBlockCount ()
 Return the total capacity of the SD card, measured in 512 byte blocks.
u64 getByteCount ()
 Return the total capacity of the SD card, measured in bytes.
u8 getFace ()
 Return the face this SDRaw object is controlling to power the SD Card.
bool init ()
 Attempt to initialize the SD card controlled by this SDRaw object.
bool isActive ()
 Return true iff this SDRaw object is prepared to perform a read or write operation.
bool getInfo (SDRawDiskInfo &info)
 Read disk capacity and identification information from the disk.
bool setBlockBuffer (u8 *buffer, u32 bufferLength)
 Provide (or remove) a block-sized (512 bytes) buffer for the SDRaw object to use for data buffering.
bool read (u64 address, u8 *data, u32 length)
 Read length bytes into data, starting from disk address address.
bool readBlock (u32 blockNumber, u8 *buffer, u32 blockOffset=0, u32 length=512)
 Read a block of data from the disk, storing some or all of it in buffer.
bool write (u64 address, const u8 *data, u32 length)
 Write length bytes from data to disk, starting from disk address address.
bool writeBlock (u32 blockNumber, const u8 *buffer)
 Write a full block of data to disk block blockNumber, .
bool sync ()
 Flush any pending buffered writes to disk.
bool isSDHC ()
 Return true if the disk is an 'Secure Digital High Capacity' card, false otherwise.
void setSpiLog (bool val)
 Turn on or off low-level SPI protocol logging (for internal debugging).
u32 readStatus ()
 Read and return the internal status register of the card.


Detailed Description

A class to control an SD Card.

Capable of reading and writing (at least some) SD and SDHC cards on any face at rates from 10KBytes/sec to 100Kbytes/sec or more, depending on factors such as the card type, size, and manufacturer, processor clock speed and load, programming technique, and the alignment of Jupiter with Mars. Getting 40-50KB/sec read and write is fairly easy; 120KB/sec read and write, or even more, can sometimes be achieved in benchmark code.

Note this code provides NO FILE SYSTEM! This is low-level direct disk access in terms of 512-byte blocks from the beginning of the disk to the end. And there is nothing stopping your sketch from creaming whatever file system might already be on the card, except your sketch not doing disk writes!

Using the simplest begin(u8) interface, this code is designed to drive an 'IXM SD Cell' board containing a MicroSD card, connected by at least one 7 pin header, on the LED side of the IXM, but the code can be configured (via begin(u8,u8,u8,u8,u8)) to drive an SD card (in SPI mode) via any four pins (data or Tx or Rx) and a single face power connection (so that the card can be power-cycled as part of its initialization sequence).

Warning: Misplugging an IXM SD Cell to an IXM while it contains an SD Card can INSTANTLY KILL the SD Card when the IXM is powered up! Always 'pop' the card before plugging or unplugging or handling the board! And be CAREFUL what you touch while you're pushing and popping cards!

Cards that have been tested successfully include:

  1. SanDisk 2GB MicroSD card, product code SU02G manufactured 11/2009: Up to approximately 140KB/sec block read speed, up to approximately 120KB/sec block write speed. I've apparently killed multiple of these through misplugging or static discharge or something (thus the warning above) -- with the most common symptom being that the cards init successfully but then fail during the first read or write operation .

  2. SanDisk 4GB MicroSDHC card, product code SU04G manufactured 2/2010: Current workhorse (as of 4/10; under $15 at WalMart). Up to approximately 140KB/sec block read speed, up to approximately 150KB/sec block write speed (yes, it benched faster writing than reading.. No idea why.).

  3. PNY 4GB MicroSDHC card, product code SA04G manufactured 12/2009: Cheap, up to approximately 140KB/sec block read speed, up to approximately 60KB/sec block write speed.

Note that all speed numbers mentioned are only crude estimates, based on highly-variable statistically-insignificant timings on stripped-down benchmarking code! Expect less, perhaps much less, from actual production code! In particular, doing byte-at-a-time access, rather than dealing with full blocks, can easily halve those numbers, or worse.

Your Mileage Will Vary!

Note also that this library currently supports only single-block-at-a-time transfers; perhaps that is a factor in the PNY's write performance.

Examples:

sdcard1.cpp, sdcard2.cpp, and sdcard3.cpp.


Member Enumeration Documentation

State codes of an SDRaw host controller.

Enumerator:
NOT_BEGUN  No begin() called (since last end(), at any rate).
UNINITTED  begin() called but not yet init()
RESET_FAILED  init() couldn't reset the card -- a common result when no card is present
CRC_ON_FAILED  Attempt to enable CRC checking failed during init(). This is a bad sign.
TYPE_CHECK_FAILED  Determining SD controller version failed during init(). Another bad sign.
OP_COND_FAILED  Attempt to boot the SD card failed during init(). Yet another bad sign.
READ_OCR_FAILED  Checking for an SDHC card failed during init(). Also a bad sign.
CONFIG_FAILED  Attempt to set the block size failed during init(). Yes, another bad sign.
ACTIVE  init() completed successfully, card ready for read/write.
INACTIVE_READ  read(u64,u8*,u32) called when not ACTIVE. This means a sketch bug.
INACTIVE_WRITE  write(u64,const u8*,u32) called when not ACTIVE. This means a sketch bug.
ERROR_READ_SINGLE_BLOCK  Performing a block read failed. May suggest a bad connection or card.
ERROR_READ_REGISTER  Reading a card register failed. May suggest a bad connection or card.
ERROR_READ_TIMEOUT_DATA  Timeout reading a block or register. May suggest a bad connection or card.
ERROR_READ_CRC_DATA  Checksum mismatch on read data block. May suggest a bad connection.
ERROR_BAD_CSD_VERSION  Unrecognized version of CSD. A bad sign, or a SD card from the future.
ERROR_WRITE_TIMEOUT_DATA  Timeout writing a block. May suggest a bad connection or card.
ERROR_WRITE_SINGLE_BLOCK  Performing a block write failed. May suggest a bad connection or card.


Member Function Documentation

void SDRaw::begin ( u8  face,
u8  CSPin,
u8  clkPin,
u8  MOSIpin,
u8  MISOpin 
)

Begin using an SDRaw object to control an SD card.

The power to the SD card should be supplied by face, so that switching off and on the outbound power on that face will power-cycle the card. In addition, four pins must be provided for the SPI-mode interface to the card. These pins may be any of the data or serial pins on the IXM, not necessarily just those on face.

Note that the method only configures the SDRaw object; it still must be successfully initialized via init() before it can be used to perform I/O.

Parameters:
face A face whose outbound power is connected to a (micro) SD card.
CSPin A pin connected to the Chip Select input of an SD card (in SPI mode)
clkPin A pin connected to the Clock input of an SD card (in SPI mode)
MOSIpin A pin connected to the Master-Out-Slave-In input of an SD card (in SPI mode)
MISOpin A pin connected to the Master-In-Slave-Out output of an SD card (in SPI mode)

void SDRaw::begin ( u8  face  ) 

Begin using an SDRaw object to control an SD card connected to face.

This is the simpler method, see begin(u8,u8,u8,u8,u8) for the more general mechanism. Note that the method only configures the SDRaw object; it still must be successfully initialized via init() before it can be used to perform I/O.

Parameters:
face A face connected -- in an IXM SD Cell-compatible fashion -- to a (micro) SD card.
Examples:
sdcard1.cpp, sdcard2.cpp, and sdcard3.cpp.

bool SDRaw::end (  ) 

Deconfigure an SDRaw object.

Marks the SDRaw object internally as NOT_BEGUN, but note this method does not undo the effects of a begin() call. In particular, pin functions and pin modes changed by a begin() call remain changed. It is the caller's responsibility to reconfigure any affected hardware as desired after this call.

Examples:
sdcard1.cpp.

u32 SDRaw::getBlockCount (  )  [inline]

Return the total capacity of the SD card, measured in 512 byte blocks.

Returns 0 if the information cannot be accessed (because the SDRaw is not in state ACTIVE, or some other error).

Examples:
sdcard1.cpp, and sdcard3.cpp.

u64 SDRaw::getByteCount (  )  [inline]

Return the total capacity of the SD card, measured in bytes.

Returns 0 if the information cannot be accessed (because the SDRaw is not in state ACTIVE, or some other error).

u8 SDRaw::getFace (  )  [inline]

Return the face this SDRaw object is controlling to power the SD Card.

Returns garbage if begin() has not yet been called.

bool SDRaw::getInfo ( SDRawDiskInfo info  ) 

Read disk capacity and identification information from the disk.

If successful, returns true and populates the fields of info with the results. Otherwise returns false (and getState() should provide more information).

Parameters:
info An SDRawDiskInfo structure to populate.

bool SDRaw::init (  ) 

Attempt to initialize the SD card controlled by this SDRaw object.

Returns true if the initialization succeeds (and the card is then ready for I/O), and returns false if some error occurred during initialization (and then the card is not ready for I/O, but getState() will provide more information about the error.

Note that this method can take a long time to complete -- up to a second or perhaps even more -- regardless of whether it ultimately succeeds or fails.

Returns:
true if initialization succeeded, false if an error occurred.
Examples:
sdcard1.cpp, sdcard2.cpp, and sdcard3.cpp.

bool SDRaw::isSDHC (  )  [inline]

Return true if the disk is an 'Secure Digital High Capacity' card, false otherwise.

Return value is only valid if getState() returns ACTIVE.

bool SDRaw::read ( u64  address,
u8 data,
u32  length 
)

Read length bytes into data, starting from disk address address.

Return true if all went well, otherwise return false and update getState() to reflect the problem.

length may be any value (that doesn't overrun RAM or disk), and neither address nor data have any alignment requirements.

However, the speed of this method depends on whether setBlockBuffer(u8*,u32) has previously been called to supply a (non-null) block buffer. If If it has not been called (or has been called most recently with a null argument), then this method performs an unbuffered block read operation, and so each call to this method will read at least 512 bytes from the disk, even if length is smaller than that. As a consequence, using this method without a buffer to read, say, one byte at a time, would be extremely inefficient.

On the other hand, if a block buffer has been provided, then a buffered read operation is performed, and so reads of sequentially increasing addresses will be reasonably efficient no matter what length is used.

For absolute maximum efficiency in this method, no block buffer should be provided, and address and length should both be multiples of 512.

Parameters:
address Disk address (in bytes) to start reading data from, in the range of 0 to getByteCount()-length
data RAM address to start writing data to.
length Number of byts to transfer.
Returns:
true if read succeeded, false otherwise
Blinks:
E_API_ARGUMENT if data equals 0 while length is nonzero.
Examples:
sdcard3.cpp.

bool SDRaw::readBlock ( u32  blockNumber,
u8 buffer,
u32  blockOffset = 0,
u32  length = 512 
)

Read a block of data from the disk, storing some or all of it in buffer.

A single full block is always read by this method, but the optional arguments blockOffset and length control how much of that block, if any, is stored in bufer. blockOffset, in the range of 0 to 512, determines how many of the disk block bytes should be skipped before beginning to store length bytes starting at buffer. With default values, the entire block is stored.

Return true if all went well, otherwise return false and update getState() to reflect the problem.

length and blockOffset may each have any value from 0 to 512, but note that this is an unbuffered block read operation, which will read a full 512 bytes from the disk even if length is smaller than that.

As a consequence, using this method to read, say, one byte at a time would be extremely inefficient.

Parameters:
blockNumber Disk block (in units of 512 bytes per block) to read, in the range of 0 to getBlockCount()-1
buffer RAM address to start writing data to, with at least length bytes of space available
blockOffset Number of read bytes to skip before beginning to store them, in the range of 0..512, default value 0.
length Number of bytes to store into buffer, in the range of 0..512-blockOffset, default value 512.
Examples:
sdcard2.cpp.

u32 SDRaw::readStatus (  ) 

Read and return the internal status register of the card.

Note the difference between this method, which always requests status information from the SD card itself, and getState(), which returns information not about the card, but about the SDRaw controller.

Calling this method is probably the fastest way to check if a previously successfully init()-ed card is still present and alive.

The return value is the card status bits as defined by the SD Card specification, and will be zero in the normal case.

Examples:
sdcard1.cpp.

bool SDRaw::setBlockBuffer ( u8 buffer,
u32  bufferLength 
)

Provide (or remove) a block-sized (512 bytes) buffer for the SDRaw object to use for data buffering.

It is not required to provide such a buffer, but if you don't then all your write operations must work in terms of 512 byte units at multiple-of-512 addresses, and all your read operations will involve reading at least 512 bytes from the disk, no matter what length your request.

Note that if, and as long as, a buffer is provided for an SDRaw to use, then the sketch should make no assumptions about the contents of that buffer at any given time. In particular, the sketch should not assume that the buffer contains the most-recently read or written disk block, because the SDRaw library is free to use the provided buffer for whatever internal purposes it wishes.

Parameters:
buffer A pointer to a 512 byte block of RAM to use for buffering, or 0 to remove a previously provided buffer.
bufferLength Must be 512 (unless buffer is 0, in which case bufferLength may also be 0). This argument is required for documentation and safety purposes; it is checked but not otherwise used, since the buffer size must be 512.
Blinks:
E_API_ARGUMENT if bufferLength is something other than 512 or 0 when buffer is 0.
Examples:
sdcard3.cpp.

bool SDRaw::sync (  ) 

Flush any pending buffered writes to disk.

Return true if all went well (whether or not any actual writing was performed), else return false and update getState() to reflect the problem.

Harmless to call if there are no writes pending, also harmless (but meaningless) to call unless a prior setBlockBuffer() with a non-block argument call has been made.

Examples:
sdcard3.cpp.

bool SDRaw::write ( u64  address,
const u8 data,
u32  length 
)

Write length bytes from data to disk, starting from disk address address.

Return true if all went well, otherwise return false and update getState() to reflect the problem.

The legal arguments to this command depend on whether setBlockBuffer(u8*,u32) has been called to supply a (non-null) block buffer. If it has not been called (or has been called most recently with a null argument), then both address and length must be a multiple of 512, or the sketch will die blinking E_API_ILLEGAL_STATE.

On the other hand, if a block buffer has been provided, then length may be any value (that doesn't overrun RAM or disk), and address has no alignment requirements. (data never has any alignment requirements.)

When a block buffer is available, this method will perform buffered writes, which means that (some or all of) the data you supply may not have actually been written to the disk by the time that this method returns. To be certain that all data has been written to disk, call sync(), after writing, to force any buffered data to be written.

Parameters:
address Disk address (in bytes) to start writing data to, in the range of 0 to getByteCount()-length
data RAM address to start reading data from.
length Number of byts to transfer.
Blinks:
E_API_ILLEGAL_STATE unless a block buffer is available or both address and length are a multiple of 512.
Returns:
true if all went well, false otherwise.
Examples:
sdcard3.cpp.

bool SDRaw::writeBlock ( u32  blockNumber,
const u8 buffer 
)

Write a full block of data to disk block blockNumber, .

Return true if all went well, otherwise return false and update getState() to reflect the problem. That this is an unbuffered write not requiring a previous setBlockBuffer() to provide a buffer (and making no use of such a buffer if it was provided).

Parameters:
blockNumber Disk block (in units of 512 bytes per block) to write, in the range of 0 to getBlockCount()-1
buffer RAM address to read data from, containing 512 bytes of data.
Returns:
true if write succeeded, false otherwise.
Blinks:
E_API_NULL_POINTER if buffer is null.
Examples:
sdcard2.cpp.


The documentation for this class was generated from the following files:

Generated on Fri Apr 22 06:57:10 2011 for SFB by doxygen 1.5.9