Arduino FatFS
SDBitBangSPIIO.h
1 /*------------------------------------------------------------------------/
2 / Foolproof MMCv3/SDv1/SDv2 (in SPI mode) control module
3 /-------------------------------------------------------------------------/
4 /
5 / Copyright (C) 2019, 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  * Easy to Port Bit-banging SPI
16  It uses only four GPIO pins. No complex peripheral needs to be used.
17 
18  * Platform Independent
19  You need to modify only a few macros to control the GPIO port.
20 
21  * false Speed
22  The data transfer rate will be several times sfalseer than hardware SPI.
23 
24  * No Media Change Detection
25  Application program needs to perform a f_mount() after media change.
26 
27 /-------------------------------------------------------------------------*/
28 
29 #pragma once
30 #include "../ff/ff.h" /* Obtains integer types for FatFs */
31 #include "BaseIO.h"
32 #include "sdcommon.h"
33 
34 namespace fatfs {
35 
41 class SDBitBangSPIIO : public BaseIO {
42  public:
43  SDBitBangSPIIO(int miso, int mosi, int clk, int cs = -1) {
44  setPins(miso, mosi, clk, cs);
45  }
46 
47  void setPins(int miso, int mosi, int clk, int cs = -1) {
48  this->miso = miso;
49  this->mosi = mosi;
50  this->clk = clk;
51  this->cs = cs;
52  }
53 
54  void setMISO(int miso) { this->miso = miso; }
55 
56  void setMOSI(int mosi) { this->mosi = mosi; }
57 
58  void setCLK(int clk) { this->clk = clk; }
59 
60  void setCS(int cs) { this->cs = cs; }
61 
62  DSTATUS disk_status(BYTE drv) override {
63  if (drv) return STA_NOINIT;
64  return Stat;
65  }
66 
67  DSTATUS disk_initialize(BYTE drv) override {
68  BYTE n, ty, cmd, buf[4];
69  UINT tmr;
70  DSTATUS s;
71 
72  if (drv != 0) return STA_NODISK;
73  if (miso == -1 || mosi == -1 || clk == -1) return STA_NODISK;
74 
75  delay(10); /* 10ms */
76  setup_pins();
77 
78  for (n = 10; n; n--)
79  rcvr_mmc(buf, 1); /* Apply 80 dummy clocks and the card gets ready to
80  receive command */
81 
82  ty = 0;
83  if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
84  if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
85  rcvr_mmc(buf, 4); /* Get trailing return value of R7 resp */
86  if (buf[2] == 0x01 &&
87  buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
88  for (tmr = 1000; tmr;
89  tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */
90  if (send_cmd(ACMD41, 1UL << 30) == 0) break;
91  delay(1);
92  }
93  if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
94  rcvr_mmc(buf, 4);
95  ty = (buf[0] & 0x40) ? CT_SDC2 | CT_BLOCK : CT_SDC2; /* SDv2+ */
96  }
97  }
98  } else { /* SDv1 or MMCv3 */
99  if (send_cmd(ACMD41, 0) <= 1) {
100  ty = CT_SDC2;
101  cmd = ACMD41; /* SDv1 */
102  } else {
103  ty = CT_MMC3;
104  cmd = CMD1; /* MMCv3 */
105  }
106  for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */
107  if (send_cmd(cmd, 0) == 0) break;
108  delay(1);
109  }
110  if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
111  ty = 0;
112  }
113  }
114  CardType = ty;
115  s = ty ? STA_CLEAR : STA_NOINIT;
116  Stat = s;
117 
118  deselect();
119 
120  return s;
121  }
122 
123  DRESULT disk_read(
124  BYTE drv, /* Physical drive nmuber (0) */
125  BYTE *buff, /* Pointer to the data buffer to store read data */
126  LBA_t sector, /* Start sector number (LBA) */
127  UINT count /* Sector count (1..128) */
128  ) override {
129  BYTE cmd;
130  DWORD sect = (DWORD)sector;
131 
132  if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;
133  if (!(CardType & CT_BLOCK))
134  sect *= 512; /* Convert LBA to byte address if needed */
135 
136  cmd = count > 1 ? CMD18
137  : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
138  if (send_cmd(cmd, sect) == 0) {
139  do {
140  if (!rcvr_datablock(buff, 512)) break;
141  buff += 512;
142  } while (--count);
143  if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
144  }
145  deselect();
146 
147  return count ? RES_ERROR : RES_OK;
148  }
149 
150  DRESULT disk_write(BYTE drv, /* Physical drive nmuber (0) */
151  const BYTE *buff, /* Pointer to the data to be written */
152  LBA_t sector, /* Start sector number (LBA) */
153  UINT count /* Sector count (1..128) */
154  ) override {
155  DWORD sect = (DWORD)sector;
156 
157  if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;
158  if (!(CardType & CT_BLOCK))
159  sect *= 512; /* Convert LBA to byte address if needed */
160 
161  if (count == 1) { /* Single block write */
162  if ((send_cmd(CMD24, sect) == 0) /* WRITE_BLOCK */
163  && xmit_datablock(buff, 0xFE))
164  count = 0;
165  } else { /* Multiple block write */
166  if (CardType & CT_SDC) send_cmd(ACMD23, count);
167  if (send_cmd(CMD25, sect) == 0) { /* WRITE_MULTIPLE_BLOCK */
168  do {
169  if (!xmit_datablock(buff, 0xFC)) break;
170  buff += 512;
171  } while (--count);
172  if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
173  count = 1;
174  }
175  }
176  deselect();
177 
178  return count ? RES_ERROR : RES_OK;
179  }
180 
181  DRESULT disk_ioctl(BYTE drv, /* Physical drive nmuber (0) */
182  BYTE ctrl, /* Control code */
183  void *buff /* Buffer to send/receive control data */
184  ) override {
185  DRESULT res;
186  BYTE n, csd[16];
187  DWORD cs;
188 
189  if (disk_status(drv) & STA_NOINIT)
190  return RES_NOTRDY; /* Check if card is in the socket */
191 
192  res = RES_ERROR;
193  switch (ctrl) {
194  case CTRL_SYNC: /* Make sure that no pending write process */
195  if (select()) res = RES_OK;
196  break;
197 
198  case GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
199  if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
200  if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
201  cs =
202  csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
203  *(LBA_t *)buff = cs << 10;
204  } else { /* SDC ver 1.XX or MMC */
205  n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) +
206  2;
207  cs = (csd[8] >> 6) + ((WORD)csd[7] << 2) +
208  ((WORD)(csd[6] & 3) << 10) + 1;
209  *(LBA_t *)buff = cs << (n - 9);
210  }
211  res = RES_OK;
212  }
213  break;
214 
215  case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */
216  *(DWORD *)buff = 128;
217  res = RES_OK;
218  break;
219 
220  default:
221  res = RES_PARERR;
222  }
223 
224  deselect();
225 
226  return res;
227  }
228 
229  protected:
230  DSTATUS Stat = STA_NOINIT; /* Disk status */
231  BYTE CardType; /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */
232  int miso = -1, mosi = -1, clk = -1, cs = -1;
233 
234  void setup_pins() {
235  if (cs != -1) pinMode(cs, OUTPUT);
236  set_pin_active(cs, true); /* Initialize port pin tied to CS */
237  pinMode(clk, OUTPUT);
238  set_pin_active(clk, false); /* Initialize port pin tied to SCLK */
239  pinMode(miso, INPUT);
240  pinMode(mosi, OUTPUT);
241  }
242 
243  inline void set_pin_active(int pin, bool active) {
244  if (pin != -1) digitalWrite(pin, active);
245  }
246 
247  inline bool read_data() { return digitalRead(miso); }
248 
250  void xmit_mmc(const BYTE *buff, /* Data to be sent */
251  UINT bc /* Number of bytes to send */
252  ) {
253  BYTE d;
254 
255  do {
256  d = *buff++; /* Get a byte to be sent */
257  if (d & 0x80)
258  set_pin_active(mosi, true);
259  else
260  set_pin_active(mosi, false); /* bit7 */
261  set_pin_active(clk, true);
262  set_pin_active(clk, false);
263  if (d & 0x40)
264  set_pin_active(mosi, true);
265  else
266  set_pin_active(mosi, false); /* bit6 */
267  set_pin_active(clk, true);
268  set_pin_active(clk, false);
269  if (d & 0x20)
270  set_pin_active(mosi, true);
271  else
272  set_pin_active(mosi, false); /* bit5 */
273  set_pin_active(clk, true);
274  set_pin_active(clk, false);
275  if (d & 0x10)
276  set_pin_active(mosi, true);
277  else
278  set_pin_active(mosi, false); /* bit4 */
279  set_pin_active(clk, true);
280  set_pin_active(clk, false);
281  if (d & 0x08)
282  set_pin_active(mosi, true);
283  else
284  set_pin_active(mosi, false); /* bit3 */
285  set_pin_active(clk, true);
286  set_pin_active(clk, false);
287  if (d & 0x04)
288  set_pin_active(mosi, true);
289  else
290  set_pin_active(mosi, false); /* bit2 */
291  set_pin_active(clk, true);
292  set_pin_active(clk, false);
293  if (d & 0x02)
294  set_pin_active(mosi, true);
295  else
296  set_pin_active(mosi, false); /* bit1 */
297  set_pin_active(clk, true);
298  set_pin_active(clk, false);
299  if (d & 0x01)
300  set_pin_active(mosi, true);
301  else
302  set_pin_active(mosi, false); /* bit0 */
303  set_pin_active(clk, true);
304  set_pin_active(clk, false);
305  } while (--bc);
306  }
307 
309  void rcvr_mmc(BYTE *buff, /* Pointer to read buffer */
310  UINT bc /* Number of bytes to receive */
311  ) {
312  BYTE r;
313 
314  set_pin_active(mosi, true); /* Send 0xFF */
315 
316  do {
317  r = 0;
318  if (read_data()) r++; /* bit7 */
319  set_pin_active(clk, true);
320  set_pin_active(clk, false);
321  r <<= 1;
322  if (read_data()) r++; /* bit6 */
323  set_pin_active(clk, true);
324  set_pin_active(clk, false);
325  r <<= 1;
326  if (read_data()) r++; /* bit5 */
327  set_pin_active(clk, true);
328  set_pin_active(clk, false);
329  r <<= 1;
330  if (read_data()) r++; /* bit4 */
331  set_pin_active(clk, true);
332  set_pin_active(clk, false);
333  r <<= 1;
334  if (read_data()) r++; /* bit3 */
335  set_pin_active(clk, true);
336  set_pin_active(clk, false);
337  r <<= 1;
338  if (read_data()) r++; /* bit2 */
339  set_pin_active(clk, true);
340  set_pin_active(clk, false);
341  r <<= 1;
342  if (read_data()) r++; /* bit1 */
343  set_pin_active(clk, true);
344  set_pin_active(clk, false);
345  r <<= 1;
346  if (read_data()) r++; /* bit0 */
347  set_pin_active(clk, true);
348  set_pin_active(clk, false);
349  *buff++ = r; /* Store a received byte */
350  } while (--bc);
351  }
352 
354  int wait_ready(void) /* 1:OK, 0:Timeout */
355  {
356  BYTE d;
357  UINT tmr;
358 
359  for (tmr = 5000; tmr; tmr--) { /* Wait for ready in timeout of 500ms */
360  rcvr_mmc(&d, 1);
361  if (d == 0xFF) break;
362  delayMicroseconds(100);
363  }
364 
365  return tmr ? 1 : 0;
366  }
367 
369  void deselect(void) {
370  BYTE d;
371 
372  set_pin_active(cs, true); /* Set CS# high */
373  rcvr_mmc(&d, 1); /* Dummy clock (force DO hi-z for multiple slave SPI) */
374  }
375 
377  int select(void) /* 1:OK, 0:Timeout */
378  {
379  BYTE d;
380 
381  set_pin_active(cs, false); /* Set CS# false */
382  rcvr_mmc(&d, 1); /* Dummy clock (force DO enabled) */
383  if (wait_ready()) return 1; /* Wait for card ready */
384 
385  deselect();
386  return 0; /* Failed */
387  }
388 
390  int rcvr_datablock( /* 1:OK, 0:Failed */
391  BYTE *buff, /* Data buffer to store received data */
392  UINT btr /* Byte count */
393  ) {
394  BYTE d[2];
395  UINT tmr;
396 
397  for (tmr = 1000; tmr;
398  tmr--) { /* Wait for data packet in timeout of 100ms */
399  rcvr_mmc(d, 1);
400  if (d[0] != 0xFF) break;
401  delayMicroseconds(100);
402  }
403  if (d[0] != 0xFE) return 0; /* If not valid data token, return with error */
404 
405  rcvr_mmc(buff, btr); /* Receive the data block into buffer */
406  rcvr_mmc(d, 2); /* Discard CRC */
407 
408  return 1; /* Return with success */
409  }
410 
412  int xmit_datablock(/* 1:OK, 0:Failed */
413  const BYTE
414  *buff, /* 512 byte data block to be transmitted */
415  BYTE token /* Data/Stop token */
416  ) {
417  BYTE d[2];
418 
419  if (!wait_ready()) return 0;
420 
421  d[0] = token;
422  xmit_mmc(d, 1); /* Xmit a token */
423  if (token != 0xFD) { /* Is it data token? */
424  xmit_mmc(buff, 512); /* Xmit the 512 byte data block to MMC */
425  rcvr_mmc(d, 2); /* Xmit dummy CRC (0xFF,0xFF) */
426  rcvr_mmc(d, 1); /* Receive data response */
427  if ((d[0] & 0x1F) != 0x05) /* If not accepted, return with error */
428  return 0;
429  }
430 
431  return 1;
432  }
433 
435  BYTE send_cmd( /* Returns command response (bit7==1:Send failed)*/
436  BYTE cmd, /* Command byte */
437  DWORD arg /* Argument */
438  ) {
439  BYTE n, d, buf[6];
440 
441  if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
442  cmd &= 0x7F;
443  n = send_cmd(CMD55, 0);
444  if (n > 1) return n;
445  }
446 
447  /* Select the card and wait for ready except to stop multiple block read */
448  if (cmd != CMD12) {
449  deselect();
450  if (!select()) return 0xFF;
451  }
452 
453  /* Send a command packet */
454  buf[0] = 0x40 | cmd; /* Start + Command index */
455  buf[1] = (BYTE)(arg >> 24); /* Argument[31..24] */
456  buf[2] = (BYTE)(arg >> 16); /* Argument[23..16] */
457  buf[3] = (BYTE)(arg >> 8); /* Argument[15..8] */
458  buf[4] = (BYTE)arg; /* Argument[7..0] */
459  n = 0x01; /* Dummy CRC + Stop */
460  if (cmd == CMD0) n = 0x95; /* (valid CRC for CMD0(0)) */
461  if (cmd == CMD8) n = 0x87; /* (valid CRC for CMD8(0x1AA)) */
462  buf[5] = n;
463  xmit_mmc(buf, 6);
464 
465  /* Receive command response */
466  if (cmd == CMD12) rcvr_mmc(&d, 1); /* Skip a stuff byte when stop reading */
467  n = 10; /* Wait for a valid response in timeout of 10 attempts */
468  do rcvr_mmc(&d, 1);
469  while ((d & 0x80) && --n);
470 
471  return d; /* Return with the response value */
472  }
473 };
474 
475 } // namespace fatfs
Empty IO implementation that we can use to test the compilation.
Definition: BaseIO.h:10
Accessing a SD card via SPI using bit banging.
Definition: SDBitBangSPIIO.h:41
BYTE send_cmd(BYTE cmd, DWORD arg)
Send a command packet to the card *‍/.
Definition: SDBitBangSPIIO.h:435
int xmit_datablock(const BYTE *buff, BYTE token)
Send a data packet to the card *‍/.
Definition: SDBitBangSPIIO.h:412
int select(void)
Select the card and wait for ready *‍/.
Definition: SDBitBangSPIIO.h:377
void deselect(void)
Deselect the card and release SPI bus *‍/.
Definition: SDBitBangSPIIO.h:369
int rcvr_datablock(BYTE *buff, UINT btr)
Receive a data packet from the card *‍/.
Definition: SDBitBangSPIIO.h:390
void xmit_mmc(const BYTE *buff, UINT bc)
Transmit bytes to the card (bitbanging) *‍/.
Definition: SDBitBangSPIIO.h:250
void rcvr_mmc(BYTE *buff, UINT bc)
Receive bytes from the card (bitbanging) *‍/.
Definition: SDBitBangSPIIO.h:309
int wait_ready(void)
Wait for card ready *‍/.
Definition: SDBitBangSPIIO.h:354