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