Mistake on this page?
Report an issue in GitHub or email us
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 "platform/PlatformMutex.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 public:
61  /** Creates an SDBlockDevice on a SPI bus specified by pins (using dynamic pin-map)
62  *
63  * @param mosi SPI master out, slave in pin
64  * @param miso SPI master in, slave out pin
65  * @param sclk SPI clock pin
66  * @param cs SPI chip select pin
67  * @param hz Clock speed of the SPI bus (defaults to 1MHz)
68  * @param crc_on Enable cyclic redundancy check (defaults to disabled)
69  */
70  SDBlockDevice(PinName mosi = MBED_CONF_SD_SPI_MOSI,
71  PinName miso = MBED_CONF_SD_SPI_MISO,
72  PinName sclk = MBED_CONF_SD_SPI_CLK,
73  PinName cs = MBED_CONF_SD_SPI_CS,
74  uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
75  bool crc_on = MBED_CONF_SD_CRC_ENABLED);
76 
77  /** Creates an SDBlockDevice on a SPI bus specified by pins (using static pin-map)
78  *
79  * @param spi_pinmap Static SPI pin-map
80  * @param hz Clock speed of the SPI bus (defaults to 1MHz)
81  * @param crc_on Enable cyclic redundancy check (defaults to disabled)
82  */
83  SDBlockDevice(const spi_pinmap_t &spi_pinmap,
84  PinName cs = MBED_CONF_SD_SPI_CS,
85  uint64_t hz = MBED_CONF_SD_TRX_FREQUENCY,
86  bool crc_on = MBED_CONF_SD_CRC_ENABLED);
87 
88  virtual ~SDBlockDevice();
89 
90  /** Initialize a block device
91  *
92  * @return BD_ERROR_OK(0) - success
93  * BD_ERROR_DEVICE_ERROR - device driver transaction failed
94  * SD_BLOCK_DEVICE_ERROR_NO_DEVICE - device (SD card) is missing or not connected
95  * SD_BLOCK_DEVICE_ERROR_UNUSABLE - unusable card
96  * SD_BLOCK_DEVICE_ERROR_CRC - crc error
97  */
98  virtual int init();
99 
100  /** Deinitialize a block device
101  *
102  * @return BD_ERROR_OK(0) - success
103  */
104  virtual int deinit();
105 
106  /** Read blocks from a block device
107  *
108  * @param buffer Buffer to write blocks to
109  * @param addr Address of block to begin reading from
110  * @param size Size to read in bytes, must be a multiple of read block size
111  * @return BD_ERROR_OK(0) - success
112  * SD_BLOCK_DEVICE_ERROR_NO_DEVICE - device (SD card) is missing or not connected
113  * SD_BLOCK_DEVICE_ERROR_CRC - crc error
114  * SD_BLOCK_DEVICE_ERROR_PARAMETER - invalid parameter
115  * SD_BLOCK_DEVICE_ERROR_NO_RESPONSE - no response from device
116  * SD_BLOCK_DEVICE_ERROR_UNSUPPORTED - unsupported command
117  */
118  virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
119 
120  /** Program blocks to a block device
121  *
122  * @note The blocks must be erased prior to programming
123  *
124  * @param buffer Buffer of data to write to blocks
125  * @param addr Address of block to begin writing to
126  * @param size Size to write in bytes. Must be a multiple of program block size
127  * @return BD_ERROR_OK(0) - success
128  * SD_BLOCK_DEVICE_ERROR_NO_DEVICE - device (SD card) is missing or not connected
129  * SD_BLOCK_DEVICE_ERROR_CRC - crc error
130  * SD_BLOCK_DEVICE_ERROR_PARAMETER - invalid parameter
131  * SD_BLOCK_DEVICE_ERROR_UNSUPPORTED - unsupported command
132  * SD_BLOCK_DEVICE_ERROR_NO_INIT - device is not initialized
133  * SD_BLOCK_DEVICE_ERROR_WRITE - SPI write error
134  * SD_BLOCK_DEVICE_ERROR_ERASE - erase error
135  */
136  virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
137 
138  /** Mark blocks as no longer in use
139  *
140  * This function provides a hint to the underlying block device that a region of blocks
141  * is no longer in use and may be erased without side effects. Erase must still be called
142  * before programming, but trimming allows flash-translation-layers to schedule erases when
143  * the device is not busy.
144  *
145  * @param addr Address of block to mark as unused
146  * @param size Size to mark as unused in bytes, must be a multiple of erase 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_ERASE - erase error
154  */
155  virtual int trim(mbed::bd_addr_t addr, mbed::bd_size_t size);
156 
157  /** Get the size of a readable block
158  *
159  * @return Size of a readable block in bytes
160  */
161  virtual mbed::bd_size_t get_read_size() const;
162 
163  /** Get the size of a programmable block
164  *
165  * @return Size of a programmable block in bytes
166  * @note Must be a multiple of the read size
167  */
168  virtual mbed::bd_size_t get_program_size() const;
169 
170  /** Get the total size of the underlying device
171  *
172  * @return Size of the underlying device in bytes
173  */
174  virtual mbed::bd_size_t size() const;
175 
176  /** Enable or disable debugging
177  *
178  * @param dbg State of debugging
179  */
180  virtual void debug(bool dbg);
181 
182  /** Set the transfer frequency
183  *
184  * @param freq Transfer frequency
185  * @note Max frequency supported is 25MHZ
186  */
187  virtual int frequency(uint64_t freq);
188 
189  /** Get the BlockDevice class type.
190  *
191  * @return A string representation of the BlockDevice class type.
192  */
193  virtual const char *get_type() const;
194 
195 private:
196  /* Commands : Listed below are commands supported
197  * in SPI mode for SD card : Only Mandatory ones
198  */
199  enum cmdSupported {
200  CMD_NOT_SUPPORTED = -1, /**< Command not supported error */
201  CMD0_GO_IDLE_STATE = 0, /**< Resets the SD Memory Card */
202  CMD1_SEND_OP_COND = 1, /**< Sends host capacity support */
203  CMD6_SWITCH_FUNC = 6, /**< Check and Switches card function */
204  CMD8_SEND_IF_COND = 8, /**< Supply voltage info */
205  CMD9_SEND_CSD = 9, /**< Provides Card Specific data */
206  CMD10_SEND_CID = 10, /**< Provides Card Identification */
207  CMD12_STOP_TRANSMISSION = 12, /**< Forces the card to stop transmission */
208  CMD13_SEND_STATUS = 13, /**< Card responds with status */
209  CMD16_SET_BLOCKLEN = 16, /**< Length for SC card is set */
210  CMD17_READ_SINGLE_BLOCK = 17, /**< Read single block of data */
211  CMD18_READ_MULTIPLE_BLOCK = 18, /**< Card transfers data blocks to host until interrupted
212  by a STOP_TRANSMISSION command */
213  CMD24_WRITE_BLOCK = 24, /**< Write single block of data */
214  CMD25_WRITE_MULTIPLE_BLOCK = 25, /**< Continuously writes blocks of data until
215  'Stop Tran' token is sent */
216  CMD27_PROGRAM_CSD = 27, /**< Programming bits of CSD */
217  CMD32_ERASE_WR_BLK_START_ADDR = 32, /**< Sets the address of the first write
218  block to be erased. */
219  CMD33_ERASE_WR_BLK_END_ADDR = 33, /**< Sets the address of the last write
220  block of the continuous range to be erased.*/
221  CMD38_ERASE = 38, /**< Erases all previously selected write blocks */
222  CMD55_APP_CMD = 55, /**< Extend to Applications specific commands */
223  CMD56_GEN_CMD = 56, /**< General Purpose Command */
224  CMD58_READ_OCR = 58, /**< Read OCR register of card */
225  CMD59_CRC_ON_OFF = 59, /**< Turns the CRC option on or off*/
226  // App Commands
227  ACMD6_SET_BUS_WIDTH = 6,
228  ACMD13_SD_STATUS = 13,
229  ACMD22_SEND_NUM_WR_BLOCKS = 22,
230  ACMD23_SET_WR_BLK_ERASE_COUNT = 23,
231  ACMD41_SD_SEND_OP_COND = 41,
232  ACMD42_SET_CLR_CARD_DETECT = 42,
233  ACMD51_SEND_SCR = 51,
234  };
235 
236  uint8_t _card_type;
237  int _cmd(SDBlockDevice::cmdSupported cmd, uint32_t arg, bool isAcmd = 0, uint32_t *resp = NULL);
238  int _cmd8();
239 
240  /* Move the SD Card into the SPI Mode idle state
241  *
242  * The card is transitioned from SD Card mode to SPI mode by sending the
243  * CMD0 (GO_IDLE_STATE) command with CS asserted. See the notes in the
244  * "SPI Startup" section of the comments at the head of the
245  * implementation file for further details and specification references.
246  *
247  * @return Response form the card. R1_IDLE_STATE (0x1), the successful
248  * response from CMD0. R1_XXX_XXX for more response
249  */
250  uint32_t _go_idle_state();
251  int _initialise_card();
252 
253  mbed::bd_size_t _sectors;
254  mbed::bd_size_t _sd_sectors();
255 
256  bool _is_valid_trim(mbed::bd_addr_t addr, mbed::bd_size_t size);
257 
258  /* SPI functions */
259  mbed::Timer _spi_timer; /**< Timer Class object used for busy wait */
260  uint32_t _init_sck; /**< Initial SPI frequency */
261  uint32_t _transfer_sck; /**< SPI frequency during data transfer/after initialization */
262  mbed::SPI _spi; /**< SPI Class object */
263 
264  /* SPI initialization function */
265  void _spi_init();
266  uint8_t _cmd_spi(SDBlockDevice::cmdSupported cmd, uint32_t arg);
267  void _spi_wait(uint8_t count);
268 
269  bool _wait_token(uint8_t token); /**< Wait for token */
270  bool _wait_ready(std::chrono::duration<uint32_t, std::milli> timeout = std::chrono::milliseconds{300}); /**< 300ms default wait for card to be ready */
271  int _read(uint8_t *buffer, uint32_t length);
272  int _read_bytes(uint8_t *buffer, uint32_t length);
273  uint8_t _write(const uint8_t *buffer, uint8_t token, uint32_t length);
274  int _freq(void);
275  void _preclock_then_select();
276  void _postclock_then_deselect();
277 
278  virtual void lock()
279  {
280  _mutex.lock();
281  }
282 
283  virtual void unlock()
284  {
285  _mutex.unlock();
286  }
287 
288  PlatformMutex _mutex;
289  static const uint32_t _block_size;
290  uint32_t _erase_size;
291  bool _is_initialized;
292  bool _dbg;
293  uint32_t _init_ref_count;
294 
295 #if MBED_CONF_SD_CRC_ENABLED
296  bool _crc_on;
297 #endif
298 };
299 
300 #endif /* DEVICE_SPI */
301 
302 #endif /* MBED_SD_BLOCK_DEVICE_H */
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.
A hardware device capable of writing and reading blocks.
Definition: BlockDevice.h:48
virtual int init()
Initialize a block device.
virtual mbed::bd_size_t size() const
Get the total size of the underlying device.
SDBlockDevice class.
Definition: SDBlockDevice.h:59
The PlatformMutex class is used to synchronize the execution of threads.
Definition: PlatformMutex.h:47
void unlock()
Unlock a PlatformMutex that the same thread has previously locked.
Definition: PlatformMutex.h:81
void lock()
Wait until a PlatformMutex becomes available.
Definition: PlatformMutex.h:71
virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
Read blocks from a block device.
virtual mbed::bd_size_t get_read_size() const
Get the size of a readable block.
A SPI Master, used for communicating with SPI slave devices.
Definition: SPI.h:98
virtual mbed::bd_size_t get_program_size() const
Get the size of a programmable block.
virtual int frequency(uint64_t freq)
Set the transfer frequency.
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)
virtual int deinit()
Deinitialize a block device.
virtual const char * get_type() const
Get the BlockDevice class type.
virtual int trim(mbed::bd_addr_t addr, mbed::bd_size_t size)
Mark blocks as no longer in use.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.