RTC auf true
components/storage/blockdevice/COMPONENT_SD/SDBlockDevice.h@2:7aab896b1a3b, 2019-03-13 (annotated)
- Committer:
- kevman
- Date:
- Wed Mar 13 11:03:24 2019 +0000
- Revision:
- 2:7aab896b1a3b
2019-03-13
Who changed what in which revision?
User | Revision | Line number | New 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 | #ifndef MBED_SD_BLOCK_DEVICE_H |
kevman | 2:7aab896b1a3b | 18 | #define MBED_SD_BLOCK_DEVICE_H |
kevman | 2:7aab896b1a3b | 19 | |
kevman | 2:7aab896b1a3b | 20 | /* If the target has no SPI support then SDCard is not supported */ |
kevman | 2:7aab896b1a3b | 21 | #ifdef DEVICE_SPI |
kevman | 2:7aab896b1a3b | 22 | |
kevman | 2:7aab896b1a3b | 23 | #include "BlockDevice.h" |
kevman | 2:7aab896b1a3b | 24 | #include "drivers/SPI.h" |
kevman | 2:7aab896b1a3b | 25 | #include "drivers/Timer.h" |
kevman | 2:7aab896b1a3b | 26 | #include "drivers/MbedCRC.h" |
kevman | 2:7aab896b1a3b | 27 | #include "drivers/DigitalOut.h" |
kevman | 2:7aab896b1a3b | 28 | #include "platform/platform.h" |
kevman | 2:7aab896b1a3b | 29 | #include "platform/PlatformMutex.h" |
kevman | 2:7aab896b1a3b | 30 | |
kevman | 2:7aab896b1a3b | 31 | /** SDBlockDevice class |
kevman | 2:7aab896b1a3b | 32 | * |
kevman | 2:7aab896b1a3b | 33 | * Access an SD Card using SPI |
kevman | 2:7aab896b1a3b | 34 | */ |
kevman | 2:7aab896b1a3b | 35 | class SDBlockDevice : public BlockDevice { |
kevman | 2:7aab896b1a3b | 36 | public: |
kevman | 2:7aab896b1a3b | 37 | /** Lifetime of an SD card |
kevman | 2:7aab896b1a3b | 38 | */ |
kevman | 2:7aab896b1a3b | 39 | SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs, uint64_t hz = 1000000, bool crc_on = 0); |
kevman | 2:7aab896b1a3b | 40 | virtual ~SDBlockDevice(); |
kevman | 2:7aab896b1a3b | 41 | |
kevman | 2:7aab896b1a3b | 42 | /** Initialize a block device |
kevman | 2:7aab896b1a3b | 43 | * |
kevman | 2:7aab896b1a3b | 44 | * @return 0 on success or a negative error code on failure |
kevman | 2:7aab896b1a3b | 45 | */ |
kevman | 2:7aab896b1a3b | 46 | virtual int init(); |
kevman | 2:7aab896b1a3b | 47 | |
kevman | 2:7aab896b1a3b | 48 | /** Deinitialize a block device |
kevman | 2:7aab896b1a3b | 49 | * |
kevman | 2:7aab896b1a3b | 50 | * @return 0 on success or a negative error code on failure |
kevman | 2:7aab896b1a3b | 51 | */ |
kevman | 2:7aab896b1a3b | 52 | virtual int deinit(); |
kevman | 2:7aab896b1a3b | 53 | |
kevman | 2:7aab896b1a3b | 54 | /** Read blocks from a block device |
kevman | 2:7aab896b1a3b | 55 | * |
kevman | 2:7aab896b1a3b | 56 | * @param buffer Buffer to write blocks to |
kevman | 2:7aab896b1a3b | 57 | * @param addr Address of block to begin reading from |
kevman | 2:7aab896b1a3b | 58 | * @param size Size to read in bytes, must be a multiple of read block size |
kevman | 2:7aab896b1a3b | 59 | * @return 0 on success, negative error code on failure |
kevman | 2:7aab896b1a3b | 60 | */ |
kevman | 2:7aab896b1a3b | 61 | virtual int read(void *buffer, bd_addr_t addr, bd_size_t size); |
kevman | 2:7aab896b1a3b | 62 | |
kevman | 2:7aab896b1a3b | 63 | /** Program blocks to a block device |
kevman | 2:7aab896b1a3b | 64 | * |
kevman | 2:7aab896b1a3b | 65 | * The blocks must have been erased prior to being programmed |
kevman | 2:7aab896b1a3b | 66 | * |
kevman | 2:7aab896b1a3b | 67 | * @param buffer Buffer of data to write to blocks |
kevman | 2:7aab896b1a3b | 68 | * @param addr Address of block to begin writing to |
kevman | 2:7aab896b1a3b | 69 | * @param size Size to write in bytes, must be a multiple of program block size |
kevman | 2:7aab896b1a3b | 70 | * @return 0 on success, negative error code on failure |
kevman | 2:7aab896b1a3b | 71 | */ |
kevman | 2:7aab896b1a3b | 72 | virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); |
kevman | 2:7aab896b1a3b | 73 | |
kevman | 2:7aab896b1a3b | 74 | /** Mark blocks as no longer in use |
kevman | 2:7aab896b1a3b | 75 | * |
kevman | 2:7aab896b1a3b | 76 | * This function provides a hint to the underlying block device that a region of blocks |
kevman | 2:7aab896b1a3b | 77 | * is no longer in use and may be erased without side effects. Erase must still be called |
kevman | 2:7aab896b1a3b | 78 | * before programming, but trimming allows flash-translation-layers to schedule erases when |
kevman | 2:7aab896b1a3b | 79 | * the device is not busy. |
kevman | 2:7aab896b1a3b | 80 | * |
kevman | 2:7aab896b1a3b | 81 | * @param addr Address of block to mark as unused |
kevman | 2:7aab896b1a3b | 82 | * @param size Size to mark as unused in bytes, must be a multiple of erase block size |
kevman | 2:7aab896b1a3b | 83 | * @return 0 on success, negative error code on failure |
kevman | 2:7aab896b1a3b | 84 | */ |
kevman | 2:7aab896b1a3b | 85 | virtual int trim(bd_addr_t addr, bd_size_t size); |
kevman | 2:7aab896b1a3b | 86 | |
kevman | 2:7aab896b1a3b | 87 | /** Get the size of a readable block |
kevman | 2:7aab896b1a3b | 88 | * |
kevman | 2:7aab896b1a3b | 89 | * @return Size of a readable block in bytes |
kevman | 2:7aab896b1a3b | 90 | */ |
kevman | 2:7aab896b1a3b | 91 | virtual bd_size_t get_read_size() const; |
kevman | 2:7aab896b1a3b | 92 | |
kevman | 2:7aab896b1a3b | 93 | /** Get the size of a programable block |
kevman | 2:7aab896b1a3b | 94 | * |
kevman | 2:7aab896b1a3b | 95 | * @return Size of a programable block in bytes |
kevman | 2:7aab896b1a3b | 96 | * @note Must be a multiple of the read size |
kevman | 2:7aab896b1a3b | 97 | */ |
kevman | 2:7aab896b1a3b | 98 | virtual bd_size_t get_program_size() const; |
kevman | 2:7aab896b1a3b | 99 | |
kevman | 2:7aab896b1a3b | 100 | /** Get the total size of the underlying device |
kevman | 2:7aab896b1a3b | 101 | * |
kevman | 2:7aab896b1a3b | 102 | * @return Size of the underlying device in bytes |
kevman | 2:7aab896b1a3b | 103 | */ |
kevman | 2:7aab896b1a3b | 104 | virtual bd_size_t size() const; |
kevman | 2:7aab896b1a3b | 105 | |
kevman | 2:7aab896b1a3b | 106 | /** Enable or disable debugging |
kevman | 2:7aab896b1a3b | 107 | * |
kevman | 2:7aab896b1a3b | 108 | * @param dbg State of debugging |
kevman | 2:7aab896b1a3b | 109 | */ |
kevman | 2:7aab896b1a3b | 110 | virtual void debug(bool dbg); |
kevman | 2:7aab896b1a3b | 111 | |
kevman | 2:7aab896b1a3b | 112 | /** Set the transfer frequency |
kevman | 2:7aab896b1a3b | 113 | * |
kevman | 2:7aab896b1a3b | 114 | * @param freq Transfer frequency |
kevman | 2:7aab896b1a3b | 115 | * @note Max frequency supported is 25MHZ |
kevman | 2:7aab896b1a3b | 116 | */ |
kevman | 2:7aab896b1a3b | 117 | virtual int frequency(uint64_t freq); |
kevman | 2:7aab896b1a3b | 118 | |
kevman | 2:7aab896b1a3b | 119 | |
kevman | 2:7aab896b1a3b | 120 | private: |
kevman | 2:7aab896b1a3b | 121 | /* Commands : Listed below are commands supported |
kevman | 2:7aab896b1a3b | 122 | * in SPI mode for SD card : Only Mandatory ones |
kevman | 2:7aab896b1a3b | 123 | */ |
kevman | 2:7aab896b1a3b | 124 | enum cmdSupported { |
kevman | 2:7aab896b1a3b | 125 | CMD_NOT_SUPPORTED = -1, /**< Command not supported error */ |
kevman | 2:7aab896b1a3b | 126 | CMD0_GO_IDLE_STATE = 0, /**< Resets the SD Memory Card */ |
kevman | 2:7aab896b1a3b | 127 | CMD1_SEND_OP_COND = 1, /**< Sends host capacity support */ |
kevman | 2:7aab896b1a3b | 128 | CMD6_SWITCH_FUNC = 6, /**< Check and Switches card function */ |
kevman | 2:7aab896b1a3b | 129 | CMD8_SEND_IF_COND = 8, /**< Supply voltage info */ |
kevman | 2:7aab896b1a3b | 130 | CMD9_SEND_CSD = 9, /**< Provides Card Specific data */ |
kevman | 2:7aab896b1a3b | 131 | CMD10_SEND_CID = 10, /**< Provides Card Identification */ |
kevman | 2:7aab896b1a3b | 132 | CMD12_STOP_TRANSMISSION = 12, /**< Forces the card to stop transmission */ |
kevman | 2:7aab896b1a3b | 133 | CMD13_SEND_STATUS = 13, /**< Card responds with status */ |
kevman | 2:7aab896b1a3b | 134 | CMD16_SET_BLOCKLEN = 16, /**< Length for SC card is set */ |
kevman | 2:7aab896b1a3b | 135 | CMD17_READ_SINGLE_BLOCK = 17, /**< Read single block of data */ |
kevman | 2:7aab896b1a3b | 136 | CMD18_READ_MULTIPLE_BLOCK = 18, /**< Card transfers data blocks to host until interrupted |
kevman | 2:7aab896b1a3b | 137 | by a STOP_TRANSMISSION command */ |
kevman | 2:7aab896b1a3b | 138 | CMD24_WRITE_BLOCK = 24, /**< Write single block of data */ |
kevman | 2:7aab896b1a3b | 139 | CMD25_WRITE_MULTIPLE_BLOCK = 25, /**< Continuously writes blocks of data until |
kevman | 2:7aab896b1a3b | 140 | 'Stop Tran' token is sent */ |
kevman | 2:7aab896b1a3b | 141 | CMD27_PROGRAM_CSD = 27, /**< Programming bits of CSD */ |
kevman | 2:7aab896b1a3b | 142 | CMD32_ERASE_WR_BLK_START_ADDR = 32, /**< Sets the address of the first write |
kevman | 2:7aab896b1a3b | 143 | block to be erased. */ |
kevman | 2:7aab896b1a3b | 144 | CMD33_ERASE_WR_BLK_END_ADDR = 33, /**< Sets the address of the last write |
kevman | 2:7aab896b1a3b | 145 | block of the continuous range to be erased.*/ |
kevman | 2:7aab896b1a3b | 146 | CMD38_ERASE = 38, /**< Erases all previously selected write blocks */ |
kevman | 2:7aab896b1a3b | 147 | CMD55_APP_CMD = 55, /**< Extend to Applications specific commands */ |
kevman | 2:7aab896b1a3b | 148 | CMD56_GEN_CMD = 56, /**< General Purpose Command */ |
kevman | 2:7aab896b1a3b | 149 | CMD58_READ_OCR = 58, /**< Read OCR register of card */ |
kevman | 2:7aab896b1a3b | 150 | CMD59_CRC_ON_OFF = 59, /**< Turns the CRC option on or off*/ |
kevman | 2:7aab896b1a3b | 151 | // App Commands |
kevman | 2:7aab896b1a3b | 152 | ACMD6_SET_BUS_WIDTH = 6, |
kevman | 2:7aab896b1a3b | 153 | ACMD13_SD_STATUS = 13, |
kevman | 2:7aab896b1a3b | 154 | ACMD22_SEND_NUM_WR_BLOCKS = 22, |
kevman | 2:7aab896b1a3b | 155 | ACMD23_SET_WR_BLK_ERASE_COUNT = 23, |
kevman | 2:7aab896b1a3b | 156 | ACMD41_SD_SEND_OP_COND = 41, |
kevman | 2:7aab896b1a3b | 157 | ACMD42_SET_CLR_CARD_DETECT = 42, |
kevman | 2:7aab896b1a3b | 158 | ACMD51_SEND_SCR = 51, |
kevman | 2:7aab896b1a3b | 159 | }; |
kevman | 2:7aab896b1a3b | 160 | |
kevman | 2:7aab896b1a3b | 161 | uint8_t _card_type; |
kevman | 2:7aab896b1a3b | 162 | int _cmd(SDBlockDevice::cmdSupported cmd, uint32_t arg, bool isAcmd = 0, uint32_t *resp = NULL); |
kevman | 2:7aab896b1a3b | 163 | int _cmd8(); |
kevman | 2:7aab896b1a3b | 164 | |
kevman | 2:7aab896b1a3b | 165 | /* Move the SDCard into the SPI Mode idle state |
kevman | 2:7aab896b1a3b | 166 | * |
kevman | 2:7aab896b1a3b | 167 | * The card is transitioned from SDCard mode to SPI mode by sending the |
kevman | 2:7aab896b1a3b | 168 | * CMD0 (GO_IDLE_STATE) command with CS asserted. See the notes in the |
kevman | 2:7aab896b1a3b | 169 | * "SPI Startup" section of the comments at the head of the |
kevman | 2:7aab896b1a3b | 170 | * implementation file for further details and specification references. |
kevman | 2:7aab896b1a3b | 171 | * |
kevman | 2:7aab896b1a3b | 172 | * @return Response form the card. R1_IDLE_STATE (0x1), the successful |
kevman | 2:7aab896b1a3b | 173 | * response from CMD0. R1_XXX_XXX for more response |
kevman | 2:7aab896b1a3b | 174 | */ |
kevman | 2:7aab896b1a3b | 175 | uint32_t _go_idle_state(); |
kevman | 2:7aab896b1a3b | 176 | int _initialise_card(); |
kevman | 2:7aab896b1a3b | 177 | |
kevman | 2:7aab896b1a3b | 178 | bd_size_t _sectors; |
kevman | 2:7aab896b1a3b | 179 | bd_size_t _sd_sectors(); |
kevman | 2:7aab896b1a3b | 180 | |
kevman | 2:7aab896b1a3b | 181 | bool _is_valid_trim(bd_addr_t addr, bd_size_t size); |
kevman | 2:7aab896b1a3b | 182 | |
kevman | 2:7aab896b1a3b | 183 | /* SPI functions */ |
kevman | 2:7aab896b1a3b | 184 | mbed::Timer _spi_timer; /**< Timer Class object used for busy wait */ |
kevman | 2:7aab896b1a3b | 185 | uint32_t _init_sck; /**< Intial SPI frequency */ |
kevman | 2:7aab896b1a3b | 186 | uint32_t _transfer_sck; /**< SPI frequency during data transfer/after initialization */ |
kevman | 2:7aab896b1a3b | 187 | mbed::SPI _spi; /**< SPI Class object */ |
kevman | 2:7aab896b1a3b | 188 | |
kevman | 2:7aab896b1a3b | 189 | /* SPI initialization function */ |
kevman | 2:7aab896b1a3b | 190 | void _spi_init(); |
kevman | 2:7aab896b1a3b | 191 | uint8_t _cmd_spi(SDBlockDevice::cmdSupported cmd, uint32_t arg); |
kevman | 2:7aab896b1a3b | 192 | void _spi_wait(uint8_t count); |
kevman | 2:7aab896b1a3b | 193 | |
kevman | 2:7aab896b1a3b | 194 | bool _wait_token(uint8_t token); /**< Wait for token */ |
kevman | 2:7aab896b1a3b | 195 | bool _wait_ready(uint16_t ms = 300); /**< 300ms default wait for card to be ready */ |
kevman | 2:7aab896b1a3b | 196 | int _read(uint8_t *buffer, uint32_t length); |
kevman | 2:7aab896b1a3b | 197 | int _read_bytes(uint8_t *buffer, uint32_t length); |
kevman | 2:7aab896b1a3b | 198 | uint8_t _write(const uint8_t *buffer, uint8_t token, uint32_t length); |
kevman | 2:7aab896b1a3b | 199 | int _freq(void); |
kevman | 2:7aab896b1a3b | 200 | |
kevman | 2:7aab896b1a3b | 201 | /* Chip Select and SPI mode select */ |
kevman | 2:7aab896b1a3b | 202 | mbed::DigitalOut _cs; |
kevman | 2:7aab896b1a3b | 203 | void _select(); |
kevman | 2:7aab896b1a3b | 204 | void _deselect(); |
kevman | 2:7aab896b1a3b | 205 | |
kevman | 2:7aab896b1a3b | 206 | virtual void lock() |
kevman | 2:7aab896b1a3b | 207 | { |
kevman | 2:7aab896b1a3b | 208 | _mutex.lock(); |
kevman | 2:7aab896b1a3b | 209 | } |
kevman | 2:7aab896b1a3b | 210 | |
kevman | 2:7aab896b1a3b | 211 | virtual void unlock() |
kevman | 2:7aab896b1a3b | 212 | { |
kevman | 2:7aab896b1a3b | 213 | _mutex.unlock(); |
kevman | 2:7aab896b1a3b | 214 | } |
kevman | 2:7aab896b1a3b | 215 | |
kevman | 2:7aab896b1a3b | 216 | PlatformMutex _mutex; |
kevman | 2:7aab896b1a3b | 217 | bd_size_t _block_size; |
kevman | 2:7aab896b1a3b | 218 | bd_size_t _erase_size; |
kevman | 2:7aab896b1a3b | 219 | bool _is_initialized; |
kevman | 2:7aab896b1a3b | 220 | bool _dbg; |
kevman | 2:7aab896b1a3b | 221 | bool _crc_on; |
kevman | 2:7aab896b1a3b | 222 | uint32_t _init_ref_count; |
kevman | 2:7aab896b1a3b | 223 | |
kevman | 2:7aab896b1a3b | 224 | mbed::MbedCRC<POLY_7BIT_SD, 7> _crc7; |
kevman | 2:7aab896b1a3b | 225 | mbed::MbedCRC<POLY_16BIT_CCITT, 16> _crc16; |
kevman | 2:7aab896b1a3b | 226 | }; |
kevman | 2:7aab896b1a3b | 227 | |
kevman | 2:7aab896b1a3b | 228 | #endif /* DEVICE_SPI */ |
kevman | 2:7aab896b1a3b | 229 | |
kevman | 2:7aab896b1a3b | 230 | #endif /* MBED_SD_BLOCK_DEVICE_H */ |