daily_automated
This commit is contained in:
485
trunk/Arduino/libraries/SdFat/src/SdCard/SdInfo.h
Normal file
485
trunk/Arduino/libraries/SdFat/src/SdCard/SdInfo.h
Normal file
@@ -0,0 +1,485 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2018 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 SdInfo_h
|
||||
#define SdInfo_h
|
||||
#include <stdint.h>
|
||||
// Based on the document:
|
||||
//
|
||||
// SD Specifications
|
||||
// Part 1
|
||||
// Physical Layer
|
||||
// Simplified Specification
|
||||
// Version 5.00
|
||||
// Aug 10, 2016
|
||||
//
|
||||
// https://www.sdcard.org/downloads/pls/
|
||||
//------------------------------------------------------------------------------
|
||||
// SD card errors
|
||||
// See the SD Specification for command info.
|
||||
typedef enum {
|
||||
SD_CARD_ERROR_NONE = 0,
|
||||
|
||||
// Basic commands and switch command.
|
||||
SD_CARD_ERROR_CMD0 = 0X20,
|
||||
SD_CARD_ERROR_CMD2,
|
||||
SD_CARD_ERROR_CMD3,
|
||||
SD_CARD_ERROR_CMD6,
|
||||
SD_CARD_ERROR_CMD7,
|
||||
SD_CARD_ERROR_CMD8,
|
||||
SD_CARD_ERROR_CMD9,
|
||||
SD_CARD_ERROR_CMD10,
|
||||
SD_CARD_ERROR_CMD12,
|
||||
SD_CARD_ERROR_CMD13,
|
||||
|
||||
// Read, write, erase, and extension commands.
|
||||
SD_CARD_ERROR_CMD17 = 0X30,
|
||||
SD_CARD_ERROR_CMD18,
|
||||
SD_CARD_ERROR_CMD24,
|
||||
SD_CARD_ERROR_CMD25,
|
||||
SD_CARD_ERROR_CMD32,
|
||||
SD_CARD_ERROR_CMD33,
|
||||
SD_CARD_ERROR_CMD38,
|
||||
SD_CARD_ERROR_CMD58,
|
||||
SD_CARD_ERROR_CMD59,
|
||||
|
||||
// Application specific commands.
|
||||
SD_CARD_ERROR_ACMD6 = 0X40,
|
||||
SD_CARD_ERROR_ACMD13,
|
||||
SD_CARD_ERROR_ACMD23,
|
||||
SD_CARD_ERROR_ACMD41,
|
||||
|
||||
// Read/write errors
|
||||
SD_CARD_ERROR_READ = 0X50,
|
||||
SD_CARD_ERROR_READ_CRC,
|
||||
SD_CARD_ERROR_READ_FIFO,
|
||||
SD_CARD_ERROR_READ_REG,
|
||||
SD_CARD_ERROR_READ_START,
|
||||
SD_CARD_ERROR_READ_TIMEOUT,
|
||||
SD_CARD_ERROR_STOP_TRAN,
|
||||
SD_CARD_ERROR_WRITE,
|
||||
SD_CARD_ERROR_WRITE_FIFO,
|
||||
SD_CARD_ERROR_WRITE_START,
|
||||
SD_CARD_ERROR_FLASH_PROGRAMMING,
|
||||
SD_CARD_ERROR_WRITE_TIMEOUT,
|
||||
|
||||
// Misc errors.
|
||||
SD_CARD_ERROR_DMA = 0X60,
|
||||
SD_CARD_ERROR_ERASE,
|
||||
SD_CARD_ERROR_ERASE_SINGLE_BLOCK,
|
||||
SD_CARD_ERROR_ERASE_TIMEOUT,
|
||||
SD_CARD_ERROR_INIT_NOT_CALLED,
|
||||
SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED
|
||||
} sd_error_code_t;
|
||||
//------------------------------------------------------------------------------
|
||||
// card types
|
||||
/** Standard capacity V1 SD card */
|
||||
const uint8_t SD_CARD_TYPE_SD1 = 1;
|
||||
/** Standard capacity V2 SD card */
|
||||
const uint8_t SD_CARD_TYPE_SD2 = 2;
|
||||
/** High Capacity SD card */
|
||||
const uint8_t SD_CARD_TYPE_SDHC = 3;
|
||||
//------------------------------------------------------------------------------
|
||||
#define SD_SCK_HZ(maxSpeed) SPISettings(maxSpeed, MSBFIRST, SPI_MODE0)
|
||||
#define SD_SCK_MHZ(maxMhz) SPISettings(1000000UL*maxMhz, MSBFIRST, SPI_MODE0)
|
||||
// SPI divisor constants
|
||||
/** Set SCK to max rate of F_CPU/2. */
|
||||
#define SPI_FULL_SPEED SD_SCK_MHZ(50)
|
||||
/** Set SCK rate to F_CPU/3 for Due */
|
||||
#define SPI_DIV3_SPEED SD_SCK_HZ(F_CPU/3)
|
||||
/** Set SCK rate to F_CPU/4. */
|
||||
#define SPI_HALF_SPEED SD_SCK_HZ(F_CPU/4)
|
||||
/** Set SCK rate to F_CPU/6 for Due */
|
||||
#define SPI_DIV6_SPEED SD_SCK_HZ(F_CPU/6)
|
||||
/** Set SCK rate to F_CPU/8. */
|
||||
#define SPI_QUARTER_SPEED SD_SCK_HZ(F_CPU/8)
|
||||
/** Set SCK rate to F_CPU/16. */
|
||||
#define SPI_EIGHTH_SPEED SD_SCK_HZ(F_CPU/16)
|
||||
/** Set SCK rate to F_CPU/32. */
|
||||
#define SPI_SIXTEENTH_SPEED SD_SCK_HZ(F_CPU/32)
|
||||
//------------------------------------------------------------------------------
|
||||
// SD operation timeouts
|
||||
/** CMD0 retry count */
|
||||
const uint8_t SD_CMD0_RETRY = 10;
|
||||
/** command timeout ms */
|
||||
const uint16_t SD_CMD_TIMEOUT = 300;
|
||||
/** init timeout ms */
|
||||
const uint16_t SD_INIT_TIMEOUT = 2000;
|
||||
/** erase timeout ms */
|
||||
const uint16_t SD_ERASE_TIMEOUT = 10000;
|
||||
/** read timeout ms */
|
||||
const uint16_t SD_READ_TIMEOUT = 1000;
|
||||
/** write time out ms */
|
||||
const uint16_t SD_WRITE_TIMEOUT = 2000;
|
||||
//------------------------------------------------------------------------------
|
||||
// SD card commands
|
||||
/** GO_IDLE_STATE - init card in spi mode if CS low */
|
||||
const uint8_t CMD0 = 0X00;
|
||||
/** ALL_SEND_CID - Asks any card to send the CID. */
|
||||
const uint8_t CMD2 = 0X02;
|
||||
/** SEND_RELATIVE_ADDR - Ask the card to publish a new RCA. */
|
||||
const uint8_t CMD3 = 0X03;
|
||||
/** SWITCH_FUNC - Switch Function Command */
|
||||
const uint8_t CMD6 = 0X06;
|
||||
/** SELECT/DESELECT_CARD - toggles between the stand-by and transfer states. */
|
||||
const uint8_t CMD7 = 0X07;
|
||||
/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
|
||||
const uint8_t CMD8 = 0X08;
|
||||
/** SEND_CSD - read the Card Specific Data (CSD register) */
|
||||
const uint8_t CMD9 = 0X09;
|
||||
/** SEND_CID - read the card identification information (CID register) */
|
||||
const uint8_t CMD10 = 0X0A;
|
||||
/** STOP_TRANSMISSION - end multiple block read sequence */
|
||||
const uint8_t CMD12 = 0X0C;
|
||||
/** SEND_STATUS - read the card status register */
|
||||
const uint8_t CMD13 = 0X0D;
|
||||
/** READ_SINGLE_BLOCK - read a single data block from the card */
|
||||
const uint8_t CMD17 = 0X11;
|
||||
/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */
|
||||
const uint8_t CMD18 = 0X12;
|
||||
/** WRITE_BLOCK - write a single data block to the card */
|
||||
const uint8_t CMD24 = 0X18;
|
||||
/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
|
||||
const uint8_t CMD25 = 0X19;
|
||||
/** ERASE_WR_BLK_START - sets the address of the first block to be erased */
|
||||
const uint8_t CMD32 = 0X20;
|
||||
/** ERASE_WR_BLK_END - sets the address of the last block of the continuous
|
||||
range to be erased*/
|
||||
const uint8_t CMD33 = 0X21;
|
||||
/** ERASE - erase all previously selected blocks */
|
||||
const uint8_t CMD38 = 0X26;
|
||||
/** APP_CMD - escape for application specific command */
|
||||
const uint8_t CMD55 = 0X37;
|
||||
/** READ_OCR - read the OCR register of a card */
|
||||
const uint8_t CMD58 = 0X3A;
|
||||
/** CRC_ON_OFF - enable or disable CRC checking */
|
||||
const uint8_t CMD59 = 0X3B;
|
||||
/** SET_BUS_WIDTH - Defines the data bus width for data transfer. */
|
||||
const uint8_t ACMD6 = 0X06;
|
||||
/** SD_STATUS - Send the SD Status. */
|
||||
const uint8_t ACMD13 = 0X0D;
|
||||
/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be
|
||||
pre-erased before writing */
|
||||
const uint8_t ACMD23 = 0X17;
|
||||
/** SD_SEND_OP_COMD - Sends host capacity support information and
|
||||
activates the card's initialization process */
|
||||
const uint8_t ACMD41 = 0X29;
|
||||
//==============================================================================
|
||||
// CARD_STATUS
|
||||
/** The command's argument was out of the allowed range for this card. */
|
||||
const uint32_t CARD_STATUS_OUT_OF_RANGE = 1UL << 31;
|
||||
/** A misaligned address which did not match the block length. */
|
||||
const uint32_t CARD_STATUS_ADDRESS_ERROR = 1UL << 30;
|
||||
/** The transferred block length is not allowed for this card. */
|
||||
const uint32_t CARD_STATUS_BLOCK_LEN_ERROR = 1UL << 29;
|
||||
/** An error in the sequence of erase commands occurred. */
|
||||
const uint32_t CARD_STATUS_ERASE_SEQ_ERROR = 1UL <<28;
|
||||
/** An invalid selection of write-blocks for erase occurred. */
|
||||
const uint32_t CARD_STATUS_ERASE_PARAM = 1UL << 27;
|
||||
/** Set when the host attempts to write to a protected block. */
|
||||
const uint32_t CARD_STATUS_WP_VIOLATION = 1UL << 26;
|
||||
/** When set, signals that the card is locked by the host. */
|
||||
const uint32_t CARD_STATUS_CARD_IS_LOCKED = 1UL << 25;
|
||||
/** Set when a sequence or password error has been detected. */
|
||||
const uint32_t CARD_STATUS_LOCK_UNLOCK_FAILED = 1UL << 24;
|
||||
/** The CRC check of the previous command failed. */
|
||||
const uint32_t CARD_STATUS_COM_CRC_ERROR = 1UL << 23;
|
||||
/** Command not legal for the card state. */
|
||||
const uint32_t CARD_STATUS_ILLEGAL_COMMAND = 1UL << 22;
|
||||
/** Card internal ECC was applied but failed to correct the data. */
|
||||
const uint32_t CARD_STATUS_CARD_ECC_FAILED = 1UL << 21;
|
||||
/** Internal card controller error */
|
||||
const uint32_t CARD_STATUS_CC_ERROR = 1UL << 20;
|
||||
/** A general or an unknown error occurred during the operation. */
|
||||
const uint32_t CARD_STATUS_ERROR = 1UL << 19;
|
||||
// bits 19, 18, and 17 reserved.
|
||||
/** Permanent WP set or attempt to change read only values of CSD. */
|
||||
const uint32_t CARD_STATUS_CSD_OVERWRITE = 1UL <<16;
|
||||
/** partial address space was erased due to write protect. */
|
||||
const uint32_t CARD_STATUS_WP_ERASE_SKIP = 1UL << 15;
|
||||
/** The command has been executed without using the internal ECC. */
|
||||
const uint32_t CARD_STATUS_CARD_ECC_DISABLED = 1UL << 14;
|
||||
/** out of erase sequence command was received. */
|
||||
const uint32_t CARD_STATUS_ERASE_RESET = 1UL << 13;
|
||||
/** The state of the card when receiving the command.
|
||||
* 0 = idle
|
||||
* 1 = ready
|
||||
* 2 = ident
|
||||
* 3 = stby
|
||||
* 4 = tran
|
||||
* 5 = data
|
||||
* 6 = rcv
|
||||
* 7 = prg
|
||||
* 8 = dis
|
||||
* 9-14 = reserved
|
||||
* 15 = reserved for I/O mode
|
||||
*/
|
||||
const uint32_t CARD_STATUS_CURRENT_STATE = 0XF << 9;
|
||||
/** Shift for current state. */
|
||||
const uint32_t CARD_STATUS_CURRENT_STATE_SHIFT = 9;
|
||||
/** Corresponds to buffer empty signaling on the bus. */
|
||||
const uint32_t CARD_STATUS_READY_FOR_DATA = 1UL << 8;
|
||||
// bit 7 reserved.
|
||||
/** Extension Functions may set this bit to get host to deal with events. */
|
||||
const uint32_t CARD_STATUS_FX_EVENT = 1UL << 6;
|
||||
/** The card will expect ACMD, or the command has been interpreted as ACMD */
|
||||
const uint32_t CARD_STATUS_APP_CMD = 1UL << 5;
|
||||
// bit 4 reserved.
|
||||
/** Error in the sequence of the authentication process. */
|
||||
const uint32_t CARD_STATUS_AKE_SEQ_ERROR = 1UL << 3;
|
||||
// bits 2,1, and 0 reserved for manufacturer test mode.
|
||||
//==============================================================================
|
||||
/** status for card in the ready state */
|
||||
const uint8_t R1_READY_STATE = 0X00;
|
||||
/** status for card in the idle state */
|
||||
const uint8_t R1_IDLE_STATE = 0X01;
|
||||
/** status bit for illegal command */
|
||||
const uint8_t R1_ILLEGAL_COMMAND = 0X04;
|
||||
/** start data token for read or write single block*/
|
||||
const uint8_t DATA_START_BLOCK = 0XFE;
|
||||
/** stop token for write multiple blocks*/
|
||||
const uint8_t STOP_TRAN_TOKEN = 0XFD;
|
||||
/** start data token for write multiple blocks*/
|
||||
const uint8_t WRITE_MULTIPLE_TOKEN = 0XFC;
|
||||
/** mask for data response tokens after a write block operation */
|
||||
const uint8_t DATA_RES_MASK = 0X1F;
|
||||
/** write data accepted token */
|
||||
const uint8_t DATA_RES_ACCEPTED = 0X05;
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class CID
|
||||
* \brief Card IDentification (CID) register.
|
||||
*/
|
||||
typedef struct CID {
|
||||
// byte 0
|
||||
/** Manufacturer ID */
|
||||
unsigned char mid;
|
||||
// byte 1-2
|
||||
/** OEM/Application ID */
|
||||
char oid[2];
|
||||
// byte 3-7
|
||||
/** Product name */
|
||||
char pnm[5];
|
||||
// byte 8
|
||||
/** Product revision least significant digit */
|
||||
unsigned char prv_m : 4;
|
||||
/** Product revision most significant digit */
|
||||
unsigned char prv_n : 4;
|
||||
// byte 9-12
|
||||
/** Product serial number */
|
||||
uint32_t psn;
|
||||
// byte 13
|
||||
/** Manufacturing date year low digit */
|
||||
unsigned char mdt_year_high : 4;
|
||||
/** not used */
|
||||
unsigned char reserved : 4;
|
||||
// byte 14
|
||||
/** Manufacturing date month */
|
||||
unsigned char mdt_month : 4;
|
||||
/** Manufacturing date year low digit */
|
||||
unsigned char mdt_year_low : 4;
|
||||
// byte 15
|
||||
/** not used always 1 */
|
||||
unsigned char always1 : 1;
|
||||
/** CRC7 checksum */
|
||||
unsigned char crc : 7;
|
||||
} __attribute__((packed)) cid_t;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class CSDV1
|
||||
* \brief CSD register for version 1.00 cards .
|
||||
*/
|
||||
typedef struct CSDV1 {
|
||||
// byte 0
|
||||
unsigned char reserved1 : 6;
|
||||
unsigned char csd_ver : 2;
|
||||
// byte 1
|
||||
unsigned char taac;
|
||||
// byte 2
|
||||
unsigned char nsac;
|
||||
// byte 3
|
||||
unsigned char tran_speed;
|
||||
// byte 4
|
||||
unsigned char ccc_high;
|
||||
// byte 5
|
||||
unsigned char read_bl_len : 4;
|
||||
unsigned char ccc_low : 4;
|
||||
// byte 6
|
||||
unsigned char c_size_high : 2;
|
||||
unsigned char reserved2 : 2;
|
||||
unsigned char dsr_imp : 1;
|
||||
unsigned char read_blk_misalign : 1;
|
||||
unsigned char write_blk_misalign : 1;
|
||||
unsigned char read_bl_partial : 1;
|
||||
// byte 7
|
||||
unsigned char c_size_mid;
|
||||
// byte 8
|
||||
unsigned char vdd_r_curr_max : 3;
|
||||
unsigned char vdd_r_curr_min : 3;
|
||||
unsigned char c_size_low : 2;
|
||||
// byte 9
|
||||
unsigned char c_size_mult_high : 2;
|
||||
unsigned char vdd_w_cur_max : 3;
|
||||
unsigned char vdd_w_curr_min : 3;
|
||||
// byte 10
|
||||
unsigned char sector_size_high : 6;
|
||||
unsigned char erase_blk_en : 1;
|
||||
unsigned char c_size_mult_low : 1;
|
||||
// byte 11
|
||||
unsigned char wp_grp_size : 7;
|
||||
unsigned char sector_size_low : 1;
|
||||
// byte 12
|
||||
unsigned char write_bl_len_high : 2;
|
||||
unsigned char r2w_factor : 3;
|
||||
unsigned char reserved3 : 2;
|
||||
unsigned char wp_grp_enable : 1;
|
||||
// byte 13
|
||||
unsigned char reserved4 : 5;
|
||||
unsigned char write_partial : 1;
|
||||
unsigned char write_bl_len_low : 2;
|
||||
// byte 14
|
||||
unsigned char reserved5: 2;
|
||||
unsigned char file_format : 2;
|
||||
unsigned char tmp_write_protect : 1;
|
||||
unsigned char perm_write_protect : 1;
|
||||
unsigned char copy : 1;
|
||||
/** Indicates the file format on the card */
|
||||
unsigned char file_format_grp : 1;
|
||||
// byte 15
|
||||
unsigned char always1 : 1;
|
||||
unsigned char crc : 7;
|
||||
} __attribute__((packed)) csd1_t;
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class CSDV2
|
||||
* \brief CSD register for version 2.00 cards.
|
||||
*/
|
||||
typedef struct CSDV2 {
|
||||
// byte 0
|
||||
unsigned char reserved1 : 6;
|
||||
unsigned char csd_ver : 2;
|
||||
// byte 1
|
||||
/** fixed to 0X0E */
|
||||
unsigned char taac;
|
||||
// byte 2
|
||||
/** fixed to 0 */
|
||||
unsigned char nsac;
|
||||
// byte 3
|
||||
unsigned char tran_speed;
|
||||
// byte 4
|
||||
unsigned char ccc_high;
|
||||
// byte 5
|
||||
/** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
|
||||
unsigned char read_bl_len : 4;
|
||||
unsigned char ccc_low : 4;
|
||||
// byte 6
|
||||
/** not used */
|
||||
unsigned char reserved2 : 4;
|
||||
unsigned char dsr_imp : 1;
|
||||
/** fixed to 0 */
|
||||
unsigned char read_blk_misalign : 1;
|
||||
/** fixed to 0 */
|
||||
unsigned char write_blk_misalign : 1;
|
||||
/** fixed to 0 - no partial read */
|
||||
unsigned char read_bl_partial : 1;
|
||||
// byte 7
|
||||
/** high part of card size */
|
||||
unsigned char c_size_high : 6;
|
||||
/** not used */
|
||||
unsigned char reserved3 : 2;
|
||||
// byte 8
|
||||
/** middle part of card size */
|
||||
unsigned char c_size_mid;
|
||||
// byte 9
|
||||
/** low part of card size */
|
||||
unsigned char c_size_low;
|
||||
// byte 10
|
||||
/** sector size is fixed at 64 KB */
|
||||
unsigned char sector_size_high : 6;
|
||||
/** fixed to 1 - erase single is supported */
|
||||
unsigned char erase_blk_en : 1;
|
||||
/** not used */
|
||||
unsigned char reserved4 : 1;
|
||||
// byte 11
|
||||
unsigned char wp_grp_size : 7;
|
||||
/** sector size is fixed at 64 KB */
|
||||
unsigned char sector_size_low : 1;
|
||||
// byte 12
|
||||
/** write_bl_len fixed for 512 byte blocks */
|
||||
unsigned char write_bl_len_high : 2;
|
||||
/** fixed value of 2 */
|
||||
unsigned char r2w_factor : 3;
|
||||
/** not used */
|
||||
unsigned char reserved5 : 2;
|
||||
/** fixed value of 0 - no write protect groups */
|
||||
unsigned char wp_grp_enable : 1;
|
||||
// byte 13
|
||||
unsigned char reserved6 : 5;
|
||||
/** always zero - no partial block read*/
|
||||
unsigned char write_partial : 1;
|
||||
/** write_bl_len fixed for 512 byte blocks */
|
||||
unsigned char write_bl_len_low : 2;
|
||||
// byte 14
|
||||
unsigned char reserved7: 2;
|
||||
/** Do not use always 0 */
|
||||
unsigned char file_format : 2;
|
||||
unsigned char tmp_write_protect : 1;
|
||||
unsigned char perm_write_protect : 1;
|
||||
unsigned char copy : 1;
|
||||
/** Do not use always 0 */
|
||||
unsigned char file_format_grp : 1;
|
||||
// byte 15
|
||||
/** not used always 1 */
|
||||
unsigned char always1 : 1;
|
||||
/** checksum */
|
||||
unsigned char crc : 7;
|
||||
} __attribute__((packed)) csd2_t;
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class csd_t
|
||||
* \brief Union of old and new style CSD register.
|
||||
*/
|
||||
union csd_t {
|
||||
csd1_t v1;
|
||||
csd2_t v2;
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
inline uint32_t sdCardCapacity(csd_t* csd) {
|
||||
if (csd->v1.csd_ver == 0) {
|
||||
uint8_t read_bl_len = csd->v1.read_bl_len;
|
||||
uint16_t c_size = (csd->v1.c_size_high << 10)
|
||||
| (csd->v1.c_size_mid << 2) | csd->v1.c_size_low;
|
||||
uint8_t c_size_mult = (csd->v1.c_size_mult_high << 1)
|
||||
| csd->v1.c_size_mult_low;
|
||||
return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
|
||||
} else if (csd->v2.csd_ver == 1) {
|
||||
uint32_t c_size = 0X10000L * csd->v2.c_size_high + 0X100L
|
||||
* (uint32_t)csd->v2.c_size_mid + csd->v2.c_size_low;
|
||||
return (c_size + 1) << 10;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif // SdInfo_h
|
||||
777
trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.cpp
Normal file
777
trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.cpp
Normal file
@@ -0,0 +1,777 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2022 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.
|
||||
*/
|
||||
#include "SdSpiCard.h"
|
||||
//==============================================================================
|
||||
class Timeout {
|
||||
public:
|
||||
Timeout() {}
|
||||
explicit Timeout(uint16_t ms) {set(ms);}
|
||||
uint16_t millis16() {return millis();}
|
||||
void set(uint16_t ms) {
|
||||
m_endTime = ms + millis16();
|
||||
}
|
||||
bool timedOut() {
|
||||
return (int16_t)(m_endTime - millis16()) < 0;
|
||||
}
|
||||
private:
|
||||
uint16_t m_endTime;
|
||||
};
|
||||
//==============================================================================
|
||||
#if USE_SD_CRC
|
||||
// CRC functions
|
||||
//------------------------------------------------------------------------------
|
||||
static uint8_t CRC7(const uint8_t* data, uint8_t n) {
|
||||
uint8_t crc = 0;
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
uint8_t d = data[i];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
crc <<= 1;
|
||||
if ((d & 0x80) ^ (crc & 0x80)) {
|
||||
crc ^= 0x09;
|
||||
}
|
||||
d <<= 1;
|
||||
}
|
||||
}
|
||||
return (crc << 1) | 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#if USE_SD_CRC == 1
|
||||
// Shift based CRC-CCITT
|
||||
// uses the x^16,x^12,x^5,x^1 polynomial.
|
||||
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
||||
uint16_t crc = 0;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
crc = (uint8_t)(crc >> 8) | (crc << 8);
|
||||
crc ^= data[i];
|
||||
crc ^= (uint8_t)(crc & 0xff) >> 4;
|
||||
crc ^= crc << 12;
|
||||
crc ^= (crc & 0xff) << 5;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
#elif USE_SD_CRC > 1 // CRC_CCITT
|
||||
//------------------------------------------------------------------------------
|
||||
// Table based CRC-CCITT
|
||||
// uses the x^16,x^12,x^5,x^1 polynomial.
|
||||
#ifdef __AVR__
|
||||
static const uint16_t crctab[] PROGMEM = {
|
||||
#else // __AVR__
|
||||
static const uint16_t crctab[] = {
|
||||
#endif // __AVR__
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
|
||||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
};
|
||||
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
||||
uint16_t crc = 0;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
#ifdef __AVR__
|
||||
crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0XFF]) ^ (crc << 8);
|
||||
#else // __AVR__
|
||||
crc = crctab[(crc >> 8 ^ data[i]) & 0XFF] ^ (crc << 8);
|
||||
#endif // __AVR__
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
#endif // CRC_CCITT
|
||||
#endif // USE_SD_CRC
|
||||
//==============================================================================
|
||||
// SharedSpiCard member functions
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
Timeout timeout;
|
||||
m_spiActive = false;
|
||||
m_beginCalled = false;
|
||||
m_errorCode = SD_CARD_ERROR_NONE;
|
||||
m_type = 0;
|
||||
m_csPin = spiConfig.csPin;
|
||||
#if SPI_DRIVER_SELECT >= 2
|
||||
m_spiDriverPtr = spiConfig.spiPort;
|
||||
if (!m_spiDriverPtr) {
|
||||
error(SD_CARD_ERROR_INVALID_CARD_CONFIG);
|
||||
goto fail;
|
||||
}
|
||||
#endif // SPI_DRIVER_SELECT
|
||||
sdCsInit(m_csPin);
|
||||
spiUnselect();
|
||||
spiSetSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ);
|
||||
spiBegin(spiConfig);
|
||||
m_beginCalled = true;
|
||||
uint32_t arg;
|
||||
m_state = IDLE_STATE;
|
||||
spiStart();
|
||||
|
||||
// must supply min of 74 clock cycles with CS high.
|
||||
spiUnselect();
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
spiSend(0XFF);
|
||||
}
|
||||
spiSelect();
|
||||
// command to go idle in SPI mode
|
||||
for (uint8_t i = 1;; i++) {
|
||||
if (cardCommand(CMD0, 0) == R1_IDLE_STATE) {
|
||||
break;
|
||||
}
|
||||
if (i == SD_CMD0_RETRY) {
|
||||
error(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
// Force any active transfer to end for an already initialized card.
|
||||
for (uint8_t j = 0; j < 0XFF; j++) {
|
||||
spiSend(0XFF);
|
||||
}
|
||||
}
|
||||
#if USE_SD_CRC
|
||||
if (cardCommand(CMD59, 1) != R1_IDLE_STATE) {
|
||||
error(SD_CARD_ERROR_CMD59);
|
||||
goto fail;
|
||||
}
|
||||
#endif // USE_SD_CRC
|
||||
// check SD version
|
||||
if (!(cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
|
||||
type(SD_CARD_TYPE_SD2);
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
m_status = spiReceive();
|
||||
}
|
||||
if (m_status != 0XAA) {
|
||||
error(SD_CARD_ERROR_CMD8);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
type(SD_CARD_TYPE_SD1);
|
||||
}
|
||||
// initialize card and send host supports SDHC if SD2
|
||||
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
|
||||
timeout.set(SD_INIT_TIMEOUT);
|
||||
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
|
||||
// check for timeout
|
||||
if (timeout.timedOut()) {
|
||||
error(SD_CARD_ERROR_ACMD41);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
// if SD2 read OCR register to check for SDHC card
|
||||
if (type() == SD_CARD_TYPE_SD2) {
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
error(SD_CARD_ERROR_CMD58);
|
||||
goto fail;
|
||||
}
|
||||
if ((spiReceive() & 0XC0) == 0XC0) {
|
||||
type(SD_CARD_TYPE_SDHC);
|
||||
}
|
||||
// Discard rest of ocr - contains allowed voltage range.
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
spiReceive();
|
||||
}
|
||||
}
|
||||
spiStop();
|
||||
spiSetSckSpeed(spiConfig.maxSck);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::cardCMD6(uint32_t arg, uint8_t* status) {
|
||||
if (cardCommand(CMD6, arg)) {
|
||||
error(SD_CARD_ERROR_CMD6);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(status, 64)) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// send command and return error code. Return zero for OK
|
||||
uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
if (!syncDevice()) {
|
||||
return 0XFF;
|
||||
}
|
||||
// select card
|
||||
if (!m_spiActive) {
|
||||
spiStart();
|
||||
}
|
||||
if (cmd != CMD0 && cmd != CMD12 && !waitReady(SD_CMD_TIMEOUT)) {
|
||||
return 0XFF;
|
||||
}
|
||||
#if USE_SD_CRC
|
||||
// form message
|
||||
uint8_t buf[6];
|
||||
buf[0] = (uint8_t)0x40U | cmd;
|
||||
buf[1] = (uint8_t)(arg >> 24U);
|
||||
buf[2] = (uint8_t)(arg >> 16U);
|
||||
buf[3] = (uint8_t)(arg >> 8U);
|
||||
buf[4] = (uint8_t)arg;
|
||||
|
||||
// add CRC
|
||||
buf[5] = CRC7(buf, 5);
|
||||
|
||||
// send message
|
||||
spiSend(buf, 6);
|
||||
#else // USE_SD_CRC
|
||||
// send command
|
||||
spiSend(cmd | 0x40);
|
||||
|
||||
// send argument
|
||||
uint8_t* pa = reinterpret_cast<uint8_t*>(&arg);
|
||||
for (int8_t i = 3; i >= 0; i--) {
|
||||
spiSend(pa[i]);
|
||||
}
|
||||
|
||||
// send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA
|
||||
spiSend(cmd == CMD0 ? 0X95 : 0X87);
|
||||
#endif // USE_SD_CRC
|
||||
|
||||
// discard first fill byte to avoid MISO pull-up problem.
|
||||
spiReceive();
|
||||
|
||||
// there are 1-8 fill bytes before response. fill bytes should be 0XFF.
|
||||
uint16_t n = 0;
|
||||
do {
|
||||
m_status = spiReceive();
|
||||
} while (m_status & 0X80 && ++n < 10);
|
||||
return m_status;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::end() {
|
||||
if (m_beginCalled) {
|
||||
spiStop();
|
||||
spiEnd();
|
||||
m_beginCalled = false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
csd_t csd;
|
||||
if (!readCSD(&csd)) {
|
||||
goto fail;
|
||||
}
|
||||
// check for single sector erase
|
||||
if (!csd.eraseSingleBlock()) {
|
||||
// erase size mask
|
||||
uint8_t m = csd.eraseSize() - 1;
|
||||
if ((firstSector & m) != 0 || ((lastSector + 1) & m) != 0) {
|
||||
// error card can't erase specified area
|
||||
error(SD_CARD_ERROR_ERASE_SINGLE_SECTOR);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (m_type != SD_CARD_TYPE_SDHC) {
|
||||
firstSector <<= 9;
|
||||
lastSector <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD32, firstSector)
|
||||
|| cardCommand(CMD33, lastSector)
|
||||
|| cardCommand(CMD38, 0)) {
|
||||
error(SD_CARD_ERROR_ERASE);
|
||||
goto fail;
|
||||
}
|
||||
if (!waitReady(SD_ERASE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::eraseSingleSectorEnable() {
|
||||
csd_t csd;
|
||||
return readCSD(&csd) ? csd.eraseSingleBlock() : false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::isBusy() {
|
||||
if (m_state == READ_STATE) {
|
||||
return false;
|
||||
}
|
||||
bool spiActive = m_spiActive;
|
||||
if (!spiActive) {
|
||||
spiStart();
|
||||
}
|
||||
bool rtn = 0XFF != spiReceive();
|
||||
if (!spiActive) {
|
||||
spiStop();
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readData(uint8_t* dst) {
|
||||
return readData(dst, 512);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readData(uint8_t* dst, size_t count) {
|
||||
#if USE_SD_CRC
|
||||
uint16_t crc;
|
||||
#endif // USE_SD_CRC
|
||||
|
||||
// wait for start sector token
|
||||
Timeout timeout(SD_READ_TIMEOUT);
|
||||
while ((m_status = spiReceive()) == 0XFF) {
|
||||
if (timeout.timedOut()) {
|
||||
error(SD_CARD_ERROR_READ_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (m_status != DATA_START_SECTOR) {
|
||||
error(SD_CARD_ERROR_READ_TOKEN);
|
||||
goto fail;
|
||||
}
|
||||
// transfer data
|
||||
if ((m_status = spiReceive(dst, count))) {
|
||||
error(SD_CARD_ERROR_DMA);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if USE_SD_CRC
|
||||
// get crc
|
||||
crc = (spiReceive() << 8) | spiReceive();
|
||||
if (crc != CRC_CCITT(dst, count)) {
|
||||
error(SD_CARD_ERROR_READ_CRC);
|
||||
goto fail;
|
||||
}
|
||||
#else // USE_SD_CRC
|
||||
// discard crc
|
||||
spiReceive();
|
||||
spiReceive();
|
||||
#endif // USE_SD_CRC
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readOCR(uint32_t* ocr) {
|
||||
uint8_t* p = reinterpret_cast<uint8_t*>(ocr);
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
error(SD_CARD_ERROR_CMD58);
|
||||
goto fail;
|
||||
}
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
p[3 - i] = spiReceive();
|
||||
#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
p[i] = spiReceive();
|
||||
#endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** read CID or CSR register */
|
||||
bool SharedSpiCard::readRegister(uint8_t cmd, void* buf) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
|
||||
if (cardCommand(cmd, 0)) {
|
||||
error(SD_CARD_ERROR_READ_REG);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, 16)) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readSCR(scr_t* scr) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(scr);
|
||||
if (cardAcmd(ACMD51, 0)) {
|
||||
error(SD_CARD_ERROR_ACMD51);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, sizeof(scr_t))) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD17, sector)) {
|
||||
error(SD_CARD_ERROR_CMD17);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, 512)) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
if (!readStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, dst += 512) {
|
||||
if (!readData(dst, 512)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return readStop();
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readStart(uint32_t sector) {
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD18, sector)) {
|
||||
error(SD_CARD_ERROR_CMD18);
|
||||
goto fail;
|
||||
}
|
||||
m_state = READ_STATE;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readStatus(SdStatus* status) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(status);
|
||||
// retrun is R2 so read extra status byte.
|
||||
if (cardAcmd(ACMD13, 0) || spiReceive()) {
|
||||
error(SD_CARD_ERROR_ACMD13);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, 64)) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readStop() {
|
||||
m_state = IDLE_STATE;
|
||||
if (cardCommand(CMD12, 0)) {
|
||||
error(SD_CARD_ERROR_CMD12);
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SharedSpiCard::sectorCount() {
|
||||
csd_t csd;
|
||||
return readCSD(&csd) ? csd.capacity() : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::spiStart() {
|
||||
if (!m_spiActive) {
|
||||
spiActivate();
|
||||
m_spiActive = true;
|
||||
spiSelect();
|
||||
// Dummy byte to drive MISO busy status.
|
||||
spiSend(0XFF);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::spiStop() {
|
||||
if (m_spiActive) {
|
||||
spiUnselect();
|
||||
// Insure MISO goes to low Z.
|
||||
spiSend(0XFF);
|
||||
spiDeactivate();
|
||||
m_spiActive = false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::syncDevice() {
|
||||
if (m_state == WRITE_STATE) {
|
||||
return writeStop();
|
||||
}
|
||||
if (m_state == READ_STATE) {
|
||||
return readStop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::waitReady(uint16_t ms) {
|
||||
Timeout timeout(ms);
|
||||
while (spiReceive() != 0XFF) {
|
||||
if (timeout.timedOut()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeData(const uint8_t* src) {
|
||||
// wait for previous write to finish
|
||||
if (!waitReady(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// send one sector of data for write sector or write multiple sectors
|
||||
bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) {
|
||||
#if USE_SD_CRC
|
||||
uint16_t crc = CRC_CCITT(src, 512);
|
||||
#else // USE_SD_CRC
|
||||
uint16_t crc = 0XFFFF;
|
||||
#endif // USE_SD_CRC
|
||||
spiSend(token);
|
||||
spiSend(src, 512);
|
||||
spiSend(crc >> 8);
|
||||
spiSend(crc & 0XFF);
|
||||
|
||||
m_status = spiReceive();
|
||||
if ((m_status & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
|
||||
error(SD_CARD_ERROR_WRITE_DATA);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD24, sector)) {
|
||||
error(SD_CARD_ERROR_CMD24);
|
||||
goto fail;
|
||||
}
|
||||
if (!writeData(DATA_START_SECTOR, src)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if CHECK_FLASH_PROGRAMMING
|
||||
// wait for flash programming to complete
|
||||
if (!waitReady(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_WRITE_PROGRAMMING);
|
||||
goto fail;
|
||||
}
|
||||
// response is r2 so get and check two bytes for nonzero
|
||||
if (cardCommand(CMD13, 0) || spiReceive()) {
|
||||
error(SD_CARD_ERROR_CMD13);
|
||||
goto fail;
|
||||
}
|
||||
#endif // CHECK_FLASH_PROGRAMMING
|
||||
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeSectors(uint32_t sector,
|
||||
const uint8_t* src, size_t ns) {
|
||||
if (!writeStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, src += 512) {
|
||||
if (!writeData(src)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return writeStop();
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeStart(uint32_t sector) {
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD25, sector)) {
|
||||
error(SD_CARD_ERROR_CMD25);
|
||||
goto fail;
|
||||
}
|
||||
m_state = WRITE_STATE;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeStop() {
|
||||
if (!waitReady(SD_WRITE_TIMEOUT)) {
|
||||
goto fail;
|
||||
}
|
||||
spiSend(STOP_TRAN_TOKEN);
|
||||
spiStop();
|
||||
m_state = IDLE_STATE;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
error(SD_CARD_ERROR_STOP_TRAN);
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//==============================================================================
|
||||
bool DedicatedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
if (!SharedSpiCard::begin(spiConfig)) {
|
||||
return false;
|
||||
}
|
||||
m_dedicatedSpi = spiOptionDedicated(spiConfig.options);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
return readSectors(sector, dst, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::readSectors(
|
||||
uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
if (sdState() != READ_STATE || sector != m_curSector) {
|
||||
if (!readStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, dst += 512) {
|
||||
if (!readData(dst)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_dedicatedSpi ? true : readStop();
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::setDedicatedSpi(bool value) {
|
||||
if (!syncDevice()) {
|
||||
return false;
|
||||
}
|
||||
m_dedicatedSpi = value;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
if (m_dedicatedSpi) {
|
||||
return writeSectors(sector, src, 1);
|
||||
}
|
||||
return SharedSpiCard::writeSector(sector, src);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::writeSectors(
|
||||
uint32_t sector, const uint8_t* src, size_t ns) {
|
||||
if (sdState() != WRITE_STATE || m_curSector != sector) {
|
||||
if (!writeStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, src += 512) {
|
||||
if (!writeData(src)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_dedicatedSpi ? true : writeStop();
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
451
trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.h
Normal file
451
trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.h
Normal file
@@ -0,0 +1,451 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2022 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.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief SdSpiCard class for V2 SD/SDHC cards
|
||||
*/
|
||||
#ifndef SdSpiCard_h
|
||||
#define SdSpiCard_h
|
||||
#include <stddef.h>
|
||||
#include "../common/SysCall.h"
|
||||
#include "SdCardInfo.h"
|
||||
#include "SdCardInterface.h"
|
||||
#include "../SpiDriver/SdSpiDriver.h"
|
||||
/** Verify correct SPI active if non-zero. */
|
||||
#define CHECK_SPI_ACTIVE 0
|
||||
#if CHECK_SPI_ACTIVE
|
||||
/** Check SPI active. */
|
||||
#define SPI_ASSERT_ACTIVE {if (!m_spiActive) {\
|
||||
Serial.print(F("SPI_ASSERTACTIVE"));\
|
||||
Serial.println(__LINE__);}}
|
||||
#else // CHECK_SPI_ACTIVE
|
||||
/** Do not check SPI active. */
|
||||
#define SPI_ASSERT_ACTIVE
|
||||
#endif // CHECK_SPI_ACTIVE
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SharedSpiCard
|
||||
* \brief Raw access to SD and SDHC flash memory cards via shared SPI port.
|
||||
*/
|
||||
#if HAS_SDIO_CLASS
|
||||
class SharedSpiCard : public SdCardInterface {
|
||||
#elif USE_BLOCK_DEVICE_INTERFACE
|
||||
class SharedSpiCard : public FsBlockDeviceInterface {
|
||||
#else // HAS_SDIO_CLASS
|
||||
class SharedSpiCard {
|
||||
#endif // HAS_SDIO_CLASS
|
||||
public:
|
||||
/** SD is in idle state */
|
||||
static const uint8_t IDLE_STATE = 0;
|
||||
/** SD is in multi-sector read state. */
|
||||
static const uint8_t READ_STATE = 1;
|
||||
/** SD is in multi-sector write state. */
|
||||
static const uint8_t WRITE_STATE = 2;
|
||||
/** Construct an instance of SharedSpiCard. */
|
||||
SharedSpiCard() {}
|
||||
/** Initialize the SD card.
|
||||
* \param[in] spiConfig SPI card configuration.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdSpiConfig spiConfig);
|
||||
/** CMD6 Switch mode: Check Function Set Function.
|
||||
* \param[in] arg CMD6 argument.
|
||||
* \param[out] status return status data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool cardCMD6(uint32_t arg, uint8_t* status);
|
||||
/** End use of card */
|
||||
void end();
|
||||
/** Erase a range of sectors.
|
||||
*
|
||||
* \param[in] firstSector The address of the first sector in the range.
|
||||
* \param[in] lastSector The address of the last sector in the range.
|
||||
*
|
||||
* \note This function requests the SD card to do a flash erase for a
|
||||
* range of sectors. The data on the card after an erase operation is
|
||||
* either 0 or 1, depends on the card vendor. The card must support
|
||||
* single sector erase.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool erase(uint32_t firstSector, uint32_t lastSector);
|
||||
/** Determine if card supports single sector erase.
|
||||
*
|
||||
* \return true is returned if single sector erase is supported.
|
||||
* false is returned if single sector erase is not supported.
|
||||
*/
|
||||
bool eraseSingleSectorEnable();
|
||||
/**
|
||||
* Set SD error code.
|
||||
* \param[in] code value for error code.
|
||||
*/
|
||||
void error(uint8_t code) {
|
||||
// (void)code;
|
||||
m_errorCode = code;
|
||||
}
|
||||
/**
|
||||
* \return code for the last error. See SdCardInfo.h for a list of error codes.
|
||||
*/
|
||||
uint8_t errorCode() const {
|
||||
return m_errorCode;
|
||||
}
|
||||
/** \return error data for last error. */
|
||||
uint32_t errorData() const {
|
||||
return m_status;
|
||||
}
|
||||
/** \return false for shared class. */
|
||||
bool hasDedicatedSpi() {return false;}
|
||||
/**
|
||||
* Check for busy. MISO low indicates the card is busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
bool isBusy();
|
||||
/** \return false, can't be in dedicated state. */
|
||||
bool isDedicatedSpi() {return false;}
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
* information such as Manufacturer ID, Product name, Product serial
|
||||
* number and Manufacturing date.
|
||||
*
|
||||
* \param[out] cid pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCID(cid_t* cid) {
|
||||
return readRegister(CMD10, cid);
|
||||
}
|
||||
/**
|
||||
* Read a card's CSD register. The CSD contains Card-Specific Data that
|
||||
* provides information regarding access to the card's contents.
|
||||
*
|
||||
* \param[out] csd pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCSD(csd_t* csd) {
|
||||
return readRegister(CMD9, csd);
|
||||
}
|
||||
/** Read one data sector in a multiple sector read sequence
|
||||
*
|
||||
* \param[out] dst Pointer to the location for the data to be read.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readData(uint8_t* dst);
|
||||
/** Read OCR register.
|
||||
*
|
||||
* \param[out] ocr Value of OCR register.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readOCR(uint32_t* ocr);
|
||||
/** Read SCR register.
|
||||
*
|
||||
* \param[out] scr Value of SCR register.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSCR(scr_t* scr);
|
||||
/**
|
||||
* Read a 512 byte sector from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSector(uint32_t sector, uint8_t* dst);
|
||||
/**
|
||||
* Read multiple 512 byte sectors from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[in] ns Number of sectors to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t ns);
|
||||
|
||||
/** Start a read multiple sector sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
*
|
||||
* \note This function is used with readData() and readStop() for optimized
|
||||
* multiple sector reads. SPI chipSelect must be low for the entire sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStart(uint32_t sector);
|
||||
/** Return the 64 byte card status
|
||||
* \param[out] status location for 64 status bytes.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStatus(SdStatus* status);
|
||||
/** End a read multiple sectors sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStop();
|
||||
/** \return SD multi-sector read/write state */
|
||||
uint8_t sdState() {return m_state;}
|
||||
/**
|
||||
* Determine the size of an SD flash memory card.
|
||||
*
|
||||
* \return The number of 512 byte data sectors in the card
|
||||
* or zero if an error occurs.
|
||||
*/
|
||||
uint32_t sectorCount();
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
// Use sectorCount(). cardSize() will be removed in the future.
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return false for shared card
|
||||
*/
|
||||
bool setDedicatedSpi(bool value) {
|
||||
(void)value;
|
||||
return false;
|
||||
}
|
||||
/** end a mult-sector transfer.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool stopTransfer();
|
||||
/** \return success if sync successful. Not for user apps. */
|
||||
bool syncDevice();
|
||||
/** Return the card type: SD V1, SD V2 or SDHC/SDXC
|
||||
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC/SDXC.
|
||||
*/
|
||||
uint8_t type() const {
|
||||
return m_type;
|
||||
}
|
||||
/**
|
||||
* Write a 512 byte sector to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSector(uint32_t sector, const uint8_t* src);
|
||||
/**
|
||||
* Write multiple 512 byte sectors to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] ns Number of sectors to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns);
|
||||
/** Write one data sector in a multiple sector write sequence.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeData(const uint8_t* src);
|
||||
/** Start a write multiple sectors sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
*
|
||||
* \note This function is used with writeData() and writeStop()
|
||||
* for optimized multiple sector writes.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeStart(uint32_t sector);
|
||||
|
||||
/** End a write multiple sectors sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeStop();
|
||||
|
||||
private:
|
||||
// private functions
|
||||
uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {
|
||||
cardCommand(CMD55, 0);
|
||||
return cardCommand(cmd, arg);
|
||||
}
|
||||
uint8_t cardCommand(uint8_t cmd, uint32_t arg);
|
||||
bool readData(uint8_t* dst, size_t count);
|
||||
bool readRegister(uint8_t cmd, void* buf);
|
||||
void spiSelect() {
|
||||
sdCsWrite(m_csPin, false);
|
||||
}
|
||||
void spiStart();
|
||||
void spiStop();
|
||||
void spiUnselect() {
|
||||
sdCsWrite(m_csPin, true);
|
||||
}
|
||||
void type(uint8_t value) {
|
||||
m_type = value;
|
||||
}
|
||||
bool waitReady(uint16_t ms);
|
||||
bool writeData(uint8_t token, const uint8_t* src);
|
||||
#if SPI_DRIVER_SELECT < 2
|
||||
void spiActivate() {
|
||||
m_spiDriver.activate();
|
||||
}
|
||||
void spiBegin(SdSpiConfig spiConfig) {
|
||||
m_spiDriver.begin(spiConfig);
|
||||
}
|
||||
void spiDeactivate() {
|
||||
m_spiDriver.deactivate();
|
||||
}
|
||||
void spiEnd() {
|
||||
m_spiDriver.end();
|
||||
}
|
||||
uint8_t spiReceive() {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
return m_spiDriver.receive();
|
||||
}
|
||||
uint8_t spiReceive(uint8_t* buf, size_t n) {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
return m_spiDriver.receive(buf, n);
|
||||
}
|
||||
void spiSend(uint8_t data) {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
m_spiDriver.send(data);
|
||||
}
|
||||
void spiSend(const uint8_t* buf, size_t n) {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
m_spiDriver.send(buf, n);
|
||||
}
|
||||
void spiSetSckSpeed(uint32_t maxSck) {
|
||||
m_spiDriver.setSckSpeed(maxSck);
|
||||
}
|
||||
SdSpiDriver m_spiDriver;
|
||||
#else // SPI_DRIVER_SELECT < 2
|
||||
void spiActivate() {
|
||||
m_spiDriverPtr->activate();
|
||||
}
|
||||
void spiBegin(SdSpiConfig spiConfig) {
|
||||
m_spiDriverPtr->begin(spiConfig);
|
||||
}
|
||||
void spiDeactivate() {
|
||||
m_spiDriverPtr->deactivate();
|
||||
}
|
||||
void spiEnd() {
|
||||
m_spiDriverPtr->end();
|
||||
}
|
||||
uint8_t spiReceive() {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
return m_spiDriverPtr->receive();
|
||||
}
|
||||
uint8_t spiReceive(uint8_t* buf, size_t n) {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
return m_spiDriverPtr->receive(buf, n);
|
||||
}
|
||||
void spiSend(uint8_t data) {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
m_spiDriverPtr->send(data);
|
||||
}
|
||||
void spiSend(const uint8_t* buf, size_t n) {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
m_spiDriverPtr->send(buf, n);
|
||||
}
|
||||
void spiSetSckSpeed(uint32_t maxSck) {
|
||||
m_spiDriverPtr->setSckSpeed(maxSck);
|
||||
}
|
||||
SdSpiDriver* m_spiDriverPtr;
|
||||
|
||||
#endif // SPI_DRIVER_SELECT < 2
|
||||
bool m_beginCalled = false;
|
||||
SdCsPin_t m_csPin;
|
||||
uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
|
||||
bool m_spiActive;
|
||||
uint8_t m_state;
|
||||
uint8_t m_status;
|
||||
uint8_t m_type = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class DedicatedSpiCard
|
||||
* \brief Raw access to SD and SDHC flash memory cards via dedicate SPI port.
|
||||
*/
|
||||
class DedicatedSpiCard : public SharedSpiCard {
|
||||
public:
|
||||
/** Construct an instance of DedicatedSpiCard. */
|
||||
DedicatedSpiCard() {}
|
||||
/** Initialize the SD card.
|
||||
* \param[in] spiConfig SPI card configuration.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdSpiConfig spiConfig);
|
||||
/** \return true, can be in dedicaded state. */
|
||||
bool hasDedicatedSpi() {return true;}
|
||||
/** \return true if in dedicated SPI state. */
|
||||
bool isDedicatedSpi() {return m_dedicatedSpi;}
|
||||
/**
|
||||
* Read a 512 byte sector from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSector(uint32_t sector, uint8_t* dst);
|
||||
/**
|
||||
* Read multiple 512 byte sectors from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[in] ns Number of sectors to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t ns);
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return true for success else false;
|
||||
*/
|
||||
bool setDedicatedSpi(bool value);
|
||||
/**
|
||||
* Write a 512 byte sector to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSector(uint32_t sector, const uint8_t* src);
|
||||
/**
|
||||
* Write multiple 512 byte sectors to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] ns Number of sectors to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns);
|
||||
|
||||
private:
|
||||
uint32_t m_curSector;
|
||||
bool m_dedicatedSpi = false;
|
||||
};
|
||||
//==============================================================================
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
/** typedef for dedicated SPI. */
|
||||
typedef DedicatedSpiCard SdSpiCard;
|
||||
#else
|
||||
/** typedef for shared SPI. */
|
||||
typedef SharedSpiCard SdSpiCard;
|
||||
#endif
|
||||
#endif // SdSpiCard_h
|
||||
94
trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCardEX.cpp
Normal file
94
trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCardEX.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2018 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.
|
||||
*/
|
||||
#include "SdSpiCard.h"
|
||||
bool SdSpiCardEX::readBlock(uint32_t block, uint8_t* dst) {
|
||||
if (m_curState != READ_STATE || block != m_curBlock) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
if (!SdSpiCard::readStart(block)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock = block;
|
||||
m_curState = READ_STATE;
|
||||
}
|
||||
if (!SdSpiCard::readData(dst)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock++;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::readBlocks(uint32_t block, uint8_t* dst, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!readBlock(block + i, dst + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::syncBlocks() {
|
||||
if (m_curState == READ_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdSpiCard::readStop()) {
|
||||
return false;
|
||||
}
|
||||
} else if (m_curState == WRITE_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdSpiCard::writeStop()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::writeBlock(uint32_t block, const uint8_t* src) {
|
||||
if (m_curState != WRITE_STATE || m_curBlock != block) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
if (!SdSpiCard::writeStart(block)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock = block;
|
||||
m_curState = WRITE_STATE;
|
||||
}
|
||||
if (!SdSpiCard::writeData(src)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock++;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::writeBlocks(uint32_t block,
|
||||
const uint8_t* src, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!writeBlock(block + i, src + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
267
trunk/Arduino/libraries/SdFat/src/SdCard/SdioCard.h
Normal file
267
trunk/Arduino/libraries/SdFat/src/SdCard/SdioCard.h
Normal file
@@ -0,0 +1,267 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2022 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 SdioCard_h
|
||||
#define SdioCard_h
|
||||
#include "../common/SysCall.h"
|
||||
#include "SdCardInterface.h"
|
||||
|
||||
#define FIFO_SDIO 0
|
||||
#define DMA_SDIO 1
|
||||
/**
|
||||
* \class SdioConfig
|
||||
* \brief SDIO card configuration.
|
||||
*/
|
||||
class SdioConfig {
|
||||
public:
|
||||
SdioConfig() {}
|
||||
/**
|
||||
* SdioConfig constructor.
|
||||
* \param[in] opt SDIO options.
|
||||
*/
|
||||
explicit SdioConfig(uint8_t opt) : m_options(opt) {}
|
||||
/** \return SDIO card options. */
|
||||
uint8_t options() {return m_options;}
|
||||
/** \return true if DMA_SDIO. */
|
||||
bool useDma() {return m_options & DMA_SDIO;}
|
||||
private:
|
||||
uint8_t m_options = FIFO_SDIO;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdioCard
|
||||
* \brief Raw SDIO access to SD and SDHC flash memory cards.
|
||||
*/
|
||||
class SdioCard : public SdCardInterface {
|
||||
public:
|
||||
/** Initialize the SD card.
|
||||
* \param[in] sdioConfig SDIO card configuration.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdioConfig sdioConfig);
|
||||
/** CMD6 Switch mode: Check Function Set Function.
|
||||
* \param[in] arg CMD6 argument.
|
||||
* \param[out] status return status data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool cardCMD6(uint32_t arg, uint8_t* status);
|
||||
/** Disable an SDIO card.
|
||||
* not implemented.
|
||||
*/
|
||||
void end() {}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Erase a range of sectors.
|
||||
*
|
||||
* \param[in] firstSector The address of the first sector in the range.
|
||||
* \param[in] lastSector The address of the last sector in the range.
|
||||
*
|
||||
* \note This function requests the SD card to do a flash erase for a
|
||||
* range of sectors. The data on the card after an erase operation is
|
||||
* either 0 or 1, depends on the card vendor. The card must support
|
||||
* single sector erase.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool erase(uint32_t firstSector, uint32_t lastSector);
|
||||
/**
|
||||
* \return code for the last error. See SdCardInfo.h for a list of error codes.
|
||||
*/
|
||||
uint8_t errorCode() const;
|
||||
/** \return error data for last error. */
|
||||
uint32_t errorData() const;
|
||||
/** \return error line for last error. Tmp function for debug. */
|
||||
uint32_t errorLine() const;
|
||||
/**
|
||||
* Check for busy with CMD13.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
bool isBusy();
|
||||
/** \return the SD clock frequency in kHz. */
|
||||
uint32_t kHzSdClk();
|
||||
/**
|
||||
* Read a 512 byte sector from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSector(uint32_t sector, uint8_t* dst);
|
||||
/**
|
||||
* Read multiple 512 byte sectors from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[in] ns Number of sectors to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t ns);
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
* information such as Manufacturer ID, Product name, Product serial
|
||||
* number and Manufacturing date.
|
||||
*
|
||||
* \param[out] cid pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCID(cid_t* cid);
|
||||
/**
|
||||
* Read a card's CSD register. The CSD contains Card-Specific Data that
|
||||
* provides information regarding access to the card's contents.
|
||||
*
|
||||
* \param[out] csd pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCSD(csd_t* csd);
|
||||
/** Read one data sector in a multiple sector read sequence
|
||||
*
|
||||
* \param[out] dst Pointer to the location for the data to be read.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readData(uint8_t* dst);
|
||||
/** Read OCR register.
|
||||
*
|
||||
* \param[out] ocr Value of OCR register.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readOCR(uint32_t* ocr);
|
||||
/** Read SCR register.
|
||||
*
|
||||
* \param[out] scr Value of SCR register.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSCR(scr_t *scr);
|
||||
/** Start a read multiple sectors sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
*
|
||||
* \note This function is used with readData() and readStop() for optimized
|
||||
* multiple sector reads. SPI chipSelect must be low for the entire sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStart(uint32_t sector);
|
||||
/** Start a read multiple sectors sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
* \param[in] count Maximum sector count.
|
||||
* \note This function is used with readData() and readStop() for optimized
|
||||
* multiple sector reads. SPI chipSelect must be low for the entire sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStart(uint32_t sector, uint32_t count);
|
||||
/** End a read multiple sectors sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readStop();
|
||||
/** \return SDIO card status. */
|
||||
uint32_t status();
|
||||
/**
|
||||
* Determine the size of an SD flash memory card.
|
||||
*
|
||||
* \return The number of 512 byte data sectors in the card
|
||||
* or zero if an error occurs.
|
||||
*/
|
||||
uint32_t sectorCount();
|
||||
/**
|
||||
* Send CMD12 to stop read or write.
|
||||
*
|
||||
* \param[in] blocking If true, wait for command complete.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool stopTransmission(bool blocking);
|
||||
/** \return success if sync successful. Not for user apps. */
|
||||
bool syncDevice();
|
||||
/** Return the card type: SD V1, SD V2 or SDHC
|
||||
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
|
||||
*/
|
||||
uint8_t type() const;
|
||||
/**
|
||||
* Writes a 512 byte sector to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSector(uint32_t sector, const uint8_t* src);
|
||||
/**
|
||||
* Write multiple 512 byte sectors to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] ns Number of sectors to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns);
|
||||
/** Write one data sector in a multiple sector write sequence.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeData(const uint8_t* src);
|
||||
/** Start a write multiple sectors sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
*
|
||||
* \note This function is used with writeData() and writeStop()
|
||||
* for optimized multiple sector writes.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeStart(uint32_t sector);
|
||||
/** Start a write multiple sectors sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
* \param[in] count Maximum sector count.
|
||||
* \note This function is used with writeData() and writeStop()
|
||||
* for optimized multiple sector writes.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeStart(uint32_t sector, uint32_t count);
|
||||
|
||||
/** End a write multiple sectors sequence.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeStop();
|
||||
|
||||
private:
|
||||
static const uint8_t IDLE_STATE = 0;
|
||||
static const uint8_t READ_STATE = 1;
|
||||
static const uint8_t WRITE_STATE = 2;
|
||||
uint32_t m_curSector;
|
||||
SdioConfig m_sdioConfig;
|
||||
uint8_t m_curState = IDLE_STATE;
|
||||
};
|
||||
#endif // SdioCard_h
|
||||
108
trunk/Arduino/libraries/SdFat/src/SdCard/SdioCardEX.cpp
Normal file
108
trunk/Arduino/libraries/SdFat/src/SdCard/SdioCardEX.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2018 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.
|
||||
*/
|
||||
#include "SdioCard.h"
|
||||
|
||||
// limit of K66 due to errata KINETIS_K_0N65N.
|
||||
const uint32_t MAX_SDHC_COUNT = 0XFFFF;
|
||||
|
||||
// Max RU is 1024 blocks.
|
||||
const uint32_t RU_MASK = 0X03FF;
|
||||
|
||||
bool SdioCardEX::readBlock(uint32_t lba, uint8_t* dst) {
|
||||
if (m_curState != READ_STATE || lba != m_curLba) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
m_limitLba = (lba + MAX_SDHC_COUNT) & ~RU_MASK;
|
||||
if (!SdioCard::readStart(lba, m_limitLba - lba)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba = lba;
|
||||
m_curState = READ_STATE;
|
||||
}
|
||||
if (!SdioCard::readData(dst)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba++;
|
||||
if (m_curLba >= m_limitLba) {
|
||||
m_curState = IDLE_STATE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::readBlocks(uint32_t lba, uint8_t* dst, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!readBlock(lba + i, dst + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::syncBlocks() {
|
||||
if (m_curState == READ_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdioCard::readStop()) {
|
||||
return false;
|
||||
}
|
||||
} else if (m_curState == WRITE_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdioCard::writeStop()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::writeBlock(uint32_t lba, const uint8_t* src) {
|
||||
if (m_curState != WRITE_STATE || m_curLba != lba) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
m_limitLba = (lba + MAX_SDHC_COUNT) & ~RU_MASK;
|
||||
if (!SdioCard::writeStart(lba , m_limitLba - lba)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba = lba;
|
||||
m_curState = WRITE_STATE;
|
||||
}
|
||||
if (!SdioCard::writeData(src)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba++;
|
||||
if (m_curLba >= m_limitLba) {
|
||||
m_curState = IDLE_STATE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::writeBlocks(uint32_t lba, const uint8_t* src, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!writeBlock(lba + i, src + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
1120
trunk/Arduino/libraries/SdFat/src/SdCard/SdioTeensy.cpp
Normal file
1120
trunk/Arduino/libraries/SdFat/src/SdCard/SdioTeensy.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user