source: asp3_tinet_ecnl_rx/trunk/ntshell/fatfs/mmc_rspi.c@ 343

Last change on this file since 343 was 343, checked in by coas-nagasima, 6 years ago

SDカードがなくても起動するよう修正

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 22.0 KB
Line 
1/*------------------------------------------------------------------------*/
2/* FRK-RX62N: MMCv3/SDv1/SDv2 (SPI mode) Control Module */
3/*------------------------------------------------------------------------*/
4/*
5/ Copyright (C) 2014, 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#include <kernel.h> /* Platform dependent include file */
15#include "diskio.h" /* Common include file for ff.c and disk layer */
16#include <sil.h>
17#include <prc_rename.h>
18#include "target_kernel_impl.h"
19#include "mmc_rspi.h"
20#include "kernel_cfg.h"
21#include <t_syslog.h>
22#include <string.h>
23
24static void CS_LOW()
25{
26 sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) & ~PORT_PODR_B0_BIT); /* Set CS# low */
27}
28
29static void CS_HIGH()
30{
31 sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) | PORT_PODR_B0_BIT); /* Set CS# high */
32}
33
34static bool_t WP()
35{
36 return false;
37}
38
39static bool_t INS()
40{
41 return (sil_reb_mem(PORT1_PIDR_ADDR) & PORT_PIDR_B5_BIT) == 0;
42}
43
44static void CTRL_INIT()
45{
46 /* CS=OUT */
47 sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B0_BIT);
48 /* INS=IN */
49 sil_wrb_mem(PORT1_PDR_ADDR, sil_reb_mem(PORT1_PDR_ADDR) & ~PORT_PDR_B5_BIT);
50 /* SPICLK,SPIMOSI=OUT */
51 sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B5_BIT | PORT_PDR_B6_BIT);
52 /* CS,SPICLK,SPIMOSI=HI */
53 sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) | PORT_PODR_B0_BIT | PORT_PDR_B5_BIT | PORT_PDR_B6_BIT);
54 /* SPIMISO=IN */
55 sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) & ~PORT_PDR_B7_BIT);
56 /* SPIMISO=PULLUP */
57 sil_wrb_mem(PORTC_PCR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B7_BIT);
58 /* CMOSを選択 */
59 sil_wrb_mem(PORTC_ODR0_ADDR, 0x00);
60 /* CMOSを選択 */
61 sil_wrb_mem(PORTC_ODR1_ADDR, 0x00);
62}
63
64#define F_PCLK 48000000UL /* PCLK frequency (configured by SCKCR.PCK) */
65#define SCLK_FAST 24000000UL /* SCLK frequency (R/W) */
66#define SCLK_SLOW 375000UL /* SCLK frequency (Init) */
67
68static void RSPI_ATTACH()
69{
70 /*
71 * モジュールストップ機能の設定(RSPI0)
72 */
73 sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* 書込み許可 */
74 sil_wrw_mem(SYSTEM_MSTPCRB_ADDR,
75 sil_rew_mem(SYSTEM_MSTPCRB_ADDR) & ~SYSTEM_MSTPCRB_MSTPB17_BIT);
76 sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* 書込み禁止 */
77
78 /* P15をGPIOとして使用 */
79 sil_wrb_mem(PORT1_PMR_ADDR,
80 sil_reb_mem(PORT1_PMR_ADDR) & ~PORT_PMR_B5_BIT);
81 /* PC0をGPIOとして使用 */
82 sil_wrb_mem(PORTC_PMR_ADDR,
83 sil_reb_mem(PORTC_PMR_ADDR) & ~PORT_PMR_B0_BIT);
84 /* PC5, PC6, PC7を周辺機能として使用 */
85 sil_wrb_mem(PORTC_PMR_ADDR,
86 sil_reb_mem(PORTC_PMR_ADDR) | PORT_PMR_B5_BIT | PORT_PMR_B6_BIT | PORT_PMR_B7_BIT);
87
88 /* 書き込みプロテクトレジスタの設定 PFSWEビットへの書き込みを許可 */
89 sil_wrb_mem(MPC_PWPR_ADDR, 0x00);
90 /* 書き込みプロテクトレジスタの設定 PxxFSレジスタへの書き込みを許可 */
91 sil_wrb_mem(MPC_PWPR_ADDR, 0x40);
92
93 /* RSPCKAを選択 */
94 sil_wrb_mem(MPC_PC5PFS_ADDR, 0x0d);
95 /* MOSIAを選択 */
96 sil_wrb_mem(MPC_PC6PFS_ADDR, 0x0d);
97 /* MISOAを選択 */
98 sil_wrb_mem(MPC_PC7PFS_ADDR, 0x0d);
99
100 /* 書き込みプロテクトレジスタの設定 書き込みを禁止 */
101 sil_wrb_mem(MPC_PWPR_ADDR, 0x80);
102}
103
104static void FCLK_FAST()
105{
106 /* RSPI機能を無効化 */
107 sil_wrb_mem(RSPI0_SPCR_ADDR,
108 sil_reb_mem(RSPI0_SPCR_ADDR) & ~RSPI_SPCR_SPE_BIT);
109 /* ビットレート設定 */
110 sil_wrb_mem(RSPI0_SPBR_ADDR, F_PCLK / 2 / SCLK_FAST - 1);
111 /* RSPI機能を有効化 */
112 sil_wrb_mem(RSPI0_SPCR_ADDR,
113 sil_reb_mem(RSPI0_SPCR_ADDR) | RSPI_SPCR_SPE_BIT);
114}
115
116#ifdef SIL_ENDIAN_LITTLE
117#define LDDW(x) rev_endian_uint32(x) /* Little endian: swap bytes */
118#else
119#define LDDW(x) x /* Big endian: no swap */
120#endif
121
122
123
124/*--------------------------------------------------------------------------
125
126 Module Private Functions
127
128---------------------------------------------------------------------------*/
129
130/* MMC/SD command */
131#define CMD0 (0) /* GO_IDLE_STATE */
132#define CMD1 (1) /* SEND_OP_COND (MMC) */
133#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
134#define CMD8 (8) /* SEND_IF_COND */
135#define CMD9 (9) /* SEND_CSD */
136#define CMD10 (10) /* SEND_CID */
137#define CMD12 (12) /* STOP_TRANSMISSION */
138#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
139#define CMD16 (16) /* SET_BLOCKLEN */
140#define CMD17 (17) /* READ_SINGLE_BLOCK */
141#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
142#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
143#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
144#define CMD24 (24) /* WRITE_BLOCK */
145#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
146#define CMD32 (32) /* ERASE_ER_BLK_START */
147#define CMD33 (33) /* ERASE_ER_BLK_END */
148#define CMD38 (38) /* ERASE */
149#define CMD55 (55) /* APP_CMD */
150#define CMD58 (58) /* READ_OCR */
151
152
153
154static volatile
155DSTATUS Stat = STA_NOINIT; /* Physical drive status */
156
157static volatile
158WORD Timer1, Timer2; /* 1000Hz decrement timer stopped at zero (driven by disk_timerproc()) */
159
160static
161BYTE CardType; /* Card type flags */
162
163static
164BYTE CSD[16], CID[16];
165
166static
167uint64_t CardCapacity;
168
169static
170uint32_t CardBlockSize;
171
172/*-----------------------------------------------------------------------*/
173/* Control SPI module */
174/*-----------------------------------------------------------------------*/
175/* Only these five functions are platform dependent. Any other functions */
176/* are portable to different system. */
177
178/*---------------------------------*/
179/* Enable SPI and MMC/SDC controls */
180/*---------------------------------*/
181static
182void power_on(void)
183{
184 /* Initialize CS/INS/WP port */
185 CTRL_INIT();
186
187 /* Attach RSPI0 module to I/O pads, disable module stop */
188 RSPI_ATTACH();
189
190 /* Initialize RSPI module */
191 sil_wrb_mem(RSPI0_SPCR_ADDR, 0); /* Stop RSPI module */
192 sil_wrb_mem(RSPI0_SPPCR_ADDR, 0); /* Fixed idle value, disable loop-back mode */
193 sil_wrb_mem(RSPI0_SPSCR_ADDR, 0); /* Disable sequence control */
194 sil_wrb_mem(RSPI0_SPDCR_ADDR, 0x20); /* SPLW=1 */
195 sil_wrh_mem(RSPI0_SPCMD0_ADDR, 0x0700); /* LSBF=0, SPB=7, BRDV=0, CPOL=0, CPHA=0 */
196 sil_wrb_mem(RSPI0_SPBR_ADDR, F_PCLK / 2 / SCLK_SLOW - 1); /* Bit rate */
197 sil_wrb_mem(RSPI0_SPCR_ADDR, 0xC9); /* Start RSPI in master mode */
198
199 ena_int(INTNO_MMC_RSPI_SPRI);
200 ena_int(INTNO_MMC_RSPI_SPTI);
201 ena_int(INTNO_MMC_RSPI_SPII);
202
203 sta_cyc(MMC_RSPI_CYC);
204}
205
206
207/*---------------------*/
208/* Disable SPI */
209/*---------------------*/
210static
211void power_off(void) /* Disable MMC/SDC interface */
212{
213 stp_cyc(MMC_RSPI_CYC);
214
215 dis_int(INTNO_MMC_RSPI_SPRI);
216 dis_int(INTNO_MMC_RSPI_SPTI);
217 dis_int(INTNO_MMC_RSPI_SPII);
218
219 sil_wrb_mem(RSPI0_SPCR_ADDR, 0); /* Stop RSPI module */
220}
221
222
223/*---------------------*/
224/* Send/Receive a byte */
225/*---------------------*/
226static
227BYTE xchg_spi(
228 BYTE dat /* Data to send */
229 )
230{
231 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
232 sil_wrw_mem(RSPI0_SPDR_ADDR, dat); /* Start transmission (lower 8bits) */
233 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
234 if (twai_sem(MMC_RSPI_SEMAPHORE, 1000) != E_OK)
235 return 0;
236 return sil_rew_mem(RSPI0_SPDR_ADDR); /* Returen received byte (lower 8bits) */
237}
238
239
240/*---------------------*/
241/* Send multiple bytes */
242/*---------------------*/
243static
244void xmit_spi_multi(
245 const BYTE *buff, /* Pointer to the data */
246 UINT btx /* Number of bytes to send (multiple of 4) */
247 )
248{
249 const DWORD *lp = (const DWORD*)buff;
250
251 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
252 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (3 << RSPI_SPCMD_SPB_OFFSET)); /* Set 32-bit mode */
253
254 do {
255 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
256 sil_wrw_mem(RSPI0_SPDR_ADDR, LDDW(*lp++)); /* Send four data bytes */
257 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
258 wai_sem(MMC_RSPI_SEMAPHORE);
259 sil_rew_mem(RSPI0_SPDR_ADDR); /* Discard four received bytes */
260 } while (btx -= 4); /* Repeat until all data sent */
261
262 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
263 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (7 << RSPI_SPCMD_SPB_OFFSET)); /* Set 8-bit mode */
264}
265
266
267/*------------------------*/
268/* Receive multiple bytes */
269/*------------------------*/
270static
271void rcvr_spi_multi(
272 BYTE *buff, /* Pointer to data buffer */
273 UINT btr /* Number of bytes to receive (multiple of 4) */
274 )
275{
276 DWORD *lp = (DWORD*)buff;
277
278 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
279 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (3 << RSPI_SPCMD_SPB_OFFSET)); /* Set 32-bit mode */
280
281 do {
282 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
283 sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
284 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
285 wai_sem(MMC_RSPI_SEMAPHORE);
286 *lp++ = LDDW(sil_rew_mem(RSPI0_SPDR_ADDR)); /* Store four received bytes */
287 } while (btr -= 4); /* Repeat until all data received */
288
289 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
290 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (7 << RSPI_SPCMD_SPB_OFFSET)); /* Set 8-bit mode */
291}
292
293
294
295
296/*-----------------------------------------------------------------------*/
297/* Wait for card ready */
298/*-----------------------------------------------------------------------*/
299
300static
301int wait_ready( /* 1:Ready, 0:Timeout */
302 UINT wt /* Timeout [ms] */
303 )
304{
305 Timer2 = (WORD)wt;
306
307 do {
308 if (xchg_spi(0xFF) == 0xFF) return 1; /* Card goes ready */
309 /* This loop takes a time. Insert rot_rdq() here for multitask envilonment. */
310 } while (Timer2); /* Wait until card goes ready or timeout */
311
312 return 0; /* Timeout occured */
313}
314
315
316
317/*-----------------------------------------------------------------------*/
318/* Deselect card and release SPI */
319/*-----------------------------------------------------------------------*/
320
321static
322void deselect(void)
323{
324 CS_HIGH(); /* Set CS# high */
325 xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
326}
327
328
329
330/*-----------------------------------------------------------------------*/
331/* Select card and wait for ready */
332/*-----------------------------------------------------------------------*/
333
334static
335int select(void) /* 1:OK, 0:Timeout */
336{
337 CS_LOW(); /* Set CS# low */
338 xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
339
340 if (wait_ready(500)) return 1; /* Wait for card ready */
341
342 deselect();
343 return 0; /* Failed to select the card due to timeout */
344}
345
346
347
348/*-----------------------------------------------------------------------*/
349/* Receive a data packet from the MMC */
350/*-----------------------------------------------------------------------*/
351
352static
353int rcvr_datablock( /* 1:OK, 0:Error */
354 BYTE *buff, /* Data buffer */
355 UINT btr /* Data block length (byte) */
356 )
357{
358 BYTE token;
359
360
361 Timer1 = 200;
362 do { /* Wait for DataStart token in timeout of 200ms */
363 token = xchg_spi(0xFF);
364 /* This loop will take a time. Insert rot_rdq() here for multitask envilonment. */
365 } while ((token == 0xFF) && Timer1);
366 if (token != 0xFE) return 0; /* Function fails if invalid DataStart token or timeout */
367
368 rcvr_spi_multi(buff, btr); /* Store trailing data to the buffer */
369 xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */
370
371 return 1; /* Function succeeded */
372}
373
374
375
376/*-----------------------------------------------------------------------*/
377/* Send a data packet to the MMC */
378/*-----------------------------------------------------------------------*/
379
380#if _USE_WRITE
381static
382int xmit_datablock( /* 1:OK, 0:Failed */
383 const BYTE *buff, /* Ponter to 512 byte data to be sent */
384 BYTE token /* Token */
385 )
386{
387 BYTE resp;
388
389
390 if (!wait_ready(500)) return 0; /* Wait for card ready */
391
392 xchg_spi(token); /* Send token */
393 if (token != 0xFD) { /* Send data if token is other than StopTran */
394 xmit_spi_multi(buff, 512); /* Data */
395 xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */
396
397 resp = xchg_spi(0xFF); /* Receive data resp */
398 if ((resp & 0x1F) != 0x05) /* Function fails if the data packet was not accepted */
399 return 0;
400 }
401 return 1;
402}
403#endif /* _USE_WRITE */
404
405
406
407/*-----------------------------------------------------------------------*/
408/* Send a command packet to the MMC */
409/*-----------------------------------------------------------------------*/
410
411static
412BYTE send_cmd( /* Return value: R1 resp (bit7==1:Failed to send) */
413 BYTE cmd, /* Command index */
414 DWORD arg /* Argument */
415 )
416{
417 BYTE n, res;
418
419
420 if (cmd & 0x80) { /* Send a CMD55 prior to ACMD<n> */
421 cmd &= 0x7F;
422 res = send_cmd(CMD55, 0);
423 if (res > 1) return res;
424 }
425
426 /* Select the card and wait for ready except to stop multiple block read */
427 if (cmd != CMD12) {
428 deselect();
429 if (!select()) return 0xFF;
430 }
431
432 /* Send command packet */
433 xchg_spi(0x40 | cmd); /* Start + command index */
434 xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
435 xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
436 xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
437 xchg_spi((BYTE)arg); /* Argument[7..0] */
438 n = 0x01; /* Dummy CRC + Stop */
439 if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
440 if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
441 xchg_spi(n);
442
443 /* Receive command resp */
444 if (cmd == CMD12) xchg_spi(0xFF); /* Diacard stuff byte on CMD12 */
445 n = 10; /* Wait for response (10 bytes max) */
446 do
447 res = xchg_spi(0xFF);
448 while ((res & 0x80) && --n);
449
450 return res; /* Return received response */
451}
452
453
454
455/*--------------------------------------------------------------------------
456
457 Public Functions
458
459---------------------------------------------------------------------------*/
460
461
462/*-----------------------------------------------------------------------*/
463/* Initialize disk drive */
464/*-----------------------------------------------------------------------*/
465
466DSTATUS mmc_rspi_initialize()
467{
468 BYTE n, cmd, ty, ocr[4];
469
470 power_on(); /* Initialize RSPI */
471 for (n = 10; n; n--) xchg_spi(0xFF);/* Send 80 dummy clocks */
472
473 ty = 0;
474 if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI/Idle state */
475 Timer1 = 1000; /* Initialization timeout = 1 sec */
476 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
477 for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */
478 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Is the card supports vcc of 2.7-3.6V? */
479 while (Timer1 && send_cmd(ACMD41, 1UL << 30)); /* Wait for end of initialization with ACMD41(HCS) */
480 if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
481 for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
482 ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Card id SDv2 */
483 }
484 }
485 }
486 else { /* Not SDv2 card */
487 if (send_cmd(ACMD41, 0) <= 1) { /* SDv1 or MMC? */
488 ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */
489 }
490 else {
491 ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */
492 }
493 while (Timer1 && send_cmd(cmd, 0)); /* Wait for end of initialization */
494 //if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */
495 // ty = 0;
496 }
497 if (ty) {
498 if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
499 && rcvr_datablock(CSD, 16)){
500 /* CSD Ver.1.0 */
501 if ((CSD[0] & 0xC0) == 0) {
502 CardBlockSize = 1 << (CSD[5] & 0x0F);
503 CardCapacity = (((CSD[6] & 0x03) << 10) | (CSD[7] << 2) | ((CSD[8] & 0xC0) >> 6)) + 1;
504 CardCapacity *= (((uint64_t)1) << ((((CSD[9] & 0x03) << 1) | (CSD[10] & 0x80) >> 7) + 2));
505 CardCapacity *= (uint64_t)CardBlockSize;
506 }
507 else {
508 CardBlockSize = 512;
509 CardCapacity = ((uint64_t)((((CSD[7] & 0x3F) << 16) | (CSD[8] << 8) | CSD[9]) + 1)) * 512 * 1024;
510 }
511 if (send_cmd(CMD10, 0) != 0 /* READ_CID */
512 || !rcvr_datablock(CID, 16)) {
513 ty = 0;
514 }
515 }
516 else {
517 ty = 0;
518 }
519 }
520 }
521 CardType = ty; /* Card type */
522 deselect();
523
524 if (ty) { /* OK */
525 FCLK_FAST(); /* Set fast clock */
526 Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */
527 }
528 else { /* Failed */
529 power_off();
530 Stat = STA_NOINIT;
531 }
532
533 return Stat;
534}
535
536
537
538/*-----------------------------------------------------------------------*/
539/* Get disk status */
540/*-----------------------------------------------------------------------*/
541
542DSTATUS mmc_rspi_status()
543{
544 return Stat; /* Return disk status */
545}
546
547
548
549/*-----------------------------------------------------------------------*/
550/* Read sector(s) */
551/*-----------------------------------------------------------------------*/
552
553DRESULT mmc_rspi_read(
554 BYTE *buff, /* Pointer to the data buffer to store read data */
555 DWORD sector, /* Start sector number (LBA) */
556 UINT count /* Number of sectors to read (1..128) */
557 )
558{
559 if (!count) return RES_PARERR; /* Check parameter */
560 if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
561
562 if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ot BA conversion (byte addressing cards) */
563
564 if (count == 1) { /* Single sector read */
565 if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
566 && rcvr_datablock(buff, 512))
567 count = 0;
568 }
569 else { /* Multiple sector read */
570 if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
571 do {
572 if (!rcvr_datablock(buff, 512)) break;
573 buff += 512;
574 } while (--count);
575 send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
576 }
577 }
578 deselect();
579
580 return count ? RES_ERROR : RES_OK; /* Return result */
581}
582
583
584
585/*-----------------------------------------------------------------------*/
586/* Write sector(s) */
587/*-----------------------------------------------------------------------*/
588
589#if _USE_WRITE
590DRESULT mmc_rspi_write(
591 const BYTE *buff, /* Ponter to the data to write */
592 DWORD sector, /* Start sector number (LBA) */
593 UINT count /* Number of sectors to write (1..128) */
594 )
595{
596 if (!count) return RES_PARERR; /* Check parameter */
597 if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */
598 if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */
599
600 if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ==> BA conversion (byte addressing cards) */
601
602 if (count == 1) { /* Single sector write */
603 if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
604 && xmit_datablock(buff, 0xFE))
605 count = 0;
606 }
607 else { /* Multiple sector write */
608 if (CardType & CT_SDC) send_cmd(ACMD23, count);
609 if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
610 do {
611 if (!xmit_datablock(buff, 0xFC)) break;
612 buff += 512;
613 } while (--count);
614 if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
615 count = 1;
616 }
617 }
618 deselect();
619
620 return count ? RES_ERROR : RES_OK; /* Return result */
621}
622#endif /* _USE_WRITE */
623
624
625
626/*-----------------------------------------------------------------------*/
627/* Miscellaneous drive controls other than data read/write */
628/*-----------------------------------------------------------------------*/
629
630#if _USE_IOCTL
631DRESULT mmc_rspi_ioctl(
632 BYTE ctrl, /* Control command code */
633 void *buff /* Pointer to the conrtol data */
634 )
635{
636 DRESULT res;
637 BYTE n, csd[16], *ptr = buff;
638 DWORD *dp, st, ed;
639
640
641 if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
642
643 res = RES_ERROR;
644
645 switch (ctrl) {
646 case CTRL_SYNC: /* Wait for end of internal write process of the drive */
647 if (select()) res = RES_OK;
648 break;
649
650 case GET_SECTOR_SIZE:
651 *(WORD*)buff = 512;
652 res = RES_OK;
653 break;
654
655 case GET_SECTOR_COUNT:
656 *(DWORD*)buff = CardCapacity / 512;
657 res = RES_OK;
658 break;
659
660 case GET_BLOCK_SIZE:
661 *(DWORD*)buff = CardBlockSize;
662 res = RES_OK;
663 break;
664
665 case CTRL_TRIM: /* Erase a block of sectors (used when _USE_TRIM == 1) */
666 if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */
667 if (mmc_rspi_ioctl(MMC_GET_CSD, csd)) break; /* Get CSD */
668 if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */
669 dp = buff; st = dp[0]; ed = dp[1]; /* Load sector block */
670 if (!(CardType & CT_BLOCK)) {
671 st *= 512; ed *= 512;
672 }
673 if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) /* Erase sector block */
674 res = RES_OK;
675 break;
676
677 /* Following command are not used by FatFs module */
678
679 case MMC_GET_TYPE: /* Get MMC/SDC type (BYTE) */
680 *ptr = CardType;
681 res = RES_OK;
682 break;
683
684 case MMC_GET_CSD: /* Read CSD (16 bytes) */
685 memcpy(ptr, CSD, sizeof(CSD));
686 res = RES_OK;
687 break;
688
689 case MMC_GET_CID: /* Read CID (16 bytes) */
690 memcpy(ptr, CID, sizeof(CID));
691 res = RES_OK;
692 break;
693
694 case MMC_GET_OCR: /* Read OCR (4 bytes) */
695 if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
696 for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
697 res = RES_OK;
698 }
699 break;
700
701 case MMC_GET_SDSTAT: /* Read SD status (64 bytes) */
702 if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
703 xchg_spi(0xFF);
704 if (rcvr_datablock(ptr, 64))
705 res = RES_OK;
706 }
707 break;
708
709 default:
710 res = RES_PARERR;
711 }
712
713 deselect();
714
715 return res;
716}
717#endif /* _USE_IOCTL */
718
719
720/*-----------------------------------------------------------------------*/
721/* Device timer function */
722/*-----------------------------------------------------------------------*/
723/* This function must be called from system timer process
724/ in period of 1 ms to generate card control timing.
725*/
726
727void mmc_rspi_cychdr(intptr_t exinf)
728{
729 WORD n;
730 BYTE s;
731
732
733 n = Timer1; /* 1kHz decrement timer stopped at 0 */
734 if (n) Timer1 = --n;
735 n = Timer2;
736 if (n) Timer2 = --n;
737
738 s = Stat;
739 if (WP()) /* Write protected */
740 s |= STA_PROTECT;
741 else /* Write enabled */
742 s &= ~STA_PROTECT;
743 if (INS()) /* Card is in socket */
744 s &= ~STA_NODISK;
745 else /* Socket empty */
746 s |= (STA_NODISK | STA_NOINIT);
747 Stat = s;
748}
749
750void mmc_rspi_spri_handler(void)
751{
752 isig_sem(MMC_RSPI_SEMAPHORE);
753}
754
755void mmc_rspi_spti_handler(void)
756{
757}
758
759void mmc_rspi_spii_handler(void)
760{
761}
762
Note: See TracBrowser for help on using the repository browser.