Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Modules / DiWheelDrive_1-1 / Boot / lib / fatfs / mmc.c @ 367c0652

History | View | Annotate | Download (21.2 KB)

1 69661903 Thomas Schöpping
/*------------------------------------------------------------------------/
2
/  MMCv3/SDv1/SDv2 (in SPI mode) control module
3
/-------------------------------------------------------------------------/
4
/
5
/  Copyright (C) 2013, ChaN, all right reserved.
6
/
7
/ * This software is a free software and there is NO WARRANTY.
8
/ * No restriction on use. You can use, modify and redistribute it for
9
/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
10
/ * Redistributions of source code must retain the above copyright notice.
11
/
12
/-------------------------------------------------------------------------*/
13
14
15
/*
16
 * This file was modified from a sample available from the FatFs
17
 * web site. It was modified to work with a Olimex STM32-P103
18
 * evaluation board.
19
 *
20
 */
21
#include "diskio.h"
22
#include "stm32f10x.h"                                /* STM32 registers               */
23
#include "stm32f10x_conf.h"                           /* STM32 peripheral drivers      */
24
#include "boot.h"
25
26
27
28
/*--------------------------------------------------------------------------
29

30
   Module Private Functions
31

32
---------------------------------------------------------------------------*/
33
34
/* Definitions for MMC/SDC command */
35
#define CMD0   (0)                        /* GO_IDLE_STATE */
36
#define CMD1   (1)                        /* SEND_OP_COND */
37
#define ACMD41 (41|0x80)        /* SEND_OP_COND (SDC) */
38
#define CMD8   (8)                        /* SEND_IF_COND */
39
#define CMD9   (9)                        /* SEND_CSD */
40
#define CMD10  (10)                        /* SEND_CID */
41
#define CMD12  (12)                        /* STOP_TRANSMISSION */
42
#define ACMD13 (13|0x80)        /* SD_STATUS (SDC) */
43
#define CMD16  (16)                        /* SET_BLOCKLEN */
44
#define CMD17  (17)                        /* READ_SINGLE_BLOCK */
45
#define CMD18  (18)                        /* READ_MULTIPLE_BLOCK */
46
#define CMD23  (23)                        /* SET_BLOCK_COUNT */
47
#define ACMD23 (23|0x80)        /* SET_WR_BLK_ERASE_COUNT (SDC) */
48
#define CMD24  (24)                        /* WRITE_BLOCK */
49
#define CMD25  (25)                        /* WRITE_MULTIPLE_BLOCK */
50
#define CMD41  (41)                        /* SEND_OP_COND (ACMD) */
51
#define CMD55  (55)                        /* APP_CMD */
52
#define CMD58  (58)                        /* READ_OCR */
53
54
55
/* Control signals (Platform dependent) */
56
#define CS_LOW()          GPIO_ResetBits(GPIOB, GPIO_Pin_12)  /* MMC CS = L */
57
#define        CS_HIGH()          GPIO_SetBits(GPIOB, GPIO_Pin_12)          /* MMC CS = H */
58
59
60
61
#define        FCLK_SLOW()                        /* Set slow clock (100k-400k) */
62
#define        FCLK_FAST()        set_max_speed()        /* Set fast clock (depends on the CSD) */
63
64
static volatile
65
DSTATUS Stat = STA_NOINIT;        /* Disk status */
66
67
static
68
UINT CardType;
69
70
71
/*-----------------------------------------------------------------------*/
72
/* Send 80 or so clock transitions with CS and DI held high. This is     */
73
/* required after card power up to get it into SPI mode                  */
74
/*-----------------------------------------------------------------------*/
75
static
76
void send_initial_clock_train(void)
77
{
78
  GPIO_InitTypeDef GPIO_InitStructure;
79
  unsigned int i;
80
81
  /* Ensure CS is held high. */
82
  CS_HIGH();
83
84
  /* Switch the SSI TX line to a GPIO and drive it high too. */
85
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;
86
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
87
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
88
  GPIO_Init(GPIOB, &GPIO_InitStructure);
89
  GPIO_SetBits(GPIOB, GPIO_Pin_15);
90
91
  /* Send 10 bytes over the SSI. This causes the clock to wiggle the */
92
  /* required number of times. */
93
  for(i = 0 ; i < 10 ; i++)
94
  {
95
    /* Loop while DR register in not empty */
96
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) { ; }
97
98
    /* Send byte through the SPI peripheral */
99
    SPI_I2S_SendData(SPI2, 0xff);
100
101
    /* Wait to receive a byte */
102
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) { ; }
103
  }
104
105
  /* Revert to hardware control of the SSI TX line. */
106
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;
107
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
108
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
109
  GPIO_Init(GPIOB, &GPIO_InitStructure);
110
}
111
112
113
/*-----------------------------------------------------------------------*/
114
/* Power Control  (Platform dependent)                                   */
115
/*-----------------------------------------------------------------------*/
116
/* When the target system does not support socket power control, there   */
117
/* is nothing to do in these functions.                                  */
118
119
static
120
void power_on (void)
121
{
122
  SPI_InitTypeDef  SPI_InitStructure;
123
  GPIO_InitTypeDef GPIO_InitStructure;
124
125
  /*
126
   * This doesn't really turn the power on, but initializes the
127
   * SSI port and pins needed to talk to the card.
128
   */
129
130
  /* Enable GPIO clock for CS */
131
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
132
  /* Enable SPI clock, SPI2: APB1 */
133
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
134
  /* Configure I/O for Flash Chip select (PB12) */
135
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
136
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
137
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
138
  GPIO_Init(GPIOB, &GPIO_InitStructure);
139
140
  /* De-select the Card: Chip Select high */
141
  GPIO_SetBits(GPIOB, GPIO_Pin_12);
142
143
  /* Configure SPI pins: SCK (PB13) and MOSI (PB15) with default alternate function (not re-mapped) push-pull */
144
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13 | GPIO_Pin_15;
145
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
146
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
147
  GPIO_Init(GPIOB, &GPIO_InitStructure);
148
  /* Configure MISO (PB14) as Input with internal pull-up */
149
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_14;
150
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
151
  GPIO_Init(GPIOB, &GPIO_InitStructure);
152
153
  /* SPI configuration */
154
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
155
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
156
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
157
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
158
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
159
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
160
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; // 72000kHz/256=281kHz < 400kHz
161
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
162
  SPI_InitStructure.SPI_CRCPolynomial = 7;
163
164
  SPI_Init(SPI2, &SPI_InitStructure);
165
  SPI_CalculateCRC(SPI2, DISABLE);
166
  SPI_Cmd(SPI2, ENABLE);
167
168
    /* Set DI and CS high and apply more than 74 pulses to SCLK for the card */
169
    /* to be able to accept a native command. */
170
    send_initial_clock_train();
171
172
}
173
// set the SSI speed to the max setting
174
static
175
void set_max_speed(void)
176
{
177
  SPI_InitTypeDef  SPI_InitStructure;
178
179
  /* Disable the SPI system */
180
  SPI_Cmd(SPI2, DISABLE);
181
182
  /* MMC/SDC can work at the clock frequency up to 20/25MHz so pick a speed close to
183
   * this but not higher
184
   */
185
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
186
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
187
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
188
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
189
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
190
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
191
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 72MHz/4=18MHz < 20MHz
192
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
193
  SPI_InitStructure.SPI_CRCPolynomial = 7;
194
  SPI_Init(SPI2, &SPI_InitStructure);
195
  SPI_CalculateCRC(SPI2, DISABLE);
196
197
  /* Enable the SPI system */
198
  SPI_Cmd(SPI2, ENABLE);
199
}
200
201
static
202
void power_off (void)
203
{
204
        Stat |= STA_NOINIT;        /* Force uninitialized */
205
}
206
207
208
/*-----------------------------------------------------------------------*/
209
/* Transmit/Receive data to/from MMC via SPI  (Platform dependent)       */
210
/*-----------------------------------------------------------------------*/
211
212
static
213
BYTE xchg_spi (BYTE dat)
214
{
215
  /* Send byte through the SPI peripheral */
216
  SPI_I2S_SendData(SPI2, dat);
217
218
  /* Wait to receive a byte */
219
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) { ; }
220
221
  /* Return the byte read from the SPI bus */
222
  return (BYTE)SPI_I2S_ReceiveData(SPI2);
223
}
224
225
static
226
void rcvr_spi_m (BYTE *dst)
227
{
228
    *dst = xchg_spi(0xFF);
229
}
230
231
232
/*-----------------------------------------------------------------------*/
233
/* Wait for card ready                                                   */
234
/*-----------------------------------------------------------------------*/
235
236
static
237
int wait_ready (void)
238
{
239
        BYTE d;
240
  ULONG timeOutTime;
241
  
242
  /* set timeout for 500 ms from now */
243
  timeOutTime = TimerGet() + 500;
244
245
        do {
246
                d = xchg_spi(0xFF);
247
        } while ((d != 0xFF) && (TimerGet() < timeOutTime));
248
249
        return (d == 0xFF) ? 1 : 0;
250
}
251
252
253
/*-----------------------------------------------------------------------*/
254
/* Deselect the card and release SPI bus                                 */
255
/*-----------------------------------------------------------------------*/
256
257
static
258
void deselect (void)
259
{
260
        CS_HIGH();
261
        xchg_spi(0xFF);                /* Dummy clock (force DO hi-z for multiple slave SPI) */
262
}
263
264
265
266
/*-----------------------------------------------------------------------*/
267
/* Select the card and wait ready                                        */
268
/*-----------------------------------------------------------------------*/
269
270
static
271
int select (void)        /* 1:Successful, 0:Timeout */
272
{
273
        CS_LOW();
274
        xchg_spi(0xFF);                /* Dummy clock (force DO enabled) */
275
276
        if (wait_ready()) return 1;        /* OK */
277
        deselect();
278
        return 0;        /* Timeout */
279
}
280
281
282
283
/*-----------------------------------------------------------------------*/
284
/* Receive a data packet from MMC                                        */
285
/*-----------------------------------------------------------------------*/
286
287
static
288
int rcvr_datablock (        /* 1:OK, 0:Failed */
289
        BYTE *buff,                        /* Data buffer to store received data */
290
        UINT btr                        /* Byte count (must be multiple of 4) */
291
)
292
{
293
        BYTE token;
294
  ULONG timeOutTime;
295
296
  /* set timeout for 100 ms from now */
297
  timeOutTime = TimerGet() + 100;
298
299
        do {                                                        /* Wait for data packet in timeout of 100ms */
300
                token = xchg_spi(0xFF);
301
        } while ((token == 0xFF) && (TimerGet() < timeOutTime));
302
303
        if(token != 0xFE) return 0;                /* If not valid data token, retutn with error */
304
  
305
    do {                            /* Receive the data block into buffer */
306
        rcvr_spi_m(buff++);
307
        rcvr_spi_m(buff++);
308
    } while (btr -= 2);
309
        xchg_spi(0xFF);                                        /* Discard CRC */
310
        xchg_spi(0xFF);
311
312
        return 1;                                                /* Return with success */
313
}
314
315
316
317
/*-----------------------------------------------------------------------*/
318
/* Send a data packet to MMC                                             */
319
/*-----------------------------------------------------------------------*/
320
321
#if _USE_WRITE
322
static
323
int xmit_datablock (        /* 1:OK, 0:Failed */
324
        const BYTE *buff,        /* 512 byte data block to be transmitted */
325
        BYTE token                        /* Data token */
326
)
327
{
328
    BYTE resp;
329
    UINT wc;
330
331
332
        if (!wait_ready()) return 0;
333
334
        xchg_spi(token);                /* Xmit a token */
335
        if (token != 0xFD) {        /* Not StopTran token */
336
        wc = 512;
337
        do {                            /* Xmit the 512 byte data block to MMC */
338
            xchg_spi(*buff++);
339
            xchg_spi(*buff++);
340
        } while (wc -= 2);
341
                xchg_spi(0xFF);                                /* CRC (Dummy) */
342
                xchg_spi(0xFF);
343
                resp = xchg_spi(0xFF);                /* Receive a data response */
344
                if ((resp & 0x1F) != 0x05)        /* If not accepted, return with error */
345
                        return 0;
346
        }
347
348
        return 1;
349
}
350
#endif
351
352
353
354
/*-----------------------------------------------------------------------*/
355
/* Send a command packet to MMC                                          */
356
/*-----------------------------------------------------------------------*/
357
358
static
359
BYTE send_cmd (
360
        BYTE cmd,                /* Command byte */
361
        DWORD arg                /* Argument */
362
)
363
{
364
        BYTE n, res;
365
366
367
        if (cmd & 0x80) {        /* ACMD<n> is the command sequense of CMD55-CMD<n> */
368
                cmd &= 0x7F;
369
                res = send_cmd(CMD55, 0);
370
                if (res > 1) return res;
371
        }
372
373
        /* Select the card and wait for ready */
374
        deselect();
375
        if (!select()) return 0xFF;
376
377
        /* Send command packet */
378
        xchg_spi(0x40 | cmd);                        /* Start + Command index */
379
        xchg_spi((BYTE)(arg >> 24));        /* Argument[31..24] */
380
        xchg_spi((BYTE)(arg >> 16));        /* Argument[23..16] */
381
        xchg_spi((BYTE)(arg >> 8));                /* Argument[15..8] */
382
        xchg_spi((BYTE)arg);                        /* Argument[7..0] */
383
        n = 0x01;                                                /* Dummy CRC + Stop */
384
        if (cmd == CMD0) n = 0x95;                /* Valid CRC for CMD0(0) + Stop */
385
        if (cmd == CMD8) n = 0x87;                /* Valid CRC for CMD8(0x1AA) + Stop */
386
        xchg_spi(n);
387
388
        /* Receive command response */
389
        if (cmd == CMD12) xchg_spi(0xFF);        /* Skip a stuff byte on stop to read */
390
        n = 10;                                                        /* Wait for a valid response in timeout of 10 attempts */
391
        do
392
                res = xchg_spi(0xFF);
393
        while ((res & 0x80) && --n);
394
395
        return res;                        /* Return with the response value */
396
}
397
398
399
400
/*--------------------------------------------------------------------------
401

402
   Public Functions
403

404
---------------------------------------------------------------------------*/
405
406
407
/*-----------------------------------------------------------------------*/
408
/* Initialize Disk Drive                                                 */
409
/*-----------------------------------------------------------------------*/
410
411
DSTATUS disk_initialize (
412
        BYTE pdrv                /* Physical drive nmuber (0) */
413
)
414
{
415
        BYTE n, cmd, ty, ocr[4];
416
  ULONG timeOutTime;
417
418
419
        if (pdrv) return STA_NOINIT;                /* Supports only single drive */
420
        if (Stat & STA_NODISK) return Stat;        /* No card in the socket */
421
422
    power_on();                            /* Force socket power on */
423
424
     CS_LOW();                /* CS = L */
425
426
        ty = 0;
427
        if (send_cmd(CMD0, 0) == 1) {                        /* Enter Idle state */
428
    timeOutTime = TimerGet() + 1000; /* Initialization timeout of 1000 msec */
429
430
                if (send_cmd(CMD8, 0x1AA) == 1) {        /* SDv2? */
431
                        for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);                        /* Get trailing return value of R7 resp */
432
                        if (ocr[2] == 0x01 && ocr[3] == 0xAA) {                                /* The card can work at vdd range of 2.7-3.6V */
433
                                while ((TimerGet() < timeOutTime) && send_cmd(ACMD41, 0x40000000));        /* Wait for leaving idle state (ACMD41 with HCS bit) */
434
                                if ((TimerGet() < timeOutTime) && send_cmd(CMD58, 0) == 0) {                        /* Check CCS bit in the OCR */
435
                                        for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
436
                                        ty = (ocr[0] & 0x40) ? CT_SD2|CT_BLOCK : CT_SD2;        /* SDv2 */
437
                                }
438
                        }
439
                } else {                                                        /* SDv1 or MMCv3 */
440
                        if (send_cmd(ACMD41, 0) <= 1)         {
441
                                ty = CT_SD1; cmd = ACMD41;        /* SDv1 */
442
                        } else {
443
                                ty = CT_MMC; cmd = CMD1;        /* MMCv3 */
444
                        }
445
                        while ((TimerGet() < timeOutTime) && send_cmd(cmd, 0));                /* Wait for leaving idle state */
446
                        if (!(TimerGet() < timeOutTime) || send_cmd(CMD16, 512) != 0)        /* Set read/write block length to 512 */
447
                                ty = 0;
448
                }
449
        }
450
        CardType = ty;
451
        deselect();
452
453
        if (ty) {                        /* Initialization succeded */
454
                Stat &= ~STA_NOINIT;        /* Clear STA_NOINIT */
455
                FCLK_FAST();
456
        } else {                        /* Initialization failed */
457
                power_off();
458
        }
459
460
        return Stat;
461
}
462
463
464
465
/*-----------------------------------------------------------------------*/
466
/* Get Disk Status                                                       */
467
/*-----------------------------------------------------------------------*/
468
469
DSTATUS disk_status (
470
        BYTE pdrv                /* Physical drive nmuber (0) */
471
)
472
{
473
        if (pdrv) return STA_NOINIT;        /* Supports only single drive */
474
        return Stat;
475
}
476
477
478
479
/*-----------------------------------------------------------------------*/
480
/* Read Sector(s)                                                        */
481
/*-----------------------------------------------------------------------*/
482
483
DRESULT disk_read (
484
        BYTE pdrv,                /* Physical drive number (0) */
485
        BYTE *buff,                /* Pointer to the data buffer to store read data */
486
        DWORD sector,        /* Start sector number (LBA) */
487
        BYTE count                /* Sector count (1..255) */
488
)
489
{
490
        if (pdrv || !count) return RES_PARERR;
491
        if (Stat & STA_NOINIT) return RES_NOTRDY;
492
493
        if (!(CardType & CT_BLOCK)) sector *= 512;        /* Convert to byte address if needed */
494
495
        if (count == 1) {                /* Single block read */
496
                if ((send_cmd(CMD17, sector) == 0)        /* READ_SINGLE_BLOCK */
497
                        && rcvr_datablock(buff, 512))
498
                        count = 0;
499
        }
500
        else {                                /* Multiple block read */
501
                if (send_cmd(CMD18, sector) == 0) {        /* READ_MULTIPLE_BLOCK */
502
                        do {
503
                                if (!rcvr_datablock(buff, 512)) break;
504
                                buff += 512;
505
                        } while (--count);
506
                        send_cmd(CMD12, 0);                                /* STOP_TRANSMISSION */
507
                }
508
        }
509
        deselect();
510
511
        return count ? RES_ERROR : RES_OK;
512
}
513
514
515
516
/*-----------------------------------------------------------------------*/
517
/* Write Sector(s)                                                       */
518
/*-----------------------------------------------------------------------*/
519
520
#if _USE_WRITE
521
DRESULT disk_write (
522
        BYTE pdrv,                                /* Physical drive nmuber (0) */
523
        const BYTE *buff,                /* Pointer to the data to be written */
524
        DWORD sector,                        /* Start sector number (LBA) */
525
        BYTE count                                /* Sector count (1..255) */
526
)
527
{
528
        if (pdrv || !count) return RES_PARERR;
529
        if (Stat & STA_NOINIT) return RES_NOTRDY;
530
        if (Stat & STA_PROTECT) return RES_WRPRT;
531
532
        if (!(CardType & CT_BLOCK)) sector *= 512;        /* Convert to byte address if needed */
533
534
        if (count == 1) {                /* Single block write */
535
                if ((send_cmd(CMD24, sector) == 0)        /* WRITE_BLOCK */
536
                        && xmit_datablock(buff, 0xFE))
537
                        count = 0;
538
        }
539
        else {                                /* Multiple block write */
540
                if (CardType & CT_SDC) send_cmd(ACMD23, count);
541
                if (send_cmd(CMD25, sector) == 0) {        /* WRITE_MULTIPLE_BLOCK */
542
                        do {
543
                                if (!xmit_datablock(buff, 0xFC)) break;
544
                                buff += 512;
545
                        } while (--count);
546
                        if (!xmit_datablock(0, 0xFD))        /* STOP_TRAN token */
547
                                count = 1;
548
                }
549
        }
550
        deselect();
551
552
        return count ? RES_ERROR : RES_OK;
553
}
554
#endif
555
556
557
558
/*-----------------------------------------------------------------------*/
559
/* Miscellaneous Functions                                               */
560
/*-----------------------------------------------------------------------*/
561
562
#if _USE_IOCTL
563
DRESULT disk_ioctl (
564
        BYTE pdrv,                /* Physical drive nmuber (0) */
565
        BYTE cmd,                /* Control code */
566
        void *buff                /* Buffer to send/receive data block */
567
)
568
{
569
        DRESULT res;
570
        BYTE n, csd[16], *ptr = buff;
571
        DWORD csz;
572
573
574
        if (pdrv) return RES_PARERR;
575
        if (Stat & STA_NOINIT) return RES_NOTRDY;
576
577
        res = RES_ERROR;
578
        switch (cmd) {
579
        case CTRL_SYNC :        /* Flush write-back cache, Wait for end of internal process */
580
                if (select()) res = RES_OK;
581
                break;
582
583
        case GET_SECTOR_COUNT :        /* Get number of sectors on the disk (WORD) */
584
                if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
585
                        if ((csd[0] >> 6) == 1) {        /* SDv2? */
586
                                csz = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
587
                                *(DWORD*)buff = csz << 10;
588
                        } else {                                        /* SDv1 or MMCv3 */
589
                                n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
590
                                csz = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
591
                                *(DWORD*)buff = csz << (n - 9);
592
                        }
593
                        res = RES_OK;
594
                }
595
                break;
596
597
        case GET_BLOCK_SIZE :        /* Get erase block size in unit of sectors (DWORD) */
598
                if (CardType & CT_SD2) {        /* SDv2? */
599
                        if (send_cmd(ACMD13, 0) == 0) {                /* Read SD status */
600
                                xchg_spi(0xFF);
601
                                if (rcvr_datablock(csd, 16)) {                                /* Read partial block */
602
                                        for (n = 64 - 16; n; n--) xchg_spi(0xFF);        /* Purge trailing data */
603
                                        *(DWORD*)buff = 16UL << (csd[10] >> 4);
604
                                        res = RES_OK;
605
                                }
606
                        }
607
                } else {                                        /* SDv1 or MMCv3 */
608
                        if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {        /* Read CSD */
609
                                if (CardType & CT_SD1) {        /* SDv1 */
610
                                        *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
611
                                } else {                                        /* MMCv3 */
612
                                        *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
613
                                }
614
                                res = RES_OK;
615
                        }
616
                }
617
                break;
618
619
        case MMC_GET_TYPE :                /* Get card type flags (1 byte) */
620
                *ptr = CardType;
621
                res = RES_OK;
622
                break;
623
624
        case MMC_GET_CSD :        /* Receive CSD as a data block (16 bytes) */
625
                if ((send_cmd(CMD9, 0) == 0)        /* READ_CSD */
626
                        && rcvr_datablock(buff, 16))
627
                        res = RES_OK;
628
                break;
629
630
        case MMC_GET_CID :        /* Receive CID as a data block (16 bytes) */
631
                if ((send_cmd(CMD10, 0) == 0)        /* READ_CID */
632
                        && rcvr_datablock(buff, 16))
633
                        res = RES_OK;
634
                break;
635
636
        case MMC_GET_OCR :        /* Receive OCR as an R3 resp (4 bytes) */
637
                if (send_cmd(CMD58, 0) == 0) {        /* READ_OCR */
638
                        for (n = 0; n < 4; n++)
639
                                *((BYTE*)buff+n) = xchg_spi(0xFF);
640
                        res = RES_OK;
641
                }
642
                break;
643
644
        case MMC_GET_SDSTAT :        /* Receive SD status as a data block (64 bytes) */
645
                if ((CardType & CT_SD2) && send_cmd(ACMD13, 0) == 0) {        /* SD_STATUS */
646
                        xchg_spi(0xFF);
647
                        if (rcvr_datablock(buff, 64))
648
                                res = RES_OK;
649
                }
650
                break;
651
652
        default:
653
                res = RES_PARERR;
654
        }
655
656
        deselect();
657
658
        return res;
659
}
660
#endif
661
662
663
/*---------------------------------------------------------*/
664
/* User Provided Timer Function for FatFs module           */
665
/*---------------------------------------------------------*/
666
/* This is a real time clock service to be called from     */
667
/* FatFs module. Any valid time must be returned even if   */
668
/* the system does not support a real time clock.          */
669
/* This is not required in read-only configuration.        */
670
671
DWORD get_fattime (void)
672
{
673
  /* No RTC supprt. Return a fixed value 2013/5/10 0:00:00 */
674
  return    ((DWORD)(2013 - 1980) << 25)  /* Y */
675
      | ((DWORD)5  << 21)       /* M */
676
      | ((DWORD)10 << 16)       /* D */
677
      | ((DWORD)0  << 11)       /* H */
678
      | ((DWORD)0  << 5)        /* M */
679
      | ((DWORD)0  >> 1);       /* S */
680
}
681
682
683