Contiki-NG
Loading...
Searching...
No Matches
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
151typedef 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
159static struct mmc_priv {
160 uint8_t status;
161 uint8_t card_type;
162} mmc_priv[MMC_CONF_DEV_COUNT];
163
164/*----------------------------------------------------------------------------*/
165static uint8_t
166mmc_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/*----------------------------------------------------------------------------*/
174static void
175mmc_spi_tx(uint8_t dev, const void *buf, size_t cnt)
176{
177 mmc_arch_spi_xfer(dev, buf, cnt, NULL, 0);
178}
179/*----------------------------------------------------------------------------*/
180static void
181mmc_spi_rx(uint8_t dev, void *buf, size_t cnt)
182{
183 mmc_arch_spi_xfer(dev, NULL, 0, buf, cnt);
184}
185/*----------------------------------------------------------------------------*/
186static bool
187mmc_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/*----------------------------------------------------------------------------*/
200static bool
201mmc_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/*----------------------------------------------------------------------------*/
212static uint8_t
213mmc_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/*----------------------------------------------------------------------------*/
267static bool
268mmc_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/*----------------------------------------------------------------------------*/
290static bool
291mmc_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/*----------------------------------------------------------------------------*/
311void
312mmc_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/*----------------------------------------------------------------------------*/
331static disk_status_t
332mmc_status(uint8_t dev)
333{
334 bool cd;
335 struct mmc_priv *priv;
336
337 if(dev >= MMC_CONF_DEV_COUNT) {
338 return DISK_STATUS_ERROR;
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/*----------------------------------------------------------------------------*/
349static disk_status_t
350mmc_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) {
360 return DISK_STATUS_ERROR;
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/*----------------------------------------------------------------------------*/
439static disk_result_t
440mmc_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);
470}
471/*----------------------------------------------------------------------------*/
472static disk_result_t
473mmc_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);
518}
519/*----------------------------------------------------------------------------*/
520static disk_result_t
521mmc_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;
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/*----------------------------------------------------------------------------*/
599const 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/** @} */
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition clock.c:150
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition watchdog.c:85
static volatile uint64_t count
Num.
Definition clock.c:50
disk_result_t
Disk access result codes.
Definition disk.h:66
disk_status_t
Disk status flags.
Definition disk.h:49
@ DISK_RESULT_IO_ERROR
Unrecoverable I/O error.
Definition disk.h:68
@ DISK_RESULT_OK
Success.
Definition disk.h:67
@ DISK_RESULT_INVALID_ARG
Invalid argument.
Definition disk.h:71
@ DISK_RESULT_WR_PROTECTED
Write-protected medium.
Definition disk.h:69
@ DISK_RESULT_NO_INIT
Device not initialized.
Definition disk.h:70
@ DISK_IOCTL_GET_SECTOR_SIZE
Get the sector size through the uint16_t pointed to by buff.
Definition disk.h:60
@ DISK_IOCTL_GET_BLOCK_SIZE
Get the erase block size (in sectors) through the uint32_t pointed to by buff.
Definition disk.h:61
@ DISK_IOCTL_GET_SECTOR_COUNT
Get the sector count through the uint32_t pointed to by buff.
Definition disk.h:59
@ DISK_IOCTL_CTRL_SYNC
Synchronize the cached writes to persistent storage.
Definition disk.h:58
@ DISK_STATUS_WRITABLE
Writable medium.
Definition disk.h:52
@ DISK_STATUS_INIT
Device initialized and ready to work.
Definition disk.h:50
@ DISK_STATUS_DISK
Medium present in the drive.
Definition disk.h:51
@ DISK_STATUS_ERROR
Device error.
Definition disk.h:53
void mmc_arch_spi_set_clock_freq(uint8_t dev, uint32_t freq)
Sets the SPI clock frequency.
Definition mmc-arch.c:108
bool mmc_arch_get_cd(uint8_t dev)
Gets the state of the card-detection signal.
Definition mmc-arch.c:73
bool mmc_arch_get_wp(uint8_t dev)
Gets the state of the write-protection signal.
Definition mmc-arch.c:92
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
void mmc_arch_spi_select(uint8_t dev, bool sel)
Sets the SPI /CS signal as indicated.
Definition mmc-arch.c:98
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
#define MMC_CONF_DEV_COUNT
Number of SD/MMC devices.
Definition mmc.h:51
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition rtimer.h:112
#define RTIMER_NOW()
Get the current clock time.
Definition rtimer.h:187
Header file for the SD/MMC device driver architecture-specific definitions.
Header file for the SD/MMC device driver.
Header file for the real-time timer module.
Disk driver API structure.
Definition disk.h:75
disk_status_t(* status)(uint8_t dev)
Get device status.
Definition disk.h:77