RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
2019-03-13

Who changed what in which revision?

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