Mbed OS Reference
Loading...
Searching...
No Matches
SDBlockDevice.h
1/* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef MBED_SD_BLOCK_DEVICE_H
19#define MBED_SD_BLOCK_DEVICE_H
20
21/* If the target has no SPI support, then SD Card is not supported. */
22#if DEVICE_SPI
23
24#include "blockdevice/BlockDevice.h"
25#include "drivers/SPI.h"
26#include "drivers/Timer.h"
27#include "drivers/MbedCRC.h"
28#include "drivers/DigitalOut.h"
29#include "platform/platform.h"
30#include "rtos/Mutex.h"
31#include "hal/static_pinmap.h"
32
33#ifndef MBED_CONF_SD_SPI_MOSI
34#define MBED_CONF_SD_SPI_MOSI NC
35#endif
36#ifndef MBED_CONF_SD_SPI_MISO
37#define MBED_CONF_SD_SPI_MISO NC
38#endif
39#ifndef MBED_CONF_SD_SPI_CLK
40#define MBED_CONF_SD_SPI_CLK NC
41#endif
42#ifndef MBED_CONF_SD_SPI_CS
43#define MBED_CONF_SD_SPI_CS NC
44#endif
45#ifndef MBED_CONF_SD_INIT_FREQUENCY
46#define MBED_CONF_SD_INIT_FREQUENCY 100000
47#endif
48#ifndef MBED_CONF_SD_TRX_FREQUENCY
49#define MBED_CONF_SD_TRX_FREQUENCY 1000000
50#endif
51#ifndef MBED_CONF_SD_CRC_ENABLED
52#define MBED_CONF_SD_CRC_ENABLED 0
53#endif
54
55/** SDBlockDevice class
56 *
57 * Access an SD Card using SPI bus
58 */
60
61 // Only HC block size is supported. Making this a static constant reduces code size.
62 static constexpr uint32_t _block_size = 512; /*!< Block size supported for SDHC card is 512 bytes */
63
64public:
65 /** Creates an SDBlockDevice on a SPI bus specified by pins (using dynamic pin-map)
66 *
67 * @param mosi SPI master out, slave in pin
68 * @param miso SPI master in, slave out pin
69 * @param sclk SPI clock pin
70 * @param cs SPI chip select pin. Currently, GPIO chip selects are always used.
71 * @param hz Clock speed of the SPI bus (defaults to 1MHz)
72 * @param crc_on Enable cyclic redundancy check (defaults to disabled)
73 */
74 SDBlockDevice(PinName mosi = MBED_CONF_SD_SPI_MOSI,
75 PinName miso = MBED_CONF_SD_SPI_MISO,
76 PinName sclk = MBED_CONF_SD_SPI_CLK,
77 PinName cs = MBED_CONF_SD_SPI_CS,
78 uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
79 bool crc_on = MBED_CONF_SD_CRC_ENABLED);
80
81 /** Creates an SDBlockDevice on a SPI bus specified by pins (using static pin-map)
82 *
83 * @param spi_pinmap Static SPI pin-map
84 * @param cs Chip select pin (can be any GPIO)
85 * @param hz Clock speed of the SPI bus (defaults to 1MHz)
86 * @param crc_on Enable cyclic redundancy check (defaults to disabled)
87 */
88 SDBlockDevice(const spi_pinmap_t &spi_pinmap,
89 PinName cs = MBED_CONF_SD_SPI_CS,
90 uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
91 bool crc_on = MBED_CONF_SD_CRC_ENABLED);
92
93 virtual ~SDBlockDevice();
94
95 /** Initialize a block device
96 *
97 * @return BD_ERROR_OK(0) - success
98 * BD_ERROR_DEVICE_ERROR - device driver transaction failed
99 * SD_BLOCK_DEVICE_ERROR_NO_DEVICE - device (SD card) is missing or not connected
100 * SD_BLOCK_DEVICE_ERROR_UNUSABLE - unusable card
101 * SD_BLOCK_DEVICE_ERROR_CRC - crc error
102 */
103 virtual int init();
104
105#if DEVICE_SPI_ASYNCH
106 /**
107 * @brief Configure the usage of asynchronous %SPI by this class.
108 *
109 * By default, async %SPI is not enabled, so this class will simply busy-wait while
110 * communicating with the card. When async %SPI is enabled, %SPI operations
111 * will be done in blocking asynchronous mode, so other threads may execute
112 * in the background while data is going to and from the card.
113 *
114 * @param enabled Whether usage of async %SPI is enabled.
115 * @param dma_usage_hint DMA usage hint to pass to the underlying #mbed::SPI instance.
116 */
117 void set_async_spi_mode(bool enabled, DMAUsage dma_usage_hint = DMAUsage::DMA_USAGE_NEVER);
118#endif
119
120 /** Deinitialize a block device
121 *
122 * @return BD_ERROR_OK(0) - success
123 */
124 virtual int deinit();
125
126 /** Read blocks from a block device
127 *
128 * @param buffer Buffer to write blocks to
129 * @param addr Address of block to begin reading from
130 * @param size Size to read in bytes, must be a multiple of read block size
131 * @return BD_ERROR_OK(0) - success
132 * SD_BLOCK_DEVICE_ERROR_NO_DEVICE - device (SD card) is missing or not connected
133 * SD_BLOCK_DEVICE_ERROR_CRC - crc error
134 * SD_BLOCK_DEVICE_ERROR_PARAMETER - invalid parameter
135 * SD_BLOCK_DEVICE_ERROR_NO_RESPONSE - no response from device
136 * SD_BLOCK_DEVICE_ERROR_UNSUPPORTED - unsupported command
137 */
138 virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
139
140 /** Program blocks to a block device
141 *
142 * @note The blocks must be erased prior to programming
143 *
144 * @param buffer Buffer of data to write to blocks
145 * @param addr Address of block to begin writing to
146 * @param size Size to write in bytes. Must be a multiple of program block size
147 * @return BD_ERROR_OK(0) - success
148 * SD_BLOCK_DEVICE_ERROR_NO_DEVICE - device (SD card) is missing or not connected
149 * SD_BLOCK_DEVICE_ERROR_CRC - crc error
150 * SD_BLOCK_DEVICE_ERROR_PARAMETER - invalid parameter
151 * SD_BLOCK_DEVICE_ERROR_UNSUPPORTED - unsupported command
152 * SD_BLOCK_DEVICE_ERROR_NO_INIT - device is not initialized
153 * SD_BLOCK_DEVICE_ERROR_WRITE - SPI write error
154 * SD_BLOCK_DEVICE_ERROR_ERASE - erase error
155 */
156 virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
157
158 /** Mark blocks as no longer in use
159 *
160 * This function provides a hint to the underlying block device that a region of blocks
161 * is no longer in use and may be erased without side effects. Erase must still be called
162 * before programming, but trimming allows flash-translation-layers to schedule erases when
163 * the device is not busy.
164 *
165 * @param addr Address of block to mark as unused
166 * @param size Size to mark as unused in bytes, must be a multiple of erase block size
167 * @return BD_ERROR_OK(0) - success
168 * SD_BLOCK_DEVICE_ERROR_NO_DEVICE - device (SD card) is missing or not connected
169 * SD_BLOCK_DEVICE_ERROR_CRC - crc error
170 * SD_BLOCK_DEVICE_ERROR_PARAMETER - invalid parameter
171 * SD_BLOCK_DEVICE_ERROR_UNSUPPORTED - unsupported command
172 * SD_BLOCK_DEVICE_ERROR_NO_INIT - device is not initialized
173 * SD_BLOCK_DEVICE_ERROR_ERASE - erase error
174 */
176
177 /** Get the size of a readable block
178 *
179 * @return Size of a readable block in bytes
180 */
182
183 /** Get the size of a programmable block
184 *
185 * @return Size of a programmable block in bytes
186 * @note Must be a multiple of the read size
187 */
189
190 /** Get the total size of the underlying device
191 *
192 * @return Size of the underlying device in bytes
193 */
194 virtual mbed::bd_size_t size() const;
195
196 /** Enable or disable debugging
197 *
198 * @param dbg State of debugging
199 */
200 virtual void debug(bool dbg);
201
202 /** Set the transfer frequency
203 *
204 * @param freq Transfer frequency
205 * @note Max frequency supported is 25MHZ
206 */
207 virtual int frequency(uint64_t freq);
208
209 /** Get the BlockDevice class type.
210 *
211 * @return A string representation of the BlockDevice class type.
212 */
213 virtual const char *get_type() const;
214
215private:
216 /* Commands : Listed below are commands supported
217 * in SPI mode for SD card : Only Mandatory ones
218 */
219 enum cmdSupported {
220 CMD_NOT_SUPPORTED = -1, /**< Command not supported error */
221 CMD0_GO_IDLE_STATE = 0, /**< Resets the SD Memory Card */
222 CMD1_SEND_OP_COND = 1, /**< Sends host capacity support */
223 CMD6_SWITCH_FUNC = 6, /**< Check and Switches card function */
224 CMD8_SEND_IF_COND = 8, /**< Supply voltage info */
225 CMD9_SEND_CSD = 9, /**< Provides Card Specific data */
226 CMD10_SEND_CID = 10, /**< Provides Card Identification */
227 CMD12_STOP_TRANSMISSION = 12, /**< Forces the card to stop transmission */
228 CMD13_SEND_STATUS = 13, /**< Card responds with status */
229 CMD16_SET_BLOCKLEN = 16, /**< Length for SC card is set */
230 CMD17_READ_SINGLE_BLOCK = 17, /**< Read single block of data */
231 CMD18_READ_MULTIPLE_BLOCK = 18, /**< Card transfers data blocks to host until interrupted
232 by a STOP_TRANSMISSION command */
233 CMD24_WRITE_BLOCK = 24, /**< Write single block of data */
234 CMD25_WRITE_MULTIPLE_BLOCK = 25, /**< Continuously writes blocks of data until
235 'Stop Tran' token is sent */
236 CMD27_PROGRAM_CSD = 27, /**< Programming bits of CSD */
237 CMD32_ERASE_WR_BLK_START_ADDR = 32, /**< Sets the address of the first write
238 block to be erased. */
239 CMD33_ERASE_WR_BLK_END_ADDR = 33, /**< Sets the address of the last write
240 block of the continuous range to be erased.*/
241 CMD38_ERASE = 38, /**< Erases all previously selected write blocks */
242 CMD55_APP_CMD = 55, /**< Extend to Applications specific commands */
243 CMD56_GEN_CMD = 56, /**< General Purpose Command */
244 CMD58_READ_OCR = 58, /**< Read OCR register of card */
245 CMD59_CRC_ON_OFF = 59, /**< Turns the CRC option on or off*/
246 // App Commands
247 ACMD6_SET_BUS_WIDTH = 6,
248 ACMD13_SD_STATUS = 13,
249 ACMD22_SEND_NUM_WR_BLOCKS = 22,
250 ACMD23_SET_WR_BLK_ERASE_COUNT = 23,
251 ACMD41_SD_SEND_OP_COND = 41,
252 ACMD42_SET_CLR_CARD_DETECT = 42,
253 ACMD51_SEND_SCR = 51,
254 };
255
256 uint8_t _card_type;
257 int _cmd(SDBlockDevice::cmdSupported cmd, uint32_t arg, bool isAcmd = 0, uint32_t *resp = NULL);
258 int _cmd8();
259
260 /* Move the SD Card into the SPI Mode idle state
261 *
262 * The card is transitioned from SD Card mode to SPI mode by sending the
263 * CMD0 (GO_IDLE_STATE) command with CS asserted. See the notes in the
264 * "SPI Startup" section of the comments at the head of the
265 * implementation file for further details and specification references.
266 *
267 * @return Response form the card. R1_IDLE_STATE (0x1), the successful
268 * response from CMD0. R1_XXX_XXX for more response
269 */
270 uint32_t _go_idle_state();
271 int _initialise_card();
272
273 mbed::bd_size_t _sectors;
274 mbed::bd_size_t _sd_sectors();
275
276 bool _is_valid_trim(mbed::bd_addr_t addr, mbed::bd_size_t size);
277
278 /* SPI functions */
279 mbed::Timer _spi_timer; /**< Timer Class object used for busy wait */
280 uint32_t _init_sck; /**< Initial SPI frequency */
281 uint32_t _transfer_sck; /**< SPI frequency during data transfer/after initialization */
282 mbed::SPI _spi; /**< SPI Class object */
283
284 /* SPI initialization function */
285 void _spi_init();
286 uint8_t _cmd_spi(SDBlockDevice::cmdSupported cmd, uint32_t arg);
287 void _spi_wait(uint8_t count);
288
289 bool _wait_token(uint8_t token); /**< Wait for token */
290 bool _wait_ready(std::chrono::duration<uint32_t, std::milli> timeout = std::chrono::milliseconds{300}); /**< 300ms default wait for card to be ready */
291 int _read(uint8_t *buffer, uint32_t length);
292 int _read_bytes(uint8_t *buffer, uint32_t length);
293 uint8_t _write(const uint8_t *buffer, uint8_t token, uint32_t length);
294 int _freq(void);
295 void _preclock_then_select();
296 void _postclock_then_deselect();
297
298 virtual void lock()
299 {
300 _mutex.lock();
301 }
302
303 virtual void unlock()
304 {
305 _mutex.unlock();
306 }
307
308 rtos::Mutex _mutex;
309 uint32_t _erase_size;
310 bool _is_initialized;
311 bool _dbg;
312 uint32_t _init_ref_count;
313
314#if MBED_CONF_SD_CRC_ENABLED
315 bool _crc_on;
316#endif
317
318#if DEVICE_SPI_ASYNCH
319 bool _async_spi_enabled = false;
321#endif
322};
323
324#endif /* DEVICE_SPI */
325
326#endif /* MBED_SD_BLOCK_DEVICE_H */
SDBlockDevice class.
Definition: SDBlockDevice.h:59
virtual const char * get_type() const
Get the BlockDevice class type.
virtual mbed::bd_size_t get_read_size() const
Get the size of a readable block.
virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
Read blocks from a block device.
virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
Program blocks to a block device.
virtual void debug(bool dbg)
Enable or disable debugging.
virtual mbed::bd_size_t get_program_size() const
Get the size of a programmable block.
virtual mbed::bd_size_t size() const
Get the total size of the underlying device.
virtual int deinit()
Deinitialize a block device.
SDBlockDevice(const spi_pinmap_t &spi_pinmap, PinName cs=NC, uint64_t hz=1000000, bool crc_on=0)
Creates an SDBlockDevice on a SPI bus specified by pins (using static pin-map)
virtual int frequency(uint64_t freq)
Set the transfer frequency.
virtual int trim(mbed::bd_addr_t addr, mbed::bd_size_t size)
Mark blocks as no longer in use.
virtual int init()
Initialize a block device.
SDBlockDevice(PinName mosi=NC, PinName miso=NC, PinName sclk=NC, PinName cs=NC, uint64_t hz=1000000, bool crc_on=0)
Creates an SDBlockDevice on a SPI bus specified by pins (using dynamic pin-map)
void set_async_spi_mode(bool enabled, DMAUsage dma_usage_hint=DMAUsage::DMA_USAGE_NEVER)
Configure the usage of asynchronous SPI by this class.
A hardware device capable of writing and reading blocks.
Definition: BlockDevice.h:53
An SPI Master, used for communicating with SPI slave devices.
Definition: SPI.h:263
CacheAlignedBuffer type designed for static allocation.
The Mutex class is used to synchronize the execution of threads.
Definition: Mutex.h:70
void unlock()
Unlock the mutex that has previously been locked by the same thread.
void lock()
Wait until a Mutex becomes available.
DMAUsage
Enumeration of possible DMA usage hints.
Definition: dma_api.h:32
uint64_t bd_size_t
Type representing a quantity of 8-bit bytes.
Definition: BlockDevice.h:48
uint64_t bd_addr_t
Type representing the address of a specific block.
Definition: BlockDevice.h:44