sdcard.c 18 KB

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