sdcard.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. #include "sdcard.h"
  2. #include "stm32f4xx.h"
  3. #include <stm32f4xx_gpio.h>
  4. static uint32_t SD_Command(uint32_t cmd, uint32_t resp, uint32_t arg);
  5. static uint32_t SD_Response(uint32_t *response, uint32_t type);
  6. static void SD_Panic(uint32_t code, char *message);
  7. static void SD_StartBlockTransfer(uint8_t *buf, uint32_t cnt, uint32_t dir);
  8. static uint32_t SDType;
  9. static uint32_t RCA;
  10. static volatile uint32_t SDIOTxRx=0;
  11. //Private Write buffers
  12. static uint8_t DatBuf[512*2]; //2 blocks (One will be in transit while other is being filled)
  13. static uint8_t *pDatBuf=DatBuf;
  14. static uint32_t BufCnt=0;
  15. #define DATATIMEOUT (0xFFFFFF) //I simply made this up. A method for computing a realistic values from CSD is described in the specs.
  16. //SDIO Commands Index
  17. #define CMD0 ((uint8_t)0)
  18. #define CMD8 ((uint8_t)8)
  19. #define CMD55 ((uint8_t)55)
  20. #define ACMD41 ((uint8_t)41)
  21. #define CMD2 ((uint8_t)2)
  22. #define CMD3 ((uint8_t)3)
  23. #define CMD9 ((uint8_t)9)
  24. #define CMD7 ((uint8_t)7)
  25. #define ACMD6 ((uint8_t)6)
  26. #define CMD24 ((uint8_t)24)
  27. #define CMD25 ((uint8_t)25)
  28. #define CMD12 ((uint8_t)12)
  29. #define CMD13 ((uint8_t)13)
  30. #define CMD17 ((uint8_t)17)
  31. #define CMD18 ((uint8_t)18)
  32. //Auxilary defines
  33. #define NORESP (0x00)
  34. #define SHRESP (0x40)
  35. #define LNRESP (0xC0)
  36. #define R3RESP (0xF40) //Note this is totaly out of standard. However, becouse of the masking in SD_Command it will be processed as SHRESP
  37. //R3 does not contain a valid CRC. Therefore, CCRCFAIL is set and CMDREND is never set for R3.
  38. //To properly process R3, exit the loop CCRCFAIL condition and don't check CMDREND
  39. #define RESP_R1 (0x01)
  40. #define RESP_R1b (0x02)
  41. #define RESP_R2 (0x03)
  42. #define RESP_R3 (0x04)
  43. #define RESP_R6 (0x05)
  44. #define RESP_R7 (0x06)
  45. #define UM2SD (0x00) //Transfer Direction
  46. #define SD2UM (0x02)
  47. void SD_LowLevel_Init(void) {
  48. uint32_t tempreg;
  49. GPIO_InitTypeDef GPIO_InitStructure;
  50. // GPIOC and GPIOD Periph clock enable
  51. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
  52. //Initialize the pins
  53. GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_SDIO);
  54. GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_SDIO);
  55. GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SDIO);
  56. GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_SDIO);
  57. GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SDIO);
  58. GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_SDIO);
  59. // Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins
  60. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
  61. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  62. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  63. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  64. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  65. GPIO_Init(GPIOC, &GPIO_InitStructure);
  66. // Configure PD.02 CMD line
  67. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  68. GPIO_Init(GPIOD, &GPIO_InitStructure);
  69. // Configure PC.12 pin: CLK pin
  70. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  71. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  72. GPIO_Init(GPIOC, &GPIO_InitStructure);
  73. //Enable the SDIO APB2 Clock
  74. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE);
  75. // Enable the DMA2 Clock
  76. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  77. //Initialize the SDIO (with initial <400Khz Clock)
  78. tempreg=0; //Reset value
  79. tempreg|=SDIO_CLKCR_CLKEN; //Clock is enabled
  80. tempreg|= (uint32_t)0xFF;//(uint32_t)0x76; //Clock Divider. Clock=48000/(118+2)=400Khz
  81. //Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width=0, Power save Disable
  82. SDIO->CLKCR=tempreg;
  83. //Power up the SDIO
  84. SDIO->POWER = 0x03;
  85. }
  86. void SD_Init(void){
  87. //uint32_t data;
  88. uint32_t response;
  89. uint32_t TimeOut=0xFFFF;
  90. uint32_t tempreg;
  91. //CMD0: GO_IDLE_STATE (No Response)
  92. SD_Command(CMD0, NORESP, 0);
  93. //CMD8: SEND_IF_COND //Response to CMD8 is R7. But I will ignore that response
  94. SD_Command(CMD8, SHRESP, 0x000001AA); //Non v2.0 compliant sd's will cause panic here due to the timeout
  95. SD_Response(&response, RESP_R7); //AA is the check pattern. If response does not match with it, execution will be blocked in panic
  96. while (1) {
  97. ////Send ACMD41
  98. //CMD55
  99. 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)
  100. SD_Response(&response, RESP_R1);
  101. //ACMD41 (Response is R3 which does not contain any CRC)
  102. //Second argument in the argument indicates that host supports SDHC. We will check acmd41 response if the SD is SC or HC
  103. SD_Command(ACMD41, R3RESP, (uint32_t) 0x80100000 | (uint32_t) 0x40000000);
  104. SD_Response(&response, RESP_R3);
  105. //Check the ready status in the response (R3)
  106. if ((response >> 31) == 1) { //When card is busy this bit will be 0
  107. //Card is now initialized. Check to see if SD is SC or HC
  108. SDType=(response & 0x40000000) >> 30; //1=HC, 0=SC
  109. break;
  110. } else {
  111. TimeOut--;
  112. if (!TimeOut) {
  113. SD_Panic(ACMD41, "SDIO:ACMD41 Timeout\n");
  114. }
  115. }
  116. }
  117. //Now we are in the Ready State. Ask for CID using CMD2
  118. //Response is R2. RESP1234 are filled with CID. I will ignore them
  119. SD_Command(CMD2, LNRESP, 0);
  120. //Now the card is in the identification mode. Request for the RCA number with cmd3
  121. SD_Command(CMD3, SHRESP, 0);
  122. SD_Response(&response, RESP_R6);
  123. //Read the RCA
  124. RCA=response>>16;
  125. //Now the card is in stand-by mode. From this point on I can change frequency as I wish (max24MHz)
  126. //Use cmd9 to read the card specific information
  127. //Response is R2 with CSI. I will ignore the response
  128. SD_Command(CMD9, LNRESP, (RCA << 16));
  129. //Put the Card in the tranfer mode using cmd7. (I will change the clock spped later together with bus width)
  130. //Bus width can only be changed in transfer mode
  131. SD_Command(CMD7, SHRESP, (RCA << 16));
  132. SD_Response(&response, RESP_R1);
  133. //Change the bus-width with cmd6
  134. //CMD55
  135. SD_Command(CMD55, SHRESP, (RCA << 16)); //Note the real RCA in the argument
  136. SD_Response(&response, RESP_R1);
  137. //ACMD6
  138. SD_Command(ACMD6, SHRESP, 0x02);
  139. SD_Response(&response, RESP_R1);
  140. //Configure SDIO->CLKCr for wide-bus width and new clock
  141. tempreg=0; //Reset value
  142. //tempreg|=(0x01)<<11; //4 bit Bus Width
  143. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  144. // ÎÑÒÀÂËßÅÌ ÏÎ ÓÌÎË×ÀÍÈÞ 1áèò øèíû
  145. // áèòû 11-12 = 00
  146. tempreg|=SDIO_CLKCR_CLKEN; //Clock is enabled
  147. //Keep the rest at 0=> HW_Flow:Disabled, Rising Edge, Disable bypass, Power save Disable, Clock Division=0
  148. //As the clock divider=0 => New clock=48/(Div+2)=48/2=24
  149. SDIO->CLKCR=tempreg;
  150. //Now we can start issuing read/write commands
  151. }
  152. void SD_WriteSingleBlock(uint8_t *buf, uint32_t blk) {
  153. uint32_t WriteAddr;
  154. uint32_t response;
  155. //uint32_t response;
  156. if (SDType==1) { //High Capacity
  157. WriteAddr=blk;
  158. } else if (SDType==0) {//Standard Capacity
  159. WriteAddr=blk*512;
  160. }
  161. //CMD24:WRITE_SINGLE_BLOCK
  162. SD_Command(CMD24, SHRESP, WriteAddr);
  163. SD_Response(&response, RESP_R1);
  164. //Card is now waiting some data from the Data lines. Start actual data transmission
  165. SD_StartBlockTransfer(buf, 512, UM2SD);
  166. //Wait for transmission to end
  167. SD_WaitTransmissionEnd();
  168. }
  169. void SD_ReadSingleBlock(uint8_t *buf, uint32_t blk) {
  170. uint32_t ReadAddr;
  171. uint32_t response;
  172. //uint32_t response;
  173. if (SDType==1) { //High Capacity
  174. ReadAddr=blk;
  175. } else if (SDType==0) {//Standard Capacity
  176. ReadAddr=blk*512;
  177. }
  178. //Send CMD17:READ_SINGLE_BLOCK
  179. SD_Command(CMD17, SHRESP, ReadAddr);
  180. SD_Response(&response, RESP_R1);
  181. //Card is now ready to send some data from the Data lines. Start actual data transmission
  182. SD_StartBlockTransfer(buf, 512, SD2UM);
  183. //Wait for transmission to end
  184. SD_WaitTransmissionEnd();
  185. }
  186. void SD_StartMultipleBlockWrite(uint32_t blk) {
  187. uint32_t WriteAddr;
  188. uint32_t response;
  189. //uint32_t response;
  190. if (SDType==1) { //High Capacity
  191. WriteAddr=blk;
  192. } else if (SDType==0) {//Standard Capacity
  193. WriteAddr=blk*512;
  194. }
  195. //CMD25:WRITE_MULT_BLOCK with argument data address
  196. SD_Command(CMD25, SHRESP, WriteAddr);
  197. SD_Response(&response, RESP_R1);
  198. //Clear any flags
  199. SDIO->ICR=(uint32_t) 0xA003FF;
  200. return;
  201. }
  202. void SD_StopMultipleBlockWrite(void) {
  203. uint32_t response;
  204. //If there is previously programmed communication, wait for it to end first
  205. SD_WaitTransmissionEnd();
  206. //CMD12:STOP_TRANSMISSION
  207. SD_Command(CMD12, SHRESP, 0);
  208. SD_Response(&response, RESP_R1b);
  209. //Discard the untransferred buffer
  210. pDatBuf=DatBuf;
  211. BufCnt=0;
  212. while (((response & 0x100)>>8)==0) {
  213. //After CMD12, SD Card puts itself to the prg mode, by pulling D0 to low.
  214. //DPSM is not aware of this. (I hope it is aware of this during multiblock communication. I need to verify this.
  215. //If it is not, then I have to repeat the same procedure after each block during multiblock write which will cause too much overhead)
  216. //Check Card status with CMD13 till, we get READY_FOR_DATA response
  217. //CMD13:Send Status
  218. SD_Command(CMD13, SHRESP, RCA << 16);
  219. SD_Response(&response, RESP_R1b);
  220. }
  221. }
  222. void SD_WriteData(uint8_t *buf, uint32_t cnt) {
  223. while (cnt>0) {
  224. //Copy the data to internal buffer
  225. *pDatBuf=*buf;
  226. pDatBuf++;
  227. buf++;
  228. cnt--;
  229. BufCnt++;
  230. if (BufCnt==512) {//Half Buffer is full.
  231. //Write Buffer to the SD
  232. SD_WaitTransmissionEnd(); //Wait for any previous transmission
  233. //Wait for busy.
  234. //With SPI we can check this by reading the dataline. SD stops holding the data line when it is not busy.
  235. //However in SDIO, the only way seems to use CMD13.
  236. //I am going to skip this part assuming that DPSM handles this properly.
  237. SD_StartBlockTransfer(pDatBuf-512, 512, UM2SD);
  238. //Switch to other half (if necessary)
  239. if (pDatBuf==(DatBuf+(512*2))) {pDatBuf=DatBuf;}
  240. //Reset Buffer counter
  241. BufCnt=0;
  242. }
  243. }
  244. }
  245. static uint32_t SD_Command(uint32_t cmd, uint32_t resp, uint32_t arg) {
  246. //Response must be:
  247. //0,2:No response (expect cmdsent) ->NORESP
  248. //1:Short Response (expect cmdrend and ccrcfail) ->SHRESP
  249. //3:Long Response (expect cmdrend and ccrcfail) ->LNRESP
  250. //Clear the Command Flags
  251. SDIO->ICR=(SDIO_STA_CCRCFAIL | SDIO_STA_CTIMEOUT | SDIO_STA_CMDREND | SDIO_STA_CMDSENT);
  252. SDIO->ARG=arg; //First adjust the argument (because I will immediately enable CPSM next)
  253. SDIO->CMD=(uint32_t)(cmd & SDIO_CMD_CMDINDEX) | (resp & SDIO_CMD_WAITRESP) | (0x0400); //The last argument is to enable CSPM
  254. //Block till we get a response
  255. if (resp==NORESP) {
  256. //We should wait for CMDSENT
  257. while (!(SDIO->STA & (SDIO_STA_CTIMEOUT | SDIO_STA_CMDSENT))) {};
  258. }
  259. else {//SHRESP or LNRESP or R3RESP
  260. //We should wait for CMDREND or CCRCFAIL
  261. while (!(SDIO->STA & (SDIO_STA_CTIMEOUT | SDIO_STA_CMDREND | SDIO_FLAG_CCRCFAIL))) {};
  262. }
  263. //Check to see if the response is valid
  264. //We consider all R3 responses without a timeout as a valid response
  265. //It seems CMDSENT and CMDREND are mutually exlusive. (though I am not sure. Check this later)
  266. if (SDIO->STA & SDIO_STA_CTIMEOUT) {
  267. SD_Panic(cmd, "SDIO: Command Timeout Error\n");
  268. } else if ((SDIO->STA & SDIO_FLAG_CCRCFAIL) && (resp!=R3RESP)) {
  269. SD_Panic(cmd, "SDIO: Command CRC Error\n");
  270. }
  271. return SDIO->STA;
  272. }
  273. static void SD_Panic(uint32_t code, char *message) {
  274. uint32_t i=0;
  275. printf("%s\r\n", message);
  276. //Block the execution with blinky leds
  277. while (1) {
  278. GPIO_SetBits(GPIOD, GPIO_Pin_13 | GPIO_Pin_12);
  279. GPIO_ResetBits(GPIOD, GPIO_Pin_15 | GPIO_Pin_14);
  280. i=168000000 / 4;
  281. while(i--){}
  282. GPIO_ResetBits(GPIOD, GPIO_Pin_13 | GPIO_Pin_12);
  283. GPIO_SetBits(GPIOD, GPIO_Pin_15 | GPIO_Pin_14);
  284. i=168000000 / 4;
  285. while(i--){}
  286. }
  287. }
  288. static uint32_t SD_Response(uint32_t *response, uint32_t type) {
  289. //I mainly use this to block the execution in case an unexpected response is received.
  290. //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
  291. //In the main code, I don't use the retun values at all. Perhaps I ought to have used void.
  292. //R1 Responses
  293. if ((type==RESP_R1) || (type==RESP_R1b)) {
  294. *response=SDIO->RESP1;
  295. if (SDIO->RESP1 & (uint32_t)0xFDFFE008) { //All error bits must be zero
  296. SD_Panic(SDIO->RESPCMD, "SDIO:Response Error\n");
  297. }
  298. return (*response & 0x1F00)>>8; //Return the card status
  299. }
  300. else if (type==RESP_R2) { //CSD or CSI register. 128 bit
  301. *response++=SDIO->RESP1;
  302. *response++=SDIO->RESP2;
  303. *response++=SDIO->RESP3;
  304. *response=SDIO->RESP4;
  305. return 0;
  306. }
  307. else if (type==RESP_R3) { //OCR
  308. if (SDIO->RESPCMD != 0x3F) {SD_Panic(SDIO->RESPCMD,"SDIO:Unexpected command index\n");} //CMD index for R3 must be 0x3F
  309. *response=SDIO->RESP1; //Equals to OCR
  310. return 0;
  311. }
  312. else if (type==RESP_R6) { //RCA Response
  313. if (SDIO->RESPCMD != 0x03) {SD_Panic(SDIO->RESPCMD,"SDIO:Unexpected command index\n");} //Only cmd3 generates R6 response
  314. *response=SDIO->RESP1; //Equals to OCR
  315. return (*response)>>16; //Return is equal to RCA. (The first 16 bit is equal to status)
  316. }
  317. else { //RESP_R7:Card Interface condition. Obtained after CMD8
  318. if (SDIO->RESPCMD != 0x08) {SD_Panic(SDIO->RESPCMD,"SDIO:Unexpected command index\n");} //Only cmd8 generates R7 response
  319. *response=SDIO->RESP1;
  320. if ((*response & 0xFF)!=0xAA) {SD_Panic(CMD8, "SDIO:Pattern did not match\n");} //Only cmd8 generates R7 response
  321. return ((*response) & 0xFF00)>>8; //Echo back value
  322. }
  323. }
  324. static void SD_StartBlockTransfer(uint8_t *buf, uint32_t cnt, uint32_t dir){
  325. //cnt must be integer multiple of 512!!! I will enforce this inside this function
  326. //Starts the actual data tranfer using the DMA.
  327. //Prior to calling this command. The SDCard must have been adjusted using commands
  328. uint32_t tempreg;
  329. //Make cnt an integer multiple of 512
  330. //Then mask it with the maximum value allowed (2^24)
  331. cnt=0x01FFFFFF & ((cnt>>8) << 8);
  332. /////PART I::::Adjust the DMA
  333. //Reset the control register (0x00 is the default value. this also disables the dma. When EN=0, it stops any ongoing DMA transfer)
  334. DMA2_Stream3->CR=0;
  335. //Clear all the flags
  336. DMA2->LIFCR=DMA_LIFCR_CTCIF3 | DMA_LIFCR_CTEIF3 | DMA_LIFCR_CDMEIF3 | DMA_LIFCR_CFEIF3 | DMA_LIFCR_CHTIF3;
  337. //Set the DMA Addresses
  338. DMA2_Stream3->PAR=((uint32_t) 0x40012C80); //SDIO FIFO Address (=SDIO Base+0x80)
  339. DMA2_Stream3->M0AR=(uint32_t) buf; //Memory address
  340. //Set the number of data to transfer
  341. DMA2_Stream3->NDTR=0; //Peripheral controls, therefore we don't need to indicate a size
  342. //Set the DMA CR
  343. tempreg=0;
  344. tempreg|=(0x04<<25) & DMA_SxCR_CHSEL; //Select Channel 4
  345. tempreg|=(0x01<<23) & DMA_SxCR_MBURST; //4 beat memory burst (memory is 32word. Therefore, each time dma access memory, it reads 4*32 bits) (FIFO size must be integer multiple of memory burst)(FIFO is 4byte. Therefore we can only use 4 beat in this case)
  346. //Note: Ref manual (p173 (the node at the end of 8.3.11) says that burst mode is not allowed when Pinc=0. However, it appears that this is not true at all. Furthermore. when I set pBurst=0, the SDIO's dma control does not work at all.)
  347. tempreg|=(0x01<<21) & DMA_SxCR_PBURST; //4 beat memory burst Mode ([Burst Size*Psize] must be equal to [FIFO size] to prevent FIFO underrun and overrun errors) (burst also does not work in direct mode).
  348. tempreg|=(0x00<<18) & DMA_SxCR_DBM; //Disable double buffer mode (when this is set, circluar mode is also automatically set. (the actual value is don't care)
  349. tempreg|=(0x03<<16) & DMA_SxCR_PL; //Priority is very_high
  350. tempreg|=(0x00<<15) & DMA_SxCR_PINCOS; //Peripheral increment offset (if this is 1 and Pinc=1, then Peripheral will be incremented by 4 regardless of Psize)
  351. tempreg|=(0x02<<13) & DMA_SxCR_MSIZE; //Memory data size is 32bit (word)
  352. tempreg|=(0x02<<11) & DMA_SxCR_PSIZE; //Peripheral data size is 32bit (word)
  353. tempreg|=(0x01<<10) & DMA_SxCR_MINC; //Enable Memory Increment
  354. tempreg|=(0x00<<9) & DMA_SxCR_MINC; //Disable Peripheral Increment
  355. tempreg|=(0x00<<8) & DMA_SxCR_CIRC; //Disable Circular mode
  356. //tempreg|=(0x00<<6) & DMA_SxCR_DIR; //Direction 0:P2M, 1:M2P
  357. tempreg|=(0x01<<5) & DMA_SxCR_PFCTRL; //Peripheral controls the flow control. (The DMA tranfer ends when the data issues end of transfer signal regardless of ndtr value)
  358. //Bit [4..1] is for interupt mask. I don't use interrupts here
  359. //Bit 0 is EN. I will set it after I set the FIFO CR. (FIFO CR cannot be modified when EN=1)
  360. DMA2_Stream3->CR=tempreg;
  361. //Set the FIFO CR
  362. tempreg=0x21; //Reset value
  363. tempreg|=(0<<7); //FEIE is disabled
  364. tempreg|=(1<<2); //Fifo is enabled (Direct mode is disabled);
  365. tempreg|=3; //Full fifo (Fifo threshold selection)
  366. DMA2_Stream3->FCR=tempreg;
  367. //Set the Direction of transfer
  368. if (dir==UM2SD) {
  369. DMA2_Stream3->CR|=(0x01<<6) & DMA_SxCR_DIR;
  370. } else if (dir==SD2UM) {
  371. DMA2_Stream3->CR|=(0x00<<6) & DMA_SxCR_DIR;
  372. }
  373. //Enable the DMA (When it is enabled, it starts to respond dma requests)
  374. DMA2_Stream3->CR|=DMA_SxCR_EN;
  375. //END of PART I
  376. ////PART II::::Adjust and enable SDIO Peripheral
  377. //Clear the Data status flags
  378. SDIO->ICR=(SDIO_STA_DCRCFAIL | SDIO_STA_DTIMEOUT | SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR | SDIO_STA_DATAEND | SDIO_STA_STBITERR | SDIO_STA_DBCKEND);
  379. //First adjust the Dtimer and Data length
  380. SDIO->DTIMER=(uint32_t) DATATIMEOUT;
  381. SDIO->DLEN=cnt;
  382. //Now adjust DCTRL (and enable it at the same time)
  383. tempreg=0; //Reset value
  384. tempreg|=(uint32_t) 9 << 4; //Block size is 512 Compute log2(BlockSize) and shift 4bit
  385. tempreg|= 1<<3; //Enable the DMA
  386. tempreg|= 0<<2; //DTMode=Block Transfer (Actualy this is the reset value. Just a remainder)
  387. tempreg|=(dir & SDIO_DCTRL_DTDIR); //Direction. 0=Controller to card, 1=Card to Controller
  388. tempreg|=1; //DPSM is enabled
  389. //Keep the rest at 0 => OTher SDIO functions is disabled(we don't need them)
  390. SDIO->DCTRL=tempreg;
  391. //End of PART II
  392. //Warn everyone that there may be a transfer in progress
  393. SDIOTxRx=1;
  394. }
  395. void SD_WaitTransmissionEnd(void) {
  396. //This function first checks if there is an ogoing tranmission and block till it ends.
  397. //It then checks the data flags to see if there is an error. In case of an error it blocks
  398. //Before the start of data transmission the data flags are all cleared. Therefore, calling this fucntion after a real transmission works as expected.
  399. ////Check if there is an ongoing transmission
  400. //Check if the DMA is disabled (SDIO disables the DMA after it is done with it)
  401. while (DMA2_Stream3->CR & DMA_SxCR_EN) {};
  402. //Wait for the DMA Interrupt flags if there exist a previous SDIO transfer.
  403. if (SDIOTxRx) {
  404. if (DMA2->LISR & (DMA_LISR_TCIF3 | DMA_LISR_TEIF3 | DMA_LISR_DMEIF3 | DMA_LISR_FEIF3)) {
  405. if (!(DMA2->LISR & DMA_LISR_TCIF3)) {//A DMA error has occured. Panic!
  406. SD_Panic(DMA2->LISR, "SDIO:DMA Error");
  407. }
  408. }
  409. }
  410. //Wait till SDIO is not active
  411. while (SDIO->STA & (SDIO_STA_RXACT | SDIO_STA_TXACT)) {};
  412. //if there exist a previous transmission, check if the transmission has been completed without error
  413. if (SDIOTxRx) {
  414. //I will block here till I get a data response
  415. while (!(SDIO->STA & (SDIO_STA_DCRCFAIL | SDIO_STA_DTIMEOUT | SDIO_STA_DBCKEND | SDIO_IT_STBITERR))) {};
  416. if (!(SDIO->STA & SDIO_STA_DBCKEND)) { //An Error has occured.
  417. SD_Panic(SDIO->STA, "SDIO:Data Transmission Error\n");
  418. }
  419. }
  420. //If we are here, we can be sure that there is no ongoing transmission any more
  421. SDIOTxRx=0;
  422. }