sd-driver 1.2.0 from github

Dependents:   Saver2

Committer:
SDesign2018
Date:
Thu Apr 12 01:36:31 2018 +0000
Revision:
0:f72b3e7f1ec8
Same stuff;

Who changed what in which revision?

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