nu_sdh.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. /**************************************************************************//**
  2. * @file sdh.c
  3. * @brief N9H30 SDH driver source file
  4. *
  5. * @note
  6. * SPDX-License-Identifier: Apache-2.0
  7. * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "N9H30.h"
  13. #include "nu_sys.h"
  14. #include "nu_sdh.h"
  15. /** @addtogroup N9H30_Device_Driver N9H30 Device Driver
  16. @{
  17. */
  18. /** @addtogroup N9H30_SDH_Driver SDH Driver
  19. @{
  20. */
  21. /** @addtogroup N9H30_SDH_EXPORTED_FUNCTIONS SDH Exported Functions
  22. @{
  23. */
  24. #define SDH_BLOCK_SIZE 512ul
  25. /** @cond HIDDEN_SYMBOLS */
  26. /* global variables */
  27. /* For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still */
  28. /* calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag */
  29. /* _sd_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error */
  30. #ifdef __ICCARM__
  31. #pragma data_alignment = 32
  32. static uint8_t _SDH0_ucSDHCBuffer[512];
  33. static uint8_t _SDH1_ucSDHCBuffer[512];
  34. #else
  35. static uint8_t _SDH0_ucSDHCBuffer[512] __attribute__((aligned(32)));
  36. static uint8_t _SDH1_ucSDHCBuffer[512] __attribute__((aligned(32)));
  37. #endif
  38. void dump_sdh_regs(SDH_T *sdh)
  39. {
  40. rt_kprintf("\n+++++++++++++++++++++++\n");
  41. rt_kprintf(" %s\n", sdh->CTL & SDH_CTL_SDPORT_Msk ? "SD1" : "SD0");
  42. rt_kprintf(" DMACTL = 0x%08x\n", sdh->DMACTL);
  43. rt_kprintf(" GCTL = 0x%08x\n", sdh->GCTL);
  44. rt_kprintf(" GINTEN = 0x%08x\n", sdh->GINTEN);
  45. rt_kprintf(" GINTSTS = 0x%08x\n", sdh->GINTSTS);
  46. rt_kprintf(" CTL = 0x%08x\n", sdh->CTL);
  47. rt_kprintf(" INTEN = 0x%08x\n", sdh->INTEN);
  48. rt_kprintf(" INTSTS = 0x%08x\n", sdh->INTSTS);
  49. rt_kprintf(" BLEN = 0x%08x\n", sdh->BLEN);
  50. rt_kprintf(" TOUT = 0x%08x\n", sdh->TOUT);
  51. rt_kprintf(" ECTL = 0x%08x\n", sdh->ECTL);
  52. rt_kprintf("\n+++++++++++++++++++++++\n");
  53. }
  54. void SDH_CheckRB(SDH_T *sdh)
  55. {
  56. while (1)
  57. {
  58. sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
  59. while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
  60. {
  61. }
  62. if ((sdh->INTSTS & SDH_INTSTS_DAT0STS_Msk) == SDH_INTSTS_DAT0STS_Msk)
  63. {
  64. break;
  65. }
  66. }
  67. }
  68. uint32_t SDH_SDCommand(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t ucCmd, uint32_t uArg)
  69. {
  70. volatile uint32_t buf, val = 0ul;
  71. sdh->CMDARG = uArg;
  72. buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8ul) | (SDH_CTL_COEN_Msk);
  73. sdh->CTL = buf;
  74. while ((sdh->CTL & SDH_CTL_COEN_Msk) == SDH_CTL_COEN_Msk)
  75. {
  76. if (pSD->IsCardInsert == 0ul)
  77. {
  78. val = SDH_NO_SD_CARD;
  79. }
  80. }
  81. return val;
  82. }
  83. uint32_t SDH_SDCmdAndRsp(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t ucCmd, uint32_t uArg, uint32_t ntickCount)
  84. {
  85. volatile uint32_t buf;
  86. sdh->CMDARG = uArg;
  87. buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8ul) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk);
  88. sdh->CTL = buf;
  89. if (ntickCount > 0ul)
  90. {
  91. while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk)
  92. {
  93. if (ntickCount-- == 0ul)
  94. {
  95. sdh->CTL |= SDH_CTL_CTLRST_Msk; /* reset SD engine */
  96. return 2ul;
  97. }
  98. if (pSD->IsCardInsert == FALSE)
  99. {
  100. return SDH_NO_SD_CARD;
  101. }
  102. }
  103. }
  104. else
  105. {
  106. while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk)
  107. {
  108. if (pSD->IsCardInsert == FALSE)
  109. {
  110. return SDH_NO_SD_CARD;
  111. }
  112. }
  113. }
  114. if (pSD->R7Flag)
  115. {
  116. uint32_t tmp0 = 0ul, tmp1 = 0ul;
  117. tmp1 = sdh->RESP1 & 0xfful;
  118. tmp0 = sdh->RESP0 & 0xful;
  119. if ((tmp1 != 0x55ul) && (tmp0 != 0x01ul))
  120. {
  121. pSD->R7Flag = 0ul;
  122. return SDH_CMD8_ERROR;
  123. }
  124. }
  125. if (!pSD->R3Flag)
  126. {
  127. if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) == SDH_INTSTS_CRC7_Msk) /* check CRC7 */
  128. {
  129. return Successful;
  130. }
  131. else
  132. {
  133. return SDH_CRC7_ERROR;
  134. }
  135. }
  136. else
  137. {
  138. /* ignore CRC error for R3 case */
  139. pSD->R3Flag = 0ul;
  140. sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
  141. return Successful;
  142. }
  143. }
  144. uint32_t SDH_Swap32(uint32_t val)
  145. {
  146. uint32_t buf;
  147. buf = val;
  148. val <<= 24;
  149. val |= (buf << 8) & 0xff0000ul;
  150. val |= (buf >> 8) & 0xff00ul;
  151. val |= (buf >> 24) & 0xfful;
  152. return val;
  153. }
  154. /* Get 16 bytes CID or CSD */
  155. uint32_t SDH_SDCmdAndRsp2(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t ucCmd, uint32_t uArg, uint32_t puR2ptr[])
  156. {
  157. uint32_t i, buf;
  158. uint32_t tmpBuf[5];
  159. sdh->CMDARG = uArg;
  160. buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_R2EN_Msk);
  161. sdh->CTL = buf;
  162. while ((sdh->CTL & SDH_CTL_R2EN_Msk) == SDH_CTL_R2EN_Msk)
  163. {
  164. if (pSD->IsCardInsert == FALSE)
  165. {
  166. return SDH_NO_SD_CARD;
  167. }
  168. }
  169. if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) == SDH_INTSTS_CRC7_Msk)
  170. {
  171. for (i = 0ul; i < 5ul; i++)
  172. {
  173. tmpBuf[i] = SDH_Swap32(sdh->FB[i]);
  174. }
  175. for (i = 0ul; i < 4ul; i++)
  176. {
  177. puR2ptr[i] = ((tmpBuf[i] & 0x00fffffful) << 8) | ((tmpBuf[i + 1ul] & 0xff000000ul) >> 24);
  178. }
  179. }
  180. else
  181. {
  182. return SDH_CRC7_ERROR;
  183. }
  184. return Successful;
  185. }
  186. uint32_t SDH_SDCmdAndRspDataIn(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t ucCmd, uint32_t uArg)
  187. {
  188. volatile uint32_t buf;
  189. sdh->CMDARG = uArg;
  190. buf = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (ucCmd << 8ul) |
  191. (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
  192. sdh->CTL = buf;
  193. while ((sdh->CTL & SDH_CTL_RIEN_Msk) == SDH_CTL_RIEN_Msk)
  194. {
  195. if (pSD->IsCardInsert == FALSE)
  196. {
  197. return SDH_NO_SD_CARD;
  198. }
  199. }
  200. while ((sdh->CTL & SDH_CTL_DIEN_Msk) == SDH_CTL_DIEN_Msk)
  201. {
  202. if (pSD->IsCardInsert == FALSE)
  203. {
  204. return SDH_NO_SD_CARD;
  205. }
  206. }
  207. if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk)
  208. {
  209. /* check CRC7 */
  210. return SDH_CRC7_ERROR;
  211. }
  212. if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk)
  213. {
  214. /* check CRC16 */
  215. return SDH_CRC16_ERROR;
  216. }
  217. return 0ul;
  218. }
  219. /* there are 8 bits for divider0, maximum is 256 */
  220. #define SDH_CLK_DIV0_MAX 256ul
  221. void SDH_Set_clock(SDH_T *sdh, uint32_t sd_clock_khz)
  222. {
  223. UINT32 div;
  224. UINT32 reg;
  225. uint32_t SDH_ReferenceClock;
  226. if (sdh == SDH0)
  227. reg = REG_CLK_DIVCTL3;
  228. else
  229. reg = REG_CLK_DIVCTL9;
  230. if (sd_clock_khz <= 2000)
  231. {
  232. SDH_ReferenceClock = 12000;
  233. outpw(reg, (inpw(reg) & ~0x18) | (0x0 << 3)); // SD clock from XIN [4:3]
  234. }
  235. else
  236. {
  237. SDH_ReferenceClock = 300000;
  238. outpw(reg, (inpw(reg) & ~0x18) | (0x3 << 3)); // SD clock from UPLL [4:3]
  239. }
  240. div = (SDH_ReferenceClock / sd_clock_khz) - 1;
  241. if (div >= SDH_CLK_DIV0_MAX) div = 0xff;
  242. outpw(reg, (inpw(reg) & ~0xff00) | ((div) << 8)); // SD clock divided by CLKDIV3[SD_N] [15:8]
  243. }
  244. uint32_t SDH_CardDetection(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t card_num)
  245. {
  246. uint32_t i, val = TRUE;
  247. uint32_t u32INTEN_CDSRC_Msk;
  248. uint32_t u32INTSTS_CDSTS_Msk;
  249. uint32_t u32CTL_CLKKEEP_Msk;
  250. if (card_num & SD_PORT0)
  251. {
  252. u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC_Msk;
  253. u32INTSTS_CDSTS_Msk = SDH_INTSTS_CDSTS_Msk;
  254. u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP0_Msk;
  255. }
  256. else if (card_num & SD_PORT1)
  257. {
  258. u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC1_Msk;
  259. u32INTSTS_CDSTS_Msk = SDH_INTSTS_CDSTS1_Msk;
  260. u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP1_Msk;
  261. }
  262. if ((sdh->INTEN & u32INTEN_CDSRC_Msk) == u32INTEN_CDSRC_Msk) /* Card detect pin from GPIO */
  263. {
  264. if ((sdh->INTSTS & u32INTSTS_CDSTS_Msk) == u32INTSTS_CDSTS_Msk) /* Card remove */
  265. {
  266. pSD->IsCardInsert = (uint8_t)FALSE;
  267. val = FALSE;
  268. }
  269. else
  270. {
  271. pSD->IsCardInsert = (uint8_t)TRUE;
  272. }
  273. }
  274. else if ((sdh->INTEN & u32INTEN_CDSRC_Msk) != u32INTEN_CDSRC_Msk)
  275. {
  276. sdh->CTL |= u32CTL_CLKKEEP_Msk;
  277. for (i = 0ul; i < 5000ul; i++)
  278. {
  279. }
  280. if ((sdh->INTSTS & u32INTSTS_CDSTS_Msk) == u32INTSTS_CDSTS_Msk) /* Card insert */
  281. {
  282. pSD->IsCardInsert = (uint8_t)TRUE;
  283. }
  284. else
  285. {
  286. pSD->IsCardInsert = (uint8_t)FALSE;
  287. val = FALSE;
  288. }
  289. sdh->CTL &= ~u32CTL_CLKKEEP_Msk;
  290. }
  291. return val;
  292. }
  293. uint32_t SDH_WhichCardIsSelected(SDH_T *sdh)
  294. {
  295. return (sdh->CTL & SDH_CTL_SDPORT_Msk) ? SD_PORT1 : SD_PORT0;
  296. }
  297. void SDH_CardSelect(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardSrc)
  298. {
  299. if (u32CardSrc & SD_PORT0)
  300. {
  301. sdh->CTL &= ~SDH_CTL_SDPORT_Msk;
  302. }
  303. else if (u32CardSrc & SD_PORT1)
  304. {
  305. sdh->CTL &= ~SDH_CTL_SDPORT_Msk;
  306. sdh->CTL |= (1 << SDH_CTL_SDPORT_Pos);
  307. }
  308. switch (pSD->CardType)
  309. {
  310. case SDH_TYPE_MMC:
  311. sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
  312. SDH_Set_clock(sdh, MMC_FREQ);
  313. break;
  314. case SDH_TYPE_SD_LOW:
  315. case SDH_TYPE_EMMC:
  316. sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
  317. SDH_Set_clock(sdh, SD_FREQ);
  318. break;
  319. case SDH_TYPE_SD_HIGH:
  320. sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
  321. SDH_Set_clock(sdh, SDHC_FREQ);
  322. break;
  323. case SDH_TYPE_UNKNOWN:
  324. default:
  325. break;
  326. }
  327. }
  328. uint32_t SDH_Init(SDH_T *sdh, SDH_INFO_T *pSD)
  329. {
  330. uint32_t volatile i, status;
  331. uint32_t resp;
  332. uint32_t CIDBuffer[4];
  333. uint32_t volatile u32CmdTimeOut;
  334. /* set the clock to 300KHz */
  335. SDH_Set_clock(sdh, 300ul);
  336. /* power ON 74 clock */
  337. sdh->CTL |= SDH_CTL_CLK74OEN_Msk;
  338. while ((sdh->CTL & SDH_CTL_CLK74OEN_Msk) == SDH_CTL_CLK74OEN_Msk)
  339. {
  340. if (pSD->IsCardInsert == FALSE)
  341. {
  342. return SDH_NO_SD_CARD;
  343. }
  344. }
  345. SDH_SDCommand(sdh, pSD, 0ul, 0ul); /* reset all cards */
  346. for (i = 0x1000ul; i > 0ul; i--)
  347. {
  348. }
  349. /* initial SDHC */
  350. pSD->R7Flag = 1ul;
  351. u32CmdTimeOut = 0xFFFFFul;
  352. //dump_sdh_regs(sdh);
  353. i = SDH_SDCmdAndRsp(sdh, pSD, 8ul, 0x00000155ul, u32CmdTimeOut);
  354. if (i == Successful)
  355. {
  356. /* SD 2.0 */
  357. SDH_SDCmdAndRsp(sdh, pSD, 55ul, 0x00ul, u32CmdTimeOut);
  358. pSD->R3Flag = 1ul;
  359. SDH_SDCmdAndRsp(sdh, pSD, 41ul, 0x40ff8000ul, u32CmdTimeOut); /* 2.7v-3.6v */
  360. resp = sdh->RESP0;
  361. while ((resp & 0x00800000ul) != 0x00800000ul) /* check if card is ready */
  362. {
  363. SDH_SDCmdAndRsp(sdh, pSD, 55ul, 0x00ul, u32CmdTimeOut);
  364. pSD->R3Flag = 1ul;
  365. SDH_SDCmdAndRsp(sdh, pSD, 41ul, 0x40ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */
  366. resp = sdh->RESP0;
  367. }
  368. if ((resp & 0x00400000ul) == 0x00400000ul)
  369. {
  370. pSD->CardType = SDH_TYPE_SD_HIGH;
  371. }
  372. else
  373. {
  374. pSD->CardType = SDH_TYPE_SD_LOW;
  375. }
  376. }
  377. else
  378. {
  379. /* SD 1.1 */
  380. SDH_SDCommand(sdh, pSD, 0ul, 0ul); /* reset all cards */
  381. for (i = 0x100ul; i > 0ul; i--)
  382. {
  383. }
  384. i = SDH_SDCmdAndRsp(sdh, pSD, 55ul, 0x00ul, u32CmdTimeOut);
  385. if (i == 2ul) /* MMC memory */
  386. {
  387. SDH_SDCommand(sdh, pSD, 0ul, 0ul); /* reset */
  388. for (i = 0x100ul; i > 0ul; i--)
  389. {
  390. }
  391. pSD->R3Flag = 1ul;
  392. if (SDH_SDCmdAndRsp(sdh, pSD, 1ul, 0x40ff8000ul, u32CmdTimeOut) != 2ul) /* eMMC memory */
  393. {
  394. resp = sdh->RESP0;
  395. while ((resp & 0x00800000ul) != 0x00800000ul)
  396. {
  397. /* check if card is ready */
  398. pSD->R3Flag = 1ul;
  399. SDH_SDCmdAndRsp(sdh, pSD, 1ul, 0x40ff8000ul, u32CmdTimeOut); /* high voltage */
  400. resp = sdh->RESP0;
  401. }
  402. if ((resp & 0x00400000ul) == 0x00400000ul)
  403. {
  404. pSD->CardType = SDH_TYPE_EMMC;
  405. }
  406. else
  407. {
  408. pSD->CardType = SDH_TYPE_MMC;
  409. }
  410. }
  411. else
  412. {
  413. pSD->CardType = SDH_TYPE_UNKNOWN;
  414. return SDH_ERR_DEVICE;
  415. }
  416. }
  417. else if (i == 0ul) /* SD Memory */
  418. {
  419. pSD->R3Flag = 1ul;
  420. SDH_SDCmdAndRsp(sdh, pSD, 41ul, 0x00ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */
  421. resp = sdh->RESP0;
  422. while ((resp & 0x00800000ul) != 0x00800000ul) /* check if card is ready */
  423. {
  424. SDH_SDCmdAndRsp(sdh, pSD, 55ul, 0x00ul, u32CmdTimeOut);
  425. pSD->R3Flag = 1ul;
  426. SDH_SDCmdAndRsp(sdh, pSD, 41ul, 0x00ff8000ul, u32CmdTimeOut); /* 3.0v-3.4v */
  427. resp = sdh->RESP0;
  428. }
  429. pSD->CardType = SDH_TYPE_SD_LOW;
  430. }
  431. else
  432. {
  433. pSD->CardType = SDH_TYPE_UNKNOWN;
  434. return SDH_INIT_ERROR;
  435. }
  436. }
  437. if (pSD->CardType != SDH_TYPE_UNKNOWN)
  438. {
  439. SDH_SDCmdAndRsp2(sdh, pSD, 2ul, 0x00ul, CIDBuffer);
  440. if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
  441. {
  442. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 3ul, 0x10000ul, 0ul)) != Successful) /* set RCA */
  443. {
  444. return status;
  445. }
  446. pSD->RCA = 0x10000ul;
  447. }
  448. else
  449. {
  450. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 3ul, 0x00ul, 0ul)) != Successful) /* get RCA */
  451. {
  452. return status;
  453. }
  454. else
  455. {
  456. pSD->RCA = (sdh->RESP0 << 8) & 0xffff0000;
  457. }
  458. }
  459. }
  460. return Successful;
  461. }
  462. uint32_t SDH_SwitchToHighSpeed(SDH_T *sdh, SDH_INFO_T *pSD)
  463. {
  464. uint32_t volatile status = 0ul;
  465. uint16_t current_comsumption, busy_status0;
  466. sdh->DMASA = (uint32_t)pSD->dmabuf;
  467. sdh->BLEN = 63ul;
  468. if ((status = SDH_SDCmdAndRspDataIn(sdh, pSD, 6ul, 0x00ffff01ul)) != Successful)
  469. {
  470. return Fail;
  471. }
  472. current_comsumption = (uint16_t)(*pSD->dmabuf) << 8;
  473. current_comsumption |= (uint16_t)(*(pSD->dmabuf + 1));
  474. if (!current_comsumption)
  475. {
  476. return Fail;
  477. }
  478. busy_status0 = (uint16_t)(*(pSD->dmabuf + 28)) << 8;
  479. busy_status0 |= (uint16_t)(*(pSD->dmabuf + 29));
  480. if (!busy_status0) /* function ready */
  481. {
  482. sdh->DMASA = (uint32_t)pSD->dmabuf;
  483. sdh->BLEN = 63ul; /* 512 bit */
  484. if ((status = SDH_SDCmdAndRspDataIn(sdh, pSD, 6ul, 0x80ffff01ul)) != Successful)
  485. {
  486. return Fail;
  487. }
  488. /* function change timing: 8 clocks */
  489. sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
  490. while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
  491. {
  492. }
  493. current_comsumption = (uint16_t)(*pSD->dmabuf) << 8;
  494. current_comsumption |= (uint16_t)(*(pSD->dmabuf + 1));
  495. if (!current_comsumption)
  496. {
  497. return Fail;
  498. }
  499. return Successful;
  500. }
  501. else
  502. {
  503. return Fail;
  504. }
  505. }
  506. uint32_t SDH_SelectCardType(SDH_T *sdh, SDH_INFO_T *pSD)
  507. {
  508. uint32_t volatile status = 0ul;
  509. uint32_t param;
  510. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 7ul, pSD->RCA, 0ul)) != Successful)
  511. {
  512. return status;
  513. }
  514. SDH_CheckRB(sdh);
  515. /* if SD card set 4bit */
  516. if (pSD->CardType == SDH_TYPE_SD_HIGH)
  517. {
  518. sdh->DMASA = (uint32_t)pSD->dmabuf;
  519. sdh->BLEN = 0x07ul; /* 64 bit */
  520. sdh->DMACTL |= SDH_DMACTL_DMARST_Msk;
  521. while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == 0x2);
  522. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 55ul, pSD->RCA, 0ul)) != Successful)
  523. {
  524. return status;
  525. }
  526. if ((status = SDH_SDCmdAndRspDataIn(sdh, pSD, 51ul, 0x00ul)) != Successful)
  527. {
  528. return status;
  529. }
  530. if ((*pSD->dmabuf & 0xful) == 0x2ul)
  531. {
  532. status = SDH_SwitchToHighSpeed(sdh, pSD);
  533. if (status == Successful)
  534. {
  535. /* divider */
  536. SDH_Set_clock(sdh, SDHC_FREQ);
  537. }
  538. }
  539. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 55ul, pSD->RCA, 0ul)) != Successful)
  540. {
  541. return status;
  542. }
  543. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 6ul, 0x02ul, 0ul)) != Successful) /* set bus width */
  544. {
  545. return status;
  546. }
  547. sdh->CTL |= SDH_CTL_DBW_Msk;
  548. }
  549. else if (pSD->CardType == SDH_TYPE_SD_LOW)
  550. {
  551. sdh->DMASA = (uint32_t)pSD->dmabuf;;
  552. sdh->BLEN = 0x07ul;
  553. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 55ul, pSD->RCA, 0ul)) != Successful)
  554. {
  555. return status;
  556. }
  557. if ((status = SDH_SDCmdAndRspDataIn(sdh, pSD, 51ul, 0x00ul)) != Successful)
  558. {
  559. return status;
  560. }
  561. /* set data bus width. ACMD6 for SD card, SDCR_DBW for host. */
  562. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 55ul, pSD->RCA, 0ul)) != Successful)
  563. {
  564. return status;
  565. }
  566. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 6ul, 0x02ul, 0ul)) != Successful)
  567. {
  568. return status;
  569. }
  570. sdh->CTL |= SDH_CTL_DBW_Msk;
  571. }
  572. else if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
  573. {
  574. if (pSD->CardType == SDH_TYPE_MMC)
  575. {
  576. sdh->CTL &= ~SDH_CTL_DBW_Msk;
  577. }
  578. /*--- sent CMD6 to MMC card to set bus width to 4 bits mode */
  579. /* set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode) */
  580. param = (3ul << 24) | (183ul << 16) | (1ul << 8);
  581. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 6ul, param, 0ul)) != Successful)
  582. {
  583. return status;
  584. }
  585. SDH_CheckRB(sdh);
  586. sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
  587. }
  588. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 16ul, SDH_BLOCK_SIZE, 0ul)) != Successful)
  589. {
  590. return status;
  591. }
  592. sdh->BLEN = SDH_BLOCK_SIZE - 1ul;
  593. SDH_SDCommand(sdh, pSD, 7ul, 0ul);
  594. sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
  595. while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
  596. {
  597. }
  598. sdh->INTEN |= SDH_INTEN_BLKDIEN_Msk;
  599. return Successful;
  600. }
  601. void SDH_Get_SD_info(SDH_T *sdh, SDH_INFO_T *pSD)
  602. {
  603. unsigned int R_LEN, C_Size, MULT, size;
  604. uint32_t Buffer[4];
  605. //unsigned char *ptr;
  606. SDH_SDCmdAndRsp2(sdh, pSD, 9ul, pSD->RCA, Buffer);
  607. if ((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
  608. {
  609. /* for MMC/eMMC card */
  610. if ((Buffer[0] & 0xc0000000) == 0xc0000000)
  611. {
  612. /* CSD_STRUCTURE [127:126] is 3 */
  613. /* CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB */
  614. SDH_SDCmdAndRsp(sdh, pSD, 7ul, pSD->RCA, 0ul);
  615. //ptr = (uint8_t *)((uint32_t)_SDH_ucSDHCBuffer );
  616. sdh->DMASA = (uint32_t)pSD->dmabuf;;
  617. sdh->BLEN = 511ul; /* read 512 bytes for EXT_CSD */
  618. if (SDH_SDCmdAndRspDataIn(sdh, pSD, 8ul, 0x00ul) == Successful)
  619. {
  620. SDH_SDCommand(sdh, pSD, 7ul, 0ul);
  621. sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
  622. while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
  623. {
  624. }
  625. pSD->totalSectorN = (uint32_t)(*(pSD->dmabuf + 215)) << 24;
  626. pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf + 214)) << 16;
  627. pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf + 213)) << 8;
  628. pSD->totalSectorN |= (uint32_t)(*(pSD->dmabuf + 212));
  629. pSD->diskSize = pSD->totalSectorN / 2ul;
  630. }
  631. }
  632. else
  633. {
  634. /* CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB */
  635. R_LEN = (Buffer[1] & 0x000f0000ul) >> 16;
  636. C_Size = ((Buffer[1] & 0x000003fful) << 2) | ((Buffer[2] & 0xc0000000ul) >> 30);
  637. MULT = (Buffer[2] & 0x00038000ul) >> 15;
  638. size = (C_Size + 1ul) * (1ul << (MULT + 2ul)) * (1ul << R_LEN);
  639. pSD->diskSize = size / 1024ul;
  640. pSD->totalSectorN = size / 512ul;
  641. }
  642. }
  643. else
  644. {
  645. if ((Buffer[0] & 0xc0000000) != 0x0ul)
  646. {
  647. C_Size = ((Buffer[1] & 0x0000003ful) << 16) | ((Buffer[2] & 0xffff0000ul) >> 16);
  648. size = (C_Size + 1ul) * 512ul; /* Kbytes */
  649. pSD->diskSize = size;
  650. pSD->totalSectorN = size << 1;
  651. }
  652. else
  653. {
  654. R_LEN = (Buffer[1] & 0x000f0000ul) >> 16;
  655. C_Size = ((Buffer[1] & 0x000003fful) << 2) | ((Buffer[2] & 0xc0000000ul) >> 30);
  656. MULT = (Buffer[2] & 0x00038000ul) >> 15;
  657. size = (C_Size + 1ul) * (1ul << (MULT + 2ul)) * (1ul << R_LEN);
  658. pSD->diskSize = size / 1024ul;
  659. pSD->totalSectorN = size / 512ul;
  660. }
  661. }
  662. pSD->sectorSize = (int)512;
  663. // printf("The size is %d KB\n", pSD->diskSize);
  664. }
  665. /** @endcond HIDDEN_SYMBOLS */
  666. /**
  667. * @brief This function use to reset SD function and select card detection source and pin.
  668. *
  669. * @param[in] sdh Select SDH0 or SDH1.
  670. * @param[in] u32CardDetSrc Select card detection pin from GPIO or DAT3 pin. ( \ref CardDetect_From_GPIO / \ref CardDetect_From_DAT3)
  671. *
  672. * @return None
  673. */
  674. void SDH_Open(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t u32CardDetSrc)
  675. {
  676. volatile int i;
  677. uint32_t u32INTEN_CDSRC_Msk = 0;
  678. uint32_t u32INTSTS_CDIF_Msk = 0;
  679. uint32_t u32INTEN_CDIEN_Msk = 0;
  680. uint32_t u32CTL_CLKKEEP_Msk = 0;
  681. if (u32CardDetSrc & SD_PORT0)
  682. {
  683. u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC_Msk;
  684. u32INTSTS_CDIF_Msk = SDH_INTSTS_CDIF_Msk;
  685. u32INTEN_CDIEN_Msk = SDH_INTEN_CDIEN_Msk;
  686. u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP0_Msk;
  687. }
  688. else if (u32CardDetSrc & SD_PORT1)
  689. {
  690. u32INTEN_CDSRC_Msk = SDH_INTEN_CDSRC1_Msk;
  691. u32INTSTS_CDIF_Msk = SDH_INTSTS_CDIF1_Msk;
  692. u32INTEN_CDIEN_Msk = SDH_INTEN_CDIEN1_Msk;
  693. u32CTL_CLKKEEP_Msk = SDH_CTL_CLKKEEP1_Msk;
  694. }
  695. // Enable DMAC
  696. sdh->DMACTL = SDH_DMACTL_DMARST_Msk;
  697. while ((sdh->DMACTL & SDH_DMACTL_DMARST_Msk) == SDH_DMACTL_DMARST_Msk)
  698. {
  699. }
  700. sdh->DMACTL = SDH_DMACTL_DMAEN_Msk;
  701. // Reset Global
  702. sdh->GCTL = SDH_GCTL_GCTLRST_Msk | SDH_GCTL_SDEN_Msk;
  703. while ((sdh->GCTL & SDH_GCTL_GCTLRST_Msk) == SDH_GCTL_GCTLRST_Msk)
  704. {
  705. }
  706. if (sdh == SDH1)
  707. {
  708. /* Enable Power, 0: Enable, 1:Disable */
  709. if (u32CardDetSrc & SD_PORT0)
  710. {
  711. sdh->ECTL &= ~SDH_ECTL_POWEROFF0_Msk;
  712. }
  713. else if (u32CardDetSrc & SD_PORT1)
  714. {
  715. sdh->ECTL &= ~SDH_ECTL_POWEROFF1_Msk;
  716. }
  717. /* disable SD clock output */
  718. sdh->CTL &= ~(0xFF | u32CTL_CLKKEEP_Msk);
  719. }
  720. sdh->CTL |= SDH_CTL_CTLRST_Msk;
  721. while ((sdh->CTL & SDH_CTL_CTLRST_Msk) == SDH_CTL_CTLRST_Msk)
  722. {
  723. }
  724. memset(pSD, 0, sizeof(SDH_INFO_T));
  725. if (sdh == SDH0)
  726. {
  727. pSD->dmabuf = (unsigned char *)((uint32_t)_SDH0_ucSDHCBuffer | 0x80000000);
  728. pSD->IsCardInsert = 1;
  729. }
  730. else if (sdh == SDH1)
  731. {
  732. pSD->dmabuf = (unsigned char *)((uint32_t)_SDH1_ucSDHCBuffer | 0x80000000);
  733. }
  734. else
  735. {
  736. }
  737. // enable SD
  738. sdh->GCTL = SDH_GCTL_SDEN_Msk;
  739. if ((u32CardDetSrc & CardDetect_From_DAT3) == CardDetect_From_DAT3)
  740. {
  741. sdh->INTEN &= ~u32INTEN_CDSRC_Msk;
  742. }
  743. else
  744. {
  745. sdh->INTEN |= u32INTEN_CDSRC_Msk;
  746. }
  747. for (i = 0; i < 0x100; i++);
  748. sdh->INTSTS = u32INTSTS_CDIF_Msk;
  749. sdh->INTEN |= u32INTEN_CDIEN_Msk;
  750. }
  751. /**
  752. * @brief This function use to initial SD card.
  753. *
  754. * @param[in] sdh Select SDH0 or SDH1.
  755. *
  756. * @return None
  757. *
  758. * @details This function is used to initial SD card.
  759. * SD initial state needs 400KHz clock output, driver will use HIRC for SD initial clock source.
  760. * And then switch back to the user's setting.
  761. */
  762. uint32_t SDH_Probe(SDH_T *sdh, SDH_INFO_T *pSD, uint32_t card_num)
  763. {
  764. uint32_t val;
  765. // Disable SD host interrupt
  766. sdh->GINTEN = 0ul;
  767. sdh->CTL &= ~SDH_CTL_SDNWR_Msk;
  768. sdh->CTL |= 0x09ul << SDH_CTL_SDNWR_Pos; /* set SDNWR = 9 */
  769. sdh->CTL &= ~SDH_CTL_BLKCNT_Msk;
  770. sdh->CTL |= 0x01ul << SDH_CTL_BLKCNT_Pos; /* set BLKCNT = 1 */
  771. sdh->CTL &= ~SDH_CTL_DBW_Msk; /* SD 1-bit data bus */
  772. if (sdh != SDH0) //EMMC
  773. {
  774. if (!(SDH_CardDetection(sdh, pSD, card_num)))
  775. {
  776. return SDH_NO_SD_CARD;
  777. }
  778. }
  779. if ((val = SDH_Init(sdh, pSD)) != 0ul)
  780. {
  781. return val;
  782. }
  783. /* divider */
  784. if (pSD->CardType == SDH_TYPE_MMC)
  785. {
  786. SDH_Set_clock(sdh, MMC_FREQ);
  787. }
  788. else
  789. {
  790. SDH_Set_clock(sdh, SD_FREQ);
  791. }
  792. SDH_Get_SD_info(sdh, pSD);
  793. if ((val = SDH_SelectCardType(sdh, pSD)) != 0ul)
  794. {
  795. return val;
  796. }
  797. return 0ul;
  798. }
  799. /**
  800. * @brief This function use to read data from SD card.
  801. *
  802. * @param[in] sdh Select SDH0 or SDH1.
  803. * @param[out] pu8BufAddr The buffer to receive the data from SD card.
  804. * @param[in] u32StartSec The start read sector address.
  805. * @param[in] u32SecCount The the read sector number of data
  806. *
  807. * @return None
  808. */
  809. uint32_t SDH_Read(SDH_T *sdh, SDH_INFO_T *pSD, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
  810. {
  811. uint32_t volatile bIsSendCmd = FALSE, buf;
  812. uint32_t volatile reg;
  813. uint32_t volatile i, loop, status;
  814. uint32_t blksize = SDH_BLOCK_SIZE;
  815. if (u32SecCount == 0ul)
  816. {
  817. return SDH_SELECT_ERROR;
  818. }
  819. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 7ul, pSD->RCA, 0ul)) != Successful)
  820. {
  821. return status;
  822. }
  823. SDH_CheckRB(sdh);
  824. sdh->BLEN = blksize - 1ul; /* the actual byte count is equal to (SDBLEN+1) */
  825. if ((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC))
  826. {
  827. sdh->CMDARG = u32StartSec;
  828. }
  829. else
  830. {
  831. sdh->CMDARG = u32StartSec * blksize;
  832. }
  833. sdh->DMASA = (uint32_t)pu8BufAddr;
  834. loop = u32SecCount / 255ul;
  835. for (i = 0ul; i < loop; i++)
  836. {
  837. pSD->DataReadyFlag = (uint8_t)FALSE;
  838. reg = sdh->CTL & ~SDH_CTL_CMDCODE_Msk;
  839. reg = reg | 0xff0000ul; /* set BLK_CNT to 255 */
  840. if (bIsSendCmd == FALSE)
  841. {
  842. sdh->CTL = reg | (18ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
  843. bIsSendCmd = TRUE;
  844. }
  845. else
  846. {
  847. sdh->CTL = reg | SDH_CTL_DIEN_Msk;
  848. }
  849. while (!pSD->DataReadyFlag)
  850. {
  851. if (pSD->DataReadyFlag)
  852. {
  853. break;
  854. }
  855. if (pSD->IsCardInsert == FALSE)
  856. {
  857. return SDH_NO_SD_CARD;
  858. }
  859. }
  860. if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk) /* check CRC7 */
  861. {
  862. return SDH_CRC7_ERROR;
  863. }
  864. if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk) /* check CRC16 */
  865. {
  866. return SDH_CRC16_ERROR;
  867. }
  868. }
  869. loop = u32SecCount % 255ul;
  870. if (loop != 0ul)
  871. {
  872. pSD->DataReadyFlag = (uint8_t)FALSE;
  873. reg = sdh->CTL & (~SDH_CTL_CMDCODE_Msk);
  874. reg = reg & (~SDH_CTL_BLKCNT_Msk);
  875. reg |= (loop << 16); /* setup SDCR_BLKCNT */
  876. if (bIsSendCmd == FALSE)
  877. {
  878. sdh->CTL = reg | (18ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
  879. bIsSendCmd = TRUE;
  880. }
  881. else
  882. {
  883. sdh->CTL = reg | SDH_CTL_DIEN_Msk;
  884. }
  885. while (!pSD->DataReadyFlag)
  886. {
  887. if (pSD->IsCardInsert == FALSE)
  888. {
  889. return SDH_NO_SD_CARD;
  890. }
  891. }
  892. if ((sdh->INTSTS & SDH_INTSTS_CRC7_Msk) != SDH_INTSTS_CRC7_Msk) /* check CRC7 */
  893. {
  894. return SDH_CRC7_ERROR;
  895. }
  896. if ((sdh->INTSTS & SDH_INTSTS_CRC16_Msk) != SDH_INTSTS_CRC16_Msk) /* check CRC16 */
  897. {
  898. return SDH_CRC16_ERROR;
  899. }
  900. }
  901. if (SDH_SDCmdAndRsp(sdh, pSD, 12ul, 0ul, 0ul)) /* stop command */
  902. {
  903. return SDH_CRC7_ERROR;
  904. }
  905. SDH_CheckRB(sdh);
  906. SDH_SDCommand(sdh, pSD, 7ul, 0ul);
  907. sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
  908. while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
  909. {
  910. }
  911. return Successful;
  912. }
  913. /**
  914. * @brief This function use to write data to SD card.
  915. *
  916. * @param[in] sdh Select SDH0 or SDH1.
  917. * @param[in] pu8BufAddr The buffer to send the data to SD card.
  918. * @param[in] u32StartSec The start write sector address.
  919. * @param[in] u32SecCount The the write sector number of data.
  920. *
  921. * @return \ref SDH_SELECT_ERROR : u32SecCount is zero. \n
  922. * \ref SDH_NO_SD_CARD : SD card be removed. \n
  923. * \ref SDH_CRC_ERROR : CRC error happen. \n
  924. * \ref SDH_CRC7_ERROR : CRC7 error happen. \n
  925. * \ref Successful : Write data to SD card success.
  926. */
  927. uint32_t SDH_Write(SDH_T *sdh, SDH_INFO_T *pSD, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
  928. {
  929. uint32_t volatile bIsSendCmd = FALSE;
  930. uint32_t volatile reg;
  931. uint32_t volatile i, loop, status;
  932. if (u32SecCount == 0ul)
  933. {
  934. return SDH_SELECT_ERROR;
  935. }
  936. if ((status = SDH_SDCmdAndRsp(sdh, pSD, 7ul, pSD->RCA, 0ul)) != Successful)
  937. {
  938. return status;
  939. }
  940. SDH_CheckRB(sdh);
  941. /* According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n. */
  942. sdh->BLEN = SDH_BLOCK_SIZE - 1ul;
  943. if ((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC))
  944. {
  945. sdh->CMDARG = u32StartSec;
  946. }
  947. else
  948. {
  949. sdh->CMDARG = u32StartSec * SDH_BLOCK_SIZE; /* set start address for SD CMD */
  950. }
  951. sdh->DMASA = (uint32_t)pu8BufAddr;
  952. loop = u32SecCount / 255ul; /* the maximum block count is 0xFF=255 for register SDCR[BLK_CNT] */
  953. for (i = 0ul; i < loop; i++)
  954. {
  955. pSD->DataReadyFlag = (uint8_t)FALSE;
  956. reg = sdh->CTL & 0xff00c080;
  957. reg = reg | 0xff0000ul; /* set BLK_CNT to 0xFF=255 */
  958. if (!bIsSendCmd)
  959. {
  960. sdh->CTL = reg | (25ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
  961. bIsSendCmd = TRUE;
  962. }
  963. else
  964. {
  965. sdh->CTL = reg | SDH_CTL_DOEN_Msk;
  966. }
  967. while (!pSD->DataReadyFlag)
  968. {
  969. if (pSD->IsCardInsert == FALSE)
  970. {
  971. return SDH_NO_SD_CARD;
  972. }
  973. }
  974. if ((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0ul)
  975. {
  976. sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
  977. return SDH_CRC_ERROR;
  978. }
  979. }
  980. loop = u32SecCount % 255ul;
  981. if (loop != 0ul)
  982. {
  983. pSD->DataReadyFlag = (uint8_t)FALSE;
  984. reg = (sdh->CTL & 0xff00c080) | (loop << 16);
  985. if (!bIsSendCmd)
  986. {
  987. sdh->CTL = reg | (25ul << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
  988. bIsSendCmd = TRUE;
  989. }
  990. else
  991. {
  992. sdh->CTL = reg | SDH_CTL_DOEN_Msk;
  993. }
  994. while (!pSD->DataReadyFlag)
  995. {
  996. if (pSD->IsCardInsert == FALSE)
  997. {
  998. return SDH_NO_SD_CARD;
  999. }
  1000. }
  1001. if ((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0ul)
  1002. {
  1003. sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
  1004. return SDH_CRC_ERROR;
  1005. }
  1006. }
  1007. sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
  1008. if (SDH_SDCmdAndRsp(sdh, pSD, 12ul, 0ul, 0ul)) /* stop command */
  1009. {
  1010. return SDH_CRC7_ERROR;
  1011. }
  1012. SDH_CheckRB(sdh);
  1013. SDH_SDCommand(sdh, pSD, 7ul, 0ul);
  1014. sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
  1015. while ((sdh->CTL & SDH_CTL_CLK8OEN_Msk) == SDH_CTL_CLK8OEN_Msk)
  1016. {
  1017. }
  1018. return Successful;
  1019. }
  1020. /*@}*/ /* end of group N9H30_SD_EXPORTED_FUNCTIONS */
  1021. /*@}*/ /* end of group N9H30_SD_Driver */
  1022. /*@}*/ /* end of group N9H30_Device_Driver */
  1023. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/