Paparazzi UAS  v5.15_devel-124-g3c411d6-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
sdcard_spi.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Bart Slinger <bartslinger@gmail.com>
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
46 #include "sdcard_spi.h"
47 
56 struct SDCard sdcard1;
57 
62 void sdcard_spi_send_cmd(struct SDCard *sdcard, uint8_t cmd, uint32_t arg);
63 void sdcard_spi_send_app_cmd(struct SDCard *sdcard, uint8_t cmd, uint32_t arg);
64 void sdcard_spi_request_bytes(struct SDCard *sdcard, uint8_t len);
74 void sdcard_spi_init(struct SDCard *sdcard, struct spi_periph *spi_p, const uint8_t slave_idx)
75 {
76  sdcard->spi_p = spi_p;
77  sdcard->spi_t.slave_idx = slave_idx;
78  sdcard->spi_t.select = SPISelectUnselect;
79  sdcard->spi_t.status = SPITransDone;
80  sdcard->spi_t.cpol = SPICpolIdleLow;
81  sdcard->spi_t.cpha = SPICphaEdge1;
82  sdcard->spi_t.dss = SPIDss8bit;
83  sdcard->spi_t.bitorder = SPIMSBFirst;
84  sdcard->spi_t.cdiv = SPIDiv64;
85  sdcard->spi_t.input_buf = sdcard->input_buf;
86  sdcard->spi_t.output_buf = sdcard->output_buf;
87  sdcard->spi_t.input_length = 0;
88  sdcard->spi_t.output_length = 0;
89 
91  sdcard->card_type = SDCardType_Unknown;
93 }
94 
99 void sdcard_spi_periodic(struct SDCard *sdcard)
100 {
101 
102  /* Do nothing if spi transaction is in progress */
103  if (sdcard->spi_t.status == SPITransPending || sdcard->spi_t.status == SPITransRunning) {
104  return;
105  }
106 
107  switch (sdcard->status) {
108 
109  /* Send dummy clock to set SD card in SPI mode */
111  sdcard->spi_t.select = SPINoSelect;
112  sdcard->spi_t.output_length = 10;
113  sdcard->spi_t.input_length = 0;
114  for (uint8_t i = 0; i < 10; i++) {
115  sdcard->output_buf[i] = 0xFF;
116  }
118  spi_submit(sdcard->spi_p, &sdcard->spi_t);
120  break;
121 
122  /* Sending ACMD41 */
124  sdcard_spi_send_app_cmd(sdcard, 41, 0x40000000);
125  sdcard->timeout_counter++;
126  break;
127 
128  /* While busy, keep checking if it is still busy */
129  case SDCard_Busy:
130  sdcard_spi_request_bytes(sdcard, 1);
131  break;
132 
133  /* While waiting for data token, keep polling */
135  sdcard_spi_request_bytes(sdcard, 1);
136  sdcard->timeout_counter++;
137  break;
138 
139  /* While multiwrite busy, keep checking if it is still busy */
141  sdcard_spi_request_bytes(sdcard, 1);
142  break;
143 
144  default:
145  break;
146  }
147 
148 }
149 
150 
157 {
158  (void) t; // ignore unused warning
159 
160  switch (sdcard1.status) {
161 
162  /* Ready with dummy clock, proceed with CMD0 */
165  sdcard_spi_send_cmd(&sdcard1, 0, 0x00000000);
167  break;
168 
169  /* Ready sending CMD0, start polling result */
170  case SDCard_SendingCMD0:
174  break;
175 
176  /* Continue polling bytes until there is a response or not */
178  if (t->input_buf[0] == 0x01) {
179  sdcard_spi_send_cmd(&sdcard1, 8, 0x000001AA);
181  } else if (sdcard1.response_counter >= 9) {
184  } else {
186  }
187  break;
188 
189  /* Ready sending CMD8, start polling result */
190  case SDCard_SendingCMD8:
194  break;
195 
196  /* Continue polling bytes until there is a response or not */
198  if (t->input_buf[0] == 0x01) {
201  } else if (sdcard1.response_counter >= 9) {
204  } else {
206  }
207  break;
208 
209  /* Process parameter from CMD8 response (after 0x01 was received) */
211  if (sdcard1.input_buf[0] == 0x00 && sdcard1.input_buf[1] == 0x00 && sdcard1.input_buf[2] == 0x01
212  && sdcard1.input_buf[3] == 0xAA) {
215  } else {
218  }
219  break;
220 
221  /* Ready sending the ACMDv2 command, start polling bytes for response */
226  break;
227 
228  /* Grabbing bytes in response to the ACMD41v2 command */
230  if (t->input_buf[0] == 0x01) {
231  if (sdcard1.timeout_counter < 500 - 1) { /* Wait 500 cycles until timeout */
233  } else {
236  }
237  } else if (t->input_buf[0] == 0x00) {
238  sdcard_spi_send_cmd(&sdcard1, 58, 0x00000000);
240  } else if (sdcard1.response_counter >= 9) {
243  } else {
245  }
246  break;
247 
248  /* Ready sending CMD58, request the first byte of R3 response */
249  case SDCard_SendingCMD58:
253  break;
254 
255  /* Continue polling bytes until there is a response to CMD58 */
257  if (sdcard1.response_counter >= 9) {
260  } else if (sdcard1.input_buf[0] == 0x00) {
263  } else {
265  }
266  break;
267 
268  /* Parameter of CMD58 ready, processing it */
270  if (sdcard1.input_buf[0] & 0x80) { // bit 31 set, CCS bit is valid
271  if (sdcard1.input_buf[0] & 0x40) { // bit 30 set
274  } else { // bit 30 not set
278  }
279  } else { // bit 31 not set, CCS bit is unvalid
282  }
283  break;
284 
285  /* Ready sending CMD16, request first byte */
286  case SDCard_SendingCMD16:
290  break;
291 
292  /* Continue polling bytes until there is a response to CMD16 */
294  if (sdcard1.input_buf[0] == 0x00) {
296  } else if (sdcard1.response_counter >= 9) {
299  } else {
301  }
302  break;
303 
304  /* Ready sending CMD24, request first response byte */
305  case SDCard_SendingCMD24:
309  break;
310 
311  /* Request additional bytes until response or timeout */
313  if (sdcard1.input_buf[0] == 0x00) {
316  } else if (sdcard1.response_counter >= 9) {
319  } else {
321  }
322  break;
323 
324  /* Send the data block */
329  sdcard1.spi_t.output_buf[0] = 0xFE; // data token
330  sdcard1.spi_t.output_buf[SD_BLOCK_SIZE + 1] = 0xFF; // Fake CRC byte 1
331  sdcard1.spi_t.output_buf[SD_BLOCK_SIZE + 2] = 0xFF; // Fake CRC byte 2
332  sdcard1.spi_t.output_buf[SD_BLOCK_SIZE + 3] = 0xFF; // to request data response
336  } else {
339  }
340  break;
341 
342  /* Finished sending the data block */
344  if ((sdcard1.input_buf[SD_BLOCK_SIZE + 3] & 0x0F) == 0x05) {
346  } else {
349  }
351  break;
352 
353  case SDCard_Busy:
354  if (sdcard1.input_buf[0] != 0x00) {
356  }
357  break;
358 
359  /* Ready sending CMD17, request first response byte */
360  case SDCard_SendingCMD17:
364  break;
365 
366  /* Read response to CMD17 until response or timeout/error */
368  if (sdcard1.input_buf[0] == 0x00) {
372  } else if (sdcard1.response_counter >= 9) {
375  } else {
377  }
378  break;
379 
380  /* Processing byte to see if it is a data token */
382  if (sdcard1.input_buf[0] == 0xFE) { // Data token received
384  sdcard1.spi_t.input_length = SD_BLOCK_SIZE + 2; // 2 Fake CRC bytes
387  for (uint16_t i = 0; i < (SD_BLOCK_SIZE + 2); i++) {
388  sdcard1.output_buf[i] = 0xFF;
389  }
393  } else if (sdcard1.timeout_counter > 498) {
396  }
397  break;
398 
399  /* Data block received in buffer, process data */
402  if (sdcard1.external_callback != NULL) {
404  }
405  break;
406 
407  /* Ready sending CMD25, request first response byte */
408  case SDCard_SendingCMD25:
412  break;
413 
414  /* Request additional bytes until response or timeout */
416  if (sdcard1.input_buf[0] == 0x00) {
419  } else if (sdcard1.response_counter >= 9) {
422  } else {
424  }
425  break;
426 
427  /* Check the response after a block was written */
429  if ((sdcard1.input_buf[SD_BLOCK_SIZE + 3] & 0x0F) == 0x05 /* Data accepted */) {
431  if(sdcard1.external_callback != NULL) {
433  }
434  } else {
437  }
438  break;
439 
440  /* Check if sd card is still busy after a packet during multiwrite */
442  if (sdcard1.input_buf[0] != 0x00) {
444  }
445  break;
446 
447  /* Finished the stop command transaction, waiting for internal processes of the SD card */
450  break;
451 
452  /* Should not reach this */
453  default:
454  break;
455  }
456 }
457 
467 void sdcard_spi_send_cmd(struct SDCard *sdcard, uint8_t cmd, uint32_t arg)
468 {
469  (void) cmd; (void) arg;
470  sdcard->spi_t.input_length = 6;
471  sdcard->spi_t.output_length = 6;
472  sdcard->output_buf[0] = 0x40 | cmd;
473  sdcard->output_buf[1] = arg >> 24;
474  sdcard->output_buf[2] = arg >> 16;
475  sdcard->output_buf[3] = arg >> 8;
476  sdcard->output_buf[4] = arg;
477  switch (cmd) {
478  case 0:
479  sdcard->output_buf[5] = 0x95; /* CRC byte for CMD0 */
480  break;
481  case 8:
482  sdcard->output_buf[5] = 0x87; /* CRC byte for CMD8 */
483  break;
484  default:
485  sdcard->output_buf[5] = 0x01; /* Fake CRC byte, will be ignored by the SDCard */
486  }
488 
489  spi_submit(sdcard->spi_p, &sdcard->spi_t);
490 }
491 
502 void sdcard_spi_send_app_cmd(struct SDCard *sdcard, uint8_t cmd, uint32_t arg)
503 {
504  sdcard->spi_t.output_length = 21;
505  sdcard->spi_t.input_length = 21;
506 
507  sdcard->output_buf[0] = 0x77; /* Begin CMD55 */
508  sdcard->output_buf[1] = 0x00;
509  sdcard->output_buf[2] = 0x00;
510  sdcard->output_buf[3] = 0x00;
511  sdcard->output_buf[4] = 0x00;
512  sdcard->output_buf[5] = 0x01; /* End CMD55 */
513  sdcard->output_buf[6] = 0xFF; /* Somewhere during the following bytes, response to CMD55 is received. */
514  sdcard->output_buf[7] = 0xFF;
515  sdcard->output_buf[8] = 0xFF;
516  sdcard->output_buf[9] = 0xFF;
517  sdcard->output_buf[10] = 0xFF;
518  sdcard->output_buf[11] = 0xFF;
519  sdcard->output_buf[12] = 0xFF;
520  sdcard->output_buf[13] = 0xFF;
521  sdcard->output_buf[14] = 0xFF;
522 
523  sdcard->output_buf[15] = 0x40 + cmd; /* Begin of the ACMD */
524  sdcard->output_buf[16] = arg >> 24;
525  sdcard->output_buf[17] = arg >> 16;
526  sdcard->output_buf[18] = arg >> 8;
527  sdcard->output_buf[19] = arg;
528  sdcard->output_buf[20] = 0x01; /* End of the ACMD */
529 
530  /* Set function to be called after transfer is finished */
532 
533  /* Submit the transaction */
534  spi_submit(sdcard->spi_p, &sdcard->spi_t);
535 }
536 
543 void sdcard_spi_request_bytes(struct SDCard *sdcard, uint8_t len)
544 {
545  sdcard->spi_t.input_length = len;
546  sdcard->spi_t.output_length = len;
547  for (uint8_t i = 0; i < len; i++) {
548  sdcard->output_buf[i] = 0xFF;
549  }
551  spi_submit(sdcard->spi_p, &sdcard->spi_t);
552  sdcard->response_counter++;
553 }
554 
560 void sdcard_spi_write_block(struct SDCard *sdcard, uint32_t addr)
561 {
562  /* Do not write data if not in idle state */
563  if (sdcard->status != SDCard_Idle) {
564  return;
565  }
566 
567  /* To high transfer speed might cause problems. */
568  sdcard->spi_t.cdiv = SPIDiv64;
569 
570  /* Translate block address to byte address */
571  if (sdcard->card_type != SDCardType_SdV2block) {
572  addr = addr * SD_BLOCK_SIZE;
573  }
574 
575  /* Send command 24 (write block) to the SDCard */
576  sdcard_spi_send_cmd(sdcard, 24, addr);
577  sdcard->status = SDCard_SendingCMD24;
578 }
579 
587 void sdcard_spi_read_block(struct SDCard *sdcard, uint32_t addr, SDCardCallback callback)
588 {
589  /* Do not read data if not in idle state */
590  if (sdcard->status != SDCard_Idle) {
591  return;
592  }
593 
594  /* To high transfer speed might cause problems. */
595  sdcard->spi_t.cdiv = SPIDiv32;
596 
597  /* Translate block address to byte address */
598  if (sdcard->card_type != SDCardType_SdV2block) {
599  addr = addr * SD_BLOCK_SIZE;
600  }
601 
602  /* Set function to be called after the read action has finished. */
603  sdcard->external_callback = callback;
604 
605  /* Send command 17 (read block) to the SDCard */
606  sdcard_spi_send_cmd(sdcard, 17, addr);
607  sdcard->status = SDCard_SendingCMD17;
608 }
609 
616 void sdcard_spi_multiwrite_start(struct SDCard *sdcard, uint32_t addr)
617 {
618  /* Do not start multiwrite if not in idle state */
619  if (sdcard->status != SDCard_Idle) {
620  return;
621  }
622 
623  /* Translate block address to byte address */
624  if (sdcard->card_type != SDCardType_SdV2block) {
625  addr = addr * SD_BLOCK_SIZE;
626  }
627 
628  /* Send command 25 (start multiwrite) to the SDCard */
629  sdcard_spi_send_cmd(sdcard, 25, addr);
630  sdcard->status = SDCard_SendingCMD25;
631 }
632 
638 void sdcard_spi_multiwrite_next(struct SDCard *sdcard, SDCardCallback callback)
639 {
640  /* Can only write next block if card is in multiwrite mode and not currently busy */
641  if (sdcard->status != SDCard_MultiWriteIdle) {
642  return;
643  }
644  sdcard->spi_t.input_length = 516;
645  sdcard->spi_t.output_length = 516;
646  sdcard->spi_t.cdiv = SPIDiv32; /* Too high write speed can cause problems */
647  sdcard->spi_t.output_buf[0] = 0xFC; /* Data token specific for multiwrite */
648  sdcard->spi_t.output_buf[513] = 0xFF; /* Fake Fake CRC byte 1 */
649  sdcard->spi_t.output_buf[514] = 0xFF; /* Fake CRC byte 2 */
650  sdcard->spi_t.output_buf[515] = 0xFF; /* Polling for busy flag */
651 
652  /* Set the callback */
654  sdcard->external_callback = callback;
655 
656  /* Submit the spi transaction */
657  spi_submit(sdcard->spi_p, &sdcard->spi_t);
658 
660 }
661 
666 void sdcard_spi_multiwrite_stop(struct SDCard *sdcard)
667 {
668  /* Can only stop if card is in multiwrite mode and not currently busy */
669  if (sdcard->status != SDCard_MultiWriteIdle) {
670  return;
671  }
672  sdcard->spi_t.input_length = 2;
673  sdcard->spi_t.output_length = 2;
674  sdcard->spi_t.cdiv = SPIDiv32; /* Too high write speed can cause problems */
675  sdcard->output_buf[0] = 0xFD; /* Stop token specific for multiwrite */
676  sdcard->output_buf[1] = 0xFF; /* One dummy byte before polling if card is busy */
677 
678  /* Set the callback */
680 
681  /* Submit the spi transaction */
682  spi_submit(sdcard->spi_p, &sdcard->spi_t);
684 }
685 
Reading R1 response to CMD0 byte by byte.
Definition: sdcard_spi.h:63
Reading the 32-bit parameter after receiving 0x00 from CMD58.
Definition: sdcard_spi.h:71
unsigned short uint16_t
Definition: types.h:16
Busy sending CMD24.
Definition: sdcard_spi.h:74
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:149
Initialization sequence succesful.
Definition: sdcard_spi.h:58
Definition: spi.h:118
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:153
enum SDCardType card_type
Type of SDCard.
Definition: sdcard_spi.h:117
uint8_t input_buf[SD_BLOCK_SIZE+10]
The input buffer for the SPI transaction.
Definition: sdcard_spi.h:113
uint16_t output_length
number of data words to write
Definition: spi.h:146
uint8_t response_counter
Response counter used at various locations.
Definition: sdcard_spi.h:115
void sdcard_spi_send_cmd(struct SDCard *sdcard, uint8_t cmd, uint32_t arg)
Send a command to the SDCard.
Definition: sdcard_spi.c:467
void sdcard_spi_write_block(struct SDCard *sdcard, uint32_t addr)
Write a single block (512 bytes) to the SDCard at a given address.
Definition: sdcard_spi.c:560
Reading R1 response to CMD24 byte by byte.
Definition: sdcard_spi.h:75
About to send dummy clock cycles to initialize spi mode.
Definition: sdcard_spi.h:60
struct spi_transaction spi_t
The SPI transaction used for the writing and reading of registers.
Definition: sdcard_spi.h:111
enum SDCardStatus status
The status of the SD card.
Definition: sdcard_spi.h:112
Reading R3 response to CMD58 byte by byte.
Definition: sdcard_spi.h:70
void sdcard_spi_init(struct SDCard *sdcard, struct spi_periph *spi_p, const uint8_t slave_idx)
Configure initial values for SDCard.
Definition: sdcard_spi.c:74
void sdcard_spi_read_block(struct SDCard *sdcard, uint32_t addr, SDCardCallback callback)
Read a single block (512 bytes) from the SDCard at a given address.
Definition: sdcard_spi.c:587
uint8_t output_buf[SD_BLOCK_SIZE+10]
The output buffer for the SPI transaction.
Definition: sdcard_spi.h:114
Reading R7 response to CMD8 byte by byte.
Definition: sdcard_spi.h:65
SPI transaction structure.
Definition: spi.h:142
slave is not selected nor unselected
Definition: spi.h:60
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:505
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:152
Reading R1 response to CMD16 byte by byte.
Definition: sdcard_spi.h:73
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
SDCardCallback external_callback
Callback to call when external operation finishes.
Definition: sdcard_spi.h:119
void sdcard_spi_multiwrite_stop(struct SDCard *sdcard)
Stop with multiwrite procedure.
Definition: sdcard_spi.c:666
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
void sdcard_spi_multiwrite_next(struct SDCard *sdcard, SDCardCallback callback)
Write a(nother) data block (512 bytes) to the SDCard.
Definition: sdcard_spi.c:638
Busy reading data block.
Definition: sdcard_spi.h:81
void sdcard_spi_periodic(struct SDCard *sdcard)
Periodic function of the SDCard.
Definition: sdcard_spi.c:99
Reading the 32-bit parameter after receiving 0x01.
Definition: sdcard_spi.h:66
void sdcard_spi_send_app_cmd(struct SDCard *sdcard, uint8_t cmd, uint32_t arg)
Send a app-command to the SDCard.
Definition: sdcard_spi.c:502
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:150
SPI peripheral structure.
Definition: spi.h:168
Definition: spi.h:84
void sdcard_spi_request_bytes(struct SDCard *sdcard, uint8_t len)
Request one or more bytes from the SDCard.
Definition: sdcard_spi.c:543
#define SD_BLOCK_SIZE
Definition: sdcard_spi.h:38
void(* SDCardCallback)(void)
SDCard Callback function.
Definition: sdcard_spi.h:36
Busy sending CMD58.
Definition: sdcard_spi.h:69
Busy sending the stop token.
Definition: sdcard_spi.h:87
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:155
struct spi_periph * spi_p
The SPI peripheral for the connection.
Definition: sdcard_spi.h:110
Busy with the SPI transfer in multiwrite.
Definition: sdcard_spi.h:85
uint32_t timeout_counter
Timeout counter used for initialization checks with ACMD41.
Definition: sdcard_spi.h:116
unsigned long uint32_t
Definition: types.h:18
Busy sending CMD16.
Definition: sdcard_spi.h:72
An error has occured, sending debug message.
Definition: sdcard_spi.h:57
CPOL = 0.
Definition: spi.h:77
Busy sending data block.
Definition: sdcard_spi.h:77
Busy sending CMD0.
Definition: sdcard_spi.h:62
void sdcard_spi_multiwrite_start(struct SDCard *sdcard, uint32_t addr)
Start writing multiple blocks of 512 bytes to the SDCard.
Definition: sdcard_spi.c:616
uint16_t input_length
number of data words to read
Definition: spi.h:145
Busy sending CMD25 (multiwrite start command)
Definition: sdcard_spi.h:82
Interface for reading and writing blocks of data to and from an SD card directly over SPI...
Reading R1 response to CMD17 byte by byte.
Definition: sdcard_spi.h:79
enum SDCardErrorStatus error_status
Contains information on where the error has occured.
Definition: sdcard_spi.h:118
struct SDCard sdcard1
This is the definition of the SD card.
Definition: sdcard_spi.c:56
unsigned char uint8_t
Definition: types.h:14
Busy sending ACMD41.
Definition: sdcard_spi.h:67
CPHA = 0.
Definition: spi.h:68
slave is selected before transaction and unselected after
Definition: spi.h:57
Reading R1 response to CMD25 byte by byte.
Definition: sdcard_spi.h:83
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:147
SDCard is busy with internal process.
Definition: sdcard_spi.h:59
Busy sending CMD17 (block read request)
Definition: sdcard_spi.h:78
Definition: spi.h:119
Busy flag after sending data block in multiwrite.
Definition: sdcard_spi.h:86
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:143
Definition: spi.h:116
Busy sending CMD8.
Definition: sdcard_spi.h:64
CMD25 complete, ready to sent blocks.
Definition: sdcard_spi.h:84
void sdcard_spi_spicallback(struct spi_transaction *t)
Callback function for SPI transactions.
Definition: sdcard_spi.c:156
Busy sending dummy clock cycles.
Definition: sdcard_spi.h:61
Reading a byte each period until there is a data token or error.
Definition: sdcard_spi.h:80
Start data block transfer.
Definition: sdcard_spi.h:76
enum SPITransactionStatus status
Definition: spi.h:156
Reading R1 response to ACMD41 byte by byte.
Definition: sdcard_spi.h:68