OpenCores
URL https://opencores.org/ocsvn/ion/ion/trunk

Subversion Repositories ion

[/] [ion/] [trunk/] [src/] [common/] [fatfs/] [mmcbb.c] - Blame information for rev 247

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 243 ja_rd
/*------------------------------------------------------------------------/
2
/  Bitbanging MMCv3/SDv1/SDv2 (in SPI mode) control module
3
/-------------------------------------------------------------------------/
4
/
5
/  Copyright (C) 2012, 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
 Features and Limitations:
14
 
15
 * Very Easy to Port
16
   It uses only 4 bit of GPIO port. No interrupt, no SPI port is used.
17
 
18
 * Platform Independent
19
   You need to modify only a few macros to control GPIO ports.
20
 
21
 * Low Speed
22
   The data transfer rate will be several times slower than hardware SPI.
23
 
24
/-------------------------------------------------------------------------*/
25
 
26
 
27
#include "diskio.h"             /* Common include file for FatFs and disk I/O layer */
28
 
29
 
30
/*-------------------------------------------------------------------------*/
31
/* Platform dependent macros and functions needed to be modified           */
32
/*-------------------------------------------------------------------------*/
33
 
34
void dly_us(unsigned n);
35
 
36
#include "../libsoc/src/hw.h"
37
 
38
 
39
#define SDPO        *((volatile unsigned int *)GPIO_P0)
40
#define SDPI        *((volatile unsigned int *)GPIO_P1)
41
 
42
/* Initialize MMC control port (CS=H, CLK=L, DI=H, DO=in) */
43
#define INIT_PORT()     SDPO = 0x05
44
#define DLY_US(n)       dly_us(n)       /* Delay n microseconds */
45
 
46
 
47
#define CS_H()          SDPO |= 0x00000001      /* Set MMC CS "high" */
48
#define CS_L()          SDPO &= 0xFFFFFFFE      /* Set MMC CS "low" */
49
#define CK_H()          SDPO |= 0x00000002      /* Set MMC SCLK "high" */
50
#define CK_L()          SDPO &= 0xFFFFFFFD      /* Set MMC SCLK "low" */
51
#define DI_H()          SDPO |= 0x00000004      /* Set MMC DI "high" */
52
#define DI_L()          SDPO &= 0xFFFFFFFB      /* Set MMC DI "low" */
53
#define DO                      (SDPI & 0x00000001)     /* Test for MMC DO ('H':true) */
54
 
55
 
56
 
57
/*--------------------------------------------------------------------------
58
 
59
   Module Private Functions
60
 
61
---------------------------------------------------------------------------*/
62
 
63
/* MMC/SD command (SPI mode) */
64
#define CMD0    (0)                     /* GO_IDLE_STATE */
65
#define CMD1    (1)                     /* SEND_OP_COND */
66
#define ACMD41  (0x80+41)       /* SEND_OP_COND (SDC) */
67
#define CMD8    (8)                     /* SEND_IF_COND */
68
#define CMD9    (9)                     /* SEND_CSD */
69
#define CMD10   (10)            /* SEND_CID */
70
#define CMD12   (12)            /* STOP_TRANSMISSION */
71
#define CMD13   (13)            /* SEND_STATUS */
72
#define ACMD13  (0x80+13)       /* SD_STATUS (SDC) */
73
#define CMD16   (16)            /* SET_BLOCKLEN */
74
#define CMD17   (17)            /* READ_SINGLE_BLOCK */
75
#define CMD18   (18)            /* READ_MULTIPLE_BLOCK */
76
#define CMD23   (23)            /* SET_BLOCK_COUNT */
77
#define ACMD23  (0x80+23)       /* SET_WR_BLK_ERASE_COUNT (SDC) */
78
#define CMD24   (24)            /* WRITE_BLOCK */
79
#define CMD25   (25)            /* WRITE_MULTIPLE_BLOCK */
80
#define CMD41   (41)            /* SEND_OP_COND (ACMD) */
81
#define CMD55   (55)            /* APP_CMD */
82
#define CMD58   (58)            /* READ_OCR */
83
 
84
/* Card type flags (CardType) */
85
#define CT_MMC          0x01            /* MMC ver 3 */
86
#define CT_SD1          0x02            /* SD ver 1 */
87
#define CT_SD2          0x04            /* SD ver 2 */
88
#define CT_SDC          0x06            /* SD */
89
#define CT_BLOCK        0x08            /* Block addressing */
90
 
91
 
92
static
93
DSTATUS Stat = STA_NOINIT;      /* Disk status */
94
 
95
static
96
BYTE CardType;                  /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */
97
 
98
 
99
 
100
/*-----------------------------------------------------------------------*/
101
/* Transmit bytes to the card (bitbanging)                               */
102
/*-----------------------------------------------------------------------*/
103
 
104
static
105
void xmit_mmc (
106
        const BYTE* buff,       /* Data to be sent */
107
        UINT bc                         /* Number of bytes to send */
108
)
109
{
110
        BYTE d;
111
 
112
 
113
        do {
114
                d = *buff++;    /* Get a byte to be sent */
115
                if (d & 0x80) DI_H(); else DI_L();      /* bit7 */
116
                CK_H(); CK_L();
117
                if (d & 0x40) DI_H(); else DI_L();      /* bit6 */
118
                CK_H(); CK_L();
119
                if (d & 0x20) DI_H(); else DI_L();      /* bit5 */
120
                CK_H(); CK_L();
121
                if (d & 0x10) DI_H(); else DI_L();      /* bit4 */
122
                CK_H(); CK_L();
123
                if (d & 0x08) DI_H(); else DI_L();      /* bit3 */
124
                CK_H(); CK_L();
125
                if (d & 0x04) DI_H(); else DI_L();      /* bit2 */
126
                CK_H(); CK_L();
127
                if (d & 0x02) DI_H(); else DI_L();      /* bit1 */
128
                CK_H(); CK_L();
129
                if (d & 0x01) DI_H(); else DI_L();      /* bit0 */
130
                CK_H(); CK_L();
131
        } while (--bc);
132
}
133
 
134
 
135
 
136
/*-----------------------------------------------------------------------*/
137
/* Receive bytes from the card (bitbanging)                              */
138
/*-----------------------------------------------------------------------*/
139
 
140
static
141
void rcvr_mmc (
142
        BYTE *buff,     /* Pointer to read buffer */
143
        UINT bc         /* Number of bytes to receive */
144
)
145
{
146
        BYTE r;
147
 
148
 
149
        DI_H(); /* Send 0xFF */
150
 
151
        do {
152
                r = 0;    if (DO) r++;   /* bit7 */
153
                CK_H(); CK_L();
154
                r <<= 1; if (DO) r++;   /* bit6 */
155
                CK_H(); CK_L();
156
                r <<= 1; if (DO) r++;   /* bit5 */
157
                CK_H(); CK_L();
158
                r <<= 1; if (DO) r++;   /* bit4 */
159
                CK_H(); CK_L();
160
                r <<= 1; if (DO) r++;   /* bit3 */
161
                CK_H(); CK_L();
162
                r <<= 1; if (DO) r++;   /* bit2 */
163
                CK_H(); CK_L();
164
                r <<= 1; if (DO) r++;   /* bit1 */
165
                CK_H(); CK_L();
166
                r <<= 1; if (DO) r++;   /* bit0 */
167
                CK_H(); CK_L();
168
                *buff++ = r;                    /* Store a received byte */
169
        } while (--bc);
170
}
171
 
172
 
173
 
174
/*-----------------------------------------------------------------------*/
175
/* Wait for card ready                                                   */
176
/*-----------------------------------------------------------------------*/
177
 
178
static
179
int wait_ready (void)   /* 1:OK, 0:Timeout */
180
{
181
        BYTE d;
182
        UINT tmr;
183
 
184
 
185
        for (tmr = 5000; tmr; tmr--) {  /* Wait for ready in timeout of 500ms */
186
                rcvr_mmc(&d, 1);
187
                if (d == 0xFF) break;
188
                DLY_US(100);
189
        }
190
 
191
        return tmr ? 1 : 0;
192
}
193
 
194
 
195
 
196
/*-----------------------------------------------------------------------*/
197
/* Deselect the card and release SPI bus                                 */
198
/*-----------------------------------------------------------------------*/
199
 
200
static
201
void deselect (void)
202
{
203
        BYTE d;
204
 
205
        CS_H();
206
        rcvr_mmc(&d, 1);        /* Dummy clock (force DO hi-z for multiple slave SPI) */
207
}
208
 
209
 
210
 
211
/*-----------------------------------------------------------------------*/
212
/* Select the card and wait for ready                                    */
213
/*-----------------------------------------------------------------------*/
214
 
215
static
216
int select (void)       /* 1:OK, 0:Timeout */
217
{
218
        BYTE d;
219
 
220
        CS_L();
221
        rcvr_mmc(&d, 1);        /* Dummy clock (force DO enabled) */
222
 
223
        if (wait_ready()) return 1;     /* OK */
224
        deselect();
225
        return 0;                        /* Failed */
226
}
227
 
228
 
229
 
230
/*-----------------------------------------------------------------------*/
231
/* Receive a data packet from the card                                   */
232
/*-----------------------------------------------------------------------*/
233
 
234
static
235
int rcvr_datablock (    /* 1:OK, 0:Failed */
236
        BYTE *buff,                     /* Data buffer to store received data */
237
        UINT btr                        /* Byte count */
238
)
239
{
240
        BYTE d[2];
241
        UINT tmr;
242
 
243
 
244
        for (tmr = 1000; tmr; tmr--) {  /* Wait for data packet in timeout of 100ms */
245
                rcvr_mmc(d, 1);
246
                if (d[0] != 0xFF) break;
247
                DLY_US(100);
248
        }
249
        if (d[0] != 0xFE) return 0;               /* If not valid data token, return with error */
250
 
251
        rcvr_mmc(buff, btr);                    /* Receive the data block into buffer */
252
        rcvr_mmc(d, 2);                                 /* Discard CRC */
253
 
254
        return 1;                                               /* Return with success */
255
}
256
 
257
 
258
 
259
/*-----------------------------------------------------------------------*/
260
/* Send a data packet to the card                                        */
261
/*-----------------------------------------------------------------------*/
262
 
263
static
264
int xmit_datablock (    /* 1:OK, 0:Failed */
265
        const BYTE *buff,       /* 512 byte data block to be transmitted */
266
        BYTE token                      /* Data/Stop token */
267
)
268
{
269
        BYTE d[2];
270
 
271
 
272
        if (!wait_ready()) return 0;
273
 
274
        d[0] = token;
275
        xmit_mmc(d, 1);                         /* Xmit a token */
276
        if (token != 0xFD) {            /* Is it data token? */
277
                xmit_mmc(buff, 512);    /* Xmit the 512 byte data block to MMC */
278
                rcvr_mmc(d, 2);                 /* Xmit dummy CRC (0xFF,0xFF) */
279
                rcvr_mmc(d, 1);                 /* Receive data response */
280
                if ((d[0] & 0x1F) != 0x05)       /* If not accepted, return with error */
281
                        return 0;
282
        }
283
 
284
        return 1;
285
}
286
 
287
 
288
 
289
/*-----------------------------------------------------------------------*/
290
/* Send a command packet to the card                                     */
291
/*-----------------------------------------------------------------------*/
292
 
293
static
294
BYTE send_cmd (         /* Returns command response (bit7==1:Send failed)*/
295
        BYTE cmd,               /* Command byte */
296
        DWORD arg               /* Argument */
297
)
298
{
299
        BYTE n, d, buf[6];
300
 
301
 
302
        if (cmd & 0x80) {       /* ACMD<n> is the command sequense of CMD55-CMD<n> */
303
                cmd &= 0x7F;
304
                n = send_cmd(CMD55, 0);
305
                if (n > 1) return n;
306
        }
307
 
308
        /* Select the card and wait for ready */
309
        deselect();
310
        if (!select()) return 0xFF;
311
 
312
        /* Send a command packet */
313
        buf[0] = 0x40 | cmd;                     /* Start + Command index */
314
        buf[1] = (BYTE)(arg >> 24);             /* Argument[31..24] */
315
        buf[2] = (BYTE)(arg >> 16);             /* Argument[23..16] */
316
        buf[3] = (BYTE)(arg >> 8);              /* Argument[15..8] */
317
        buf[4] = (BYTE)arg;                             /* Argument[7..0] */
318
        n = 0x01;                                               /* Dummy CRC + Stop */
319
        if (cmd == CMD0) n = 0x95;              /* (valid CRC for CMD0(0)) */
320
        if (cmd == CMD8) n = 0x87;              /* (valid CRC for CMD8(0x1AA)) */
321
        buf[5] = n;
322
        xmit_mmc(buf, 6);
323
 
324
        /* Receive command response */
325
        if (cmd == CMD12) rcvr_mmc(&d, 1);      /* Skip a stuff byte when stop reading */
326
        n = 10;                                                         /* Wait for a valid response in timeout of 10 attempts */
327
        do
328
                rcvr_mmc(&d, 1);
329
        while ((d & 0x80) && --n);
330
 
331
        return d;                       /* Return with the response value */
332
}
333
 
334
 
335
 
336
/*--------------------------------------------------------------------------
337
 
338
   Public Functions
339
 
340
---------------------------------------------------------------------------*/
341
 
342
 
343
/*-----------------------------------------------------------------------*/
344
/* Get Disk Status                                                       */
345
/*-----------------------------------------------------------------------*/
346
 
347
DSTATUS disk_status (
348
        BYTE drv                        /* Drive number (always 0) */
349
)
350
{
351
        DSTATUS s;
352
        BYTE d;
353
 
354
 
355
        if (drv) return STA_NOINIT;
356
 
357
        /* Check if the card is kept initialized */
358
        s = Stat;
359
        if (!(s & STA_NOINIT)) {
360
                if (send_cmd(CMD13, 0))  /* Read card status */
361
                        s = STA_NOINIT;
362
                rcvr_mmc(&d, 1);                /* Receive following half of R2 */
363
                deselect();
364
        }
365
        Stat = s;
366
 
367
        return s;
368
}
369
 
370
 
371
 
372
/*-----------------------------------------------------------------------*/
373
/* Initialize Disk Drive                                                 */
374
/*-----------------------------------------------------------------------*/
375
 
376
DSTATUS disk_initialize (
377
        BYTE drv                /* Physical drive nmuber (0) */
378
)
379
{
380
        BYTE n, ty, cmd, buf[4];
381
        UINT tmr;
382
        DSTATUS s;
383
 
384
 
385
        if (drv) return RES_NOTRDY;
386
 
387
        INIT_PORT();                            /* Initialize control port */
388
        for (n = 10; n; n--) rcvr_mmc(buf, 1);  /* 80 dummy clocks */
389
 
390
        ty = 0;
391
        if (send_cmd(CMD0, 0) == 1) {                    /* Enter Idle state */
392
                if (send_cmd(CMD8, 0x1AA) == 1) {       /* SDv2? */
393
                        rcvr_mmc(buf, 4);                                                       /* Get trailing return value of R7 resp */
394
                        if (buf[2] == 0x01 && buf[3] == 0xAA) {         /* The card can work at vdd range of 2.7-3.6V */
395
                                for (tmr = 1000; tmr; tmr--) {                  /* Wait for leaving idle state (ACMD41 with HCS bit) */
396
                                        if (send_cmd(ACMD41, 1UL << 30) == 0) break;
397
                                        DLY_US(1000);
398
                                }
399
                                if (tmr && send_cmd(CMD58, 0) == 0) {     /* Check CCS bit in the OCR */
400
                                        rcvr_mmc(buf, 4);
401
                                        ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;       /* SDv2 */
402
                                }
403
                        }
404
                } else {                                                        /* SDv1 or MMCv3 */
405
                        if (send_cmd(ACMD41, 0) <= 1)    {
406
                                ty = CT_SD1; cmd = ACMD41;      /* SDv1 */
407
                        } else {
408
                                ty = CT_MMC; cmd = CMD1;        /* MMCv3 */
409
                        }
410
                        for (tmr = 1000; tmr; tmr--) {                  /* Wait for leaving idle state */
411
                                if (send_cmd(cmd, 0) == 0) break;
412
                                DLY_US(1000);
413
                        }
414
                        if (!tmr || send_cmd(CMD16, 512) != 0)   /* Set R/W block length to 512 */
415
                                ty = 0;
416
                }
417
        }
418
        CardType = ty;
419
        s = ty ? 0 : STA_NOINIT;
420
        Stat = s;
421
 
422
        deselect();
423
 
424
        return s;
425
}
426
 
427
 
428
 
429
/*-----------------------------------------------------------------------*/
430
/* Read Sector(s)                                                        */
431
/*-----------------------------------------------------------------------*/
432
 
433
DRESULT disk_read (
434
        BYTE drv,                       /* Physical drive nmuber (0) */
435
        BYTE *buff,                     /* Pointer to the data buffer to store read data */
436
        DWORD sector,           /* Start sector number (LBA) */
437
        BYTE count                      /* Sector count (1..128) */
438
)
439
{
440
        if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;
441
        if (!count) return RES_PARERR;
442
        if (!(CardType & CT_BLOCK)) sector *= 512;      /* Convert LBA to byte address if needed */
443
 
444
        if (count == 1) {       /* Single block read */
445
                if ((send_cmd(CMD17, sector) == 0)       /* READ_SINGLE_BLOCK */
446
                        && rcvr_datablock(buff, 512))
447
                        count = 0;
448
        }
449
        else {                          /* Multiple block read */
450
                if (send_cmd(CMD18, sector) == 0) {      /* READ_MULTIPLE_BLOCK */
451
                        do {
452
                                if (!rcvr_datablock(buff, 512)) break;
453
                                buff += 512;
454
                        } while (--count);
455
                        send_cmd(CMD12, 0);                              /* STOP_TRANSMISSION */
456
                }
457
        }
458
        deselect();
459
 
460
        return count ? RES_ERROR : RES_OK;
461
}
462
 
463
 
464
 
465
/*-----------------------------------------------------------------------*/
466
/* Write Sector(s)                                                       */
467
/*-----------------------------------------------------------------------*/
468
 
469
DRESULT disk_write (
470
        BYTE drv,                       /* Physical drive nmuber (0) */
471
        const BYTE *buff,       /* Pointer to the data to be written */
472
        DWORD sector,           /* Start sector number (LBA) */
473
        BYTE count                      /* Sector count (1..128) */
474
)
475
{
476
        if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;
477
        if (!count) return RES_PARERR;
478
        if (!(CardType & CT_BLOCK)) sector *= 512;      /* Convert LBA to byte address if needed */
479
 
480
        if (count == 1) {       /* Single block write */
481
                if ((send_cmd(CMD24, sector) == 0)       /* WRITE_BLOCK */
482
                        && xmit_datablock(buff, 0xFE))
483
                        count = 0;
484
        }
485
        else {                          /* Multiple block write */
486
                if (CardType & CT_SDC) send_cmd(ACMD23, count);
487
                if (send_cmd(CMD25, sector) == 0) {      /* WRITE_MULTIPLE_BLOCK */
488
                        do {
489
                                if (!xmit_datablock(buff, 0xFC)) break;
490
                                buff += 512;
491
                        } while (--count);
492
                        if (!xmit_datablock(0, 0xFD))    /* STOP_TRAN token */
493
                                count = 1;
494
                }
495
        }
496
        deselect();
497
 
498
        return count ? RES_ERROR : RES_OK;
499
}
500
 
501
 
502
 
503
/*-----------------------------------------------------------------------*/
504
/* Miscellaneous Functions                                               */
505
/*-----------------------------------------------------------------------*/
506
 
507
DRESULT disk_ioctl (
508
        BYTE drv,               /* Physical drive nmuber (0) */
509
        BYTE ctrl,              /* Control code */
510
        void *buff              /* Buffer to send/receive control data */
511
)
512
{
513
        DRESULT res;
514
        BYTE n, csd[16];
515
        DWORD cs;
516
 
517
 
518
        if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;   /* Check if card is in the socket */
519
 
520
        res = RES_ERROR;
521
        switch (ctrl) {
522
                case CTRL_SYNC :                /* Make sure that no pending write process */
523
                        if (select()) {
524
                                deselect();
525
                                res = RES_OK;
526
                        }
527
                        break;
528
 
529
                case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
530
                        if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
531
                                if ((csd[0] >> 6) == 1) {        /* SDC ver 2.00 */
532
                                        cs = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 8) + 1;
533
                                        *(DWORD*)buff = cs << 10;
534
                                } else {                                        /* SDC ver 1.XX or MMC */
535
                                        n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
536
                                        cs = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
537
                                        *(DWORD*)buff = cs << (n - 9);
538
                                }
539
                                res = RES_OK;
540
                        }
541
                        break;
542
 
543
                case GET_BLOCK_SIZE :   /* Get erase block size in unit of sector (DWORD) */
544
                        *(DWORD*)buff = 128;
545
                        res = RES_OK;
546
                        break;
547
 
548
                default:
549
                        res = RES_PARERR;
550
        }
551
 
552
        deselect();
553
 
554
        return res;
555
}
556
 
557
 
558
 
559
void dly_us(unsigned n){
560
    volatile unsigned i;
561
    volatile static unsigned j = 0;
562
 
563
    for(i=0;i<40*n;i++){
564
        j = i + 7;
565
    }
566
}
567
 
568
 
569
 
570
/*-----------------------------------------------------------------------*/
571
/* This function is defined for only project compatibility               */
572
 
573
void disk_timerproc (void)
574
{
575
        /* Nothing to do */
576
}
577
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.