ARMEBS4  revision-26.06.2015
stm32_sd.c
Go to the documentation of this file.
1 /**
2  * \file heivs/stm32_sd.c
3  * \brief SD memory card access for STM32 boards
4  * \author marc dot pignat at hevs dot ch
5  */
6 
7 #include "heivs/stm32_sd.h"
8 #include "stm32/stm32f4xx.h"
9 #include "stm32/stm32f4xx_gpio.h"
10 #include "stm32/stm32f4xx_rcc.h"
11 #include "stm32/stm32f4xx_dma.h"
12 #include "stm32/stm32f4xx_sdio.h"
13 #include "heivs/stm32_gpio.h"
14 
15 #include "heivs/time.h"
16 #include <string.h>
17 
18 #define SD_TIMEOUT_MS 1000
19 #define SD_BLOCK_SIZE 512
20 
21 enum direction_e
22 {
23  DIRECTION_NONE,
24  DIRECTION_TX,
25  DIRECTION_RX,
26 };
27 
28 struct sd_state_t
29 {
30  uint32_t sdhc;
31  uint32_t RCA;
32  uint32_t sector_count;
33  void *buf;
34  volatile enum direction_e direction;
35 };
36 static struct sd_state_t sd_state;
37 
38 #define DATATIMEOUT (0xFFFFFF) //I simply made this up. A method for computing a realistic values from CSD is described in the specs.
39 
40 //SDIO Commands Index
41 #define CMD0 ((uint8_t)0)
42 #define CMD8 ((uint8_t)8)
43 #define CMD55 ((uint8_t)55)
44 #define ACMD41 ((uint8_t)41)
45 #define CMD2 ((uint8_t)2)
46 #define CMD3 ((uint8_t)3)
47 #define CMD9 ((uint8_t)9)
48 #define CMD7 ((uint8_t)7)
49 #define ACMD6 ((uint8_t)6)
50 #define CMD24 ((uint8_t)24)
51 #define CMD25 ((uint8_t)25)
52 #define CMD12 ((uint8_t)12)
53 #define CMD13 ((uint8_t)13)
54 #define CMD17 ((uint8_t)17)
55 #define CMD18 ((uint8_t)18)
56 
57 //Auxilary defines
58 #define NORESP (0x00)
59 #define SHRESP (0x40)
60 #define LNRESP (0xC0)
61 #define R3RESP (0xF40) //Note this is totaly out of standard. However, becouse of the masking in status = SD_Command it will be processed as SHRESP
62 //R3 does not contain a valid CRC. Therefore, CCRCFAIL is set and CMDREND is never set for R3.
63 //To properly process R3, exit the loop CCRCFAIL condition and don't check CMDREND
64 
65 #define RESP_R1 (0x01)
66 #define RESP_R1b (0x02)
67 #define RESP_R2 (0x03)
68 #define RESP_R3 (0x04)
69 #define RESP_R6 (0x05)
70 #define RESP_R7 (0x06)
71 
72 static void SD_Panic(uint32_t code, const char *message) {(void)code; (void)message;}
73 
74 static const struct gpio_t detect_pin = DEF_GPIOC(13, GPIO_INPUT | GPIO_PULLUP | GPIO_SPEED_2);
75 status_e SD_Detect(void)
76 {
77  return gpio_get(&detect_pin) ? ERROR_SD_NOT_PRESENT : NO_ERROR;
78 }
79 
80 status_e SD_GetStatus(void)
81 {
82  if (sd_state.direction != DIRECTION_NONE)
83  {
84  return ERROR_AGAIN;
85  }
86 
87  return NO_ERROR;
88 }
89 
90 static status_e SD_Command(uint32_t cmd, uint32_t resp, uint32_t arg)
91 {
92  uint32_t sd_status;
93  timeout_t timeout = time_set_timeout_ms(SD_TIMEOUT_MS);
94  //Response must be:
95  //0,2:No response (expect cmdsent) ->NORESP
96  //1:Short Response (expect cmdrend and ccrcfail) ->SHRESP
97  //3:Long Response (expect cmdrend and ccrcfail) ->LNRESP
98 
99  //Clear the Command Flags
100  SDIO->ICR = (0x3<<22)|0x3ff;
101 
102  SDIO->ARG = arg; //First adjust the argument (because I will immediately enable CPSM next)
103  SDIO->CMD = (uint32_t) (cmd & SDIO_CMD_CMDINDEX)
104  | (resp & SDIO_CMD_WAITRESP) | (0x0400); //The last argument is to enable CSPM
105 
106  //Block till we get a response
107  if (resp == NORESP)
108  {
109  //We should wait for CMDSENT
110  while (1)
111  {
112  sd_status = SDIO->STA;
113 
114  if (sd_status & SDIO_STA_CMDSENT)
115  {
116  break;
117  }
118 
119  if (sd_status & SDIO_STA_CTIMEOUT)
120  {
121  return ERROR_TIMEOUT;
122  }
123 
124  if (time_elapsed(timeout))
125  {
126  return ERROR_TIMEOUT;
127  }
128  }
129  }
130  else
131  { //SHRESP or LNRESP or R3RESP
132  //We should wait for CMDREND or CCRCFAIL
133 
134  while (1)
135  {
136  sd_status = SDIO->STA;
137 
138  if (sd_status & SDIO_STA_CTIMEOUT)
139  {
140  SD_Panic(cmd, "SDIO: Command Timeout Error\n");
141  return ERROR_TIMEOUT;
142  }
143 
144  if (!(sd_status & SDIO_STA_CMDACT))
145  {
146  if (sd_status & (SDIO_STA_CMDREND | SDIO_FLAG_CCRCFAIL))
147  {
148  break;
149  }
150  }
151 
152  if (time_elapsed(timeout))
153  {
154  return ERROR_TIMEOUT;
155  }
156  }
157  }
158 
159  //Check to see if the response is valid
160  //We consider all R3 responses without a timeout as a valid response
161  //It seems CMDSENT and CMDREND are mutually exlusive. (though I am not sure. Check this later)
162  if (sd_status & SDIO_FLAG_CCRCFAIL)
163  {
164  if (resp == R3RESP)
165  {
166  return NO_ERROR;
167  }
168 
169  if (resp == LNRESP)
170  {
171  return NO_ERROR;
172  }
173  SD_Panic(cmd, "SDIO: Command CRC Error\n");
174  return ERROR_SD_ACCESS_FAILED;
175  }
176 
177  return NO_ERROR;
178 
179 }
180 
181 static status_e SD_Response(uint32_t *response, uint32_t type)
182 {
183  //I mainly use this to block the execution in case an unexpected response is received.
184  //Actually I don't need this at all. However, just for the sake of extra information I keep this. All I reall need is for this function to return SDIO->RESP1
185  //In the main code, I don't use the retun values at all. Perhaps I ought to have used void.
186 
187  //R1 Responses
188  if ((type == RESP_R1) || (type == RESP_R1b))
189  {
190  *response = SDIO->RESP1;
191  if (*response & (uint32_t) 0xFDFFE008)
192  { //All error bits must be zero
193  SD_Panic(SDIO->RESPCMD, "SDIO:Response Error\n");
194  return ERROR_SD_ACCESS_FAILED;
195  }
196  return NO_ERROR; //(*response & 0x1F00)>>8; //Return the card status
197  }
198 
199  if (type == RESP_R2)
200  { //CSD or CSI register. 128 bit
201  *response++ = SDIO->RESP1;
202  *response++ = SDIO->RESP2;
203  *response++ = SDIO->RESP3;
204  *response = SDIO->RESP4;
205 
206  return NO_ERROR; //0;
207  }
208 
209  if (type == RESP_R3)
210  { //OCR
211  if (SDIO->RESPCMD != 0x3F)
212  {
213  SD_Panic(SDIO->RESPCMD, "SDIO:Unexpected command index\n");
214  return ERROR_SD_ACCESS_FAILED;
215  } //CMD index for R3 must be 0x3F
216  *response = SDIO->RESP1; //Equals to OCR
217  return NO_ERROR; //0;
218  }
219 
220  if (type == RESP_R6)
221  { //RCA Response
222  if (SDIO->RESPCMD != 0x03)
223  {
224  SD_Panic(SDIO->RESPCMD, "SDIO:Unexpected command index\n");
225  return ERROR_SD_ACCESS_FAILED;
226  } //Only cmd3 generates R6 response
227  *response = SDIO->RESP1; //Equals to OCR
228 
229  return NO_ERROR; //(*response)>>16; //Return is equal to RCA. (The first 16 bit is equal to status)
230  }
231  else
232  { //RESP_R7:Card Interface condition. Obtained after CMD8
233  if (SDIO->RESPCMD != 0x08)
234  {
235  SD_Panic(SDIO->RESPCMD, "SDIO:Unexpected command index\n");
236  return ERROR_SD_ACCESS_FAILED;
237  } //Only cmd8 generates R7 response
238  *response = SDIO->RESP1;
239  if ((*response & 0xFF) != 0xAA)
240  {
241  SD_Panic(CMD8, "SDIO:Pattern did not match\n");
242  return ERROR_SD_ACCESS_FAILED;
243  } //Only cmd8 generates R7 response
244  return NO_ERROR; //((*response) & 0xFF00)>>8; //Echo back value
245  }
246 }
247 
248 static uint32_t dmable_buffer[SD_BLOCK_SIZE/sizeof(uint32_t)];
249 
250 static void SD_StartBlockTransfer(uint8_t *buf, uint32_t cnt, enum direction_e direction)
251 {
252  DMA_InitTypeDef SDDMA_InitStructure;
253 
254  DMA_ClearFlag(DMA2_Stream3,
255  DMA_FLAG_FEIF3 | DMA_FLAG_DMEIF3 | DMA_FLAG_TEIF3 | DMA_FLAG_HTIF3
256  | DMA_FLAG_TCIF3);
257 
258  /* DMA2 Stream3 or Stream6 disable */
259  DMA_Cmd(DMA2_Stream3, DISABLE);
260 
261  /* DMA2 Stream3 or Stream6 Config */
262  DMA_DeInit(DMA2_Stream3);
263 
264  SDDMA_InitStructure.DMA_Channel = DMA_Channel_4;
265  SDDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &SDIO->FIFO;
266  SDDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) dmable_buffer;
267 
268  if (direction == DIRECTION_TX)
269  {
270  memcpy(dmable_buffer, buf, SD_BLOCK_SIZE);
271  SDDMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
272  }
273  else
274  {
275  SDDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
276  }
277  SDDMA_InitStructure.DMA_BufferSize = 0;
278  SDDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
279  SDDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
280  SDDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
281  SDDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
282  SDDMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
283  SDDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
284  SDDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
285  SDDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
286  SDDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
287  SDDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4;
288  DMA_Init(DMA2_Stream3, &SDDMA_InitStructure);
289  DMA_ITConfig(DMA2_Stream3, DMA_IT_TC, ENABLE);
290  DMA_FlowControllerConfig(DMA2_Stream3, DMA_FlowCtrl_Peripheral);
291 
292  /* DMA2 Stream3 or Stream6 enable */
293  DMA_Cmd(DMA2_Stream3, ENABLE);
294 
295  ////PART II::::Adjust and enable SDIO Peripheral
296  //Clear the Data status flags
299  | SDIO_STA_DBCKEND);
300 
301  //First adjust the Dtimer and Data length
302  SDIO->DTIMER = (uint32_t) DATATIMEOUT;
303  SDIO->DLEN = cnt;
304 
305  //Now adjust DCTRL (and enable it at the same time)
306  uint32_t tempreg;
307  tempreg = 0; //Reset value
308  tempreg |= (uint32_t) 9 << 4; //Block size is SD_BLOCK_SIZE Compute log2(BlockSize) and shift 4bit
309  tempreg |= 1 << 3; //Enable the DMA
310  tempreg |= 0 << 2; //DTMode=Block Transfer (Actualy this is the reset value. Just a remainder)
311  if (direction == DIRECTION_RX)
312  {
313  tempreg |= SDIO_DCTRL_DTDIR;
314  }
315  tempreg |= 1; //DPSM is enabled
316  //Keep the rest at 0 => OTher SDIO functions is disabled(we don't need them)
317  SDIO->DCTRL = tempreg;
318  //End of PART II
319 
320  //Warn everyone that there may be a transfer in progress
321  sd_state.direction = direction;
322  sd_state.buf = buf;
323 }
324 
325 status_e SD_LowLevel_Init(void)
326 {
327  uint32_t tempreg;
328 
329  gpio_setup(&detect_pin);
330  GPIO_InitTypeDef GPIO_InitStructure;
331 
332  // GPIOC and GPIOD Periph clock enable
333  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
334 
335  //Initialize the pins
336  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_SDIO);
337  GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SDIO);
338  GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_SDIO);
339 
340  // Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins
341  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
342  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
343  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
344  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
345  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
346  GPIO_Init(GPIOC, &GPIO_InitStructure);
347 
348  // Configure PD.02 CMD line
349  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
350  GPIO_Init(GPIOD, &GPIO_InitStructure);
351 
352  // Configure PC.12 pin: CLK pin
353  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
354  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
355  GPIO_Init(GPIOC, &GPIO_InitStructure);
356 
357  //Enable the SDIO APB2 Clock
358  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE);
359 
360  // Enable the DMA2 Clock
361  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
362 
363  //Initialize the SDIO (with initial <400Khz Clock)
364  tempreg = 0; //Reset value
365  tempreg |= SDIO_CLKCR_CLKEN; //Clock is enabled
366  tempreg |= (uint32_t) 0x76; //Clock Divider. Clock=48000/(118+2)=400Khz
367  //Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width=0, Power save Disable
368  SDIO->CLKCR = tempreg;
369 
370  //Power up the SDIO
371  SDIO->POWER = 0x03;
372 
373  return NO_ERROR;
374 }
375 
376 static status_e compute_size(struct sd_state_t *state, uint32_t *CSD_Tab)
377 {
378  uint8_t tmp;
379  uint32_t tmp32;
380  uint32_t read_bl_len;
381 
382  /*!< Byte 5 */
383  tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16);
384 
385  read_bl_len = tmp & 0x0F;
386 
387  if (!state->sdhc)
388  {
389  uint32_t mul;
390  tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8);
391 
392  tmp32 = (tmp & 0x03) << 10;
393 
394  /*!< Byte 7 */
395  tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
396  tmp32 |= (tmp) << 2;
397 
398  /*!< Byte 8 */
399  tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
400  tmp32 |= (tmp & 0xC0) >> 6;
401 
402  /*!< Byte 9 */
403  tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
404  mul = (tmp & 0x03) << 1;
405  /*!< Byte 10 */
406  tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
407  mul |= (tmp & 0x80) >> 7;
408 
409  state->sector_count = (tmp32 + 1) ;
410  state->sector_count *= (1 << (mul + 2));
411  state->sector_count *= (1<<read_bl_len)/512;
412  }
413  else
414  {
415  uint32_t tmp32;
416 
417  /*!< Byte 7 */
418  tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
419  tmp32 = (tmp & 0x3F) << 16;
420 
421  /*!< Byte 8 */
422  tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
423 
424  tmp32 |= (tmp << 8);
425 
426  /*!< Byte 9 */
427  tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
428 
429  tmp32 |= (tmp);
430 
431  /*!< Byte 10 */
432  tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
433 
434  state->sector_count = tmp32 *1024;
435  }
436 
437  return NO_ERROR;
438 }
439 
440 status_e SD_Init(void)
441 {
442  timeout_t timeout = time_set_timeout_ms(SD_TIMEOUT_MS);
443  status_e status;
444  //uint32_t data;
445  uint32_t response;
446  uint32_t tempreg;
447 
448  //CMD0: GO_IDLE_STATE (No Response)
449  status = SD_Command(CMD0, NORESP, 0);
450  if (status != NO_ERROR)
451  {
452  return status;
453  }
454 
455  //CMD8: SEND_IF_COND //Response to CMD8 is R7. But I will ignore that response
456  status = SD_Command(CMD8, SHRESP, 0x000001AA); //Non v2.0 compliant sd's will cause panic here due to the timeout
457  if (status != NO_ERROR)
458  {
459  return status;
460  }
461  status = SD_Response(&response, RESP_R7); //AA is the check pattern. If response does not match with it, execution will be blocked in panic
462  if (status != NO_ERROR)
463  {
464  return status;
465  }
466 
467  while (1)
468  {
469  ////Send ACMD41
470  //CMD55
471  status = SD_Command(CMD55, SHRESP, 0); //Note that argument should be RCA. But at this point RCA of SD is 0. (It will be changed after cmd3)
472  status = SD_Response(&response, RESP_R1);
473 
474  //ACMD41 (Response is R3 which does not contain any CRC)
475  //Second argument in the argument indicates that host supports SDHC. We will check acmd41 response if the SD is SC or HC
476  status = SD_Command(ACMD41, R3RESP, (uint32_t) 0x80100000 | (uint32_t) 0x40000000);
477  status = SD_Response(&response, RESP_R3);
478 
479  //Check the ready status in the response (R3)
480  if ((response >> 31) == 1)
481  { //When card is busy this bit will be 0
482  //Card is now initialized. Check to see if SD is SC or HC
483  sd_state.sdhc = (response & 0x40000000) >> 30; //1=HC, 0=SC
484  break;
485  }
486 
487  if (time_elapsed(timeout))
488  {
489  SD_Panic(ACMD41, "SDIO:ACMD41 Timeout\n");
490  return ERROR_TIMEOUT;
491  }
492  }
493 
494  //Now we are in the Ready State. Ask for CID using CMD2
495  //Response is R2. RESP1234 are filled with CID. I will ignore them
496  status = SD_Command(CMD2, LNRESP, 0);
497  if (status != NO_ERROR)
498  {
499  return status;
500  }
501 
502  uint32_t cid[4];
503  status = SD_Response(cid, RESP_R2);
504  if (status != NO_ERROR)
505  {
506  return status;
507  }
508 
509  //Now the card is in the identification mode. Request for the RCA number with cmd3
510  status = SD_Command(CMD3, SHRESP, 0);
511  if (status != NO_ERROR)
512  {
513  return status;
514  }
515 
516  status = SD_Response(&response, RESP_R6);
517  if (status != NO_ERROR)
518  {
519  return status;
520  }
521  //Read the RCA
522  sd_state.RCA = response >> 16;
523 
524  //Now the card is in stand-by mode. From this point on I can change frequency as I wish (max24MHz)
525 
526  //Use cmd9 to read the card specific information
527  //Response is R2 with CSI. I will ignore the response
528  status = SD_Command(CMD9, LNRESP, (sd_state.RCA << 16));
529  if (status != NO_ERROR)
530  {
531  return status;
532  }
533 
534  uint32_t csd[4];
535  status = SD_Response(csd, RESP_R2);
536  if (status != NO_ERROR)
537  {
538  return status;
539  }
540 
541  status = compute_size(&sd_state, csd);
542  if (status != NO_ERROR)
543  {
544  return status;
545  }
546 
547  //Put the Card in the tranfer mode using cmd7. (I will change the clock spped later together with bus width)
548  //Bus width can only be changed in transfer mode
549  status = SD_Command(CMD7, SHRESP, (sd_state.RCA << 16));
550  if (status != NO_ERROR)
551  {
552  return status;
553  }
554  status = SD_Response(&response, RESP_R1);
555  if (status != NO_ERROR)
556  {
557  return status;
558  }
559 
560  //Change the bus-width with cmd6
561  //CMD55
562  status = SD_Command(CMD55, SHRESP, (sd_state.RCA << 16)); //Note the real RCA in the argument
563  if (status != NO_ERROR)
564  {
565  return status;
566  }
567 
568  status = SD_Response(&response, RESP_R1);
569  if (status != NO_ERROR)
570  {
571  return status;
572  }
573 
574  //ACMD6
575  //status = SD_Command(ACMD6, SHRESP, 0x02);
576  status = SD_Command(ACMD6, SHRESP, 0x00);
577  if (status != NO_ERROR)
578  {
579  return status;
580  }
581 
582  status = SD_Response(&response, RESP_R1);
583  if (status != NO_ERROR)
584  {
585  return status;
586  }
587 
588  //Configure SDIO->CLKCr for wide-bus width and new clock
589  tempreg = 0; //Reset value
590  /*
591  tempreg|=(0x01)<<11; //4 bit Bus Width
592  */
593  tempreg |= (0x00) << 11; // 1 bit bus
594  tempreg |= SDIO_CLKCR_CLKEN; //Clock is enabled
595  //Keep the rest at 0=> HW_Flow:Disabled, Rising Edge, Disable bypass, Power save Disable, Clock Division=0
596  //As the clock divider=0 => New clock=48/(Div+2)=48/2=24
597  SDIO->CLKCR = tempreg;
598 
599  //Now we can start issuing read/write commands
600  return NO_ERROR;
601 }
602 
603 status_e SD_GetSectorCount(uint32_t *count)
604 {
605  *count = sd_state.sector_count;
606  return NO_ERROR;
607 }
608 
609 status_e SD_WaitTransmissionEnd(void)
610 {
611  timeout_t timeout = time_set_timeout_ms(SD_TIMEOUT_MS);
612  //This function first checks if there is an ogoing tranmission and block till it ends.
613  //It then checks the data flags to see if there is an error. In case of an error it blocks
614  //Before the start of data transmission the data flags are all cleared. Therefore, calling this fucntion after a real transmission works as expected.
615 
616  ////Check if there is an ongoing transmission
617  //Check if the DMA is disabled (SDIO disables the DMA after it is done with it)
618  while (1)
619  {
620  if (!(DMA2_Stream3->CR & DMA_SxCR_EN))
621  {
622  break;
623  }
624 
625  if (time_elapsed(timeout))
626  {
627  return ERROR_TIMEOUT;
628  }
629  }
630 
631  //Wait for the DMA Interrupt flags if there exist a previous SDIO transfer.
632  if (sd_state.direction != DIRECTION_NONE)
633  {
634  if (DMA2->LISR
635  & (DMA_LISR_TCIF3 | DMA_LISR_TEIF3 | DMA_LISR_DMEIF3
636  | DMA_LISR_FEIF3))
637  {
638  if (!(DMA2->LISR & DMA_LISR_TCIF3))
639  { //A DMA error has occured. Panic!
640  SD_Panic(DMA2->LISR, "SDIO:DMA Error");
641  return ERROR_SD_ACCESS_FAILED;
642  }
643  }
644  }
645 
646  while (1)
647  {
648  if (!(SDIO->STA & (SDIO_STA_RXACT | SDIO_STA_TXACT)))
649  {
650  break;
651  }
652 
653  if (time_elapsed(timeout))
654  {
655  return ERROR_TIMEOUT;
656  }
657  }
658 
659  //if there exist a previous transmission, check if the transmission has been completed without error
660  if (sd_state.direction != DIRECTION_NONE)
661  {
662  //I will block here till I get a data response
663  while (!(SDIO->STA
665  | SDIO_IT_STBITERR)))
666  {
667  };
668  if (!(SDIO->STA & SDIO_STA_DBCKEND))
669  { //An Error has occured.
670  SD_Panic(SDIO->STA, "SDIO:Data Transmission Error\n");
671  return ERROR_SD_ACCESS_FAILED;
672  }
673  }
674 
675  //If we are here, we can be sure that there is no ongoing transmission any more
676  if (sd_state.direction == DIRECTION_RX)
677  {
678  memcpy(sd_state.buf, dmable_buffer, SD_BLOCK_SIZE);
679  }
680  sd_state.direction = DIRECTION_NONE;
681 
682  return NO_ERROR;
683 }
684 
685 status_e SD_WriteSingleBlock(const void *_buf, uint32_t blk)
686 {
687  status_e status;
688  const uint8_t *buf = _buf;
689  uint32_t WriteAddr;
690  uint32_t response;
691 
692  //uint32_t response;
693  WriteAddr = blk * SD_BLOCK_SIZE;
694  if (sd_state.sdhc == 1)
695  { //High Capacity
696  WriteAddr = blk;
697  }
698 
699  //CMD24:WRITE_SINGLE_BLOCK
700  status = SD_Command(CMD24, SHRESP, WriteAddr);
701  if (status != NO_ERROR)
702  {
703  return status;
704  }
705 
706  status = SD_Response(&response, RESP_R1);
707  if (status != NO_ERROR)
708  {
709  return status;
710  }
711 
712  //Card is now waiting some data from the Data lines. Start actual data transmission
713  SD_StartBlockTransfer((void *)buf, SD_BLOCK_SIZE, DIRECTION_TX);
714 
715  //Wait for transmission to end
716  status = SD_WaitTransmissionEnd();
717  if (status != NO_ERROR)
718  {
719  return status;
720  }
721 
722  return NO_ERROR;
723 }
724 
725 status_e SD_ReadSingleBlock(void *_buf, uint32_t blk)
726 {
727  status_e status;
728 
729  uint8_t *buf = _buf;
730  uint32_t ReadAddr;
731  uint32_t response;
732 
733  //uint32_t response;
734  ReadAddr = blk * SD_BLOCK_SIZE;
735  if (sd_state.sdhc == 1)
736  { //High Capacity
737  ReadAddr = blk;
738  }
739 
740  //Send CMD17:READ_SINGLE_BLOCK
741  status = SD_Command(CMD17, SHRESP, ReadAddr);
742  if (status != NO_ERROR)
743  {
744  return status;
745  }
746  status = SD_Response(&response, RESP_R1);
747  if (status != NO_ERROR)
748  {
749  return status;
750  }
751 
752  //Card is now ready to send some data from the Data lines. Start actual data transmission
753  SD_StartBlockTransfer(buf, SD_BLOCK_SIZE, DIRECTION_RX);
754 
755  //Wait for transmission to end
756  status = SD_WaitTransmissionEnd();
757  if (status != NO_ERROR)
758  {
759  return status;
760  }
761 
762  return NO_ERROR;
763 }
764 
765 #ifdef SD_MULTIBLOCK_WRITE
766 #warning SD_MULTIBLOCK_WRITE is completely untested
767 //Private Write buffers
768 static uint8_t DatBuf[SD_BLOCK_SIZE * 2]; //2 blocks (One will be in transit while other is being filled)
769 static uint8_t *pDatBuf = DatBuf;
770 static uint32_t BufCnt = 0;
771 #endif
772 
773 #ifdef SD_MULTIBLOCK_WRITE
774 status_e SD_StartMultipleBlockWrite(uint32_t blk)
775 {
776  status_e status;
777 
778  uint32_t WriteAddr;
779  uint32_t response;
780 
781  //uint32_t response;
782  WriteAddr = blk * SD_BLOCK_SIZE;
783  if (sd_state.sdhc == 1)
784  { //High Capacity
785  WriteAddr = blk;
786  }
787 
788  //CMD25:WRITE_MULT_BLOCK with argument data address
789  status = SD_Command(CMD25, SHRESP, WriteAddr);
790  if (status != NO_ERROR)
791  {
792  return status;
793  }
794  status = SD_Response(&response, RESP_R1);
795  if (status != NO_ERROR)
796  {
797  return status;
798  }
799 
800  //Clear any flags
801  SDIO->ICR = (uint32_t) 0xA003FF;
802 
803  return NO_ERROR;
804 }
805 
806 status_e SD_StopMultipleBlockWrite(void)
807 {
808  status_e status;
809  uint32_t response;
810 
811  //If there is previously programmed communication, wait for it to end first
812  status = SD_WaitTransmissionEnd();
813  if (status != NO_ERROR)
814  {
815  return status;
816  }
817 
818  //CMD12:STOP_TRANSMISSION
819  status = SD_Command(CMD12, SHRESP, 0);
820  status = SD_Response(&response, RESP_R1b);
821  //Discard the untransferred buffer
822  pDatBuf = DatBuf;
823  BufCnt = 0;
824 
825  while (((response & 0x100) >> 8) == 0)
826  {
827  //After CMD12, SD Card puts itself to the prg mode, by pulling D0 to low.
828  //DPSM is not aware of this. (I hope it is aware of this during multiblock communication. I need to verify this.
829  //If it is not, then I have to repeat the same procedure after each block during multiblock write which will cause too much overhead)
830  //Check Card status with CMD13 till, we get READY_FOR_DATA response
831  //CMD13:Send Status
832  status = SD_Command(CMD13, SHRESP, sd_state.RCA << 16);
833  status = SD_Response(&response, RESP_R1b);
834  }
835  return NO_ERROR;
836 }
837 
838 status_e SD_WriteData(uint8_t *buf, uint32_t cnt)
839 {
840  status_e status;
841 
842  while (cnt > 0)
843  {
844  //Copy the data to internal buffer
845  *pDatBuf = *buf;
846  pDatBuf++;
847  buf++;
848  cnt--;
849  BufCnt++;
850 
851  if (BufCnt == SD_BLOCK_SIZE)
852  { //Half Buffer is full.
853  //Write Buffer to the SD
854  status = SD_WaitTransmissionEnd(); //Wait for any previous transmission
855  if (status != NO_ERROR)
856  {
857  return status;
858  }
859  //Wait for busy.
860  //With SPI we can check this by reading the dataline. SD stops holding the data line when it is not busy.
861  //However in SDIO, the only way seems to use CMD13.
862  //I am going to skip this part assuming that DPSM handles this properly.
863  SD_StartBlockTransfer(pDatBuf - SD_BLOCK_SIZE, SD_BLOCK_SIZE, DIRECTION_TX);
864 
865  //Switch to other half (if necessary)
866  if (pDatBuf == (DatBuf + (SD_BLOCK_SIZE * 2)))
867  {
868  pDatBuf = DatBuf;
869  }
870 
871  //Reset Buffer counter
872  BufCnt = 0;
873  }
874  }
875  return NO_ERROR;
876 }
877 #endif /* SD_MULTIBLOCK_WRITE */
This file contains all the functions prototypes for the RCC firmware library.
This file contains all the functions prototypes for the GPIO firmware library.
uint32_t DMA_MemoryInc
Definition: stm32f4xx_dma.h:70
No comment.
Definition: error.h:64
uint32_t DMA_Channel
Definition: stm32f4xx_dma.h:50
GPIOOType_TypeDef GPIO_OType
DMA Init structure definition.
Definition: stm32f4xx_dma.h:48
#define SDIO_STA_TXUNDERR
Definition: stm32f4xx.h:5662
simple time abstraction
#define SDIO_STA_TXACT
Definition: stm32f4xx.h:5670
uint32_t DMA_MemoryBurst
Definition: stm32f4xx_dma.h:95
void * memcpy(void *dest, const void *src, size_t n)
GPIOSpeed_TypeDef GPIO_Speed
#define SDIO_STA_CMDACT
Definition: stm32f4xx.h:5669
uint32_t DMA_MemoryDataSize
Definition: stm32f4xx_dma.h:76
SD card not detected.
Definition: error.h:88
CMSIS Cortex-M4 Device Peripheral Access Layer Header File. This file contains all the peripheral reg...
#define SDIO_STA_CMDREND
Definition: stm32f4xx.h:5664
uint32_t DMA_DIR
Definition: stm32f4xx_dma.h:59
uint32_t DMA_PeripheralInc
Definition: stm32f4xx_dma.h:67
static uint32_t time_elapsed(timeout_t timeout)
Is this time passed?
Definition: time.h:71
uint32_t DMA_PeripheralDataSize
Definition: stm32f4xx_dma.h:73
static uint32_t gpio_get(const struct gpio_t *gpio)
Get gpio level.
Definition: stm32_gpio.h:219
SD memory card access for STM32 boards.
GPIO Init structure definition.
uint32_t DMA_PeripheralBurst
#define SDIO_DCTRL_DTDIR
Definition: stm32f4xx.h:5639
This file contains all the functions prototypes for the DMA firmware library.
board specific defines
uint32_t DMA_PeripheralBaseAddr
Definition: stm32f4xx_dma.h:53
uint32_t DMA_Memory0BaseAddr
Definition: stm32f4xx_dma.h:55
#define SDIO_STA_STBITERR
Definition: stm32f4xx.h:5667
GPIO control structure.
Definition: stm32_gpio.h:96
Input.
Definition: stm32_gpio.h:44
#define SDIO_STA_DBCKEND
Definition: stm32f4xx.h:5668
This file contains all the functions prototypes for the SDIO firmware library.
uint32_t DMA_FIFOThreshold
Definition: stm32f4xx_dma.h:92
#define SDIO_STA_DATAEND
Definition: stm32f4xx.h:5666
GPIOMode_TypeDef GPIO_Mode
Retry later.
Definition: error.h:49
#define SDIO_STA_CMDSENT
Definition: stm32f4xx.h:5665
uint32_t DMA_FIFOMode
Definition: stm32f4xx_dma.h:87
#define SDIO_STA_DTIMEOUT
Definition: stm32f4xx.h:5661
#define DEF_GPIOC(__PIN, __MODE)
same as DEF_GPIOA for port C
Definition: stm32_gpio.h:361
Timeout structure.
Definition: time.h:34
No comment.
Definition: error.h:89
timeout_t time_set_timeout_ms(uint32_t ms)
Set an obscure time at least ms milliseconds in the future.
Definition: time.c:15
uint32_t DMA_Mode
Definition: stm32f4xx_dma.h:79
#define SDIO_STA_DCRCFAIL
Definition: stm32f4xx.h:5659
#define SDIO_CMD_WAITRESP
Definition: stm32f4xx.h:5601
#define SDIO_CMD_CMDINDEX
Definition: stm32f4xx.h:5599
Output speed : 2 MHz.
Definition: stm32_gpio.h:68
status_e gpio_setup(const struct gpio_t *gpio)
Setup a gpio.
Definition: stm32_gpio.c:9
uint32_t DMA_BufferSize
Definition: stm32f4xx_dma.h:63
GPIOPuPd_TypeDef GPIO_PuPd
status_e
Known errors.
Definition: error.h:21
uint32_t DMA_Priority
Definition: stm32f4xx_dma.h:84
#define SDIO_CLKCR_CLKEN
Definition: stm32f4xx.h:5584
#define SDIO_STA_RXACT
Definition: stm32f4xx.h:5671
No error.
Definition: error.h:28
#define SDIO_STA_CTIMEOUT
Definition: stm32f4xx.h:5660
Pull up.
Definition: stm32_gpio.h:83
#define SDIO_STA_RXOVERR
Definition: stm32f4xx.h:5663