Fork of https://github.com/ARMmbed/sd-driver. Added pin config for MAX32630FTHR

Dependents:   CircularBufferSDCardLib time_between_inerupt

Committer:
DVLevine
Date:
Tue Mar 20 17:35:00 2018 +0000
Revision:
0:69bfc1595ae5
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DVLevine 0:69bfc1595ae5 1 /* mbed Microcontroller Library
DVLevine 0:69bfc1595ae5 2 * Copyright (c) 2006-2013 ARM Limited
DVLevine 0:69bfc1595ae5 3 *
DVLevine 0:69bfc1595ae5 4 * Licensed under the Apache License, Version 2.0 (the "License");
DVLevine 0:69bfc1595ae5 5 * you may not use this file except in compliance with the License.
DVLevine 0:69bfc1595ae5 6 * You may obtain a copy of the License at
DVLevine 0:69bfc1595ae5 7 *
DVLevine 0:69bfc1595ae5 8 * http://www.apache.org/licenses/LICENSE-2.0
DVLevine 0:69bfc1595ae5 9 *
DVLevine 0:69bfc1595ae5 10 * Unless required by applicable law or agreed to in writing, software
DVLevine 0:69bfc1595ae5 11 * distributed under the License is distributed on an "AS IS" BASIS,
DVLevine 0:69bfc1595ae5 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
DVLevine 0:69bfc1595ae5 13 * See the License for the specific language governing permissions and
DVLevine 0:69bfc1595ae5 14 * limitations under the License.
DVLevine 0:69bfc1595ae5 15 */
DVLevine 0:69bfc1595ae5 16
DVLevine 0:69bfc1595ae5 17 /* Introduction
DVLevine 0:69bfc1595ae5 18 * ------------
DVLevine 0:69bfc1595ae5 19 * SD and MMC cards support a number of interfaces, but common to them all
DVLevine 0:69bfc1595ae5 20 * is one based on SPI. Since we already have the mbed SPI Interface, it will
DVLevine 0:69bfc1595ae5 21 * be used for SD cards.
DVLevine 0:69bfc1595ae5 22 *
DVLevine 0:69bfc1595ae5 23 * The main reference I'm using is Chapter 7, "SPI Mode" of:
DVLevine 0:69bfc1595ae5 24 * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
DVLevine 0:69bfc1595ae5 25 *
DVLevine 0:69bfc1595ae5 26 * SPI Startup
DVLevine 0:69bfc1595ae5 27 * -----------
DVLevine 0:69bfc1595ae5 28 * The SD card powers up in SD mode. The start-up procedure is complicated
DVLevine 0:69bfc1595ae5 29 * by the requirement to support older SDCards in a backwards compatible
DVLevine 0:69bfc1595ae5 30 * way with the new higher capacity variants SDHC and SDHC.
DVLevine 0:69bfc1595ae5 31 *
DVLevine 0:69bfc1595ae5 32 * The following figures from the specification with associated text describe
DVLevine 0:69bfc1595ae5 33 * the SPI mode initialisation process:
DVLevine 0:69bfc1595ae5 34 * - Figure 7-1: SD Memory Card State Diagram (SPI mode)
DVLevine 0:69bfc1595ae5 35 * - Figure 7-2: SPI Mode Initialization Flow
DVLevine 0:69bfc1595ae5 36 *
DVLevine 0:69bfc1595ae5 37 * Firstly, a low initial clock should be selected (in the range of 100-
DVLevine 0:69bfc1595ae5 38 * 400kHZ). After initialisation has been completed, the switch to a
DVLevine 0:69bfc1595ae5 39 * higher clock speed can be made (e.g. 1MHz). Newer cards will support
DVLevine 0:69bfc1595ae5 40 * higher speeds than the default _transfer_sck defined here.
DVLevine 0:69bfc1595ae5 41 *
DVLevine 0:69bfc1595ae5 42 * Next, note the following from the SDCard specification (note to
DVLevine 0:69bfc1595ae5 43 * Figure 7-1):
DVLevine 0:69bfc1595ae5 44 *
DVLevine 0:69bfc1595ae5 45 * In any of the cases CMD1 is not recommended because it may be difficult for the host
DVLevine 0:69bfc1595ae5 46 * to distinguish between MultiMediaCard and SD Memory Card
DVLevine 0:69bfc1595ae5 47 *
DVLevine 0:69bfc1595ae5 48 * Hence CMD1 is not used for the initialisation sequence.
DVLevine 0:69bfc1595ae5 49 *
DVLevine 0:69bfc1595ae5 50 * The SPI interface mode is selected by asserting CS low and sending the
DVLevine 0:69bfc1595ae5 51 * reset command (CMD0). The card will respond with a (R1) response.
DVLevine 0:69bfc1595ae5 52 * In practice many cards initially respond with 0xff or invalid data
DVLevine 0:69bfc1595ae5 53 * which is ignored. Data is read until a valid response is received
DVLevine 0:69bfc1595ae5 54 * or the number of re-reads has exceeded a maximim count. If a valid
DVLevine 0:69bfc1595ae5 55 * response is not received then the CMD0 can be retried. This
DVLevine 0:69bfc1595ae5 56 * has been found to successfully initialise cards where the SPI master
DVLevine 0:69bfc1595ae5 57 * (on MCU) has been reset but the SDCard has not, so the first
DVLevine 0:69bfc1595ae5 58 * CMD0 may be lost.
DVLevine 0:69bfc1595ae5 59 *
DVLevine 0:69bfc1595ae5 60 * CMD8 is optionally sent to determine the voltage range supported, and
DVLevine 0:69bfc1595ae5 61 * indirectly determine whether it is a version 1.x SD/non-SD card or
DVLevine 0:69bfc1595ae5 62 * version 2.x. I'll just ignore this for now.
DVLevine 0:69bfc1595ae5 63 *
DVLevine 0:69bfc1595ae5 64 * ACMD41 is repeatedly issued to initialise the card, until "in idle"
DVLevine 0:69bfc1595ae5 65 * (bit 0) of the R1 response goes to '0', indicating it is initialised.
DVLevine 0:69bfc1595ae5 66 *
DVLevine 0:69bfc1595ae5 67 * You should also indicate whether the host supports High Capicity cards,
DVLevine 0:69bfc1595ae5 68 * and check whether the card is high capacity - i'll also ignore this
DVLevine 0:69bfc1595ae5 69 *
DVLevine 0:69bfc1595ae5 70 * SPI Protocol
DVLevine 0:69bfc1595ae5 71 * ------------
DVLevine 0:69bfc1595ae5 72 * The SD SPI protocol is based on transactions made up of 8-bit words, with
DVLevine 0:69bfc1595ae5 73 * the host starting every bus transaction by asserting the CS signal low. The
DVLevine 0:69bfc1595ae5 74 * card always responds to commands, data blocks and errors.
DVLevine 0:69bfc1595ae5 75 *
DVLevine 0:69bfc1595ae5 76 * The protocol supports a CRC, but by default it is off (except for the
DVLevine 0:69bfc1595ae5 77 * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
DVLevine 0:69bfc1595ae5 78 * I'll leave the CRC off I think!
DVLevine 0:69bfc1595ae5 79 *
DVLevine 0:69bfc1595ae5 80 * Standard capacity cards have variable data block sizes, whereas High
DVLevine 0:69bfc1595ae5 81 * Capacity cards fix the size of data block to 512 bytes. I'll therefore
DVLevine 0:69bfc1595ae5 82 * just always use the Standard Capacity cards with a block size of 512 bytes.
DVLevine 0:69bfc1595ae5 83 * This is set with CMD16.
DVLevine 0:69bfc1595ae5 84 *
DVLevine 0:69bfc1595ae5 85 * You can read and write single blocks (CMD17, CMD25) or multiple blocks
DVLevine 0:69bfc1595ae5 86 * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
DVLevine 0:69bfc1595ae5 87 * the card gets a read command, it responds with a response token, and then
DVLevine 0:69bfc1595ae5 88 * a data token or an error.
DVLevine 0:69bfc1595ae5 89 *
DVLevine 0:69bfc1595ae5 90 * SPI Command Format
DVLevine 0:69bfc1595ae5 91 * ------------------
DVLevine 0:69bfc1595ae5 92 * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
DVLevine 0:69bfc1595ae5 93 *
DVLevine 0:69bfc1595ae5 94 * +---------------+------------+------------+-----------+----------+--------------+
DVLevine 0:69bfc1595ae5 95 * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
DVLevine 0:69bfc1595ae5 96 * +---------------+------------+------------+-----------+----------+--------------+
DVLevine 0:69bfc1595ae5 97 *
DVLevine 0:69bfc1595ae5 98 * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
DVLevine 0:69bfc1595ae5 99 *
DVLevine 0:69bfc1595ae5 100 * All Application Specific commands shall be preceded with APP_CMD (CMD55).
DVLevine 0:69bfc1595ae5 101 *
DVLevine 0:69bfc1595ae5 102 * SPI Response Format
DVLevine 0:69bfc1595ae5 103 * -------------------
DVLevine 0:69bfc1595ae5 104 * The main response format (R1) is a status byte (normally zero). Key flags:
DVLevine 0:69bfc1595ae5 105 * idle - 1 if the card is in an idle state/initialising
DVLevine 0:69bfc1595ae5 106 * cmd - 1 if an illegal command code was detected
DVLevine 0:69bfc1595ae5 107 *
DVLevine 0:69bfc1595ae5 108 * +-------------------------------------------------+
DVLevine 0:69bfc1595ae5 109 * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
DVLevine 0:69bfc1595ae5 110 * +-------------------------------------------------+
DVLevine 0:69bfc1595ae5 111 *
DVLevine 0:69bfc1595ae5 112 * R1b is the same, except it is followed by a busy signal (zeros) until
DVLevine 0:69bfc1595ae5 113 * the first non-zero byte when it is ready again.
DVLevine 0:69bfc1595ae5 114 *
DVLevine 0:69bfc1595ae5 115 * Data Response Token
DVLevine 0:69bfc1595ae5 116 * -------------------
DVLevine 0:69bfc1595ae5 117 * Every data block written to the card is acknowledged by a byte
DVLevine 0:69bfc1595ae5 118 * response token
DVLevine 0:69bfc1595ae5 119 *
DVLevine 0:69bfc1595ae5 120 * +----------------------+
DVLevine 0:69bfc1595ae5 121 * | xxx | 0 | status | 1 |
DVLevine 0:69bfc1595ae5 122 * +----------------------+
DVLevine 0:69bfc1595ae5 123 * 010 - OK!
DVLevine 0:69bfc1595ae5 124 * 101 - CRC Error
DVLevine 0:69bfc1595ae5 125 * 110 - Write Error
DVLevine 0:69bfc1595ae5 126 *
DVLevine 0:69bfc1595ae5 127 * Single Block Read and Write
DVLevine 0:69bfc1595ae5 128 * ---------------------------
DVLevine 0:69bfc1595ae5 129 *
DVLevine 0:69bfc1595ae5 130 * Block transfers have a byte header, followed by the data, followed
DVLevine 0:69bfc1595ae5 131 * by a 16-bit CRC. In our case, the data will always be 512 bytes.
DVLevine 0:69bfc1595ae5 132 *
DVLevine 0:69bfc1595ae5 133 * +------+---------+---------+- - - -+---------+-----------+----------+
DVLevine 0:69bfc1595ae5 134 * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
DVLevine 0:69bfc1595ae5 135 * +------+---------+---------+- - - -+---------+-----------+----------+
DVLevine 0:69bfc1595ae5 136 */
DVLevine 0:69bfc1595ae5 137
DVLevine 0:69bfc1595ae5 138 /* If the target has no SPI support then SDCard is not supported */
DVLevine 0:69bfc1595ae5 139 #ifdef DEVICE_SPI
DVLevine 0:69bfc1595ae5 140
DVLevine 0:69bfc1595ae5 141 #include "SDBlockDevice.h"
DVLevine 0:69bfc1595ae5 142 #include "mbed_debug.h"
DVLevine 0:69bfc1595ae5 143 #include <errno.h>
DVLevine 0:69bfc1595ae5 144
DVLevine 0:69bfc1595ae5 145 /* Required version: 5.6.1 and above */
DVLevine 0:69bfc1595ae5 146 #if defined(MBED_MAJOR_VERSION) && MBED_MAJOR_VERSION >= 5
DVLevine 0:69bfc1595ae5 147 #if (MBED_VERSION < MBED_ENCODE_VERSION(5,6,1))
DVLevine 0:69bfc1595ae5 148 #error "Incompatible mbed-os version detected! Required 5.6.1 and above"
DVLevine 0:69bfc1595ae5 149 #endif
DVLevine 0:69bfc1595ae5 150 #else
DVLevine 0:69bfc1595ae5 151 #warning "mbed-os version 5.6.1 or above required"
DVLevine 0:69bfc1595ae5 152 #endif
DVLevine 0:69bfc1595ae5 153
DVLevine 0:69bfc1595ae5 154 #ifndef MBED_CONF_SD_CMD_TIMEOUT
DVLevine 0:69bfc1595ae5 155 #define MBED_CONF_SD_CMD_TIMEOUT 5000 /*!< Timeout in ms for response */
DVLevine 0:69bfc1595ae5 156 #endif
DVLevine 0:69bfc1595ae5 157
DVLevine 0:69bfc1595ae5 158 #ifndef MBED_CONF_SD_CMD0_IDLE_STATE_RETRIES
DVLevine 0:69bfc1595ae5 159 #define MBED_CONF_SD_CMD0_IDLE_STATE_RETRIES 5 /*!< Number of retries for sending CMDO */
DVLevine 0:69bfc1595ae5 160 #endif
DVLevine 0:69bfc1595ae5 161
DVLevine 0:69bfc1595ae5 162 #define SD_COMMAND_TIMEOUT MBED_CONF_SD_CMD_TIMEOUT
DVLevine 0:69bfc1595ae5 163 #define SD_CMD0_GO_IDLE_STATE_RETRIES MBED_CONF_SD_CMD0_IDLE_STATE_RETRIES
DVLevine 0:69bfc1595ae5 164 #define SD_DBG 0 /*!< 1 - Enable debugging */
DVLevine 0:69bfc1595ae5 165 #define SD_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */
DVLevine 0:69bfc1595ae5 166
DVLevine 0:69bfc1595ae5 167 #define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */
DVLevine 0:69bfc1595ae5 168 #define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */
DVLevine 0:69bfc1595ae5 169 #define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */
DVLevine 0:69bfc1595ae5 170 #define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */
DVLevine 0:69bfc1595ae5 171 #define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */
DVLevine 0:69bfc1595ae5 172 #define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */
DVLevine 0:69bfc1595ae5 173 #define SD_BLOCK_DEVICE_ERROR_UNUSABLE -5007 /*!< unusable card */
DVLevine 0:69bfc1595ae5 174 #define SD_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008 /*!< No response from device */
DVLevine 0:69bfc1595ae5 175 #define SD_BLOCK_DEVICE_ERROR_CRC -5009 /*!< CRC error */
DVLevine 0:69bfc1595ae5 176 #define SD_BLOCK_DEVICE_ERROR_ERASE -5010 /*!< Erase error: reset/sequence */
DVLevine 0:69bfc1595ae5 177 #define SD_BLOCK_DEVICE_ERROR_WRITE -5011 /*!< SPI Write error: !SPI_DATA_ACCEPTED */
DVLevine 0:69bfc1595ae5 178
DVLevine 0:69bfc1595ae5 179 #define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes */
DVLevine 0:69bfc1595ae5 180 #define WRITE_BL_PARTIAL 0 /*!< Partial block write - Not supported */
DVLevine 0:69bfc1595ae5 181 #define CRC_SUPPORT 0 /*!< CRC - Not supported */
DVLevine 0:69bfc1595ae5 182 #define SPI_CMD(x) (0x40 | (x & 0x3f))
DVLevine 0:69bfc1595ae5 183
DVLevine 0:69bfc1595ae5 184 /* R1 Response Format */
DVLevine 0:69bfc1595ae5 185 #define R1_NO_RESPONSE (0xFF)
DVLevine 0:69bfc1595ae5 186 #define R1_RESPONSE_RECV (0x80)
DVLevine 0:69bfc1595ae5 187 #define R1_IDLE_STATE (1 << 0)
DVLevine 0:69bfc1595ae5 188 #define R1_ERASE_RESET (1 << 1)
DVLevine 0:69bfc1595ae5 189 #define R1_ILLEGAL_COMMAND (1 << 2)
DVLevine 0:69bfc1595ae5 190 #define R1_COM_CRC_ERROR (1 << 3)
DVLevine 0:69bfc1595ae5 191 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
DVLevine 0:69bfc1595ae5 192 #define R1_ADDRESS_ERROR (1 << 5)
DVLevine 0:69bfc1595ae5 193 #define R1_PARAMETER_ERROR (1 << 6)
DVLevine 0:69bfc1595ae5 194
DVLevine 0:69bfc1595ae5 195 // Types
DVLevine 0:69bfc1595ae5 196 #define SDCARD_NONE 0 /**< No card is present */
DVLevine 0:69bfc1595ae5 197 #define SDCARD_V1 1 /**< v1.x Standard Capacity */
DVLevine 0:69bfc1595ae5 198 #define SDCARD_V2 2 /**< v2.x Standard capacity SD card */
DVLevine 0:69bfc1595ae5 199 #define SDCARD_V2HC 3 /**< v2.x High capacity SD card */
DVLevine 0:69bfc1595ae5 200 #define CARD_UNKNOWN 4 /**< Unknown or unsupported card */
DVLevine 0:69bfc1595ae5 201
DVLevine 0:69bfc1595ae5 202 /* SIZE in Bytes */
DVLevine 0:69bfc1595ae5 203 #define PACKET_SIZE 6 /*!< SD Packet size CMD+ARG+CRC */
DVLevine 0:69bfc1595ae5 204 #define R1_RESPONSE_SIZE 1 /*!< Size of R1 response */
DVLevine 0:69bfc1595ae5 205 #define R2_RESPONSE_SIZE 2 /*!< Size of R2 response */
DVLevine 0:69bfc1595ae5 206 #define R3_R7_RESPONSE_SIZE 5 /*!< Size of R3/R7 response */
DVLevine 0:69bfc1595ae5 207
DVLevine 0:69bfc1595ae5 208 /* R1b Response */
DVLevine 0:69bfc1595ae5 209 #define DEVICE_BUSY (0x00)
DVLevine 0:69bfc1595ae5 210
DVLevine 0:69bfc1595ae5 211 /* R2 Response Format */
DVLevine 0:69bfc1595ae5 212 #define R2_CARD_LOCKED (1 << 0)
DVLevine 0:69bfc1595ae5 213 #define R2_CMD_FAILED (1 << 1)
DVLevine 0:69bfc1595ae5 214 #define R2_ERROR (1 << 2)
DVLevine 0:69bfc1595ae5 215 #define R2_CC_ERROR (1 << 3)
DVLevine 0:69bfc1595ae5 216 #define R2_CC_FAILED (1 << 4)
DVLevine 0:69bfc1595ae5 217 #define R2_WP_VIOLATION (1 << 5)
DVLevine 0:69bfc1595ae5 218 #define R2_ERASE_PARAM (1 << 6)
DVLevine 0:69bfc1595ae5 219 #define R2_OUT_OF_RANGE (1 << 7)
DVLevine 0:69bfc1595ae5 220
DVLevine 0:69bfc1595ae5 221 /* R3 Response : OCR Register */
DVLevine 0:69bfc1595ae5 222 #define OCR_HCS_CCS (0x1 << 30)
DVLevine 0:69bfc1595ae5 223 #define OCR_LOW_VOLTAGE (0x01 << 24)
DVLevine 0:69bfc1595ae5 224 #define OCR_3_3V (0x1 << 20)
DVLevine 0:69bfc1595ae5 225
DVLevine 0:69bfc1595ae5 226 /* R7 response pattern for CMD8 */
DVLevine 0:69bfc1595ae5 227 #define CMD8_PATTERN (0xAA)
DVLevine 0:69bfc1595ae5 228
DVLevine 0:69bfc1595ae5 229 /* CRC Enable */
DVLevine 0:69bfc1595ae5 230 #define CRC_ENABLE (0) /*!< CRC 1 - Enable 0 - Disable */
DVLevine 0:69bfc1595ae5 231
DVLevine 0:69bfc1595ae5 232 /* Control Tokens */
DVLevine 0:69bfc1595ae5 233 #define SPI_DATA_RESPONSE_MASK (0x1F)
DVLevine 0:69bfc1595ae5 234 #define SPI_DATA_ACCEPTED (0x05)
DVLevine 0:69bfc1595ae5 235 #define SPI_DATA_CRC_ERROR (0x0B)
DVLevine 0:69bfc1595ae5 236 #define SPI_DATA_WRITE_ERROR (0x0D)
DVLevine 0:69bfc1595ae5 237 #define SPI_START_BLOCK (0xFE) /*!< For Single Block Read/Write and Multiple Block Read */
DVLevine 0:69bfc1595ae5 238 #define SPI_START_BLK_MUL_WRITE (0xFC) /*!< Start Multi-block write */
DVLevine 0:69bfc1595ae5 239 #define SPI_STOP_TRAN (0xFD) /*!< Stop Multi-block write */
DVLevine 0:69bfc1595ae5 240
DVLevine 0:69bfc1595ae5 241 #define SPI_DATA_READ_ERROR_MASK (0xF) /*!< Data Error Token: 4 LSB bits */
DVLevine 0:69bfc1595ae5 242 #define SPI_READ_ERROR (0x1 << 0) /*!< Error */
DVLevine 0:69bfc1595ae5 243 #define SPI_READ_ERROR_CC (0x1 << 1) /*!< CC Error*/
DVLevine 0:69bfc1595ae5 244 #define SPI_READ_ERROR_ECC_C (0x1 << 2) /*!< Card ECC failed */
DVLevine 0:69bfc1595ae5 245 #define SPI_READ_ERROR_OFR (0x1 << 3) /*!< Out of Range */
DVLevine 0:69bfc1595ae5 246
DVLevine 0:69bfc1595ae5 247 SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz)
DVLevine 0:69bfc1595ae5 248 : _sectors(0), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0)
DVLevine 0:69bfc1595ae5 249 {
DVLevine 0:69bfc1595ae5 250 _cs = 1;
DVLevine 0:69bfc1595ae5 251 _card_type = SDCARD_NONE;
DVLevine 0:69bfc1595ae5 252
DVLevine 0:69bfc1595ae5 253 // Set default to 100kHz for initialisation and 1MHz for data transfer
DVLevine 0:69bfc1595ae5 254 _init_sck = 100000;
DVLevine 0:69bfc1595ae5 255 _transfer_sck = hz;
DVLevine 0:69bfc1595ae5 256
DVLevine 0:69bfc1595ae5 257 // Only HC block size is supported.
DVLevine 0:69bfc1595ae5 258 _block_size = BLOCK_SIZE_HC;
DVLevine 0:69bfc1595ae5 259 _erase_size = BLOCK_SIZE_HC;
DVLevine 0:69bfc1595ae5 260 }
DVLevine 0:69bfc1595ae5 261
DVLevine 0:69bfc1595ae5 262 SDBlockDevice::~SDBlockDevice()
DVLevine 0:69bfc1595ae5 263 {
DVLevine 0:69bfc1595ae5 264 if (_is_initialized) {
DVLevine 0:69bfc1595ae5 265 deinit();
DVLevine 0:69bfc1595ae5 266 }
DVLevine 0:69bfc1595ae5 267 }
DVLevine 0:69bfc1595ae5 268
DVLevine 0:69bfc1595ae5 269 int SDBlockDevice::_initialise_card()
DVLevine 0:69bfc1595ae5 270 {
DVLevine 0:69bfc1595ae5 271 // Detail debugging is for commands
DVLevine 0:69bfc1595ae5 272 _dbg = SD_DBG ? SD_CMD_TRACE : 0;
DVLevine 0:69bfc1595ae5 273 int32_t status = BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 274 uint32_t response, arg;
DVLevine 0:69bfc1595ae5 275
DVLevine 0:69bfc1595ae5 276 // Initialize the SPI interface: Card by default is in SD mode
DVLevine 0:69bfc1595ae5 277 _spi_init();
DVLevine 0:69bfc1595ae5 278
DVLevine 0:69bfc1595ae5 279 // The card is transitioned from SDCard mode to SPI mode by sending the CMD0 + CS Asserted("0")
DVLevine 0:69bfc1595ae5 280 if (_go_idle_state() != R1_IDLE_STATE) {
DVLevine 0:69bfc1595ae5 281 debug_if(SD_DBG, "No disk, or could not put SD card in to SPI idle state\n");
DVLevine 0:69bfc1595ae5 282 return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
DVLevine 0:69bfc1595ae5 283 }
DVLevine 0:69bfc1595ae5 284
DVLevine 0:69bfc1595ae5 285 // Send CMD8, if the card rejects the command then it's probably using the
DVLevine 0:69bfc1595ae5 286 // legacy protocol, or is a MMC, or just flat-out broken
DVLevine 0:69bfc1595ae5 287 status = _cmd8();
DVLevine 0:69bfc1595ae5 288 if (BD_ERROR_OK != status && SD_BLOCK_DEVICE_ERROR_UNSUPPORTED != status) {
DVLevine 0:69bfc1595ae5 289 return status;
DVLevine 0:69bfc1595ae5 290 }
DVLevine 0:69bfc1595ae5 291
DVLevine 0:69bfc1595ae5 292 // Read OCR - CMD58 Response contains OCR register
DVLevine 0:69bfc1595ae5 293 if (BD_ERROR_OK != (status = _cmd(CMD58_READ_OCR, 0x0, 0x0, &response))) {
DVLevine 0:69bfc1595ae5 294 return status;
DVLevine 0:69bfc1595ae5 295 }
DVLevine 0:69bfc1595ae5 296
DVLevine 0:69bfc1595ae5 297 // Check if card supports voltage range: 3.3V
DVLevine 0:69bfc1595ae5 298 if (!(response & OCR_3_3V)) {
DVLevine 0:69bfc1595ae5 299 _card_type = CARD_UNKNOWN;
DVLevine 0:69bfc1595ae5 300 status = SD_BLOCK_DEVICE_ERROR_UNUSABLE;
DVLevine 0:69bfc1595ae5 301 return status;
DVLevine 0:69bfc1595ae5 302 }
DVLevine 0:69bfc1595ae5 303
DVLevine 0:69bfc1595ae5 304 // HCS is set 1 for HC/XC capacity cards for ACMD41, if supported
DVLevine 0:69bfc1595ae5 305 arg = 0x0;
DVLevine 0:69bfc1595ae5 306 if (SDCARD_V2 == _card_type) {
DVLevine 0:69bfc1595ae5 307 arg |= OCR_HCS_CCS;
DVLevine 0:69bfc1595ae5 308 }
DVLevine 0:69bfc1595ae5 309
DVLevine 0:69bfc1595ae5 310 /* Idle state bit in the R1 response of ACMD41 is used by the card to inform the host
DVLevine 0:69bfc1595ae5 311 * if initialization of ACMD41 is completed. "1" indicates that the card is still initializing.
DVLevine 0:69bfc1595ae5 312 * "0" indicates completion of initialization. The host repeatedly issues ACMD41 until
DVLevine 0:69bfc1595ae5 313 * this bit is set to "0".
DVLevine 0:69bfc1595ae5 314 */
DVLevine 0:69bfc1595ae5 315 _spi_timer.start();
DVLevine 0:69bfc1595ae5 316 do {
DVLevine 0:69bfc1595ae5 317 status = _cmd(ACMD41_SD_SEND_OP_COND, arg, 1, &response);
DVLevine 0:69bfc1595ae5 318 } while ((response & R1_IDLE_STATE) && (_spi_timer.read_ms() < SD_COMMAND_TIMEOUT));
DVLevine 0:69bfc1595ae5 319 _spi_timer.stop();
DVLevine 0:69bfc1595ae5 320
DVLevine 0:69bfc1595ae5 321 // Initialization complete: ACMD41 successful
DVLevine 0:69bfc1595ae5 322 if ((BD_ERROR_OK != status) || (0x00 != response)) {
DVLevine 0:69bfc1595ae5 323 _card_type = CARD_UNKNOWN;
DVLevine 0:69bfc1595ae5 324 debug_if(SD_DBG, "Timeout waiting for card\n");
DVLevine 0:69bfc1595ae5 325 return status;
DVLevine 0:69bfc1595ae5 326 }
DVLevine 0:69bfc1595ae5 327
DVLevine 0:69bfc1595ae5 328 if (SDCARD_V2 == _card_type) {
DVLevine 0:69bfc1595ae5 329 // Get the card capacity CCS: CMD58
DVLevine 0:69bfc1595ae5 330 if (BD_ERROR_OK == (status = _cmd(CMD58_READ_OCR, 0x0, 0x0, &response))) {
DVLevine 0:69bfc1595ae5 331 // High Capacity card
DVLevine 0:69bfc1595ae5 332 if (response & OCR_HCS_CCS) {
DVLevine 0:69bfc1595ae5 333 _card_type = SDCARD_V2HC;
DVLevine 0:69bfc1595ae5 334 debug_if(SD_DBG, "Card Initialized: High Capacity Card \n");
DVLevine 0:69bfc1595ae5 335 } else {
DVLevine 0:69bfc1595ae5 336 debug_if(SD_DBG, "Card Initialized: Standard Capacity Card: Version 2.x \n");
DVLevine 0:69bfc1595ae5 337 }
DVLevine 0:69bfc1595ae5 338 }
DVLevine 0:69bfc1595ae5 339 } else {
DVLevine 0:69bfc1595ae5 340 _card_type = SDCARD_V1;
DVLevine 0:69bfc1595ae5 341 debug_if(SD_DBG, "Card Initialized: Version 1.x Card\n");
DVLevine 0:69bfc1595ae5 342 }
DVLevine 0:69bfc1595ae5 343
DVLevine 0:69bfc1595ae5 344 // Disable CRC
DVLevine 0:69bfc1595ae5 345 status = _cmd(CMD59_CRC_ON_OFF, 0);
DVLevine 0:69bfc1595ae5 346
DVLevine 0:69bfc1595ae5 347 return status;
DVLevine 0:69bfc1595ae5 348 }
DVLevine 0:69bfc1595ae5 349
DVLevine 0:69bfc1595ae5 350
DVLevine 0:69bfc1595ae5 351 int SDBlockDevice::init()
DVLevine 0:69bfc1595ae5 352 {
DVLevine 0:69bfc1595ae5 353 lock();
DVLevine 0:69bfc1595ae5 354 int err = _initialise_card();
DVLevine 0:69bfc1595ae5 355 _is_initialized = (err == BD_ERROR_OK);
DVLevine 0:69bfc1595ae5 356 if (!_is_initialized) {
DVLevine 0:69bfc1595ae5 357 debug_if(SD_DBG, "Fail to initialize card\n");
DVLevine 0:69bfc1595ae5 358 unlock();
DVLevine 0:69bfc1595ae5 359 return err;
DVLevine 0:69bfc1595ae5 360 }
DVLevine 0:69bfc1595ae5 361 debug_if(SD_DBG, "init card = %d\n", _is_initialized);
DVLevine 0:69bfc1595ae5 362 _sectors = _sd_sectors();
DVLevine 0:69bfc1595ae5 363 // CMD9 failed
DVLevine 0:69bfc1595ae5 364 if (0 == _sectors) {
DVLevine 0:69bfc1595ae5 365 unlock();
DVLevine 0:69bfc1595ae5 366 return BD_ERROR_DEVICE_ERROR;
DVLevine 0:69bfc1595ae5 367 }
DVLevine 0:69bfc1595ae5 368
DVLevine 0:69bfc1595ae5 369 // Set block length to 512 (CMD16)
DVLevine 0:69bfc1595ae5 370 if (_cmd(CMD16_SET_BLOCKLEN, _block_size) != 0) {
DVLevine 0:69bfc1595ae5 371 debug_if(SD_DBG, "Set %d-byte block timed out\n", _block_size);
DVLevine 0:69bfc1595ae5 372 unlock();
DVLevine 0:69bfc1595ae5 373 return BD_ERROR_DEVICE_ERROR;
DVLevine 0:69bfc1595ae5 374 }
DVLevine 0:69bfc1595ae5 375
DVLevine 0:69bfc1595ae5 376 // Set SCK for data transfer
DVLevine 0:69bfc1595ae5 377 err = _freq();
DVLevine 0:69bfc1595ae5 378 if (err) {
DVLevine 0:69bfc1595ae5 379 unlock();
DVLevine 0:69bfc1595ae5 380 return err;
DVLevine 0:69bfc1595ae5 381 }
DVLevine 0:69bfc1595ae5 382 unlock();
DVLevine 0:69bfc1595ae5 383 return BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 384 }
DVLevine 0:69bfc1595ae5 385
DVLevine 0:69bfc1595ae5 386 int SDBlockDevice::deinit()
DVLevine 0:69bfc1595ae5 387 {
DVLevine 0:69bfc1595ae5 388 lock();
DVLevine 0:69bfc1595ae5 389 _is_initialized = false;
DVLevine 0:69bfc1595ae5 390 _sectors = 0;
DVLevine 0:69bfc1595ae5 391 unlock();
DVLevine 0:69bfc1595ae5 392 return 0;
DVLevine 0:69bfc1595ae5 393 }
DVLevine 0:69bfc1595ae5 394
DVLevine 0:69bfc1595ae5 395
DVLevine 0:69bfc1595ae5 396 int SDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
DVLevine 0:69bfc1595ae5 397 {
DVLevine 0:69bfc1595ae5 398 if (!is_valid_program(addr, size)) {
DVLevine 0:69bfc1595ae5 399 return SD_BLOCK_DEVICE_ERROR_PARAMETER;
DVLevine 0:69bfc1595ae5 400 }
DVLevine 0:69bfc1595ae5 401
DVLevine 0:69bfc1595ae5 402 lock();
DVLevine 0:69bfc1595ae5 403 if (!_is_initialized) {
DVLevine 0:69bfc1595ae5 404 unlock();
DVLevine 0:69bfc1595ae5 405 return SD_BLOCK_DEVICE_ERROR_NO_INIT;
DVLevine 0:69bfc1595ae5 406 }
DVLevine 0:69bfc1595ae5 407
DVLevine 0:69bfc1595ae5 408 const uint8_t *buffer = static_cast<const uint8_t*>(b);
DVLevine 0:69bfc1595ae5 409 int status = BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 410 uint8_t response;
DVLevine 0:69bfc1595ae5 411
DVLevine 0:69bfc1595ae5 412 // Get block count
DVLevine 0:69bfc1595ae5 413 bd_addr_t blockCnt = size / _block_size;
DVLevine 0:69bfc1595ae5 414
DVLevine 0:69bfc1595ae5 415 // SDSC Card (CCS=0) uses byte unit address
DVLevine 0:69bfc1595ae5 416 // SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit)
DVLevine 0:69bfc1595ae5 417 if(SDCARD_V2HC == _card_type) {
DVLevine 0:69bfc1595ae5 418 addr = addr / _block_size;
DVLevine 0:69bfc1595ae5 419 }
DVLevine 0:69bfc1595ae5 420
DVLevine 0:69bfc1595ae5 421 // Send command to perform write operation
DVLevine 0:69bfc1595ae5 422 if (blockCnt == 1) {
DVLevine 0:69bfc1595ae5 423 // Single block write command
DVLevine 0:69bfc1595ae5 424 if (BD_ERROR_OK != (status = _cmd(CMD24_WRITE_BLOCK, addr))) {
DVLevine 0:69bfc1595ae5 425 unlock();
DVLevine 0:69bfc1595ae5 426 return status;
DVLevine 0:69bfc1595ae5 427 }
DVLevine 0:69bfc1595ae5 428
DVLevine 0:69bfc1595ae5 429 // Write data
DVLevine 0:69bfc1595ae5 430 response = _write(buffer, SPI_START_BLOCK, _block_size);
DVLevine 0:69bfc1595ae5 431
DVLevine 0:69bfc1595ae5 432 // Only CRC and general write error are communicated via response token
DVLevine 0:69bfc1595ae5 433 if ((response == SPI_DATA_CRC_ERROR) || (response == SPI_DATA_WRITE_ERROR)) {
DVLevine 0:69bfc1595ae5 434 debug_if(SD_DBG, "Single Block Write failed: 0x%x \n", response);
DVLevine 0:69bfc1595ae5 435 status = SD_BLOCK_DEVICE_ERROR_WRITE;
DVLevine 0:69bfc1595ae5 436 }
DVLevine 0:69bfc1595ae5 437 } else {
DVLevine 0:69bfc1595ae5 438 // Pre-erase setting prior to multiple block write operation
DVLevine 0:69bfc1595ae5 439 _cmd(ACMD23_SET_WR_BLK_ERASE_COUNT, blockCnt, 1);
DVLevine 0:69bfc1595ae5 440
DVLevine 0:69bfc1595ae5 441 // Multiple block write command
DVLevine 0:69bfc1595ae5 442 if (BD_ERROR_OK != (status = _cmd(CMD25_WRITE_MULTIPLE_BLOCK, addr))) {
DVLevine 0:69bfc1595ae5 443 unlock();
DVLevine 0:69bfc1595ae5 444 return status;
DVLevine 0:69bfc1595ae5 445 }
DVLevine 0:69bfc1595ae5 446
DVLevine 0:69bfc1595ae5 447 // Write the data: one block at a time
DVLevine 0:69bfc1595ae5 448 do {
DVLevine 0:69bfc1595ae5 449 response = _write(buffer, SPI_START_BLK_MUL_WRITE, _block_size);
DVLevine 0:69bfc1595ae5 450 if (response != SPI_DATA_ACCEPTED) {
DVLevine 0:69bfc1595ae5 451 debug_if(SD_DBG, "Multiple Block Write failed: 0x%x \n", response);
DVLevine 0:69bfc1595ae5 452 break;
DVLevine 0:69bfc1595ae5 453 }
DVLevine 0:69bfc1595ae5 454 buffer += _block_size;
DVLevine 0:69bfc1595ae5 455 }while (--blockCnt); // Receive all blocks of data
DVLevine 0:69bfc1595ae5 456
DVLevine 0:69bfc1595ae5 457 /* In a Multiple Block write operation, the stop transmission will be done by
DVLevine 0:69bfc1595ae5 458 * sending 'Stop Tran' token instead of 'Start Block' token at the beginning
DVLevine 0:69bfc1595ae5 459 * of the next block
DVLevine 0:69bfc1595ae5 460 */
DVLevine 0:69bfc1595ae5 461 _spi.write(SPI_STOP_TRAN);
DVLevine 0:69bfc1595ae5 462 }
DVLevine 0:69bfc1595ae5 463
DVLevine 0:69bfc1595ae5 464 _deselect();
DVLevine 0:69bfc1595ae5 465 unlock();
DVLevine 0:69bfc1595ae5 466 return status;
DVLevine 0:69bfc1595ae5 467 }
DVLevine 0:69bfc1595ae5 468
DVLevine 0:69bfc1595ae5 469 int SDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
DVLevine 0:69bfc1595ae5 470 {
DVLevine 0:69bfc1595ae5 471 if (!is_valid_read(addr, size)) {
DVLevine 0:69bfc1595ae5 472 return SD_BLOCK_DEVICE_ERROR_PARAMETER;
DVLevine 0:69bfc1595ae5 473 }
DVLevine 0:69bfc1595ae5 474
DVLevine 0:69bfc1595ae5 475 lock();
DVLevine 0:69bfc1595ae5 476 if (!_is_initialized) {
DVLevine 0:69bfc1595ae5 477 unlock();
DVLevine 0:69bfc1595ae5 478 return SD_BLOCK_DEVICE_ERROR_PARAMETER;
DVLevine 0:69bfc1595ae5 479 }
DVLevine 0:69bfc1595ae5 480
DVLevine 0:69bfc1595ae5 481 uint8_t *buffer = static_cast<uint8_t *>(b);
DVLevine 0:69bfc1595ae5 482 int status = BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 483 bd_addr_t blockCnt = size / _block_size;
DVLevine 0:69bfc1595ae5 484
DVLevine 0:69bfc1595ae5 485 // SDSC Card (CCS=0) uses byte unit address
DVLevine 0:69bfc1595ae5 486 // SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit)
DVLevine 0:69bfc1595ae5 487 if (SDCARD_V2HC == _card_type) {
DVLevine 0:69bfc1595ae5 488 addr = addr / _block_size;
DVLevine 0:69bfc1595ae5 489 }
DVLevine 0:69bfc1595ae5 490
DVLevine 0:69bfc1595ae5 491 // Write command ro receive data
DVLevine 0:69bfc1595ae5 492 if (blockCnt > 1) {
DVLevine 0:69bfc1595ae5 493 status = _cmd(CMD18_READ_MULTIPLE_BLOCK, addr);
DVLevine 0:69bfc1595ae5 494 } else {
DVLevine 0:69bfc1595ae5 495 status = _cmd(CMD17_READ_SINGLE_BLOCK, addr);
DVLevine 0:69bfc1595ae5 496 }
DVLevine 0:69bfc1595ae5 497 if (BD_ERROR_OK != status) {
DVLevine 0:69bfc1595ae5 498 unlock();
DVLevine 0:69bfc1595ae5 499 return status;
DVLevine 0:69bfc1595ae5 500 }
DVLevine 0:69bfc1595ae5 501
DVLevine 0:69bfc1595ae5 502 // receive the data : one block at a time
DVLevine 0:69bfc1595ae5 503 while (blockCnt) {
DVLevine 0:69bfc1595ae5 504 if (0 != _read(buffer, _block_size)) {
DVLevine 0:69bfc1595ae5 505 status = SD_BLOCK_DEVICE_ERROR_NO_RESPONSE;
DVLevine 0:69bfc1595ae5 506 break;
DVLevine 0:69bfc1595ae5 507 }
DVLevine 0:69bfc1595ae5 508 buffer += _block_size;
DVLevine 0:69bfc1595ae5 509 --blockCnt;
DVLevine 0:69bfc1595ae5 510 }
DVLevine 0:69bfc1595ae5 511 _deselect();
DVLevine 0:69bfc1595ae5 512
DVLevine 0:69bfc1595ae5 513 // Send CMD12(0x00000000) to stop the transmission for multi-block transfer
DVLevine 0:69bfc1595ae5 514 if (size > _block_size) {
DVLevine 0:69bfc1595ae5 515 status = _cmd(CMD12_STOP_TRANSMISSION, 0x0);
DVLevine 0:69bfc1595ae5 516 }
DVLevine 0:69bfc1595ae5 517 unlock();
DVLevine 0:69bfc1595ae5 518 return status;
DVLevine 0:69bfc1595ae5 519 }
DVLevine 0:69bfc1595ae5 520
DVLevine 0:69bfc1595ae5 521 bool SDBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size)
DVLevine 0:69bfc1595ae5 522 {
DVLevine 0:69bfc1595ae5 523 return (
DVLevine 0:69bfc1595ae5 524 addr % _erase_size == 0 &&
DVLevine 0:69bfc1595ae5 525 size % _erase_size == 0 &&
DVLevine 0:69bfc1595ae5 526 addr + size <= this->size());
DVLevine 0:69bfc1595ae5 527 }
DVLevine 0:69bfc1595ae5 528
DVLevine 0:69bfc1595ae5 529 int SDBlockDevice::trim(bd_addr_t addr, bd_size_t size)
DVLevine 0:69bfc1595ae5 530 {
DVLevine 0:69bfc1595ae5 531 if (!_is_valid_trim(addr, size)) {
DVLevine 0:69bfc1595ae5 532 return SD_BLOCK_DEVICE_ERROR_PARAMETER;
DVLevine 0:69bfc1595ae5 533 }
DVLevine 0:69bfc1595ae5 534
DVLevine 0:69bfc1595ae5 535 lock();
DVLevine 0:69bfc1595ae5 536 if (!_is_initialized) {
DVLevine 0:69bfc1595ae5 537 unlock();
DVLevine 0:69bfc1595ae5 538 return SD_BLOCK_DEVICE_ERROR_NO_INIT;
DVLevine 0:69bfc1595ae5 539 }
DVLevine 0:69bfc1595ae5 540 int status = BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 541
DVLevine 0:69bfc1595ae5 542 size -= _block_size;
DVLevine 0:69bfc1595ae5 543 // SDSC Card (CCS=0) uses byte unit address
DVLevine 0:69bfc1595ae5 544 // SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit)
DVLevine 0:69bfc1595ae5 545 if (SDCARD_V2HC == _card_type) {
DVLevine 0:69bfc1595ae5 546 size = size / _block_size;
DVLevine 0:69bfc1595ae5 547 addr = addr / _block_size;
DVLevine 0:69bfc1595ae5 548 }
DVLevine 0:69bfc1595ae5 549
DVLevine 0:69bfc1595ae5 550 // Start lba sent in start command
DVLevine 0:69bfc1595ae5 551 if (BD_ERROR_OK != (status = _cmd(CMD32_ERASE_WR_BLK_START_ADDR, addr))) {
DVLevine 0:69bfc1595ae5 552 unlock();
DVLevine 0:69bfc1595ae5 553 return status;
DVLevine 0:69bfc1595ae5 554 }
DVLevine 0:69bfc1595ae5 555
DVLevine 0:69bfc1595ae5 556 // End lba = addr+size sent in end addr command
DVLevine 0:69bfc1595ae5 557 if (BD_ERROR_OK != (status = _cmd(CMD33_ERASE_WR_BLK_END_ADDR, addr+size))) {
DVLevine 0:69bfc1595ae5 558 unlock();
DVLevine 0:69bfc1595ae5 559 return status;
DVLevine 0:69bfc1595ae5 560 }
DVLevine 0:69bfc1595ae5 561 status = _cmd(CMD38_ERASE, 0x0);
DVLevine 0:69bfc1595ae5 562 unlock();
DVLevine 0:69bfc1595ae5 563 return status;
DVLevine 0:69bfc1595ae5 564 }
DVLevine 0:69bfc1595ae5 565
DVLevine 0:69bfc1595ae5 566 bd_size_t SDBlockDevice::get_read_size() const
DVLevine 0:69bfc1595ae5 567 {
DVLevine 0:69bfc1595ae5 568 return _block_size;
DVLevine 0:69bfc1595ae5 569 }
DVLevine 0:69bfc1595ae5 570
DVLevine 0:69bfc1595ae5 571 bd_size_t SDBlockDevice::get_program_size() const
DVLevine 0:69bfc1595ae5 572 {
DVLevine 0:69bfc1595ae5 573 return _block_size;
DVLevine 0:69bfc1595ae5 574 }
DVLevine 0:69bfc1595ae5 575
DVLevine 0:69bfc1595ae5 576 bd_size_t SDBlockDevice::size() const
DVLevine 0:69bfc1595ae5 577 {
DVLevine 0:69bfc1595ae5 578 return _block_size*_sectors;
DVLevine 0:69bfc1595ae5 579 }
DVLevine 0:69bfc1595ae5 580
DVLevine 0:69bfc1595ae5 581 void SDBlockDevice::debug(bool dbg)
DVLevine 0:69bfc1595ae5 582 {
DVLevine 0:69bfc1595ae5 583 _dbg = dbg;
DVLevine 0:69bfc1595ae5 584 }
DVLevine 0:69bfc1595ae5 585
DVLevine 0:69bfc1595ae5 586 int SDBlockDevice::frequency(uint64_t freq)
DVLevine 0:69bfc1595ae5 587 {
DVLevine 0:69bfc1595ae5 588 lock();
DVLevine 0:69bfc1595ae5 589 _transfer_sck = freq;
DVLevine 0:69bfc1595ae5 590 int err = _freq();
DVLevine 0:69bfc1595ae5 591 unlock();
DVLevine 0:69bfc1595ae5 592 return err;
DVLevine 0:69bfc1595ae5 593 }
DVLevine 0:69bfc1595ae5 594
DVLevine 0:69bfc1595ae5 595 // PRIVATE FUNCTIONS
DVLevine 0:69bfc1595ae5 596 int SDBlockDevice::_freq(void)
DVLevine 0:69bfc1595ae5 597 {
DVLevine 0:69bfc1595ae5 598 // Max frequency supported is 25MHZ
DVLevine 0:69bfc1595ae5 599 if (_transfer_sck <= 25000000) {
DVLevine 0:69bfc1595ae5 600 _spi.frequency(_transfer_sck);
DVLevine 0:69bfc1595ae5 601 return 0;
DVLevine 0:69bfc1595ae5 602 } else { // TODO: Switch function to be implemented for higher frequency
DVLevine 0:69bfc1595ae5 603 _transfer_sck = 25000000;
DVLevine 0:69bfc1595ae5 604 _spi.frequency(_transfer_sck);
DVLevine 0:69bfc1595ae5 605 return -EINVAL;
DVLevine 0:69bfc1595ae5 606 }
DVLevine 0:69bfc1595ae5 607 }
DVLevine 0:69bfc1595ae5 608
DVLevine 0:69bfc1595ae5 609 uint8_t SDBlockDevice::_cmd_spi(SDBlockDevice::cmdSupported cmd, uint32_t arg) {
DVLevine 0:69bfc1595ae5 610 uint8_t response;
DVLevine 0:69bfc1595ae5 611 char cmdPacket[PACKET_SIZE];
DVLevine 0:69bfc1595ae5 612
DVLevine 0:69bfc1595ae5 613 // Prepare the command packet
DVLevine 0:69bfc1595ae5 614 cmdPacket[0] = SPI_CMD(cmd);
DVLevine 0:69bfc1595ae5 615 cmdPacket[1] = (arg >> 24);
DVLevine 0:69bfc1595ae5 616 cmdPacket[2] = (arg >> 16);
DVLevine 0:69bfc1595ae5 617 cmdPacket[3] = (arg >> 8);
DVLevine 0:69bfc1595ae5 618 cmdPacket[4] = (arg >> 0);
DVLevine 0:69bfc1595ae5 619 // CMD0 is executed in SD mode, hence should have correct CRC
DVLevine 0:69bfc1595ae5 620 // CMD8 CRC verification is always enabled
DVLevine 0:69bfc1595ae5 621 switch(cmd) {
DVLevine 0:69bfc1595ae5 622 case CMD0_GO_IDLE_STATE:
DVLevine 0:69bfc1595ae5 623 cmdPacket[5] = 0x95;
DVLevine 0:69bfc1595ae5 624 break;
DVLevine 0:69bfc1595ae5 625 case CMD8_SEND_IF_COND:
DVLevine 0:69bfc1595ae5 626 cmdPacket[5] = 0x87;
DVLevine 0:69bfc1595ae5 627 break;
DVLevine 0:69bfc1595ae5 628 default:
DVLevine 0:69bfc1595ae5 629 cmdPacket[5] = 0xFF; // Make sure bit 0-End bit is high
DVLevine 0:69bfc1595ae5 630 break;
DVLevine 0:69bfc1595ae5 631 }
DVLevine 0:69bfc1595ae5 632
DVLevine 0:69bfc1595ae5 633 // send a command
DVLevine 0:69bfc1595ae5 634 for (int i = 0; i < PACKET_SIZE; i++) {
DVLevine 0:69bfc1595ae5 635 _spi.write(cmdPacket[i]);
DVLevine 0:69bfc1595ae5 636 }
DVLevine 0:69bfc1595ae5 637
DVLevine 0:69bfc1595ae5 638 // The received byte immediataly following CMD12 is a stuff byte,
DVLevine 0:69bfc1595ae5 639 // it should be discarded before receive the response of the CMD12.
DVLevine 0:69bfc1595ae5 640 if (CMD12_STOP_TRANSMISSION == cmd) {
DVLevine 0:69bfc1595ae5 641 _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 642 }
DVLevine 0:69bfc1595ae5 643
DVLevine 0:69bfc1595ae5 644 // Loop for response: Response is sent back within command response time (NCR), 0 to 8 bytes for SDC
DVLevine 0:69bfc1595ae5 645 for (int i = 0; i < 0x10; i++) {
DVLevine 0:69bfc1595ae5 646 response = _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 647 // Got the response
DVLevine 0:69bfc1595ae5 648 if (!(response & R1_RESPONSE_RECV)) {
DVLevine 0:69bfc1595ae5 649 break;
DVLevine 0:69bfc1595ae5 650 }
DVLevine 0:69bfc1595ae5 651 }
DVLevine 0:69bfc1595ae5 652 return response;
DVLevine 0:69bfc1595ae5 653 }
DVLevine 0:69bfc1595ae5 654
DVLevine 0:69bfc1595ae5 655 int SDBlockDevice::_cmd(SDBlockDevice::cmdSupported cmd, uint32_t arg, bool isAcmd, uint32_t *resp) {
DVLevine 0:69bfc1595ae5 656 int32_t status = BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 657 uint32_t response;
DVLevine 0:69bfc1595ae5 658
DVLevine 0:69bfc1595ae5 659 // Select card and wait for card to be ready before sending next command
DVLevine 0:69bfc1595ae5 660 // Note: next command will fail if card is not ready
DVLevine 0:69bfc1595ae5 661 _select();
DVLevine 0:69bfc1595ae5 662
DVLevine 0:69bfc1595ae5 663 // No need to wait for card to be ready when sending the stop command
DVLevine 0:69bfc1595ae5 664 if (CMD12_STOP_TRANSMISSION != cmd) {
DVLevine 0:69bfc1595ae5 665 if (false == _wait_ready(SD_COMMAND_TIMEOUT)) {
DVLevine 0:69bfc1595ae5 666 debug_if(SD_DBG, "Card not ready yet \n");
DVLevine 0:69bfc1595ae5 667 }
DVLevine 0:69bfc1595ae5 668 }
DVLevine 0:69bfc1595ae5 669
DVLevine 0:69bfc1595ae5 670 // Re-try command
DVLevine 0:69bfc1595ae5 671 for(int i = 0; i < 3; i++) {
DVLevine 0:69bfc1595ae5 672 // Send CMD55 for APP command first
DVLevine 0:69bfc1595ae5 673 if (isAcmd) {
DVLevine 0:69bfc1595ae5 674 response = _cmd_spi(CMD55_APP_CMD, 0x0);
DVLevine 0:69bfc1595ae5 675 // Wait for card to be ready after CMD55
DVLevine 0:69bfc1595ae5 676 if (false == _wait_ready(SD_COMMAND_TIMEOUT)) {
DVLevine 0:69bfc1595ae5 677 debug_if(SD_DBG, "Card not ready yet \n");
DVLevine 0:69bfc1595ae5 678 }
DVLevine 0:69bfc1595ae5 679 }
DVLevine 0:69bfc1595ae5 680
DVLevine 0:69bfc1595ae5 681 // Send command over SPI interface
DVLevine 0:69bfc1595ae5 682 response = _cmd_spi(cmd, arg);
DVLevine 0:69bfc1595ae5 683 if (R1_NO_RESPONSE == response) {
DVLevine 0:69bfc1595ae5 684 debug_if(SD_DBG, "No response CMD:%d \n", cmd);
DVLevine 0:69bfc1595ae5 685 continue;
DVLevine 0:69bfc1595ae5 686 }
DVLevine 0:69bfc1595ae5 687 break;
DVLevine 0:69bfc1595ae5 688 }
DVLevine 0:69bfc1595ae5 689
DVLevine 0:69bfc1595ae5 690 // Pass the response to the command call if required
DVLevine 0:69bfc1595ae5 691 if (NULL != resp) {
DVLevine 0:69bfc1595ae5 692 *resp = response;
DVLevine 0:69bfc1595ae5 693 }
DVLevine 0:69bfc1595ae5 694
DVLevine 0:69bfc1595ae5 695 // Process the response R1 : Exit on CRC/Illegal command error/No response
DVLevine 0:69bfc1595ae5 696 if (R1_NO_RESPONSE == response) {
DVLevine 0:69bfc1595ae5 697 _deselect();
DVLevine 0:69bfc1595ae5 698 debug_if(SD_DBG, "No response CMD:%d response: 0x%x\n",cmd, response);
DVLevine 0:69bfc1595ae5 699 return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; // No device
DVLevine 0:69bfc1595ae5 700 }
DVLevine 0:69bfc1595ae5 701 if (response & R1_COM_CRC_ERROR) {
DVLevine 0:69bfc1595ae5 702 _deselect();
DVLevine 0:69bfc1595ae5 703 debug_if(SD_DBG, "CRC error CMD:%d response 0x%x \n",cmd, response);
DVLevine 0:69bfc1595ae5 704 return SD_BLOCK_DEVICE_ERROR_CRC; // CRC error
DVLevine 0:69bfc1595ae5 705 }
DVLevine 0:69bfc1595ae5 706 if (response & R1_ILLEGAL_COMMAND) {
DVLevine 0:69bfc1595ae5 707 _deselect();
DVLevine 0:69bfc1595ae5 708 debug_if(SD_DBG, "Illegal command CMD:%d response 0x%x\n",cmd, response);
DVLevine 0:69bfc1595ae5 709 if (CMD8_SEND_IF_COND == cmd) { // Illegal command is for Ver1 or not SD Card
DVLevine 0:69bfc1595ae5 710 _card_type = CARD_UNKNOWN;
DVLevine 0:69bfc1595ae5 711 }
DVLevine 0:69bfc1595ae5 712 return SD_BLOCK_DEVICE_ERROR_UNSUPPORTED; // Command not supported
DVLevine 0:69bfc1595ae5 713 }
DVLevine 0:69bfc1595ae5 714
DVLevine 0:69bfc1595ae5 715 debug_if(_dbg, "CMD:%d \t arg:0x%x \t Response:0x%x \n", cmd, arg, response);
DVLevine 0:69bfc1595ae5 716 // Set status for other errors
DVLevine 0:69bfc1595ae5 717 if ((response & R1_ERASE_RESET) || (response & R1_ERASE_SEQUENCE_ERROR)) {
DVLevine 0:69bfc1595ae5 718 status = SD_BLOCK_DEVICE_ERROR_ERASE; // Erase error
DVLevine 0:69bfc1595ae5 719 }else if ((response & R1_ADDRESS_ERROR) || (response & R1_PARAMETER_ERROR)) {
DVLevine 0:69bfc1595ae5 720 // Misaligned address / invalid address block length
DVLevine 0:69bfc1595ae5 721 status = SD_BLOCK_DEVICE_ERROR_PARAMETER;
DVLevine 0:69bfc1595ae5 722 }
DVLevine 0:69bfc1595ae5 723
DVLevine 0:69bfc1595ae5 724 // Get rest of the response part for other commands
DVLevine 0:69bfc1595ae5 725 switch(cmd) {
DVLevine 0:69bfc1595ae5 726 case CMD8_SEND_IF_COND: // Response R7
DVLevine 0:69bfc1595ae5 727 debug_if(_dbg, "V2-Version Card\n");
DVLevine 0:69bfc1595ae5 728 _card_type = SDCARD_V2;
DVLevine 0:69bfc1595ae5 729 // Note: No break here, need to read rest of the response
DVLevine 0:69bfc1595ae5 730 case CMD58_READ_OCR: // Response R3
DVLevine 0:69bfc1595ae5 731 response = (_spi.write(SPI_FILL_CHAR) << 24);
DVLevine 0:69bfc1595ae5 732 response |= (_spi.write(SPI_FILL_CHAR) << 16);
DVLevine 0:69bfc1595ae5 733 response |= (_spi.write(SPI_FILL_CHAR) << 8);
DVLevine 0:69bfc1595ae5 734 response |= _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 735 debug_if(_dbg, "R3/R7: 0x%x \n", response);
DVLevine 0:69bfc1595ae5 736 break;
DVLevine 0:69bfc1595ae5 737
DVLevine 0:69bfc1595ae5 738 case CMD12_STOP_TRANSMISSION: // Response R1b
DVLevine 0:69bfc1595ae5 739 case CMD38_ERASE:
DVLevine 0:69bfc1595ae5 740 _wait_ready(SD_COMMAND_TIMEOUT);
DVLevine 0:69bfc1595ae5 741 break;
DVLevine 0:69bfc1595ae5 742
DVLevine 0:69bfc1595ae5 743 case ACMD13_SD_STATUS: // Response R2
DVLevine 0:69bfc1595ae5 744 response = _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 745 debug_if(_dbg, "R2: 0x%x \n", response);
DVLevine 0:69bfc1595ae5 746 break;
DVLevine 0:69bfc1595ae5 747
DVLevine 0:69bfc1595ae5 748 default: // Response R1
DVLevine 0:69bfc1595ae5 749 break;
DVLevine 0:69bfc1595ae5 750 }
DVLevine 0:69bfc1595ae5 751
DVLevine 0:69bfc1595ae5 752 // Pass the updated response to the command
DVLevine 0:69bfc1595ae5 753 if (NULL != resp) {
DVLevine 0:69bfc1595ae5 754 *resp = response;
DVLevine 0:69bfc1595ae5 755 }
DVLevine 0:69bfc1595ae5 756
DVLevine 0:69bfc1595ae5 757 // Do not deselect card if read is in progress.
DVLevine 0:69bfc1595ae5 758 if (((CMD9_SEND_CSD == cmd) || (ACMD22_SEND_NUM_WR_BLOCKS == cmd) ||
DVLevine 0:69bfc1595ae5 759 (CMD24_WRITE_BLOCK == cmd) || (CMD25_WRITE_MULTIPLE_BLOCK == cmd) ||
DVLevine 0:69bfc1595ae5 760 (CMD17_READ_SINGLE_BLOCK == cmd) || (CMD18_READ_MULTIPLE_BLOCK == cmd))
DVLevine 0:69bfc1595ae5 761 && (BD_ERROR_OK == status)) {
DVLevine 0:69bfc1595ae5 762 return BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 763 }
DVLevine 0:69bfc1595ae5 764 // Deselect card
DVLevine 0:69bfc1595ae5 765 _deselect();
DVLevine 0:69bfc1595ae5 766 return status;
DVLevine 0:69bfc1595ae5 767 }
DVLevine 0:69bfc1595ae5 768
DVLevine 0:69bfc1595ae5 769 int SDBlockDevice::_cmd8() {
DVLevine 0:69bfc1595ae5 770 uint32_t arg = (CMD8_PATTERN << 0); // [7:0]check pattern
DVLevine 0:69bfc1595ae5 771 uint32_t response = 0;
DVLevine 0:69bfc1595ae5 772 int32_t status = BD_ERROR_OK;
DVLevine 0:69bfc1595ae5 773
DVLevine 0:69bfc1595ae5 774 arg |= (0x1 << 8); // 2.7-3.6V // [11:8]supply voltage(VHS)
DVLevine 0:69bfc1595ae5 775
DVLevine 0:69bfc1595ae5 776 status = _cmd(CMD8_SEND_IF_COND, arg, 0x0, &response);
DVLevine 0:69bfc1595ae5 777 // Verify voltage and pattern for V2 version of card
DVLevine 0:69bfc1595ae5 778 if ((BD_ERROR_OK == status) && (SDCARD_V2 == _card_type)) {
DVLevine 0:69bfc1595ae5 779 // If check pattern is not matched, CMD8 communication is not valid
DVLevine 0:69bfc1595ae5 780 if((response & 0xFFF) != arg)
DVLevine 0:69bfc1595ae5 781 {
DVLevine 0:69bfc1595ae5 782 debug_if(SD_DBG, "CMD8 Pattern mismatch 0x%x : 0x%x\n", arg, response);
DVLevine 0:69bfc1595ae5 783 _card_type = CARD_UNKNOWN;
DVLevine 0:69bfc1595ae5 784 status = SD_BLOCK_DEVICE_ERROR_UNUSABLE;
DVLevine 0:69bfc1595ae5 785 }
DVLevine 0:69bfc1595ae5 786 }
DVLevine 0:69bfc1595ae5 787 return status;
DVLevine 0:69bfc1595ae5 788 }
DVLevine 0:69bfc1595ae5 789
DVLevine 0:69bfc1595ae5 790 uint32_t SDBlockDevice::_go_idle_state() {
DVLevine 0:69bfc1595ae5 791 uint32_t response;
DVLevine 0:69bfc1595ae5 792
DVLevine 0:69bfc1595ae5 793 /* Reseting the MCU SPI master may not reset the on-board SDCard, in which
DVLevine 0:69bfc1595ae5 794 * case when MCU power-on occurs the SDCard will resume operations as
DVLevine 0:69bfc1595ae5 795 * though there was no reset. In this scenario the first CMD0 will
DVLevine 0:69bfc1595ae5 796 * not be interpreted as a command and get lost. For some cards retrying
DVLevine 0:69bfc1595ae5 797 * the command overcomes this situation. */
DVLevine 0:69bfc1595ae5 798 for (int i = 0; i < SD_CMD0_GO_IDLE_STATE_RETRIES; i++) {
DVLevine 0:69bfc1595ae5 799 _cmd(CMD0_GO_IDLE_STATE, 0x0, 0x0, &response);
DVLevine 0:69bfc1595ae5 800 if (R1_IDLE_STATE == response)
DVLevine 0:69bfc1595ae5 801 break;
DVLevine 0:69bfc1595ae5 802 wait_ms(1);
DVLevine 0:69bfc1595ae5 803 }
DVLevine 0:69bfc1595ae5 804 return response;
DVLevine 0:69bfc1595ae5 805 }
DVLevine 0:69bfc1595ae5 806
DVLevine 0:69bfc1595ae5 807 int SDBlockDevice::_read_bytes(uint8_t *buffer, uint32_t length) {
DVLevine 0:69bfc1595ae5 808 uint16_t crc;
DVLevine 0:69bfc1595ae5 809
DVLevine 0:69bfc1595ae5 810 // read until start byte (0xFE)
DVLevine 0:69bfc1595ae5 811 if (false == _wait_token(SPI_START_BLOCK)) {
DVLevine 0:69bfc1595ae5 812 debug_if(SD_DBG, "Read timeout\n");
DVLevine 0:69bfc1595ae5 813 _deselect();
DVLevine 0:69bfc1595ae5 814 return SD_BLOCK_DEVICE_ERROR_NO_RESPONSE;
DVLevine 0:69bfc1595ae5 815 }
DVLevine 0:69bfc1595ae5 816
DVLevine 0:69bfc1595ae5 817 // read data
DVLevine 0:69bfc1595ae5 818 for (uint32_t i = 0; i < length; i++) {
DVLevine 0:69bfc1595ae5 819 buffer[i] = _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 820 }
DVLevine 0:69bfc1595ae5 821
DVLevine 0:69bfc1595ae5 822 // Read the CRC16 checksum for the data block
DVLevine 0:69bfc1595ae5 823 crc = (_spi.write(SPI_FILL_CHAR) << 8);
DVLevine 0:69bfc1595ae5 824 crc |= _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 825
DVLevine 0:69bfc1595ae5 826 _deselect();
DVLevine 0:69bfc1595ae5 827 return 0;
DVLevine 0:69bfc1595ae5 828 }
DVLevine 0:69bfc1595ae5 829
DVLevine 0:69bfc1595ae5 830 int SDBlockDevice::_read(uint8_t *buffer, uint32_t length) {
DVLevine 0:69bfc1595ae5 831 uint16_t crc;
DVLevine 0:69bfc1595ae5 832
DVLevine 0:69bfc1595ae5 833 // read until start byte (0xFE)
DVLevine 0:69bfc1595ae5 834 if (false == _wait_token(SPI_START_BLOCK)) {
DVLevine 0:69bfc1595ae5 835 debug_if(SD_DBG, "Read timeout\n");
DVLevine 0:69bfc1595ae5 836 _deselect();
DVLevine 0:69bfc1595ae5 837 return SD_BLOCK_DEVICE_ERROR_NO_RESPONSE;
DVLevine 0:69bfc1595ae5 838 }
DVLevine 0:69bfc1595ae5 839
DVLevine 0:69bfc1595ae5 840 // read data
DVLevine 0:69bfc1595ae5 841 _spi.write(NULL, 0, (char*)buffer, length);
DVLevine 0:69bfc1595ae5 842
DVLevine 0:69bfc1595ae5 843 // Read the CRC16 checksum for the data block
DVLevine 0:69bfc1595ae5 844 crc = (_spi.write(SPI_FILL_CHAR) << 8);
DVLevine 0:69bfc1595ae5 845 crc |= _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 846
DVLevine 0:69bfc1595ae5 847 return 0;
DVLevine 0:69bfc1595ae5 848 }
DVLevine 0:69bfc1595ae5 849
DVLevine 0:69bfc1595ae5 850 uint8_t SDBlockDevice::_write(const uint8_t *buffer, uint8_t token, uint32_t length) {
DVLevine 0:69bfc1595ae5 851 uint16_t crc = 0xFFFF;
DVLevine 0:69bfc1595ae5 852 uint8_t response = 0xFF;
DVLevine 0:69bfc1595ae5 853
DVLevine 0:69bfc1595ae5 854 // indicate start of block
DVLevine 0:69bfc1595ae5 855 _spi.write(token);
DVLevine 0:69bfc1595ae5 856
DVLevine 0:69bfc1595ae5 857 // write the data
DVLevine 0:69bfc1595ae5 858 _spi.write((char*)buffer, length, NULL, 0);
DVLevine 0:69bfc1595ae5 859
DVLevine 0:69bfc1595ae5 860 // write the checksum CRC16
DVLevine 0:69bfc1595ae5 861 _spi.write(crc >> 8);
DVLevine 0:69bfc1595ae5 862 _spi.write(crc);
DVLevine 0:69bfc1595ae5 863
DVLevine 0:69bfc1595ae5 864 // check the response token
DVLevine 0:69bfc1595ae5 865 response = _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 866
DVLevine 0:69bfc1595ae5 867 // Wait for last block to be written
DVLevine 0:69bfc1595ae5 868 if (false == _wait_ready(SD_COMMAND_TIMEOUT)) {
DVLevine 0:69bfc1595ae5 869 debug_if(SD_DBG, "Card not ready yet \n");
DVLevine 0:69bfc1595ae5 870 }
DVLevine 0:69bfc1595ae5 871
DVLevine 0:69bfc1595ae5 872 return (response & SPI_DATA_RESPONSE_MASK);
DVLevine 0:69bfc1595ae5 873 }
DVLevine 0:69bfc1595ae5 874
DVLevine 0:69bfc1595ae5 875 static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
DVLevine 0:69bfc1595ae5 876 uint32_t bits = 0;
DVLevine 0:69bfc1595ae5 877 uint32_t size = 1 + msb - lsb;
DVLevine 0:69bfc1595ae5 878 for (uint32_t i = 0; i < size; i++) {
DVLevine 0:69bfc1595ae5 879 uint32_t position = lsb + i;
DVLevine 0:69bfc1595ae5 880 uint32_t byte = 15 - (position >> 3);
DVLevine 0:69bfc1595ae5 881 uint32_t bit = position & 0x7;
DVLevine 0:69bfc1595ae5 882 uint32_t value = (data[byte] >> bit) & 1;
DVLevine 0:69bfc1595ae5 883 bits |= value << i;
DVLevine 0:69bfc1595ae5 884 }
DVLevine 0:69bfc1595ae5 885 return bits;
DVLevine 0:69bfc1595ae5 886 }
DVLevine 0:69bfc1595ae5 887
DVLevine 0:69bfc1595ae5 888 bd_size_t SDBlockDevice::_sd_sectors() {
DVLevine 0:69bfc1595ae5 889 uint32_t c_size, c_size_mult, read_bl_len;
DVLevine 0:69bfc1595ae5 890 uint32_t block_len, mult, blocknr;
DVLevine 0:69bfc1595ae5 891 uint32_t hc_c_size;
DVLevine 0:69bfc1595ae5 892 bd_size_t blocks = 0, capacity = 0;
DVLevine 0:69bfc1595ae5 893
DVLevine 0:69bfc1595ae5 894 // CMD9, Response R2 (R1 byte + 16-byte block read)
DVLevine 0:69bfc1595ae5 895 if (_cmd(CMD9_SEND_CSD, 0x0) != 0x0) {
DVLevine 0:69bfc1595ae5 896 debug_if(SD_DBG, "Didn't get a response from the disk\n");
DVLevine 0:69bfc1595ae5 897 return 0;
DVLevine 0:69bfc1595ae5 898 }
DVLevine 0:69bfc1595ae5 899 uint8_t csd[16];
DVLevine 0:69bfc1595ae5 900 if (_read_bytes(csd, 16) != 0) {
DVLevine 0:69bfc1595ae5 901 debug_if(SD_DBG, "Couldn't read csd response from disk\n");
DVLevine 0:69bfc1595ae5 902 return 0;
DVLevine 0:69bfc1595ae5 903 }
DVLevine 0:69bfc1595ae5 904
DVLevine 0:69bfc1595ae5 905 // csd_structure : csd[127:126]
DVLevine 0:69bfc1595ae5 906 int csd_structure = ext_bits(csd, 127, 126);
DVLevine 0:69bfc1595ae5 907 switch (csd_structure) {
DVLevine 0:69bfc1595ae5 908 case 0:
DVLevine 0:69bfc1595ae5 909 c_size = ext_bits(csd, 73, 62); // c_size : csd[73:62]
DVLevine 0:69bfc1595ae5 910 c_size_mult = ext_bits(csd, 49, 47); // c_size_mult : csd[49:47]
DVLevine 0:69bfc1595ae5 911 read_bl_len = ext_bits(csd, 83, 80); // read_bl_len : csd[83:80] - the *maximum* read block length
DVLevine 0:69bfc1595ae5 912 block_len = 1 << read_bl_len; // BLOCK_LEN = 2^READ_BL_LEN
DVLevine 0:69bfc1595ae5 913 mult = 1 << (c_size_mult + 2); // MULT = 2^C_SIZE_MULT+2 (C_SIZE_MULT < 8)
DVLevine 0:69bfc1595ae5 914 blocknr = (c_size + 1) * mult; // BLOCKNR = (C_SIZE+1) * MULT
DVLevine 0:69bfc1595ae5 915 capacity = blocknr * block_len; // memory capacity = BLOCKNR * BLOCK_LEN
DVLevine 0:69bfc1595ae5 916 blocks = capacity / _block_size;
DVLevine 0:69bfc1595ae5 917 debug_if(SD_DBG, "Standard Capacity: c_size: %d \n", c_size);
DVLevine 0:69bfc1595ae5 918 debug_if(SD_DBG, "Sectors: 0x%x : %llu\n", blocks, blocks);
DVLevine 0:69bfc1595ae5 919 debug_if(SD_DBG, "Capacity: 0x%x : %llu MB\n", capacity, (capacity/(1024U*1024U)));
DVLevine 0:69bfc1595ae5 920
DVLevine 0:69bfc1595ae5 921 // ERASE_BLK_EN = 1: Erase in multiple of 512 bytes supported
DVLevine 0:69bfc1595ae5 922 if (ext_bits(csd, 46, 46)) {
DVLevine 0:69bfc1595ae5 923 _erase_size = BLOCK_SIZE_HC;
DVLevine 0:69bfc1595ae5 924 } else {
DVLevine 0:69bfc1595ae5 925 // ERASE_BLK_EN = 1: Erase in multiple of SECTOR_SIZE supported
DVLevine 0:69bfc1595ae5 926 _erase_size = BLOCK_SIZE_HC * (ext_bits(csd, 45, 39) + 1);
DVLevine 0:69bfc1595ae5 927 }
DVLevine 0:69bfc1595ae5 928 break;
DVLevine 0:69bfc1595ae5 929
DVLevine 0:69bfc1595ae5 930 case 1:
DVLevine 0:69bfc1595ae5 931 hc_c_size = ext_bits(csd, 69, 48); // device size : C_SIZE : [69:48]
DVLevine 0:69bfc1595ae5 932 blocks = (hc_c_size+1) << 10; // block count = C_SIZE+1) * 1K byte (512B is block size)
DVLevine 0:69bfc1595ae5 933 debug_if(SD_DBG, "SDHC/SDXC Card: hc_c_size: %d \n", hc_c_size);
DVLevine 0:69bfc1595ae5 934 debug_if(SD_DBG, "Sectors: 0x%x : %llu\n", blocks, blocks);
DVLevine 0:69bfc1595ae5 935 debug_if(SD_DBG, "Capacity: %llu MB\n", (blocks/(2048U)));
DVLevine 0:69bfc1595ae5 936 // ERASE_BLK_EN is fixed to 1, which means host can erase one or multiple of 512 bytes.
DVLevine 0:69bfc1595ae5 937 _erase_size = BLOCK_SIZE_HC;
DVLevine 0:69bfc1595ae5 938 break;
DVLevine 0:69bfc1595ae5 939
DVLevine 0:69bfc1595ae5 940 default:
DVLevine 0:69bfc1595ae5 941 debug_if(SD_DBG, "CSD struct unsupported\r\n");
DVLevine 0:69bfc1595ae5 942 return 0;
DVLevine 0:69bfc1595ae5 943 };
DVLevine 0:69bfc1595ae5 944 return blocks;
DVLevine 0:69bfc1595ae5 945 }
DVLevine 0:69bfc1595ae5 946
DVLevine 0:69bfc1595ae5 947 // SPI function to wait till chip is ready and sends start token
DVLevine 0:69bfc1595ae5 948 bool SDBlockDevice::_wait_token(uint8_t token) {
DVLevine 0:69bfc1595ae5 949 _spi_timer.reset();
DVLevine 0:69bfc1595ae5 950 _spi_timer.start();
DVLevine 0:69bfc1595ae5 951
DVLevine 0:69bfc1595ae5 952 do {
DVLevine 0:69bfc1595ae5 953 if (token == _spi.write(SPI_FILL_CHAR)) {
DVLevine 0:69bfc1595ae5 954 _spi_timer.stop();
DVLevine 0:69bfc1595ae5 955 return true;
DVLevine 0:69bfc1595ae5 956 }
DVLevine 0:69bfc1595ae5 957 } while (_spi_timer.read_ms() < 300); // Wait for 300 msec for start token
DVLevine 0:69bfc1595ae5 958 _spi_timer.stop();
DVLevine 0:69bfc1595ae5 959 debug_if(SD_DBG, "_wait_token: timeout\n");
DVLevine 0:69bfc1595ae5 960 return false;
DVLevine 0:69bfc1595ae5 961 }
DVLevine 0:69bfc1595ae5 962
DVLevine 0:69bfc1595ae5 963 // SPI function to wait till chip is ready
DVLevine 0:69bfc1595ae5 964 // The host controller should wait for end of the process until DO goes high (a 0xFF is received).
DVLevine 0:69bfc1595ae5 965 bool SDBlockDevice::_wait_ready(uint16_t ms) {
DVLevine 0:69bfc1595ae5 966 uint8_t response;
DVLevine 0:69bfc1595ae5 967 _spi_timer.reset();
DVLevine 0:69bfc1595ae5 968 _spi_timer.start();
DVLevine 0:69bfc1595ae5 969 do {
DVLevine 0:69bfc1595ae5 970 response = _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 971 if (response == 0xFF) {
DVLevine 0:69bfc1595ae5 972 _spi_timer.stop();
DVLevine 0:69bfc1595ae5 973 return true;
DVLevine 0:69bfc1595ae5 974 }
DVLevine 0:69bfc1595ae5 975 } while (_spi_timer.read_ms() < ms);
DVLevine 0:69bfc1595ae5 976 _spi_timer.stop();
DVLevine 0:69bfc1595ae5 977 return false;
DVLevine 0:69bfc1595ae5 978 }
DVLevine 0:69bfc1595ae5 979
DVLevine 0:69bfc1595ae5 980 // SPI function to wait for count
DVLevine 0:69bfc1595ae5 981 void SDBlockDevice::_spi_wait(uint8_t count)
DVLevine 0:69bfc1595ae5 982 {
DVLevine 0:69bfc1595ae5 983 for (uint8_t i = 0; i < count; ++i) {
DVLevine 0:69bfc1595ae5 984 _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 985 }
DVLevine 0:69bfc1595ae5 986 }
DVLevine 0:69bfc1595ae5 987
DVLevine 0:69bfc1595ae5 988 void SDBlockDevice::_spi_init() {
DVLevine 0:69bfc1595ae5 989 _spi.lock();
DVLevine 0:69bfc1595ae5 990 // Set to SCK for initialization, and clock card with cs = 1
DVLevine 0:69bfc1595ae5 991 _spi.frequency(_init_sck);
DVLevine 0:69bfc1595ae5 992 _spi.format(8, 0);
DVLevine 0:69bfc1595ae5 993 _spi.set_default_write_value(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 994 // Initial 74 cycles required for few cards, before selecting SPI mode
DVLevine 0:69bfc1595ae5 995 _cs = 1;
DVLevine 0:69bfc1595ae5 996 _spi_wait(10);
DVLevine 0:69bfc1595ae5 997 _spi.unlock();
DVLevine 0:69bfc1595ae5 998 }
DVLevine 0:69bfc1595ae5 999
DVLevine 0:69bfc1595ae5 1000 void SDBlockDevice::_select() {
DVLevine 0:69bfc1595ae5 1001 _spi.lock();
DVLevine 0:69bfc1595ae5 1002 _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 1003 _cs = 0;
DVLevine 0:69bfc1595ae5 1004 }
DVLevine 0:69bfc1595ae5 1005
DVLevine 0:69bfc1595ae5 1006 void SDBlockDevice::_deselect() {
DVLevine 0:69bfc1595ae5 1007 _cs = 1;
DVLevine 0:69bfc1595ae5 1008 _spi.write(SPI_FILL_CHAR);
DVLevine 0:69bfc1595ae5 1009 _spi.unlock();
DVLevine 0:69bfc1595ae5 1010 }
DVLevine 0:69bfc1595ae5 1011
DVLevine 0:69bfc1595ae5 1012 #endif /* DEVICE_SPI */