sdcard.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2007-12-02 Yi.Qiu the first version
  9. * 2010-01-01 Bernard Modify for mini2440
  10. * 2010-10-13 Wangmeng Added sep4020 support
  11. */
  12. #include <rtthread.h>
  13. #include "sdcard.h"
  14. #ifdef RT_USING_DFS
  15. volatile rt_int32_t RCA;
  16. /* RT-Thread Device Driver Interface */
  17. #include <dfs_fs.h>
  18. /*GLOBAL SD DEVICE PONITER*/
  19. static struct sd_device *ptr_sddev;
  20. static rt_uint8_t gsec_buf[SECTOR_SIZE];
  21. #define USE_TIMEOUT
  22. /*This file is to power on/off the SEP4020 SDC*/
  23. /**
  24. * This function will power on/off the SEP4020 SDC
  25. *
  26. * @param sd_ctl: 0/power on; 1/power off
  27. * @return none
  28. *
  29. */
  30. static void sd_pwr(int sd_ctl)
  31. {
  32. if (sd_ctl)
  33. {
  34. *(RP)GPIO_PORTA_SEL |= 0x0200;
  35. *(RP)GPIO_PORTA_DIR &= (~0x0200);
  36. *(RP)GPIO_PORTA_DATA |= 0x0200;
  37. }
  38. else
  39. {
  40. *(RP)GPIO_PORTA_SEL |= 0x0200;
  41. *(RP)GPIO_PORTA_DIR &= (~0x0200);
  42. *(RP)GPIO_PORTA_DATA &= (~0x0200);
  43. }
  44. }
  45. /*a nop operation to delay*/
  46. static void delay(U32 j)
  47. {
  48. U32 i;
  49. for (i = 0; i < j; i++)
  50. {
  51. /* nothing */
  52. }
  53. }
  54. /*
  55. * Send the command to set the data transfer mode
  56. * @param cmd:the command to sent
  57. * @param arg:the argument of the command
  58. * @param mode:SDC transfer mode
  59. * @param blk_len:the block size of each data
  60. * @param num:number of blocks
  61. * @param mask:sdc interrupt mask
  62. */
  63. static rt_err_t cmd_data(U16 cmd, U32 arg, U16 mode, U16 blk_len, U16 num, U16 mask)
  64. {
  65. U32 i;
  66. #ifdef USE_TIMEOUT
  67. U32 to = 10000;
  68. #endif
  69. *(RP)SDC_CLOCK_CONTROL = 0Xff00;
  70. *(RP)SDC_CLOCK_CONTROL = 0Xff04;
  71. *(RP)SDC_INTERRUPT_STATUS_MASK = mask;
  72. *(RP)SDC_TRANSFER_MODE = mode;
  73. *(RP)SDC_BLOCK_SIZE = blk_len;
  74. *(RP)SDC_BLOCK_COUNT = num;
  75. *(RP)SDC_ARGUMENT = arg;
  76. *(RP)SDC_COMMAND = cmd;
  77. delay(10);
  78. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  79. while (i != 0x1000)
  80. {
  81. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  82. #ifdef USE_TIMEOUT
  83. to --;
  84. if (!to)
  85. {
  86. EOUT("%s TIMEOUT\n", __FUNCTION__);
  87. return RT_ETIMEOUT;
  88. }
  89. #endif
  90. }
  91. delay(160);
  92. return *(RP)SDC_RESPONSE0;
  93. }
  94. static rt_err_t cmd_response(U16 Cmd, U32 Arg, U16 TransMode, U16 BlkLen, U16 Nob, U16 IntMask)
  95. {
  96. U32 i;
  97. #ifdef USE_TIMEOUT
  98. U32 to = 50000;
  99. #endif
  100. *(RP)SDC_CLOCK_CONTROL = 0Xff00;
  101. *(RP)SDC_CLOCK_CONTROL = 0Xff04;
  102. *(RP)SDC_INTERRUPT_STATUS_MASK = IntMask;
  103. *(RP)SDC_TRANSFER_MODE = TransMode;
  104. *(RP)SDC_BLOCK_SIZE = BlkLen;
  105. *(RP)SDC_BLOCK_COUNT = Nob;
  106. *(RP)SDC_ARGUMENT = Arg;
  107. *(RP)SDC_COMMAND = Cmd;
  108. delay(10);
  109. i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
  110. while (i != 0x1040)
  111. {
  112. i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
  113. #ifdef USE_TIMEOUT
  114. to--;
  115. if (!to)
  116. {
  117. EOUT("%s Timeout\n", __FUNCTION__);
  118. return RT_ETIMEOUT;
  119. }
  120. #endif
  121. }
  122. //DBOUT("cmd_response TO is %d\n",to);
  123. delay(100);
  124. return RT_EOK;
  125. }
  126. static rt_err_t cmd_wait(U16 Cmd, U32 Arg, U16 IntMask)
  127. {
  128. int i;
  129. #ifdef USE_TIMEOUT
  130. U32 to = 200000;
  131. #endif
  132. *(RP)SDC_CLOCK_CONTROL = 0Xff00;
  133. *(RP)SDC_CLOCK_CONTROL = 0Xff04;
  134. *(RP)SDC_COMMAND = Cmd;
  135. *(RP)SDC_INTERRUPT_STATUS_MASK = IntMask;
  136. *(RP)SDC_ARGUMENT = Arg;
  137. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  138. while (i != 0x1000)
  139. {
  140. i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
  141. #ifdef USE_TIMEOUT
  142. to--;
  143. if (!to)
  144. {
  145. EOUT("%s Timeout\n", __FUNCTION__);
  146. return RT_ETIMEOUT;
  147. }
  148. #endif
  149. }
  150. //DBOUT("cmd_wait TO is %d\n",to);
  151. delay(10);
  152. return RT_EOK;
  153. }
  154. /**
  155. * This function will set a hook function, which will be invoked when a memory
  156. * block is allocated from heap memory.
  157. *
  158. * @param hook the hook function
  159. */
  160. static rt_err_t sd_init(void)
  161. {
  162. rt_err_t err;
  163. #ifdef USE_TIMEOUT
  164. rt_uint32_t to = 1000;
  165. #endif
  166. sd_pwr(1);
  167. *(RP)SDC_SOFTWARE_RESET = 0x0;
  168. delay(200);
  169. *(RP)SDC_SOFTWARE_RESET = 0x1;
  170. delay(200);
  171. cmd_wait(0x08, 0x0, 0xfff);
  172. do
  173. {
  174. err = cmd_wait(0x6ea, 0x0, 0xfff);
  175. #ifdef USE_TIMEOUT
  176. if (err != RT_EOK)
  177. {
  178. EOUT("cmd_wait err in %s\n", __FUNCTION__);
  179. return RT_ETIMEOUT;
  180. }
  181. #endif
  182. delay(3);
  183. err = cmd_wait(0x52a, 0x80ff8000, 0xfff);
  184. if (err != RT_EOK)
  185. {
  186. EOUT("cmd_wait err in %s\n", __FUNCTION__);
  187. return RT_ETIMEOUT;
  188. }
  189. #ifdef USE_TIMEOUT
  190. to--;
  191. if (!to)
  192. {
  193. EOUT("%s timeout\n", __FUNCTION__);
  194. return RT_ETIMEOUT;
  195. }
  196. #endif
  197. }
  198. while (*(RP)SDC_RESPONSE0 < 0X80008000);
  199. cmd_data(0x49, 0X0, 0X0, 0x0, 0x0, 0Xfff);
  200. cmd_data(0x6a, 0X0, 0X0, 0x0, 0x0, 0Xfff);
  201. RCA = *(RP)SDC_RESPONSE0;
  202. cmd_data(0xea, RCA, 0X0, 0x0, 0x0, 0Xfff);
  203. return RT_EOK;
  204. }
  205. /**
  206. * This function will set a hook function, which will be invoked when a memory
  207. * block is allocated from heap memory.
  208. *
  209. * @param hook the hook function
  210. */
  211. static rt_err_t sd_readblock(rt_uint32_t address, rt_uint8_t *buf)
  212. {
  213. U32 complete, i;
  214. rt_uint8_t temp;
  215. rt_err_t err;
  216. RT_UNUSED rt_uint32_t discard;
  217. #ifdef USE_TIMEOUT
  218. rt_uint32_t to = 10;
  219. #endif
  220. //rt_kprintf("in readblock:%x\n",address);
  221. //Clear all the errors & interrups
  222. *(RP)DMAC_INTINTERRCLR |= 0x1;
  223. *(RP)DMAC_INTINTERRCLR &= ~0x1;
  224. *(RP)DMAC_INTTCCLEAR |= 0x1;
  225. *(RP)DMAC_INTTCCLEAR &= ~0x1;
  226. /*Clear read fifo*/
  227. *(RP)(SDC_INTERRUPT_STATUS_MASK) = ~(0x1 << 9); //don't mask fifo empty
  228. while ((*(RP)SDC_INTERRUPT_STATUS) & 0x200 != 0x200)
  229. discard = *(RP)SDC_READ_BUFER_ACCESS;
  230. /*DMAC2,word,size=0x80*/
  231. *(RP)DMAC_C2SRCADDR = SDC_READ_BUFER_ACCESS;
  232. *(RP)DMAC_C2DESTADDR = (rt_uint32_t)buf;
  233. *(RP)DMAC_C2CONTROL = 0x20249b;
  234. *(RP)DMAC_C2CONFIGURATION = 0x38d;
  235. err = cmd_wait(0x6ea, RCA, 0xfff);
  236. if (err != RT_EOK)
  237. {
  238. rt_set_errno(err);
  239. return err;
  240. }
  241. err = cmd_wait(0xca, 0x2, 0xfff);
  242. if (err != RT_EOK)
  243. {
  244. rt_set_errno(err);
  245. return err;
  246. }
  247. err = cmd_response(0x22e, address, 0X1, 0x0200, 0x1, 0Xfff); //CMD17 4bit mode
  248. if (err != RT_EOK)
  249. {
  250. rt_set_errno(err);
  251. return err;
  252. }
  253. complete = *(RP)SDC_INTERRUPT_STATUS;
  254. /*CRC*/
  255. if ((complete | 0xfffffffd) != 0xfffffffd)
  256. {
  257. rt_kprintf("CRC ERROR!!!\n");
  258. complete = *(RP)SDC_INTERRUPT_STATUS;
  259. }
  260. while (((*(RP)(DMAC_INTTCSTATUS)) & 0x4) != 0x4)
  261. {
  262. delay(10);
  263. #ifdef USE_TIMEOUT
  264. to--;
  265. if (!to)
  266. {
  267. EOUT("%s TIMEOUT\n", __FUNCTION__);
  268. return RT_ETIMEOUT;
  269. }
  270. #endif
  271. }
  272. #ifdef USE_TIMEOUT
  273. //DBOUT("%s timeout is %d\n",__FUNCTION__,to);
  274. #endif
  275. /*for the buf is big-endian we must reverse it*/
  276. for (i = 0; i < 0x80; i++)
  277. {
  278. temp = buf[0];
  279. buf[0] = buf[3];
  280. buf[3] = temp;
  281. temp = buf[1];
  282. buf[1] = buf[2];
  283. buf[2] = temp;
  284. buf += 4;
  285. }
  286. return RT_EOK;
  287. }
  288. static rt_uint8_t sd_readmultiblock(rt_uint32_t address, rt_uint8_t *buf, rt_uint32_t size)
  289. {
  290. rt_int32_t index;
  291. rt_uint8_t status = RT_EOK;
  292. for (index = 0; index < size; index++)
  293. {
  294. status = sd_readblock(address + index * SECTOR_SIZE, buf + index * SECTOR_SIZE);
  295. if (status != RT_EOK)
  296. break;
  297. }
  298. return status;
  299. }
  300. /**
  301. * This function will set a hook function, which will be invoked when a memory
  302. * block is allocated from heap memory.
  303. *
  304. * @param hook the hook function
  305. */
  306. static rt_uint8_t sd_writeblock(rt_uint32_t address, rt_uint8_t *buf)
  307. {
  308. U32 complete;
  309. rt_uint8_t temp;
  310. rt_uint8_t *ptr = buf;
  311. rt_err_t err;
  312. #ifdef USE_TIMEOUT
  313. rt_uint32_t to = 10;
  314. #endif
  315. int i;
  316. rt_kprintf("in writeblock:%x\n", address);
  317. /*for the buf is big-endian we must reverse it*/
  318. for (i = 0; i < 0x80; i++)
  319. {
  320. temp = ptr[0];
  321. ptr[0] = ptr[3];
  322. ptr[3] = temp;
  323. temp = ptr[1];
  324. ptr[1] = ptr[2];
  325. ptr[2] = temp;
  326. ptr += 4;
  327. }
  328. //Clear all the errors & interrups
  329. *(RP)DMAC_INTINTERRCLR |= 0x1;
  330. *(RP)DMAC_INTINTERRCLR &= ~0x1;
  331. *(RP)DMAC_INTTCCLEAR |= 0x1;
  332. *(RP)DMAC_INTTCCLEAR &= ~0x1;
  333. *(RP)DMAC_C2SRCADDR = (U32)buf;
  334. *(RP)DMAC_C2DESTADDR = SDC_WRITE_BUFER_ACCESS;
  335. *(RP)DMAC_C2CONTROL = 0x20149b;
  336. *(RP)DMAC_C2CONFIGURATION = 0x380b;
  337. err = cmd_wait(0x6ea, RCA, 0xfff);
  338. if (err != RT_EOK)
  339. {
  340. rt_set_errno(err);
  341. return err;
  342. }
  343. err = cmd_wait(0xca, 0x2, 0xfff);
  344. if (err != RT_EOK)
  345. {
  346. rt_set_errno(err);
  347. return err;
  348. }
  349. err = cmd_response(0x30e, address, 0X3, 0x0200, 0x1, 0Xfff); //CMD24 1bit mode
  350. if (err != RT_EOK)
  351. {
  352. rt_set_errno(err);
  353. return err;
  354. }
  355. complete = *(RP)SDC_INTERRUPT_STATUS;
  356. if ((complete | 0xfffffffe) != 0xfffffffe)
  357. {
  358. //printf("CRC ERROR");
  359. complete = *(RP)SDC_INTERRUPT_STATUS;
  360. }
  361. while (((*(RP)(DMAC_INTTCSTATUS)) & 0x4) != 0x4)
  362. {
  363. delay(10);
  364. #ifdef USE_TIMEOUT
  365. to--;
  366. if (!to)
  367. {
  368. EOUT("%s TIMEOUT\n", __FUNCTION__);
  369. }
  370. #endif
  371. }
  372. #ifdef USE_TIMEOUT
  373. //DBOUT("%s timeout is %d\n",__FUNCTION__,to);
  374. #endif
  375. return RT_EOK;
  376. }
  377. /**
  378. * This function will set a hook function, which will be invoked when a memory
  379. * block is allocated from heap memory.
  380. *
  381. * @param hook the hook function
  382. */
  383. static rt_err_t rt_sdcard_init(rt_device_t dev)
  384. {
  385. return 0;
  386. }
  387. /**
  388. * This function will set a hook function, which will be invoked when a memory
  389. * block is allocated from heap memory.
  390. *
  391. * @param hook the hook function
  392. */
  393. static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
  394. {
  395. return 0;
  396. }
  397. /**
  398. * This function will set a hook function, which will be invoked when a memory
  399. * block is allocated from heap memory.
  400. *
  401. * @param hook the hook function
  402. */
  403. static rt_err_t rt_sdcard_close(rt_device_t dev)
  404. {
  405. return 0;
  406. }
  407. /**
  408. * This function will set a hook function, which will be invoked when a memory
  409. * block is allocated from heap memory.
  410. *
  411. * @param hook the hook function
  412. */
  413. static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
  414. {
  415. rt_kprintf("cmd = %d\n", cmd);
  416. RT_ASSERT(dev != RT_NULL);
  417. if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
  418. {
  419. struct rt_device_blk_geometry *geometry;
  420. geometry = (struct rt_device_blk_geometry *)args;
  421. if (geometry == RT_NULL) return -RT_ERROR;
  422. geometry->bytes_per_sector = 512;
  423. geometry->block_size = 0x200000;
  424. //if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  425. // geometry->sector_count = (SDCardInfo.SD_csd.DeviceSize + 1) * 1024;
  426. //else
  427. geometry->sector_count = 0x200000;//SDCardInfo.CardCapacity/SDCardInfo.CardBlockSize;
  428. }
  429. return RT_EOK;
  430. }
  431. /**
  432. * This function will set a hook function, which will be invoked when a memory
  433. * block is allocated from heap memory.
  434. *
  435. * @param hook the hook function
  436. */
  437. static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  438. {
  439. rt_uint32_t retry = 3;
  440. rt_uint8_t status;
  441. rt_uint32_t index;
  442. struct dfs_partition *part;
  443. if (dev == RT_NULL)
  444. {
  445. rt_set_errno(-DFS_STATUS_EINVAL);
  446. return 0;
  447. }
  448. part = (struct dfs_partition *)dev->user_data;
  449. // take the semaphore
  450. rt_sem_take(part->lock, RT_WAITING_FOREVER);
  451. while (retry--)
  452. {
  453. if (((rt_uint32_t)buffer % 4 != 0) ||
  454. ((rt_uint32_t)buffer > 0x20080000))
  455. {
  456. for (index = 0; index < size; index++)
  457. {
  458. status = sd_readblock((part->offset + pos) * SECTOR_SIZE, ptr_sddev->sec_buf);
  459. if (status != RT_EOK)
  460. break;
  461. rt_memcpy((rt_uint8_t *)buffer + (index * SECTOR_SIZE), ptr_sddev->sec_buf, SECTOR_SIZE);
  462. }
  463. }
  464. else
  465. {
  466. for (index = 0; index < size; index++)
  467. {
  468. status = sd_readblock((pos) * SECTOR_SIZE, (rt_uint8_t *)buffer + index * SECTOR_SIZE);
  469. if (status != RT_EOK)
  470. break;
  471. }
  472. }
  473. }
  474. rt_sem_release(part->lock);
  475. if (status == RT_EOK)
  476. return size;
  477. rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
  478. return 0;
  479. }
  480. /**
  481. * This function will set a hook function, which will be invoked when a memory
  482. * block is allocated from heap memory.
  483. *
  484. * @param hook the hook function
  485. */
  486. static rt_size_t rt_sdcard_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  487. {
  488. int i;
  489. rt_uint8_t status;
  490. struct dfs_partition *part;
  491. if (dev == RT_NULL)
  492. {
  493. rt_set_errno(-DFS_STATUS_EINVAL);
  494. return 0;
  495. }
  496. part = (struct dfs_partition *)dev->user_data;
  497. rt_sem_take(part->lock, RT_WAITING_FOREVER);
  498. if (((rt_uint32_t)buffer % 4 != 0) ||
  499. ((rt_uint32_t)buffer > 0x20080000))
  500. {
  501. rt_uint32_t index;
  502. for (index = 0; index < size; index++)
  503. {
  504. rt_memcpy(ptr_sddev->sec_buf, ((rt_uint8_t *)buffer + index * SECTOR_SIZE), SECTOR_SIZE);
  505. status = sd_writeblock((part->offset + index + pos) * SECTOR_SIZE, ptr_sddev->sec_buf);
  506. }
  507. }
  508. else
  509. {
  510. for (i = 0; i < size; i++)
  511. {
  512. status = sd_writeblock((part->offset + i + pos) * SECTOR_SIZE,
  513. (rt_uint8_t *)((rt_uint8_t *)buffer + i * SECTOR_SIZE));
  514. if (status != RT_EOK) break;
  515. }
  516. }
  517. rt_sem_release(part->lock);
  518. if (status == RT_EOK)
  519. return size;
  520. rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
  521. return 0;
  522. }
  523. rt_err_t rt_hw_sdcard_exit()
  524. {
  525. if (ptr_sddev->device != RT_NULL)
  526. rt_free(ptr_sddev->device);
  527. if (ptr_sddev->part != RT_NULL)
  528. rt_free(ptr_sddev->part);
  529. if (ptr_sddev != RT_NULL)
  530. rt_free(ptr_sddev);
  531. return RT_EOK;
  532. }
  533. /**
  534. * This function will init sd card
  535. *
  536. * @param void
  537. */
  538. rt_err_t rt_hw_sdcard_init()
  539. {
  540. /*For test*/
  541. rt_err_t err;
  542. rt_int32_t i;
  543. char dname[4];
  544. char sname[8];
  545. /*Initialize structure*/
  546. ptr_sddev = (struct sd_device *)rt_malloc(sizeof(struct sd_device));
  547. if (ptr_sddev == RT_NULL)
  548. {
  549. EOUT("Failed to allocate sdcard device structure\n");
  550. return RT_ENOMEM;
  551. }
  552. /*sdcard intialize*/
  553. err = sd_init();
  554. if (err != RT_EOK)
  555. goto FAIL2;
  556. /*set sector buffer*/
  557. ptr_sddev->sec_buf = gsec_buf;
  558. ptr_sddev->buf_size = SECTOR_SIZE;
  559. ptr_sddev->sdc = (struct sd_c *)SD_BASE;
  560. //DBOUT("allocate partition sector buffer OK!");
  561. err = sd_readblock(0, ptr_sddev->sec_buf);
  562. if (err != RT_EOK)
  563. {
  564. EOUT("read first block error\n");
  565. goto FAIL2;
  566. }
  567. /*sdcard driver initialize*/
  568. ptr_sddev->part = (struct dfs_partition *)rt_malloc(4 * sizeof(struct dfs_partition));
  569. if (ptr_sddev->part == RT_NULL)
  570. {
  571. EOUT("allocate partition failed\n");
  572. err = RT_ENOMEM;
  573. goto FAIL2;
  574. }
  575. /*alloc device buffer*/
  576. ptr_sddev->device = (struct rt_device *)rt_malloc(4 * sizeof(struct rt_device));
  577. if (ptr_sddev->device == RT_NULL)
  578. {
  579. EOUT("allocate device failed\n");
  580. err = RT_ENOMEM;
  581. goto FAIL1;
  582. }
  583. ptr_sddev->part_num = 0;
  584. err = sd_readblock(0, ptr_sddev->sec_buf);
  585. if (err != RT_EOK)
  586. {
  587. EOUT("Read block 0 to initialize ERROR\n");
  588. goto FAIL1;
  589. }
  590. for (i = 0; i < 4; i++)
  591. {
  592. /* get the first partition */
  593. err = dfs_filesystem_get_partition(&(ptr_sddev->part[i]), ptr_sddev->sec_buf, i);
  594. if (err == RT_EOK)
  595. {
  596. rt_snprintf(dname, 4, "sd%d", i);
  597. rt_snprintf(sname, 8, "sem_sd%d", i);
  598. ptr_sddev->part[i].lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
  599. /* register sdcard device */
  600. ptr_sddev->device[i].init = rt_sdcard_init;
  601. ptr_sddev->device[i].open = rt_sdcard_open;
  602. ptr_sddev->device[i].close = rt_sdcard_close;
  603. ptr_sddev->device[i].read = rt_sdcard_read;
  604. ptr_sddev->device[i].write = rt_sdcard_write;
  605. ptr_sddev->device[i].control = rt_sdcard_control;
  606. ptr_sddev->device[i].user_data = &ptr_sddev->part[i];
  607. err = rt_device_register(&ptr_sddev->device[i], dname,
  608. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  609. if (err == RT_EOK)
  610. ptr_sddev->part_num++;
  611. }
  612. else
  613. {
  614. if (i == 0)
  615. {
  616. /* there is no partition table */
  617. ptr_sddev->part[0].offset = 0;
  618. ptr_sddev->part[0].size = 0;
  619. ptr_sddev->part[0].lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO);
  620. /* register sdcard device */
  621. ptr_sddev->device[0].init = rt_sdcard_init;
  622. ptr_sddev->device[0].open = rt_sdcard_open;
  623. ptr_sddev->device[0].close = rt_sdcard_close;
  624. ptr_sddev->device[0].read = rt_sdcard_read;
  625. ptr_sddev->device[0].write = rt_sdcard_write;
  626. ptr_sddev->device[0].control = rt_sdcard_control;
  627. ptr_sddev->device[0].user_data = &ptr_sddev->part[0];
  628. err = rt_device_register(&ptr_sddev->device[0], "sd0",
  629. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  630. if (err == RT_EOK)
  631. ptr_sddev->part_num++;
  632. break;
  633. }
  634. }
  635. }
  636. if (ptr_sddev->part_num == 0)
  637. goto FAIL0;
  638. return err;
  639. FAIL0:
  640. rt_free(ptr_sddev->device);
  641. ptr_sddev->device = RT_NULL;
  642. FAIL1:
  643. rt_free(ptr_sddev->part);
  644. ptr_sddev->part = RT_NULL;
  645. FAIL2:
  646. rt_free(ptr_sddev);
  647. ptr_sddev = RT_NULL;
  648. return err;
  649. }
  650. #endif