CLEON  Version 1
Cloud-Offloaded GPS Receiver
diskio.c
Go to the documentation of this file.
1 /*-----------------------------------------------------------------------*/
2 /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2012 */
3 /*-----------------------------------------------------------------------*/
4 /* If a working storage control module is available, it should be */
5 /* attached to the FatFs via a glue function rather than modifying it. */
6 /* This is an example of glue functions to attach various exsisting */
7 /* storage control module to the FatFs module with a defined API. */
8 /*-----------------------------------------------------------------------*/
9 
10 #include "hal_define.h"
11 #include "sys_define.h"
12 #include "fs_define.h"
13 
14 /*
15  *-------------------------------------------------------------------------
16  * Platform dependent macros and functions needed to be modified
17  *-------------------------------------------------------------------------
18  */
19 
20 #define INIT_PORT() HAL_SPI_Init() /* Initialize MMC control port */
21 #define FAST_MODE() SYS_MMC_FastMode() /* Maximize SD Card transfer speed */
22 #define DLY_US(n) __delay_cycles(n * 12)
23 
24 #define CS_H() SYS_MMC_DeselectCard() /* Set MMC CS "high" */
25 #define CS_L() SYS_MMC_SelectCard() /* Set MMC CS "low" */
26 
27 BYTE INS = 1;
28 #define WP (0) /* Card is write protected (yes:true, no:false, default:false) */
29 
30 /*
31  *-------------------------------------------------------------------------
32  * Platform dependent RTC Function for FatFs module
33  *-------------------------------------------------------------------------
34  */
36 {
37  DWORD tmr;
38 
39  /* Pack date and time into a DWORD variable */
40  tmr = (((DWORD)(HAL_GetRTCYear()-1980)) << 25)
41  | ((DWORD)HAL_GetRTCMon() << 21)
42  | ((DWORD)HAL_GetRTCDay() << 16)
43  | (WORD)(((unsigned char) HAL_GetRTCHour()) << 11)
44  | (WORD)(((unsigned char) HAL_GetRTCMin()) << 5)
45  | (WORD)(((unsigned char) HAL_GetRTCSec()) >> 1);
46 
47  return (tmr);
48 }
49 
50 /*--------------------------------------------------------------------------
51  * Module Private Functions
52  * ---------------------------------------------------------------------------*/
53 /* MMC/SD command (SPI mode) */
54 #define CMD0 (0) /* GO_IDLE_STATE */
55 #define CMD1 (1) /* SEND_OP_COND */
56 #define ACMD41 (0x80 + 41) /* SEND_OP_COND (SDC) */
57 #define CMD8 (8) /* SEND_IF_COND */
58 #define CMD9 (9) /* SEND_CSD */
59 #define CMD10 (10) /* SEND_CID */
60 #define CMD12 (12) /* STOP_TRANSMISSION */
61 #define ACMD13 (0x80 + 13) /* SD_STATUS (SDC) */
62 #define CMD16 (16) /* SET_BLOCKLEN */
63 #define CMD17 (17) /* READ_SINGLE_BLOCK */
64 #define CMD18 (18) /* READ_MULTIPLE_BLOCK */
65 #define CMD23 (23) /* SET_BLOCK_COUNT */
66 #define ACMD23 (0x80 + 23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
67 #define CMD24 (24) /* WRITE_BLOCK */
68 #define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
69 #define CMD41 (41) /* SEND_OP_COND (ACMD) */
70 #define CMD55 (55) /* APP_CMD */
71 #define CMD58 (58) /* READ_OCR */
72 
73 static
74 DSTATUS Stat = STA_NOINIT; /* Disk status */
75 
76 static
77 BYTE CardType; /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */
78 
79 /*
80  *-----------------------------------------------------------------------
81  * Transmit bytes to the MMC
82  *-----------------------------------------------------------------------
83  */
84 
85 static
86 void xmit_mmc (
87  const BYTE* buff, /* Data to be sent */
88  UINT bc /* Number of bytes to send */
89  )
90 {
91  SYS_MMC_SendFrame((uint8_t *)buff, bc);
92 }
93 
94 /*
95  *-----------------------------------------------------------------------
96  * Receive bytes from the MMC
97  *-----------------------------------------------------------------------
98  */
99 
100 static
101 void rcvr_mmc (
102  BYTE *buff, /* Pointer to read buffer */
103  UINT bc /* Number of bytes to receive */
104  )
105 {
106  SYS_MMC_ReadFrame(buff, bc);
107 }
108 
109 /*
110  *-----------------------------------------------------------------------
111  * Wait for card ready
112  *-----------------------------------------------------------------------
113  */
114 
115 static
116 int wait_ready (void) /* 1:OK, 0:Timeout */
117 {
118  BYTE d;
119  UINT tmr;
120 
121 
122  for (tmr = 5000; tmr; tmr--){ /* Wait for ready in timeout of 500ms */
123  rcvr_mmc(&d, 1);
124  if (d == 0xFF){
125  return ( 1) ;
126  }
127  DLY_US(100);
128  }
129 
130  return (0);
131 }
132 
133 /*
134  *-----------------------------------------------------------------------
135  * Deselect the card and release SPI bus
136  *-----------------------------------------------------------------------
137  */
138 
139 static
140 void deselect (void)
141 {
142  BYTE d;
143 
144  CS_H();
145  rcvr_mmc(&d, 1);
146 }
147 
148 /*
149  *-----------------------------------------------------------------------
150  * Select the card and wait for ready
151  *-----------------------------------------------------------------------
152  */
153 
154 static
155 int select (void) /* 1:OK, 0:Timeout */
156 {
157  CS_L();
158  if (!wait_ready()){
159  deselect();
160  return (0);
161  }
162  return (1);
163 }
164 
165 /*
166  *-----------------------------------------------------------------------
167  * Receive a data packet from MMC
168  *-----------------------------------------------------------------------
169  */
170 
171 static
172 int rcvr_datablock ( /* 1:OK, 0:Failed */
173  BYTE *buff, /* Data buffer to store received data */
174  UINT btr /* Byte count */
175  )
176 {
177  BYTE d[2];
178  UINT tmr;
179 
180 
181  for (tmr = 1000; tmr; tmr--){ /* Wait for data packet in timeout of 100ms */
182  rcvr_mmc(d, 1);
183  if (d[0] != 0xFF){
184  break;
185  }
186  DLY_US(100);
187  }
188  if (d[0] != 0xFE){
189  return ( 0) ; /* If not valid data token, retutn with error */
190  }
191  rcvr_mmc(buff, btr); /* Receive the data block into buffer */
192  rcvr_mmc(d, 2); /* Discard CRC */
193 
194  return (1); /* Return with success */
195 }
196 
197 /*
198  *-----------------------------------------------------------------------
199  * Send a data packet to MMC
200  *-----------------------------------------------------------------------
201  */
202 
203 static
204 int xmit_datablock ( /* 1:OK, 0:Failed */
205  const BYTE *buff, /* 512 byte data block to be transmitted */
206  BYTE token /* Data/Stop token */
207  )
208 {
209  BYTE d[2];
210 
211 
212  if (!wait_ready()){
213  return ( 0) ;
214  }
215 
216  d[0] = token;
217  xmit_mmc(d, 1); /* Xmit a token */
218  if (token != 0xFD){ /* Is it data token? */
219  xmit_mmc(buff, 512); /* Xmit the 512 byte data block to MMC */
220  rcvr_mmc(d, 2); /* Dummy CRC (FF,FF) */
221  rcvr_mmc(d, 1); /* Receive data response */
222  if ((d[0] & 0x1F) != 0x05){ /* If not accepted, return with error */
223  return (0);
224  }
225  }
226 
227  return (1);
228 }
229 
230 /*
231  *-----------------------------------------------------------------------
232  * Send a command packet to MMC
233  *-----------------------------------------------------------------------
234  */
235 
236 static
237 BYTE send_cmd ( /* Returns command response (bit7==1:Send failed)*/
238  BYTE cmd, /* Command byte */
239  DWORD arg /* Argument */
240  )
241 {
242  BYTE n, d, buf[6];
243 
244 
245  if (cmd & 0x80){ /* ACMD<n> is the command sequense of CMD55-CMD<n> */
246  cmd &= 0x7F;
247  n = send_cmd(CMD55, 0);
248  if (n > 1){
249  return ( n) ;
250  }
251  }
252 
253  /* Select the card and wait for ready */
254  deselect();
255  if (!select()){
256  return ( 0xFF) ;
257  }
258 
259  /* Send a command packet */
260  buf[0] = 0x40 | cmd; /* Start + Command index */
261  buf[1] = (BYTE)(arg >> 24); /* Argument[31..24] */
262  buf[2] = (BYTE)(arg >> 16); /* Argument[23..16] */
263  buf[3] = (BYTE)(arg >> 8); /* Argument[15..8] */
264  buf[4] = (BYTE)arg; /* Argument[7..0] */
265  n = 0x01; /* Dummy CRC + Stop */
266  if (cmd == CMD0){
267  n = 0x95; /* (valid CRC for CMD0(0)) */
268  }
269  if (cmd == CMD8){
270  n = 0x87; /* (valid CRC for CMD8(0x1AA)) */
271  }
272  buf[5] = n;
273  xmit_mmc(buf, 6);
274 
275  /* Receive command response */
276  if (cmd == CMD12){
277  rcvr_mmc(&d, 1); /* Skip a stuff byte when stop reading */
278  }
279  n = 10; /* Wait for a valid response in timeout of 10 attempts */
280  do {
281  rcvr_mmc(&d, 1);
282  }
283  while ((d & 0x80) && --n);
284 
285  return (d); /* Return with the response value */
286 }
287 
288 /*--------------------------------------------------------------------------
289  *
290  * Public Functions
291  *
292  * ---------------------------------------------------------------------------*/
293 
294 
295 /*
296  *-----------------------------------------------------------------------
297  * Get Disk Status
298  *-----------------------------------------------------------------------
299  */
300 
302  BYTE drv /* Drive number (0) */
303  )
304 {
305  DSTATUS s = Stat;
306 
307 
308  if (drv || !INS){
309  s = STA_NODISK | STA_NOINIT;
310  } else {
311  s &= ~STA_NODISK;
312  if (WP){
313  s |= STA_PROTECT;
314  } else {
315  s &= ~STA_PROTECT;
316  }
317  }
318  Stat = s;
319 
320  return (s);
321 }
322 
323 uint8_t validateCSD (void)
324 {
325  BYTE csd0[16], csd1[16], i;
326  WORD sum = 0;
327 
328  //Pull the CSD -- twice. If the response codes are invalid, then we know the card isn't there or initialized.
329  if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd0, 16)){
330  if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd1, 16)){
331  //The response codes were good -- but maybe the SPI input was just floating low. Let's evaluate the CSD data.
332  //First, look for all zero or all ones. If the SPI input is floating, these are the most likely outcomes.
333  for (i = 0; i <= 15; i++){
334  sum += csd0[i];
335  }
336  if (!((sum == 0) || (sum == 4096))){
337  //The response was a mix of 0's and 1's. Floating inputs could still do that -- but it's unlikely they'd
338  //produce the same pattern twice. Compare to ensure the two are identical.
339  i = 0;
340  while (i <= 15)
341  {
342  if (csd0[i] != csd1[i]){
343  break;
344  }
345  i++;
346  }
347  if (i > 15){
348  return ( 1) ;
349  }
350  }
351  }
352  }
353  return ( 0) ;
354 }
355 
356 //Attempt to detect the card by commanding it to return its CSD register and evaluating it. Returns the
357 //result, and also updates FatFs's internal INS variable.
358 //The proper way to detect a card is by sensing its presence on the DAT3 signal. The EXP board doesn't
359 //contain the necessary h/w, so this s/w method works instead.
360 unsigned char detectCard (void)
361 {
362  //Check for a valid CSD response
363  if (validateCSD()){
364  disk_status(0); //Update the INS variable
365  return ( 1) ; //Card is present
366  }
367 
368  //We didn't get a valid response. So we now know the status is one of two things:
369  //a) The card isn't there at all;
370  //b) or, it was just inserted recently, and needs to be initialized
371 
372  INS = 0x01; //Trick disk_initialize into thinking it's inserted...
373  disk_initialize(0); //Attempt to initialize it
374 
375  INS = validateCSD(); //Try again
376  disk_status(0); //Update the INS variable
377 
378  return ( INS) ; //1 = card is present; 0 = not present
379 }
380 
382 /*-----------------------------------------------------------------------*/
383 /* Inidialize a Drive */
384 /*-----------------------------------------------------------------------*/
385 
387  BYTE drv /* Physical drive nmuber (0) */
388  )
389 {
390 #pragma diag_suppress=Pe550
391  BYTE n, ty, cmd, buf[4];
392 
393  UINT tmr;
394  DSTATUS s;
395 
396 
397  INIT_PORT(); /* Initialize control port */
398 
399  s = disk_status(drv); /* Check if card is in the socket */
400  if (s & STA_NODISK){
401  return ( s) ;
402  }
403 
404  CS_H();
405  for (n = 10; n; n--){rcvr_mmc(buf, 1); /* 80 dummy clocks */
406  }
407  ty = 0;
408  if (send_cmd(CMD0, 0) == 1){ /* Enter Idle state */
409  if (send_cmd(CMD8, 0x1AA) == 1){ /* SDv2? */
410  rcvr_mmc(buf, 4); /* Get trailing return value of R7 resp */
411  if (buf[2] == 0x01 && buf[3] == 0xAA){ /* The card can work at vdd range of 2.7-3.6V */
412  for (tmr = 1000; tmr; tmr--)
413  { /* Wait for leaving idle state (ACMD41 with HCS bit) */
414  if (send_cmd(ACMD41, 1UL << 30) == 0){
415  break;
416  }
417  DLY_US(1000);
418  }
419  if (tmr && send_cmd(CMD58, 0) == 0){ /* Check CCS bit in the OCR */
420  rcvr_mmc(buf, 4);
421  ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
422  }
423  }
424  } else { /* SDv1 or MMCv3 */
425  if (send_cmd(ACMD41, 0) <= 1){
426  ty = CT_SD1; cmd = ACMD41; /* SDv1 */
427  } else {
428  ty = CT_MMC; cmd = CMD1; /* MMCv3 */
429  }
430  for (tmr = 1000; tmr; tmr--)
431  { /* Wait for leaving idle state */
432  if (send_cmd(ACMD41, 0) == 0){
433  break;
434  }
435  DLY_US(1000);
436  }
437  if (!tmr || send_cmd(CMD16, 512) != 0){ /* Set R/W block length to 512 */
438  ty = 0;
439  }
440  }
441  }
442  CardType = ty;
443  deselect();
444 
445  if (ty){ /* Initialization succeded */
446  FAST_MODE();
447  s &= ~STA_NOINIT;
448  } else { /* Initialization failed */
449  s |= STA_NOINIT;
450  }
451 
452  Stat = s;
453 
454  return (s);
455 }
456 
457 /*-----------------------------------------------------------------------*/
458 /* Read Sector(s) */
459 /*-----------------------------------------------------------------------*/
460 
462  BYTE drv, /* Physical drive nmuber (0) */
463  BYTE *buff, /* Pointer to the data buffer to store read data */
464  DWORD sector, /* Start sector number (LBA) */
465  BYTE count /* Sector count (1..128) */
466  )
467 {
468  DSTATUS s;
469 
470 
471  s = disk_status(drv);
472  if (s & STA_NOINIT){
473  return ( RES_NOTRDY) ;
474  }
475  if (!count){
476  return ( RES_PARERR) ;
477  }
478  if (!(CardType & CT_BLOCK)){
479  sector *= 512; /* Convert LBA to byte address if needed */
480  }
481  if (count == 1){ /* Single block read */
482  if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
483  && rcvr_datablock(buff, 512)){
484  count = 0;
485  }
486  } else { /* Multiple block read */
487  if (send_cmd(CMD18, sector) == 0){ /* READ_MULTIPLE_BLOCK */
488  do {
489  if (!rcvr_datablock(buff, 512)){
490  break;
491  }
492  buff += 512;
493  } while (--count);
494  send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
495  }
496  }
497  deselect();
498 
499  return (count ? RES_ERROR : RES_OK);
500 }
501 
502 
503 
504 /*-----------------------------------------------------------------------*/
505 /* Write Sector(s) */
506 /*-----------------------------------------------------------------------*/
507 
508 #if _USE_WRITE
510  BYTE drv, /* Physical drive nmuber (0) */
511  const BYTE *buff, /* Pointer to the data to be written */
512  DWORD sector, /* Start sector number (LBA) */
513  BYTE count /* Sector count (1..128) */
514  )
515 {
516  DSTATUS s;
517 
518 
519  s = disk_status(drv);
520  if (s & STA_NOINIT){
521  return ( RES_NOTRDY) ;
522  }
523  if (s & STA_PROTECT){
524  return ( RES_WRPRT) ;
525  }
526  if (!count){
527  return ( RES_PARERR) ;
528  }
529  if (!(CardType & CT_BLOCK)){
530  sector *= 512; /* Convert LBA to byte address if needed */
531  }
532  if (count == 1){ /* Single block write */
533  if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
534  && xmit_datablock(buff, 0xFE)){
535  count = 0;
536  }
537  } else { /* Multiple block write */
538  if (CardType & CT_SDC){
539  send_cmd(ACMD23, count);
540  }
541  if (send_cmd(CMD25, sector) == 0){ /* WRITE_MULTIPLE_BLOCK */
542  do {
543  if (!xmit_datablock(buff, 0xFC)){
544  break;
545  }
546  buff += 512;
547  } while (--count);
548  if (!xmit_datablock(0, 0xFD)){ /* STOP_TRAN token */
549  count = 1;
550  }
551  }
552  }
553  deselect();
554 
555  return (count ? RES_ERROR : RES_OK);
556 }
557 #endif
558 
559 
560 /*-----------------------------------------------------------------------*/
561 /* Miscellaneous Functions */
562 /*-----------------------------------------------------------------------*/
563 
564 #if _USE_IOCTL
566  BYTE drv, /* Physical drive nmuber (0) */
567  BYTE ctrl, /* Control code */
568  DWORD *buff /* Buffer to send/receive control data */
569  )
570 {
571  DRESULT res;
572  BYTE n, csd[16];
573  WORD cs;
574 
575 
576  if (disk_status(drv) & STA_NOINIT){ /* Check if card is in the socket */
577  return (RES_NOTRDY);
578  }
579 
580  res = RES_ERROR;
581  switch (ctrl){
582  case CTRL_SYNC: /* Make sure that no pending write process */
583  if (select()){
584  deselect();
585  res = RES_OK;
586  }
587  break;
588 
589  case GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
590  if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)){
591  if ((csd[0] >> 6) == 1){ /* SDC ver 2.00 */
592  cs = csd[9] + ((WORD)csd[8] << 8) + 1;
593  *buff = ((DWORD)cs) << 10;
594  } else { /* SDC ver 1.XX or MMC */
595  n =
596  (csd[5] &
597  15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
598  cs =
599  (csd[8] >>
600  6) +
601  ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
602  *(DWORD*)buff = (DWORD)cs << (n - 9);
603  }
604  res = RES_OK;
605  }
606  break;
607 
608  case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */
609  *(DWORD*)buff = 128;
610  res = RES_OK;
611  break;
612 
613  default:
614  res = RES_PARERR;
615  }
616 
617  deselect();
618 
619  return (res);
620 }
621 #endif
622 
623 
624 
625 
626