Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-os-example-filesystem-sdio
storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp@0:d90c6c9a7600, 2020-11-11 (annotated)
- Committer:
- elelthvd
- Date:
- Wed Nov 11 03:05:14 2020 +0000
- Revision:
- 0:d90c6c9a7600
initial commit
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| elelthvd | 0:d90c6c9a7600 | 1 | /* mbed Microcontroller Library |
| elelthvd | 0:d90c6c9a7600 | 2 | * Copyright (c) 2019 ARM Limited |
| elelthvd | 0:d90c6c9a7600 | 3 | * SPDX-License-Identifier: Apache-2.0 |
| elelthvd | 0:d90c6c9a7600 | 4 | * |
| elelthvd | 0:d90c6c9a7600 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| elelthvd | 0:d90c6c9a7600 | 6 | * you may not use this file except in compliance with the License. |
| elelthvd | 0:d90c6c9a7600 | 7 | * You may obtain a copy of the License at |
| elelthvd | 0:d90c6c9a7600 | 8 | * |
| elelthvd | 0:d90c6c9a7600 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| elelthvd | 0:d90c6c9a7600 | 10 | * |
| elelthvd | 0:d90c6c9a7600 | 11 | * Unless required by applicable law or agreed to in writing, software |
| elelthvd | 0:d90c6c9a7600 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| elelthvd | 0:d90c6c9a7600 | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| elelthvd | 0:d90c6c9a7600 | 14 | * See the License for the specific language governing permissions and |
| elelthvd | 0:d90c6c9a7600 | 15 | * limitations under the License. |
| elelthvd | 0:d90c6c9a7600 | 16 | */ |
| elelthvd | 0:d90c6c9a7600 | 17 | |
| elelthvd | 0:d90c6c9a7600 | 18 | |
| elelthvd | 0:d90c6c9a7600 | 19 | #include "sdio_api.h" |
| elelthvd | 0:d90c6c9a7600 | 20 | #if DEVICE_SDIO_ASYNC |
| elelthvd | 0:d90c6c9a7600 | 21 | #include "us_ticker_api.h" |
| elelthvd | 0:d90c6c9a7600 | 22 | #endif |
| elelthvd | 0:d90c6c9a7600 | 23 | #include "SDIOBlockDevice.h" |
| elelthvd | 0:d90c6c9a7600 | 24 | #include "platform/mbed_debug.h" |
| elelthvd | 0:d90c6c9a7600 | 25 | |
| elelthvd | 0:d90c6c9a7600 | 26 | using namespace mbed; |
| elelthvd | 0:d90c6c9a7600 | 27 | |
| elelthvd | 0:d90c6c9a7600 | 28 | #if DEVICE_SDIO |
| elelthvd | 0:d90c6c9a7600 | 29 | |
| elelthvd | 0:d90c6c9a7600 | 30 | /* |
| elelthvd | 0:d90c6c9a7600 | 31 | * defines |
| elelthvd | 0:d90c6c9a7600 | 32 | */ |
| elelthvd | 0:d90c6c9a7600 | 33 | |
| elelthvd | 0:d90c6c9a7600 | 34 | #define SDIO_DBG 1 /*!< 1 - Enable debugging */ |
| elelthvd | 0:d90c6c9a7600 | 35 | #define SDIO_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */ |
| elelthvd | 0:d90c6c9a7600 | 36 | |
| elelthvd | 0:d90c6c9a7600 | 37 | #define SDIO_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ |
| elelthvd | 0:d90c6c9a7600 | 38 | #define SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ |
| elelthvd | 0:d90c6c9a7600 | 39 | #define SDIO_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ |
| elelthvd | 0:d90c6c9a7600 | 40 | #define SDIO_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ |
| elelthvd | 0:d90c6c9a7600 | 41 | #define SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ |
| elelthvd | 0:d90c6c9a7600 | 42 | #define SDIO_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ |
| elelthvd | 0:d90c6c9a7600 | 43 | #define SDIO_BLOCK_DEVICE_ERROR_UNUSABLE -5007 /*!< unusable card */ |
| elelthvd | 0:d90c6c9a7600 | 44 | #define SDIO_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008 /*!< No response from device */ |
| elelthvd | 0:d90c6c9a7600 | 45 | #define SDIO_BLOCK_DEVICE_ERROR_CRC -5009 /*!< CRC error */ |
| elelthvd | 0:d90c6c9a7600 | 46 | #define SDIO_BLOCK_DEVICE_ERROR_ERASE -5010 /*!< Erase error: reset/sequence */ |
| elelthvd | 0:d90c6c9a7600 | 47 | #define SDIO_BLOCK_DEVICE_ERROR_WRITE -5011 /*!< SPI Write error: !SPI_DATA_ACCEPTED */ |
| elelthvd | 0:d90c6c9a7600 | 48 | #define SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE -5012 /*!< unsupported blocksize, only 512 byte supported */ |
| elelthvd | 0:d90c6c9a7600 | 49 | #define SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS -5013 /*!< read data blocks from SD failed */ |
| elelthvd | 0:d90c6c9a7600 | 50 | #define SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS -5014 /*!< write data blocks to SD failed */ |
| elelthvd | 0:d90c6c9a7600 | 51 | #define SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS -5015 /*!< erase data blocks to SD failed */ |
| elelthvd | 0:d90c6c9a7600 | 52 | |
| elelthvd | 0:d90c6c9a7600 | 53 | #define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes */ |
| elelthvd | 0:d90c6c9a7600 | 54 | |
| elelthvd | 0:d90c6c9a7600 | 55 | // Types |
| elelthvd | 0:d90c6c9a7600 | 56 | #define SDCARD_NONE 0 /**< No card is present */ |
| elelthvd | 0:d90c6c9a7600 | 57 | #define SDCARD_V1 1 /**< v1.x Standard Capacity */ |
| elelthvd | 0:d90c6c9a7600 | 58 | #define SDCARD_V2 2 /**< v2.x Standard capacity SD card */ |
| elelthvd | 0:d90c6c9a7600 | 59 | #define SDCARD_V2HC 3 /**< v2.x High capacity SD card */ |
| elelthvd | 0:d90c6c9a7600 | 60 | #define CARD_UNKNOWN 4 /**< Unknown or unsupported card */ |
| elelthvd | 0:d90c6c9a7600 | 61 | |
| elelthvd | 0:d90c6c9a7600 | 62 | SDIOBlockDevice::SDIOBlockDevice(PinName card_detect) : _card_detect(card_detect), |
| elelthvd | 0:d90c6c9a7600 | 63 | _is_initialized(0), |
| elelthvd | 0:d90c6c9a7600 | 64 | _sectors(0), |
| elelthvd | 0:d90c6c9a7600 | 65 | _init_ref_count(0) |
| elelthvd | 0:d90c6c9a7600 | 66 | { |
| elelthvd | 0:d90c6c9a7600 | 67 | // Only HC block size is supported. |
| elelthvd | 0:d90c6c9a7600 | 68 | _block_size = BLOCK_SIZE_HC; |
| elelthvd | 0:d90c6c9a7600 | 69 | _erase_size = BLOCK_SIZE_HC; |
| elelthvd | 0:d90c6c9a7600 | 70 | } |
| elelthvd | 0:d90c6c9a7600 | 71 | |
| elelthvd | 0:d90c6c9a7600 | 72 | SDIOBlockDevice::~SDIOBlockDevice() |
| elelthvd | 0:d90c6c9a7600 | 73 | { |
| elelthvd | 0:d90c6c9a7600 | 74 | if (_is_initialized) { |
| elelthvd | 0:d90c6c9a7600 | 75 | deinit(); |
| elelthvd | 0:d90c6c9a7600 | 76 | } |
| elelthvd | 0:d90c6c9a7600 | 77 | } |
| elelthvd | 0:d90c6c9a7600 | 78 | |
| elelthvd | 0:d90c6c9a7600 | 79 | int SDIOBlockDevice::init() |
| elelthvd | 0:d90c6c9a7600 | 80 | { |
| elelthvd | 0:d90c6c9a7600 | 81 | debug_if(SDIO_DBG, "init Card...\r\n"); |
| elelthvd | 0:d90c6c9a7600 | 82 | |
| elelthvd | 0:d90c6c9a7600 | 83 | lock(); |
| elelthvd | 0:d90c6c9a7600 | 84 | |
| elelthvd | 0:d90c6c9a7600 | 85 | if (!_is_initialized) { |
| elelthvd | 0:d90c6c9a7600 | 86 | _init_ref_count = 0; |
| elelthvd | 0:d90c6c9a7600 | 87 | } |
| elelthvd | 0:d90c6c9a7600 | 88 | |
| elelthvd | 0:d90c6c9a7600 | 89 | _init_ref_count++; |
| elelthvd | 0:d90c6c9a7600 | 90 | |
| elelthvd | 0:d90c6c9a7600 | 91 | if (_init_ref_count != 1) { |
| elelthvd | 0:d90c6c9a7600 | 92 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 93 | return BD_ERROR_OK; |
| elelthvd | 0:d90c6c9a7600 | 94 | } |
| elelthvd | 0:d90c6c9a7600 | 95 | |
| elelthvd | 0:d90c6c9a7600 | 96 | if (is_present() == false) { |
| elelthvd | 0:d90c6c9a7600 | 97 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 98 | return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; |
| elelthvd | 0:d90c6c9a7600 | 99 | } |
| elelthvd | 0:d90c6c9a7600 | 100 | |
| elelthvd | 0:d90c6c9a7600 | 101 | int status = sdio_init(); |
| elelthvd | 0:d90c6c9a7600 | 102 | if (BD_ERROR_OK != status) { |
| elelthvd | 0:d90c6c9a7600 | 103 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 104 | return BD_ERROR_DEVICE_ERROR; |
| elelthvd | 0:d90c6c9a7600 | 105 | } |
| elelthvd | 0:d90c6c9a7600 | 106 | |
| elelthvd | 0:d90c6c9a7600 | 107 | sdio_get_card_info(&_card_info); |
| elelthvd | 0:d90c6c9a7600 | 108 | _is_initialized = true; |
| elelthvd | 0:d90c6c9a7600 | 109 | debug_if(SDIO_DBG, "SDIO initialized: type: %lu version: %lu class: %lu\n", |
| elelthvd | 0:d90c6c9a7600 | 110 | _card_info.card_type, _card_info.card_version, _card_info.card_class); |
| elelthvd | 0:d90c6c9a7600 | 111 | debug_if(SDIO_DBG, "SDIO size: %lu MB\n", |
| elelthvd | 0:d90c6c9a7600 | 112 | _card_info.log_block_count / 2 / 1024); |
| elelthvd | 0:d90c6c9a7600 | 113 | |
| elelthvd | 0:d90c6c9a7600 | 114 | // get sectors count from card_info |
| elelthvd | 0:d90c6c9a7600 | 115 | _sectors = _card_info.log_block_count; |
| elelthvd | 0:d90c6c9a7600 | 116 | if (BLOCK_SIZE_HC != _card_info.block_size) { |
| elelthvd | 0:d90c6c9a7600 | 117 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 118 | return SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE; |
| elelthvd | 0:d90c6c9a7600 | 119 | } |
| elelthvd | 0:d90c6c9a7600 | 120 | |
| elelthvd | 0:d90c6c9a7600 | 121 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 122 | return status; |
| elelthvd | 0:d90c6c9a7600 | 123 | } |
| elelthvd | 0:d90c6c9a7600 | 124 | |
| elelthvd | 0:d90c6c9a7600 | 125 | int SDIOBlockDevice::deinit() |
| elelthvd | 0:d90c6c9a7600 | 126 | { |
| elelthvd | 0:d90c6c9a7600 | 127 | debug_if(SDIO_DBG, "deinit SDIO Card...\r\n"); |
| elelthvd | 0:d90c6c9a7600 | 128 | lock(); |
| elelthvd | 0:d90c6c9a7600 | 129 | |
| elelthvd | 0:d90c6c9a7600 | 130 | if (!_is_initialized) { |
| elelthvd | 0:d90c6c9a7600 | 131 | _init_ref_count = 0; |
| elelthvd | 0:d90c6c9a7600 | 132 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 133 | return BD_ERROR_OK; |
| elelthvd | 0:d90c6c9a7600 | 134 | } |
| elelthvd | 0:d90c6c9a7600 | 135 | |
| elelthvd | 0:d90c6c9a7600 | 136 | _init_ref_count--; |
| elelthvd | 0:d90c6c9a7600 | 137 | |
| elelthvd | 0:d90c6c9a7600 | 138 | if (_init_ref_count) { |
| elelthvd | 0:d90c6c9a7600 | 139 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 140 | return BD_ERROR_OK; |
| elelthvd | 0:d90c6c9a7600 | 141 | } |
| elelthvd | 0:d90c6c9a7600 | 142 | |
| elelthvd | 0:d90c6c9a7600 | 143 | int status = sdio_deinit(); |
| elelthvd | 0:d90c6c9a7600 | 144 | _is_initialized = false; |
| elelthvd | 0:d90c6c9a7600 | 145 | |
| elelthvd | 0:d90c6c9a7600 | 146 | _sectors = 0; |
| elelthvd | 0:d90c6c9a7600 | 147 | |
| elelthvd | 0:d90c6c9a7600 | 148 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 149 | return status; |
| elelthvd | 0:d90c6c9a7600 | 150 | } |
| elelthvd | 0:d90c6c9a7600 | 151 | |
| elelthvd | 0:d90c6c9a7600 | 152 | int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) |
| elelthvd | 0:d90c6c9a7600 | 153 | { |
| elelthvd | 0:d90c6c9a7600 | 154 | int status = 0; |
| elelthvd | 0:d90c6c9a7600 | 155 | lock(); |
| elelthvd | 0:d90c6c9a7600 | 156 | if (is_present() == false) { |
| elelthvd | 0:d90c6c9a7600 | 157 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 158 | return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; |
| elelthvd | 0:d90c6c9a7600 | 159 | } |
| elelthvd | 0:d90c6c9a7600 | 160 | |
| elelthvd | 0:d90c6c9a7600 | 161 | if (!_is_initialized) { |
| elelthvd | 0:d90c6c9a7600 | 162 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 163 | return SDIO_BLOCK_DEVICE_ERROR_NO_INIT; |
| elelthvd | 0:d90c6c9a7600 | 164 | } |
| elelthvd | 0:d90c6c9a7600 | 165 | |
| elelthvd | 0:d90c6c9a7600 | 166 | if (!is_valid_read(addr, size)) { |
| elelthvd | 0:d90c6c9a7600 | 167 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 168 | return SDIO_BLOCK_DEVICE_ERROR_PARAMETER; |
| elelthvd | 0:d90c6c9a7600 | 169 | } |
| elelthvd | 0:d90c6c9a7600 | 170 | |
| elelthvd | 0:d90c6c9a7600 | 171 | uint8_t *_buffer = static_cast<uint8_t *>(buffer); |
| elelthvd | 0:d90c6c9a7600 | 172 | |
| elelthvd | 0:d90c6c9a7600 | 173 | // ReadBlocks uses byte unit address |
| elelthvd | 0:d90c6c9a7600 | 174 | // SDHC and SDXC Cards different addressing is handled in ReadBlocks() |
| elelthvd | 0:d90c6c9a7600 | 175 | bd_addr_t block_count = size / _block_size; |
| elelthvd | 0:d90c6c9a7600 | 176 | addr = addr / _block_size; |
| elelthvd | 0:d90c6c9a7600 | 177 | |
| elelthvd | 0:d90c6c9a7600 | 178 | #if DEVICE_SDIO_ASYNC |
| elelthvd | 0:d90c6c9a7600 | 179 | // make sure card is ready |
| elelthvd | 0:d90c6c9a7600 | 180 | { |
| elelthvd | 0:d90c6c9a7600 | 181 | uint32_t tickstart = us_ticker_read(); |
| elelthvd | 0:d90c6c9a7600 | 182 | while (sdio_get_card_state() != SD_TRANSFER_OK) { |
| elelthvd | 0:d90c6c9a7600 | 183 | // wait until SD ready |
| elelthvd | 0:d90c6c9a7600 | 184 | if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { |
| elelthvd | 0:d90c6c9a7600 | 185 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 186 | return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 187 | } |
| elelthvd | 0:d90c6c9a7600 | 188 | } |
| elelthvd | 0:d90c6c9a7600 | 189 | } |
| elelthvd | 0:d90c6c9a7600 | 190 | |
| elelthvd | 0:d90c6c9a7600 | 191 | // receive the data : one block/ multiple blocks is handled in ReadBlocks() |
| elelthvd | 0:d90c6c9a7600 | 192 | status = sdio_read_blocks_async(_buffer, addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 193 | debug_if(SDIO_DBG, "SDIO read blocks dbgtest addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 194 | |
| elelthvd | 0:d90c6c9a7600 | 195 | if (status == MSD_OK) { |
| elelthvd | 0:d90c6c9a7600 | 196 | // wait until DMA finished |
| elelthvd | 0:d90c6c9a7600 | 197 | uint32_t tickstart = us_ticker_read(); |
| elelthvd | 0:d90c6c9a7600 | 198 | while (sdio_read_pending() != SD_TRANSFER_OK) { |
| elelthvd | 0:d90c6c9a7600 | 199 | if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { |
| elelthvd | 0:d90c6c9a7600 | 200 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 201 | return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 202 | } |
| elelthvd | 0:d90c6c9a7600 | 203 | } |
| elelthvd | 0:d90c6c9a7600 | 204 | // make sure card is ready |
| elelthvd | 0:d90c6c9a7600 | 205 | tickstart = us_ticker_read(); |
| elelthvd | 0:d90c6c9a7600 | 206 | while (sdio_get_card_state() != SD_TRANSFER_OK) { |
| elelthvd | 0:d90c6c9a7600 | 207 | // wait until SD ready |
| elelthvd | 0:d90c6c9a7600 | 208 | if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { |
| elelthvd | 0:d90c6c9a7600 | 209 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 210 | return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 211 | } |
| elelthvd | 0:d90c6c9a7600 | 212 | } |
| elelthvd | 0:d90c6c9a7600 | 213 | } else { |
| elelthvd | 0:d90c6c9a7600 | 214 | debug_if(SDIO_DBG, "SDIO read_blocks failed! addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 215 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 216 | return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 217 | } |
| elelthvd | 0:d90c6c9a7600 | 218 | #else |
| elelthvd | 0:d90c6c9a7600 | 219 | status = sdio_read_blocks(_buffer, addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 220 | debug_if(SDIO_DBG, "SDIO read blocks dbgtest addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 221 | |
| elelthvd | 0:d90c6c9a7600 | 222 | if (status != MSD_OK) { |
| elelthvd | 0:d90c6c9a7600 | 223 | debug_if(SDIO_DBG, "SDIO read blocks failed! addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 224 | status = SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 225 | } |
| elelthvd | 0:d90c6c9a7600 | 226 | #endif |
| elelthvd | 0:d90c6c9a7600 | 227 | |
| elelthvd | 0:d90c6c9a7600 | 228 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 229 | return status; |
| elelthvd | 0:d90c6c9a7600 | 230 | } |
| elelthvd | 0:d90c6c9a7600 | 231 | |
| elelthvd | 0:d90c6c9a7600 | 232 | int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) |
| elelthvd | 0:d90c6c9a7600 | 233 | { |
| elelthvd | 0:d90c6c9a7600 | 234 | int status = 0; |
| elelthvd | 0:d90c6c9a7600 | 235 | lock(); |
| elelthvd | 0:d90c6c9a7600 | 236 | |
| elelthvd | 0:d90c6c9a7600 | 237 | if (is_present() == false) { |
| elelthvd | 0:d90c6c9a7600 | 238 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 239 | return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; |
| elelthvd | 0:d90c6c9a7600 | 240 | } |
| elelthvd | 0:d90c6c9a7600 | 241 | |
| elelthvd | 0:d90c6c9a7600 | 242 | if (!_is_initialized) { |
| elelthvd | 0:d90c6c9a7600 | 243 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 244 | return SDIO_BLOCK_DEVICE_ERROR_NO_INIT; |
| elelthvd | 0:d90c6c9a7600 | 245 | } |
| elelthvd | 0:d90c6c9a7600 | 246 | |
| elelthvd | 0:d90c6c9a7600 | 247 | if (!is_valid_program(addr, size)) { |
| elelthvd | 0:d90c6c9a7600 | 248 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 249 | return SDIO_BLOCK_DEVICE_ERROR_PARAMETER; |
| elelthvd | 0:d90c6c9a7600 | 250 | } |
| elelthvd | 0:d90c6c9a7600 | 251 | |
| elelthvd | 0:d90c6c9a7600 | 252 | uint8_t *_buffer = (uint8_t *)(buffer); |
| elelthvd | 0:d90c6c9a7600 | 253 | |
| elelthvd | 0:d90c6c9a7600 | 254 | // Get block count |
| elelthvd | 0:d90c6c9a7600 | 255 | bd_size_t block_count = size / _block_size; |
| elelthvd | 0:d90c6c9a7600 | 256 | addr = addr / _block_size; |
| elelthvd | 0:d90c6c9a7600 | 257 | |
| elelthvd | 0:d90c6c9a7600 | 258 | #if DEVICE_SDIO_ASYNC |
| elelthvd | 0:d90c6c9a7600 | 259 | // make sure card is ready |
| elelthvd | 0:d90c6c9a7600 | 260 | { |
| elelthvd | 0:d90c6c9a7600 | 261 | uint32_t tickstart = us_ticker_read(); |
| elelthvd | 0:d90c6c9a7600 | 262 | while (sdio_get_card_state() != SD_TRANSFER_OK) { |
| elelthvd | 0:d90c6c9a7600 | 263 | // wait until SD ready |
| elelthvd | 0:d90c6c9a7600 | 264 | if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { |
| elelthvd | 0:d90c6c9a7600 | 265 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 266 | return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 267 | } |
| elelthvd | 0:d90c6c9a7600 | 268 | } |
| elelthvd | 0:d90c6c9a7600 | 269 | } |
| elelthvd | 0:d90c6c9a7600 | 270 | |
| elelthvd | 0:d90c6c9a7600 | 271 | status = sdio_write_blocks_async(_buffer, addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 272 | debug_if(SDIO_DBG, "SDIO write blocks async dbgtest addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 273 | |
| elelthvd | 0:d90c6c9a7600 | 274 | if (status == MSD_OK) { |
| elelthvd | 0:d90c6c9a7600 | 275 | // wait until DMA finished |
| elelthvd | 0:d90c6c9a7600 | 276 | uint32_t tickstart = us_ticker_read(); |
| elelthvd | 0:d90c6c9a7600 | 277 | while (sdio_write_pending() != SD_TRANSFER_OK) { |
| elelthvd | 0:d90c6c9a7600 | 278 | if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { |
| elelthvd | 0:d90c6c9a7600 | 279 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 280 | return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 281 | } |
| elelthvd | 0:d90c6c9a7600 | 282 | } |
| elelthvd | 0:d90c6c9a7600 | 283 | // make sure card is ready |
| elelthvd | 0:d90c6c9a7600 | 284 | tickstart = us_ticker_read(); |
| elelthvd | 0:d90c6c9a7600 | 285 | while (sdio_get_card_state() != SD_TRANSFER_OK) { |
| elelthvd | 0:d90c6c9a7600 | 286 | // wait until SD ready |
| elelthvd | 0:d90c6c9a7600 | 287 | if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { |
| elelthvd | 0:d90c6c9a7600 | 288 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 289 | return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 290 | } |
| elelthvd | 0:d90c6c9a7600 | 291 | } |
| elelthvd | 0:d90c6c9a7600 | 292 | } else { |
| elelthvd | 0:d90c6c9a7600 | 293 | debug_if(SDIO_DBG, "SDIO write blocks async failed! addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 294 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 295 | return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 296 | } |
| elelthvd | 0:d90c6c9a7600 | 297 | #else |
| elelthvd | 0:d90c6c9a7600 | 298 | status = sdio_write_blocks(_buffer, addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 299 | |
| elelthvd | 0:d90c6c9a7600 | 300 | debug_if(SDIO_DBG, "SDIO write blocks dbgtest addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 301 | |
| elelthvd | 0:d90c6c9a7600 | 302 | if (status != MSD_OK) { |
| elelthvd | 0:d90c6c9a7600 | 303 | debug_if(SDIO_DBG, "SDIO write blocks failed! addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 304 | status = SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 305 | } |
| elelthvd | 0:d90c6c9a7600 | 306 | #endif |
| elelthvd | 0:d90c6c9a7600 | 307 | |
| elelthvd | 0:d90c6c9a7600 | 308 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 309 | return status; |
| elelthvd | 0:d90c6c9a7600 | 310 | } |
| elelthvd | 0:d90c6c9a7600 | 311 | |
| elelthvd | 0:d90c6c9a7600 | 312 | int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) |
| elelthvd | 0:d90c6c9a7600 | 313 | { |
| elelthvd | 0:d90c6c9a7600 | 314 | debug_if(SDIO_DBG, "SDIO trim Card...\r\n"); |
| elelthvd | 0:d90c6c9a7600 | 315 | lock(); |
| elelthvd | 0:d90c6c9a7600 | 316 | if (is_present() == false) { |
| elelthvd | 0:d90c6c9a7600 | 317 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 318 | return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; |
| elelthvd | 0:d90c6c9a7600 | 319 | } |
| elelthvd | 0:d90c6c9a7600 | 320 | |
| elelthvd | 0:d90c6c9a7600 | 321 | if (!_is_initialized) { |
| elelthvd | 0:d90c6c9a7600 | 322 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 323 | return SDIO_BLOCK_DEVICE_ERROR_NO_INIT; |
| elelthvd | 0:d90c6c9a7600 | 324 | } |
| elelthvd | 0:d90c6c9a7600 | 325 | |
| elelthvd | 0:d90c6c9a7600 | 326 | if (!_is_valid_trim(addr, size)) { |
| elelthvd | 0:d90c6c9a7600 | 327 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 328 | return SDIO_BLOCK_DEVICE_ERROR_PARAMETER; |
| elelthvd | 0:d90c6c9a7600 | 329 | } |
| elelthvd | 0:d90c6c9a7600 | 330 | |
| elelthvd | 0:d90c6c9a7600 | 331 | bd_size_t block_count = size / _block_size; |
| elelthvd | 0:d90c6c9a7600 | 332 | addr = addr / _block_size; |
| elelthvd | 0:d90c6c9a7600 | 333 | |
| elelthvd | 0:d90c6c9a7600 | 334 | int status = sdio_erase(addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 335 | if (status != 0) { |
| elelthvd | 0:d90c6c9a7600 | 336 | debug_if(SDIO_DBG, "SDIO erase blocks failed! addr: %lld block_count: %lld \n", addr, block_count); |
| elelthvd | 0:d90c6c9a7600 | 337 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 338 | return SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 339 | #if DEVICE_SDIO_ASYNC |
| elelthvd | 0:d90c6c9a7600 | 340 | } else { |
| elelthvd | 0:d90c6c9a7600 | 341 | uint32_t tickstart = us_ticker_read(); |
| elelthvd | 0:d90c6c9a7600 | 342 | while (sdio_get_card_state() != SD_TRANSFER_OK) { |
| elelthvd | 0:d90c6c9a7600 | 343 | // wait until SD ready |
| elelthvd | 0:d90c6c9a7600 | 344 | if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { |
| elelthvd | 0:d90c6c9a7600 | 345 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 346 | return SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS; |
| elelthvd | 0:d90c6c9a7600 | 347 | } |
| elelthvd | 0:d90c6c9a7600 | 348 | } |
| elelthvd | 0:d90c6c9a7600 | 349 | #endif |
| elelthvd | 0:d90c6c9a7600 | 350 | } |
| elelthvd | 0:d90c6c9a7600 | 351 | |
| elelthvd | 0:d90c6c9a7600 | 352 | unlock(); |
| elelthvd | 0:d90c6c9a7600 | 353 | return status; |
| elelthvd | 0:d90c6c9a7600 | 354 | } |
| elelthvd | 0:d90c6c9a7600 | 355 | |
| elelthvd | 0:d90c6c9a7600 | 356 | bd_size_t SDIOBlockDevice::get_read_size() const |
| elelthvd | 0:d90c6c9a7600 | 357 | { |
| elelthvd | 0:d90c6c9a7600 | 358 | return _block_size; |
| elelthvd | 0:d90c6c9a7600 | 359 | } |
| elelthvd | 0:d90c6c9a7600 | 360 | |
| elelthvd | 0:d90c6c9a7600 | 361 | bd_size_t SDIOBlockDevice::get_program_size() const |
| elelthvd | 0:d90c6c9a7600 | 362 | { |
| elelthvd | 0:d90c6c9a7600 | 363 | return _block_size; |
| elelthvd | 0:d90c6c9a7600 | 364 | } |
| elelthvd | 0:d90c6c9a7600 | 365 | |
| elelthvd | 0:d90c6c9a7600 | 366 | bd_size_t SDIOBlockDevice::size() const |
| elelthvd | 0:d90c6c9a7600 | 367 | { |
| elelthvd | 0:d90c6c9a7600 | 368 | return _block_size * _sectors; |
| elelthvd | 0:d90c6c9a7600 | 369 | } |
| elelthvd | 0:d90c6c9a7600 | 370 | |
| elelthvd | 0:d90c6c9a7600 | 371 | void SDIOBlockDevice::debug(bool dbg) |
| elelthvd | 0:d90c6c9a7600 | 372 | { |
| elelthvd | 0:d90c6c9a7600 | 373 | } |
| elelthvd | 0:d90c6c9a7600 | 374 | |
| elelthvd | 0:d90c6c9a7600 | 375 | bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) const |
| elelthvd | 0:d90c6c9a7600 | 376 | { |
| elelthvd | 0:d90c6c9a7600 | 377 | return ( |
| elelthvd | 0:d90c6c9a7600 | 378 | addr % _erase_size == 0 && |
| elelthvd | 0:d90c6c9a7600 | 379 | size % _erase_size == 0 && |
| elelthvd | 0:d90c6c9a7600 | 380 | addr + size <= this->size()); |
| elelthvd | 0:d90c6c9a7600 | 381 | } |
| elelthvd | 0:d90c6c9a7600 | 382 | |
| elelthvd | 0:d90c6c9a7600 | 383 | bool SDIOBlockDevice::is_present(void) |
| elelthvd | 0:d90c6c9a7600 | 384 | { |
| elelthvd | 0:d90c6c9a7600 | 385 | if (_card_detect.is_connected()) { |
| elelthvd | 0:d90c6c9a7600 | 386 | return (_card_detect.read() == 0); |
| elelthvd | 0:d90c6c9a7600 | 387 | } else { |
| elelthvd | 0:d90c6c9a7600 | 388 | return true; |
| elelthvd | 0:d90c6c9a7600 | 389 | } |
| elelthvd | 0:d90c6c9a7600 | 390 | } |
| elelthvd | 0:d90c6c9a7600 | 391 | |
| elelthvd | 0:d90c6c9a7600 | 392 | const char *SDIOBlockDevice::get_type() const |
| elelthvd | 0:d90c6c9a7600 | 393 | { |
| elelthvd | 0:d90c6c9a7600 | 394 | return "SDIO"; |
| elelthvd | 0:d90c6c9a7600 | 395 | } |
| elelthvd | 0:d90c6c9a7600 | 396 | |
| elelthvd | 0:d90c6c9a7600 | 397 | #endif //DEVICE_SDIO |