Contiki-NG
mmc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
3  * All rights reserved.
4  *
5  * Based on the FatFs Module STM32 Sample Project,
6  * Copyright (c) 2014, ChaN
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software
21  * without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 /**
36  * \addtogroup mmc
37  * @{
38  *
39  * \file
40  * Implementation of the SD/MMC device driver.
41  */
42 #include <stddef.h>
43 #include <stdint.h>
44 #include "contiki.h"
45 #include "sys/clock.h"
46 #include "sys/rtimer.h"
47 #include "dev/watchdog.h"
50 
51 /* Data read/write block length */
52 #define BLOCK_LEN 512
53 /*
54  * Logical sector size exposed to the disk API, not to be confused with the SDSC
55  * sector size, which is the size of an erasable sector
56  */
57 #define SECTOR_SIZE BLOCK_LEN
58 
59 /* Clock frequency in card identification mode: fOD <= 400 kHz */
60 #define CLOCK_FREQ_CARD_ID_MODE 400000
61 /*
62  * Clock frequency in data transfer mode: fPP <= 20 MHz, limited by the
63  * backward-compatible MMC interface timings
64  */
65 #define CLOCK_FREQ_DATA_XFER_MODE 20000000
66 
67 /* SPI-mode command list */
68 #define CMD0 0 /* GO_IDLE_STATE */
69 #define CMD1 1 /* SEND_OP_COND */
70 #define CMD8 8 /* SEND_IF_COND */
71 #define CMD8_VHS_2_7_3_6 0x1
72 #define CMD8_ARG(vhs, check_pattern) ((vhs) << 8 | (check_pattern))
73 #define CMD8_ECHO_MASK 0x00000fff
74 #define CMD9 9 /* SEND_CSD */
75 #define CMD10 10 /* SEND_CID */
76 #define CMD12 12 /* STOP_TRANSMISSION */
77 #define CMD13 13 /* SEND_STATUS */
78 #define CMD16 16 /* SET_BLOCKLEN */
79 #define CMD17 17 /* READ_SINGLE_BLOCK */
80 #define CMD18 18 /* READ_MULTIPLE_BLOCK */
81 #define CMD23 23 /* SET_BLOCK_COUNT */
82 #define CMD24 24 /* WRITE_BLOCK */
83 #define CMD25 25 /* WRITE_MULTIPLE_BLOCK */
84 #define CMD32 32 /* ERASE_WR_BLK_START */
85 #define CMD33 33 /* ERASE_WR_BLK_END */
86 #define CMD38 38 /* ERASE */
87 #define CMD55 55 /* APP_CMD */
88 #define CMD58 58 /* READ_OCR */
89 #define ACMD 0x80 /* Application-specific command */
90 #define ACMD13 (ACMD | 13) /* SD_STATUS */
91 #define ACMD23 (ACMD | 23) /* SET_WR_BLK_ERASE_COUNT */
92 #define ACMD41 (ACMD | 41) /* SD_APP_OP_COND */
93 #define ACMD41_HCS (1 << 30)
94 
95 #define CMD_TX 0x40 /* Command transmission bit */
96 
97 #define R1_MSB 0x00
98 #define R1_SUCCESS 0x00
99 #define R1_IDLE_STATE (1 << 0)
100 #define R1_ERASE_RESET (1 << 1)
101 #define R1_ILLEGAL_COMMAND (1 << 2)
102 #define R1_COM_CRC_ERROR (1 << 3)
103 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
104 #define R1_ADDRESS_ERROR (1 << 5)
105 #define R1_PARAMETER_ERROR (1 << 6)
106 
107 #define TOK_DATA_RESP_MASK 0x1f
108 #define TOK_DATA_RESP_ACCEPTED 0x05
109 #define TOK_DATA_RESP_CRC_ERROR 0x0b
110 #define TOK_DATA_RESP_WR_ERROR 0x0d
111 #define TOK_RD_SINGLE_WR_START_BLOCK 0xfe
112 #define TOK_MULTI_WR_START_BLOCK 0xfc
113 #define TOK_MULTI_WR_STOP_TRAN 0xfd
114 
115 /* The SD Status is one data block of 512 bits. */
116 #define SD_STATUS_SIZE (512 / 8)
117 #define SD_STATUS_AU_SIZE(sd_status) ((sd_status)[10] >> 4)
118 
119 #define OCR_CCS (1 << 30)
120 
121 #define CSD_SIZE 16
122 #define CSD_STRUCTURE(csd) ((csd)[0] >> 6)
123 #define CSD_STRUCTURE_SD_V1_0 0
124 #define CSD_STRUCTURE_SD_V2_0 1
125 #define CSD_SD_V1_0_READ_BL_LEN(csd) ((csd)[5] & 0x0f)
126 #define CSD_SD_V1_0_BLOCK_LEN(csd) (1ull << CSD_SD_V1_0_READ_BL_LEN(csd))
127 #define CSD_SD_V1_0_C_SIZE(csd) \
128  (((csd)[6] & 0x03) << 10 | (csd)[7] << 2 | (csd)[8] >> 6)
129 #define CSD_SD_V1_0_C_SIZE_MULT(csd) \
130  (((csd)[9] & 0x03) << 1 | (csd)[10] >> 7)
131 #define CSD_SD_V1_0_MULT(csd) \
132  (1 << (CSD_SD_V1_0_C_SIZE_MULT(csd) + 2))
133 #define CSD_SD_V1_0_BLOCKNR(csd) \
134  (((uint32_t)CSD_SD_V1_0_C_SIZE(csd) + 1) * CSD_SD_V1_0_MULT(csd))
135 #define CSD_SD_V1_0_CAPACITY(csd) \
136  (CSD_SD_V1_0_BLOCKNR(csd) * CSD_SD_V1_0_BLOCK_LEN(csd))
137 #define CSD_SD_V1_0_SECTOR_SIZE(csd) \
138  (((csd)[10] & 0x3f) << 1 | (csd)[11] >> 7)
139 #define CSD_SD_V1_0_WRITE_BL_LEN(csd) \
140  (((csd)[12] & 0x03) << 2 | (csd)[13] >> 6)
141 #define CSD_SD_V2_0_C_SIZE(csd) \
142  (((csd)[7] & 0x3f) << 16 | (csd)[8] << 8 | (csd)[9])
143 #define CSD_SD_V2_0_CAPACITY(csd) \
144  (((uint64_t)CSD_SD_V2_0_C_SIZE(csd) + 1) << 19)
145 #define CSD_MMC_ERASE_GRP_SIZE(csd) (((csd)[10] & 0x7c) >> 2)
146 #define CSD_MMC_ERASE_GRP_MULT(csd) \
147  (((csd)[10] & 0x03) << 3 | (csd)[11] >> 5)
148 #define CSD_MMC_WRITE_BL_LEN(csd) \
149  (((csd)[12] & 0x03) << 2 | (csd)[13] >> 6)
150 
151 typedef enum {
152  CARD_TYPE_MMC = 0x01, /* MMC v3 */
153  CARD_TYPE_SD1 = 0x02, /* SD v1 */
154  CARD_TYPE_SD2 = 0x04, /* SD v2 */
155  CARD_TYPE_SD = CARD_TYPE_SD1 | CARD_TYPE_SD2, /* SD */
156  CARD_TYPE_BLOCK = 0x08 /* Block addressing */
157 } card_type_t;
158 
159 static struct mmc_priv {
160  uint8_t status;
161  uint8_t card_type;
162 } mmc_priv[MMC_CONF_DEV_COUNT];
163 
164 /*----------------------------------------------------------------------------*/
165 static uint8_t
166 mmc_spi_xchg(uint8_t dev, uint8_t tx_byte)
167 {
168  uint8_t rx_byte;
169 
170  mmc_arch_spi_xfer(dev, &tx_byte, 1, &rx_byte, 1);
171  return rx_byte;
172 }
173 /*----------------------------------------------------------------------------*/
174 static void
175 mmc_spi_tx(uint8_t dev, const void *buf, size_t cnt)
176 {
177  mmc_arch_spi_xfer(dev, buf, cnt, NULL, 0);
178 }
179 /*----------------------------------------------------------------------------*/
180 static void
181 mmc_spi_rx(uint8_t dev, void *buf, size_t cnt)
182 {
183  mmc_arch_spi_xfer(dev, NULL, 0, buf, cnt);
184 }
185 /*----------------------------------------------------------------------------*/
186 static bool
187 mmc_wait_ready(uint8_t dev, uint16_t timeout_ms)
188 {
189  rtimer_clock_t timeout_end =
190  RTIMER_NOW() + ((uint32_t)timeout_ms * RTIMER_SECOND + 999) / 1000;
191  uint8_t rx_byte;
192 
193  do {
194  rx_byte = mmc_spi_xchg(dev, 0xff);
196  } while(rx_byte != 0xff && RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end));
197  return rx_byte == 0xff;
198 }
199 /*----------------------------------------------------------------------------*/
200 static bool
201 mmc_select(uint8_t dev, bool sel)
202 {
203  mmc_arch_spi_select(dev, sel);
204  mmc_spi_xchg(dev, 0xff); /* Dummy clock (force D0) */
205  if(sel && !mmc_wait_ready(dev, 500)) {
206  mmc_select(dev, false);
207  return false;
208  }
209  return true;
210 }
211 /*----------------------------------------------------------------------------*/
212 static uint8_t
213 mmc_send_cmd(uint8_t dev, uint8_t cmd, uint32_t arg)
214 {
215  uint8_t resp, n;
216 
217  /* Send a CMD55 prior to a ACMD<n>. */
218  if(cmd & ACMD) {
219  cmd &= ~ACMD;
220  resp = mmc_send_cmd(dev, CMD55, 0);
221  if(resp != R1_SUCCESS && resp != R1_IDLE_STATE) {
222  return resp;
223  }
224  }
225 
226  /*
227  * Select the card and wait for ready, except to stop a multiple-block read.
228  */
229  if(cmd != CMD12) {
230  mmc_select(dev, false);
231  if(!mmc_select(dev, true)) {
232  return 0xff;
233  }
234  }
235 
236  /* Send the command packet. */
237  mmc_spi_xchg(dev, CMD_TX | cmd); /* Start & tx bits, cmd index */
238  mmc_spi_xchg(dev, arg >> 24); /* Argument[31..24] */
239  mmc_spi_xchg(dev, arg >> 16); /* Argument[23..16] */
240  mmc_spi_xchg(dev, arg >> 8); /* Argument[15..8] */
241  mmc_spi_xchg(dev, arg); /* Argument[7..0] */
242  switch(cmd) {
243  case CMD0:
244  n = 0x95; /* CMD0(0) CRC7, end bit */
245  break;
246  case CMD8:
247  n = 0x87; /* CMD8(0x1aa) CRC7, end bit */
248  break;
249  default:
250  n = 0x01; /* Dummy CRC7, end bit */
251  break;
252  }
253  mmc_spi_xchg(dev, n);
254 
255  /* Receive the command response. */
256  if(cmd == CMD12) {
257  mmc_spi_xchg(dev, 0xff); /* Discard following byte if CMD12. */
258  }
259  /* Wait for the response (max. 10 bytes). */
260  n = 10;
261  do {
262  resp = mmc_spi_xchg(dev, 0xff);
263  } while((resp & 0x80) != R1_MSB && --n);
264  return resp;
265 }
266 /*----------------------------------------------------------------------------*/
267 static bool
268 mmc_tx_block(uint8_t dev, const void *buf, uint8_t token)
269 {
270  uint8_t resp;
271 
272  if(!mmc_wait_ready(dev, 500)) {
273  return false;
274  }
275 
276  mmc_spi_xchg(dev, token);
277  if(token != TOK_MULTI_WR_STOP_TRAN) {
278  mmc_spi_tx(dev, buf, BLOCK_LEN);
279  mmc_spi_xchg(dev, 0xff); /* Dummy CRC */
280  mmc_spi_xchg(dev, 0xff);
281 
282  resp = mmc_spi_xchg(dev, 0xff);
283  if((resp & TOK_DATA_RESP_MASK) != TOK_DATA_RESP_ACCEPTED) {
284  return false;
285  }
286  }
287  return true;
288 }
289 /*----------------------------------------------------------------------------*/
290 static bool
291 mmc_rx(uint8_t dev, void *buf, size_t cnt)
292 {
293  rtimer_clock_t timeout_end =
294  RTIMER_NOW() + (200ul * RTIMER_SECOND + 999) / 1000;
295  uint8_t token;
296 
297  do {
298  token = mmc_spi_xchg(dev, 0xff);
300  } while(token == 0xff && RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end));
301  if(token != TOK_RD_SINGLE_WR_START_BLOCK) {
302  return false;
303  }
304 
305  mmc_spi_rx(dev, buf, cnt);
306  mmc_spi_xchg(dev, 0xff); /* Discard CRC. */
307  mmc_spi_xchg(dev, 0xff);
308  return true;
309 }
310 /*----------------------------------------------------------------------------*/
311 void
312 mmc_arch_cd_changed_callback(uint8_t dev, bool cd)
313 {
314  uint8_t status;
315 
316  if(dev >= MMC_CONF_DEV_COUNT) {
317  return;
318  }
319 
320  if(cd) {
321  status = DISK_STATUS_DISK;
322  if(!mmc_arch_get_wp(dev)) {
323  status |= DISK_STATUS_WRITABLE;
324  }
325  } else {
326  status = 0;
327  }
328  mmc_priv[dev].status = status;
329 }
330 /*----------------------------------------------------------------------------*/
331 static disk_status_t
332 mmc_status(uint8_t dev)
333 {
334  bool cd;
335  struct mmc_priv *priv;
336 
337  if(dev >= MMC_CONF_DEV_COUNT) {
339  }
340 
341  cd = mmc_arch_get_cd(dev);
342  priv = &mmc_priv[dev];
343  if(cd == !(priv->status & DISK_STATUS_DISK)) {
345  }
346  return priv->status;
347 }
348 /*----------------------------------------------------------------------------*/
349 static disk_status_t
350 mmc_initialize(uint8_t dev)
351 {
352  disk_status_t status;
353  uint8_t n, cmd;
354  card_type_t card_type;
355  rtimer_clock_t timeout_end;
356  uint32_t arg, resp, ocr;
357  struct mmc_priv *priv;
358 
359  if(dev >= MMC_CONF_DEV_COUNT) {
361  }
362  status = mmc_status(dev);
363  if(!(status & DISK_STATUS_DISK)) {
364  return status;
365  }
366 
367  mmc_arch_spi_select(dev, false);
368  clock_delay_usec(10000);
369 
370  mmc_arch_spi_set_clock_freq(dev, CLOCK_FREQ_CARD_ID_MODE);
371  for(n = 10; n; n--) {
372  mmc_spi_xchg(dev, 0xff); /* Generate 80 dummy clock cycles. */
373  }
374 
375  card_type = 0;
376  if(mmc_send_cmd(dev, CMD0, 0) == R1_IDLE_STATE) {
377  timeout_end = RTIMER_NOW() + RTIMER_SECOND;
378  arg = CMD8_ARG(CMD8_VHS_2_7_3_6, 0xaa); /* Arbitrary check pattern */
379  if(mmc_send_cmd(dev, CMD8, arg) == R1_IDLE_STATE) { /* SD v2? */
380  resp = 0;
381  for(n = 4; n; n--) {
382  resp = resp << 8 | mmc_spi_xchg(dev, 0xff);
383  }
384  /* Does the card support 2.7 V - 3.6 V? */
385  if((arg & CMD8_ECHO_MASK) == (resp & CMD8_ECHO_MASK)) {
386  /* Wait for end of initialization. */
387  while(RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) &&
388  mmc_send_cmd(dev, ACMD41, ACMD41_HCS) != R1_SUCCESS) {
390  }
391  if(RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) &&
392  mmc_send_cmd(dev, CMD58, 0) == R1_SUCCESS) { /* Read OCR. */
393  ocr = 0;
394  for(n = 4; n; n--) {
395  ocr = ocr << 8 | mmc_spi_xchg(dev, 0xff);
396  }
397  card_type = CARD_TYPE_SD2;
398  if(ocr & OCR_CCS) {
399  card_type |= CARD_TYPE_BLOCK;
400  }
401  }
402  }
403  } else { /* Not SD v2 */
404  resp = mmc_send_cmd(dev, ACMD41, 0);
405  if(resp == R1_SUCCESS || resp == R1_IDLE_STATE) { /* SD v1 or MMC? */
406  card_type = CARD_TYPE_SD1;
407  cmd = ACMD41;
408  } else {
409  card_type = CARD_TYPE_MMC;
410  cmd = CMD1;
411  }
412  /* Wait for end of initialization. */
413  while(RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) &&
414  mmc_send_cmd(dev, cmd, 0) != R1_SUCCESS) {
416  }
417  /* Set block length. */
418  if(!RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) ||
419  mmc_send_cmd(dev, CMD16, BLOCK_LEN) != R1_SUCCESS) {
420  card_type = 0;
421  }
422  }
423  }
424  priv = &mmc_priv[dev];
425  priv->card_type = card_type;
426  mmc_select(dev, false);
427 
428  status = priv->status;
429  if(status & DISK_STATUS_DISK && card_type) { /* OK */
430  mmc_arch_spi_set_clock_freq(dev, CLOCK_FREQ_DATA_XFER_MODE);
431  status |= DISK_STATUS_INIT;
432  } else { /* Failed */
433  status &= ~DISK_STATUS_INIT;
434  }
435  priv->status = status;
436  return status;
437 }
438 /*----------------------------------------------------------------------------*/
439 static disk_result_t
440 mmc_read(uint8_t dev, void *buff, uint32_t sector, uint32_t count)
441 {
442  if(dev >= MMC_CONF_DEV_COUNT || !count) {
444  }
445  if(!(mmc_status(dev) & DISK_STATUS_INIT)) {
446  return DISK_RESULT_NO_INIT;
447  }
448 
449  if(!(mmc_priv[dev].card_type & CARD_TYPE_BLOCK)) {
450  sector *= SECTOR_SIZE;
451  }
452 
453  if(count == 1) {
454  if(mmc_send_cmd(dev, CMD17, sector) == R1_SUCCESS &&
455  mmc_rx(dev, buff, SECTOR_SIZE)) {
456  count = 0;
457  }
458  } else if(mmc_send_cmd(dev, CMD18, sector) == R1_SUCCESS) {
459  do {
460  if(!mmc_rx(dev, buff, SECTOR_SIZE)) {
461  break;
462  }
463  buff = (uint8_t *)buff + SECTOR_SIZE;
465  } while(--count);
466  mmc_send_cmd(dev, CMD12, 0); /* Stop transmission. */
467  }
468  mmc_select(dev, false);
469  return count ? DISK_RESULT_IO_ERROR : DISK_RESULT_OK;
470 }
471 /*----------------------------------------------------------------------------*/
472 static disk_result_t
473 mmc_write(uint8_t dev, const void *buff, uint32_t sector, uint32_t count)
474 {
475  disk_status_t status;
476  card_type_t card_type;
477 
478  if(dev >= MMC_CONF_DEV_COUNT || !count) {
480  }
481  status = mmc_status(dev);
482  if(!(status & DISK_STATUS_INIT)) {
483  return DISK_RESULT_NO_INIT;
484  }
485  if(!(status & DISK_STATUS_WRITABLE)) {
487  }
488 
489  card_type = mmc_priv[dev].card_type;
490  if(!(card_type & CARD_TYPE_BLOCK)) {
491  sector *= SECTOR_SIZE;
492  }
493 
494  if(count == 1) {
495  if(mmc_send_cmd(dev, CMD24, sector) == R1_SUCCESS &&
496  mmc_tx_block(dev, buff, TOK_RD_SINGLE_WR_START_BLOCK)) {
497  count = 0;
498  }
499  } else {
500  if(card_type & CARD_TYPE_SD) {
501  mmc_send_cmd(dev, ACMD23, count);
502  }
503  if(mmc_send_cmd(dev, CMD25, sector) == R1_SUCCESS) {
504  do {
505  if(!mmc_tx_block(dev, buff, TOK_MULTI_WR_START_BLOCK)) {
506  break;
507  }
508  buff = (uint8_t *)buff + BLOCK_LEN;
510  } while(--count);
511  if(!mmc_tx_block(dev, NULL, TOK_MULTI_WR_STOP_TRAN)) {
512  count = 1;
513  }
514  }
515  }
516  mmc_select(dev, false);
517  return count ? DISK_RESULT_IO_ERROR : DISK_RESULT_OK;
518 }
519 /*----------------------------------------------------------------------------*/
520 static disk_result_t
521 mmc_ioctl(uint8_t dev, uint8_t cmd, void *buff)
522 {
523  card_type_t card_type;
524  disk_result_t res;
525  uint8_t csd[CSD_SIZE], sd_status[SD_STATUS_SIZE], au_size;
526  uint64_t capacity;
527  uint32_t block_size;
528 
529  static const uint8_t AU_TO_BLOCK_SIZE[] = {12, 16, 24, 32, 64};
530 
531  if(dev >= MMC_CONF_DEV_COUNT) {
533  }
534  if(!(mmc_status(dev) & DISK_STATUS_INIT)) {
535  return DISK_RESULT_NO_INIT;
536  }
537 
538  card_type = mmc_priv[dev].card_type;
539  res = DISK_RESULT_IO_ERROR;
540 
541  switch(cmd) {
543  if(mmc_select(dev, true)) {
544  res = DISK_RESULT_OK;
545  }
546  break;
547 
549  if(mmc_send_cmd(dev, CMD9, 0) == R1_SUCCESS && mmc_rx(dev, csd, CSD_SIZE)) {
550  capacity = CSD_STRUCTURE(csd) == CSD_STRUCTURE_SD_V2_0 ?
551  CSD_SD_V2_0_CAPACITY(csd) : CSD_SD_V1_0_CAPACITY(csd);
552  *(uint32_t *)buff = capacity / SECTOR_SIZE;
553  res = DISK_RESULT_OK;
554  }
555  break;
556 
558  *(uint16_t *)buff = SECTOR_SIZE;
559  res = DISK_RESULT_OK;
560  break;
561 
563  if(card_type & CARD_TYPE_SD2) {
564  if(mmc_send_cmd(dev, ACMD13, 0) == R1_SUCCESS) { /* Read SD status. */
565  mmc_spi_xchg(dev, 0xff);
566  if(mmc_rx(dev, sd_status, SD_STATUS_SIZE)) {
567  au_size = SD_STATUS_AU_SIZE(sd_status);
568  if(au_size) {
569  block_size = au_size <= 0xa ? 8192ull << au_size :
570  (uint32_t)AU_TO_BLOCK_SIZE[au_size - 0xb] << 20;
571  *(uint32_t *)buff = block_size / SECTOR_SIZE;
572  res = DISK_RESULT_OK;
573  }
574  }
575  }
576  } else if(mmc_send_cmd(dev, CMD9, 0) == R1_SUCCESS &&
577  mmc_rx(dev, csd, CSD_SIZE)) {
578  if(card_type & CARD_TYPE_SD1) {
579  block_size = (uint32_t)(CSD_SD_V1_0_SECTOR_SIZE(csd) + 1) <<
580  CSD_SD_V1_0_WRITE_BL_LEN(csd);
581  } else { /* MMC */
582  block_size = (uint32_t)(CSD_MMC_ERASE_GRP_SIZE(csd) + 1) *
583  (CSD_MMC_ERASE_GRP_MULT(csd) + 1) <<
584  CSD_MMC_WRITE_BL_LEN(csd);
585  }
586  *(uint32_t *)buff = block_size / SECTOR_SIZE;
587  res = DISK_RESULT_OK;
588  }
589  break;
590 
591  default:
593  break;
594  }
595  mmc_select(dev, false);
596  return res;
597 }
598 /*----------------------------------------------------------------------------*/
599 const struct disk_driver mmc_driver = {
600  .status = mmc_status,
601  .initialize = mmc_initialize,
602  .read = mmc_read,
603  .write = mmc_write,
604  .ioctl = mmc_ioctl
605 };
606 /*----------------------------------------------------------------------------*/
607 
608 /** @} */
bool mmc_arch_get_wp(uint8_t dev)
Gets the state of the write-protection signal.
Definition: mmc-arch.c:92
static volatile uint64_t count
Num.
Definition: clock.c:50
void mmc_arch_cd_changed_callback(uint8_t dev, bool cd)
Callback of the SD/MMC driver to call when the card-detection signal changes.
Definition: mmc.c:312
disk_status_t(* status)(uint8_t dev)
Get device status.
Definition: disk.h:76
bool mmc_arch_get_cd(uint8_t dev)
Gets the state of the card-detection signal.
Definition: mmc-arch.c:73
Invalid argument.
Definition: disk.h:70
Disk driver API structure.
Definition: disk.h:74
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
void mmc_arch_spi_select(uint8_t dev, bool sel)
Sets the SPI /CS signal as indicated.
Definition: mmc-arch.c:98
Header file for the SD/MMC device driver architecture-specific definitions.
void mmc_arch_spi_set_clock_freq(uint8_t dev, uint32_t freq)
Sets the SPI clock frequency.
Definition: mmc-arch.c:108
Synchronize the cached writes to persistent storage.
Definition: disk.h:57
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
disk_result_t
Disk access result codes.
Definition: disk.h:65
disk_status_t
Disk status flags.
Definition: disk.h:49
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
Write-protected medium.
Definition: disk.h:68
#define MMC_CONF_DEV_COUNT
Number of SD/MMC devices.
Definition: mmc.h:51
void mmc_arch_spi_xfer(uint8_t dev, const void *tx_buf, size_t tx_cnt, void *rx_buf, size_t rx_cnt)
Performs an SPI transfer.
Definition: mmc-arch.c:114
Device not initialized.
Definition: disk.h:69
Header file for the real-time timer module.
Writable medium.
Definition: disk.h:52
Get the sector count through the uint32_t pointed to by buff.
Definition: disk.h:58
Medium present in the drive.
Definition: disk.h:51
Success.
Definition: disk.h:66
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85
Header file for the SD/MMC device driver.
Unrecoverable I/O error.
Definition: disk.h:67
Get the sector size through the uint16_t pointed to by buff.
Definition: disk.h:59
Device initialized and ready to work.
Definition: disk.h:50
Get the erase block size (in sectors) through the uint32_t pointed to by buff.
Definition: disk.h:60