ql_sdmmc_demo.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /*================================================================
  2. Copyright (c) 2021, Quectel Wireless Solutions Co., Ltd. All rights reserved.
  3. Quectel Wireless Solutions Proprietary and Confidential.
  4. =================================================================*/
  5. /*=================================================================
  6. EDIT HISTORY FOR MODULE
  7. This section contains comments describing changes made to the module.
  8. Notice that changes are listed in reverse chronological order.
  9. WHEN WHO WHAT, WHERE, WHY
  10. ------------ ------- -------------------------------------------------------------------------------
  11. =================================================================*/
  12. /*===========================================================================
  13. * include files
  14. ===========================================================================*/
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include "ql_log.h"
  19. #include "osi_api.h"
  20. #include "ql_sdmmc.h"
  21. #include "ql_sdmmc_demo.h"
  22. #include "ql_api_osi.h"
  23. #include "ql_fs.h"
  24. #include "ql_gpio.h"
  25. #include "ql_pin_cfg.h"
  26. /*===========================================================================
  27. *Definition
  28. ===========================================================================*/
  29. #define QL_SDMMC_DEMO_LOG_LEVEL QL_LOG_LEVEL_INFO
  30. #define QL_SDMMC_DEMO_LOG(msg, ...) QL_LOG(QL_SDMMC_DEMO_LOG_LEVEL, "SDMMC_DEMO", msg, ##__VA_ARGS__)
  31. #define QL_SDMMC_DEMO_LOG_PUSH(msg, ...) QL_LOG_PUSH("ql_SDMMC_DEMO", msg, ##__VA_ARGS__)
  32. #define QL_FM_FAT32 0x02
  33. #define QL_SDMMC_TASK_STACK_SIZE 4096
  34. #define QL_SDMMC_TASK_PRIO APP_PRIORITY_NORMAL
  35. #define QL_SDMMC_TASK_EVENT_CNT 5
  36. #define QL_SDMMC_FILE_PATH "SD:test.txt"
  37. #define QL_SDMMC_FILE_PATH1 "SD1:test.txt"
  38. #define QL_SDMMC_TEST_STR "1234567890abcdefg"
  39. #define QL_SDMMC_CLK_FREQ 25000000
  40. #define QL_SDMMC_BLOCK_NUM 10
  41. #define QL_SDMMC_FS_TEST 0 //开启文件系统api测试
  42. #define QL_SDMMC_MUTIL_PARTITION_TEST 1 //多分区功能
  43. #define QL_SDMMC_EVENT_PLUGOUT 0
  44. #define QL_SDMMC_EVENT_INSERT 1
  45. #define QL_SDMMC_DET_TEST 0
  46. /*#############################################################################*/
  47. #define QL_SDMMC_ONLY_USE_DRIVER 1 //0--使用文件系统 1--仅使用sdmmc驱动层
  48. /*#############################################################################*/
  49. /*===========================================================================
  50. * Variate
  51. ===========================================================================*/
  52. #ifdef QL_SDMMC_DET_TEST
  53. ql_task_t ql_sdmmc_det_task = NULL;
  54. #define QL_SDMMC_DET_DEBOUNCE_TIME 100
  55. ql_timer_t ql_sdmmc_det_debounce_timer = NULL;
  56. #endif
  57. /*===========================================================================
  58. * Functions
  59. ===========================================================================*/
  60. #ifdef QL_SDMMC_DET_TEST
  61. void ql_sdmmc_det_debounce_callback(void *ctx)
  62. {
  63. if( ql_sdmmc_det_debounce_timer == NULL || ql_rtos_timer_is_running(ql_sdmmc_det_debounce_timer))
  64. {
  65. return;
  66. }
  67. ql_rtos_timer_start(ql_sdmmc_det_debounce_timer, QL_SDMMC_DET_DEBOUNCE_TIME, 1);
  68. QL_SDMMC_DEMO_LOG("sd_det timer start");
  69. }
  70. void ql_sdmmc_det_callback(void *ctx)
  71. {
  72. ql_event_t ql_event;
  73. ql_LvlMode sdmmc_det_value;
  74. ql_event.id = QUEC_SDDET_EVENT_IND;
  75. ql_rtos_timer_stop(ql_sdmmc_det_debounce_timer);
  76. ql_gpio_get_level(GPIO_43, &sdmmc_det_value);
  77. if(sdmmc_det_value == LVL_LOW)
  78. {
  79. ql_event.param1 = QL_SDMMC_EVENT_INSERT;
  80. QL_SDMMC_DEMO_LOG("sd detect plug_in");
  81. }
  82. else
  83. {
  84. ql_event.param1 = QL_SDMMC_EVENT_PLUGOUT;
  85. QL_SDMMC_DEMO_LOG("sd detect plug_out ");
  86. }
  87. ql_rtos_event_send(ql_sdmmc_det_task, &ql_event);
  88. }
  89. #if 1
  90. //sdmmc供电复位
  91. void _sdmmc_pwd_up_opt()
  92. {
  93. //例如通过某个pin控制是否给SD卡/emmc供电
  94. #define PIN_SDMMC_POWER_NUM 10
  95. #define PORT_SDMMC_POWER_NUM GPIO_20
  96. //SD卡下电
  97. //低电平SD卡下电
  98. ql_gpio_set_level(PORT_SDMMC_POWER_NUM, LVL_LOW);
  99. ql_rtos_task_sleep_ms(100);
  100. //sd卡重新上电
  101. //高电平SD卡上电
  102. ql_gpio_set_level(PORT_SDMMC_POWER_NUM, LVL_HIGH);
  103. QL_SDMMC_DEMO_LOG("sdmmc power down and up");
  104. }
  105. #endif
  106. void ql_sdmmc_pin_init(void)
  107. {
  108. #if QL_SDMMC_DET_TEST
  109. ql_pin_set_func(QL_SDMMC_PIN_DET , QL_PIN_SDMMC_MODE_FUNC_GPIO); //Pin reuse
  110. #endif
  111. ql_pin_set_func(QL_PIN_SDMMC_CMD , QL_PIN_SDMMC_MODE_FUNC); //Pin reuse
  112. ql_pin_set_func(QL_PIN_SDMMC_DATA_0 , QL_PIN_SDMMC_MODE_FUNC); //Pin reuse
  113. ql_pin_set_func(QL_PIN_SDMMC_DATA_1 , QL_PIN_SDMMC_MODE_FUNC); //Pin reuse
  114. ql_pin_set_func(QL_PIN_SDMMC_DATA_2 , QL_PIN_SDMMC_MODE_FUNC); //Pin reuse
  115. ql_pin_set_func(QL_PIN_SDMMC_DATA_3 , QL_PIN_SDMMC_MODE_FUNC); //Pin reuse
  116. ql_pin_set_func(QL_PIN_SDMMC_CLK , QL_PIN_SDMMC_MODE_FUNC); //Pin reuse
  117. #if 0
  118. ql_sdmmc_cfg_t cfg = {
  119. .dev = QL_SDMMC_EMMC_ONLY, //只以sd卡方式进行初始化
  120. .sd_mv = 0, //SD卡默认电压域3.2v
  121. .emmc_mv = 0, //emmc默认电压域1.8v
  122. };
  123. ql_sdmmc_set_dev_cfg(cfg);
  124. ql_sdmmc_register_power_reset_cb(_sdmmc_pwd_up_opt,true);//注册power reset操作并使能retry功能
  125. #endif
  126. }
  127. ql_errcode_sdmmc_e ql_sdmmc_det_init(void)
  128. {
  129. /*sd det interrup*/
  130. if(QL_GPIO_SUCCESS != ql_int_register(GPIO_43, EDGE_TRIGGER, DEBOUNCE_EN, EDGE_BOTH, PULL_UP, ql_sdmmc_det_debounce_callback, NULL))
  131. {
  132. QL_SDMMC_DEMO_LOG("det init reg err");
  133. return QL_SDMMC_INIT_ERR;
  134. }
  135. ql_int_enable(GPIO_43);
  136. return QL_SDMMC_SUCCESS;
  137. }
  138. #if 0
  139. static void ql_sdmmc_demo_det_thread(void *param)
  140. {
  141. if(QL_SDMMC_SUCCESS != ql_sdmmc_det_init())
  142. {
  143. QL_SDMMC_DEMO_LOG("exit det init err");
  144. ql_rtos_task_delete(NULL);
  145. }
  146. else
  147. {
  148. QL_SDMMC_DEMO_LOG("QL_SDMMC_DEMO_LOG++++++++++++");
  149. }
  150. while(1)
  151. {
  152. ql_rtos_task_sleep_s(2);
  153. QL_SDMMC_DEMO_LOG("WHILE++++++++++++");
  154. if(QL_SDMMC_SUCCESS != ql_sdmmc_open())
  155. {
  156. QL_SDMMC_DEMO_LOG("det sdmmc open failed");
  157. }
  158. else
  159. {
  160. QL_SDMMC_DEMO_LOG("det sdmmc open succeed");
  161. }
  162. #if 0
  163. ql_event_t ql_event = {0};
  164. if(ql_event_try_wait(&ql_event) != 0)
  165. {
  166. continue;
  167. }
  168. QL_SDMMC_DEMO_LOG("WHILE++++++++++++");
  169. if( ql_event.id == QUEC_SDDET_EVENT_IND )
  170. {
  171. if(ql_event.param1 == QL_SDMMC_EVENT_INSERT)
  172. {
  173. #if QL_SDMMC_ONLY_USE_DRIVER
  174. if(QL_SDMMC_SUCCESS != ql_sdmmc_open())
  175. {
  176. QL_SDMMC_DEMO_LOG("det sdmmc open failed");
  177. }
  178. else
  179. {
  180. QL_SDMMC_DEMO_LOG("det sdmmc open succeed");
  181. }
  182. #else
  183. if(QL_SDMMC_SUCCESS != ql_sdmmc_mount())
  184. {
  185. QL_SDMMC_DEMO_LOG("det mount failed");
  186. }
  187. else
  188. {
  189. QL_SDMMC_DEMO_LOG("det mount succeed");
  190. }
  191. #endif
  192. }
  193. else if(ql_event.param1 == QL_SDMMC_EVENT_PLUGOUT)
  194. {
  195. #if QL_SDMMC_DET_MOUNT_OR_DRIVER
  196. ql_sdmmc_close();
  197. QL_SDMMC_DEMO_LOG("det sdmmc close succeed");
  198. #else
  199. ql_sdmmc_umount();
  200. QL_SDMMC_DEMO_LOG("det umount succeed");
  201. #endif
  202. }
  203. }
  204. #endif
  205. }
  206. }
  207. #endif
  208. #endif
  209. #if QL_SDMMC_ONLY_USE_DRIVER == 0
  210. ql_errcode_sdmmc_e ql_sdmmc_mount_demo(void)
  211. {
  212. if(QL_SDMMC_SUCCESS != ql_sdmmc_mount())
  213. {
  214. QL_SDMMC_DEMO_LOG("Mount failed");
  215. return QL_SDMMC_MOUNT_ERR;
  216. }
  217. else
  218. {
  219. QL_SDMMC_DEMO_LOG("Mount succeed");
  220. }
  221. //ql_rtos_task_sleep_s(3);
  222. return QL_SDMMC_SUCCESS;
  223. }
  224. #endif
  225. #if QL_SDMMC_ONLY_USE_DRIVER //只使用sdmmc驱动
  226. static void ql_sdmmc_demo_thread(void *param)
  227. {
  228. #define SDMMC_SECTOR_SIZE 512
  229. #define SDMMC_OPT_ADDR_ALIN CONFIG_CACHE_LINE_SIZE
  230. //char wbuffer[512] = {QL_SDMMC_TEST_STR};
  231. //char rbuffer[512] = {0};
  232. char *wMollocBufPtr = (char*)calloc(1, SDMMC_SECTOR_SIZE+SDMMC_OPT_ADDR_ALIN);
  233. if(wMollocBufPtr == NULL)
  234. {
  235. QL_SDMMC_DEMO_LOG("calloc err");
  236. goto calloc_err;
  237. }
  238. char *wbuffer = (char *)OSI_ALIGN_UP(wMollocBufPtr, SDMMC_OPT_ADDR_ALIN);
  239. memcpy(wbuffer,QL_SDMMC_TEST_STR,strlen(QL_SDMMC_TEST_STR));
  240. char *rMollocBufPtr = (char*)calloc(1, SDMMC_SECTOR_SIZE+SDMMC_OPT_ADDR_ALIN);
  241. if(rMollocBufPtr == NULL)
  242. {
  243. QL_SDMMC_DEMO_LOG("calloc err");
  244. goto calloc_err;
  245. }
  246. char *rbuffer = (char *)OSI_ALIGN_UP(rMollocBufPtr, SDMMC_OPT_ADDR_ALIN);
  247. uint32_t clk_freq = QL_SDMMC_CLK_FREQ;
  248. ql_errcode_sdmmc_e ret;
  249. ret = ql_sdmmc_open();
  250. if(ret)
  251. {
  252. QL_SDMMC_DEMO_LOG("sdmmc open fail:%d",ret);
  253. goto exit;
  254. }
  255. ql_sdmmc_hw_info_t info = {0};
  256. ret = ql_sdmmc_get_hw_info(&info);
  257. if(ret)
  258. {
  259. QL_SDMMC_DEMO_LOG("sdmmc get info fail:%d",ret);
  260. goto exit;
  261. }
  262. //sdmmc初始化 SD1 CID[127-96] [95-64] [63-32] [31-0]
  263. QL_SDMMC_DEMO_LOG("sdmmc info:mid/0x%0x,pnm/0x%x%x%x%x%x%x,psn/0x%x%x%x%x,blknum/%d,blksize/%d",\
  264. info.mid,\
  265. info.pnm[0],info.pnm[1],info.pnm[2],info.pnm[3],info.pnm[4],info.pnm[5],\
  266. info.psn[0],info.psn[1],info.psn[2],info.psn[3],\
  267. info.blknum,\
  268. info.blksize);
  269. uint32_t block_num = ql_sdmmc_get_block_number();
  270. QL_SDMMC_DEMO_LOG("block num:%d",block_num);
  271. ret = ql_sdmmc_write(QL_SDMMC_BLOCK_NUM, wbuffer, SDMMC_SECTOR_SIZE);
  272. if(ret)
  273. {
  274. QL_SDMMC_DEMO_LOG("sdmmc write fail:%d",ret);
  275. goto exit;
  276. }
  277. ret = ql_sdmmc_read(QL_SDMMC_BLOCK_NUM, rbuffer, SDMMC_SECTOR_SIZE);
  278. if(ret)
  279. {
  280. QL_SDMMC_DEMO_LOG("sdmmc read fail:%d",ret);
  281. goto exit;
  282. }
  283. QL_SDMMC_DEMO_LOG("sdmmc read :%s",rbuffer);
  284. ret = ql_sdmmc_set_clk(clk_freq);
  285. if(ret)
  286. {
  287. QL_SDMMC_DEMO_LOG("sdmmc set clk fail:%d",ret);
  288. goto exit;
  289. }
  290. QL_SDMMC_DEMO_LOG("sdmmc set clk :%ld",clk_freq);
  291. exit:
  292. free(wMollocBufPtr);
  293. free(rMollocBufPtr);
  294. calloc_err:
  295. QL_SDMMC_DEMO_LOG("exit ql_sdmmc_demo_thread");
  296. ql_rtos_task_delete(NULL);
  297. }
  298. #else //通过文件系统操作sdmmc
  299. #if QL_SDMMC_FS_TEST
  300. #ifdef CONFIG_QUEC_PROJECT_FEATURE_FILE
  301. static int64 ql_sdmmc_fs_test(char* path_name)
  302. {
  303. int fd = 0;
  304. int64 err = 0;
  305. char buffer[100];
  306. char *str = QL_SDMMC_TEST_STR;
  307. fd = ql_fopen(path_name, "wb+");
  308. if(fd < 0)
  309. {
  310. QL_SDMMC_DEMO_LOG("open file failed");
  311. err = fd;
  312. goto exit;
  313. }
  314. err = ql_fwrite(str, strlen(str) + 1, 1, fd); //strlen not include '\0'
  315. if(err < 0)
  316. {
  317. QL_SDMMC_DEMO_LOG("write file failed");
  318. ql_fclose(fd);
  319. goto exit;
  320. }
  321. err = ql_frewind(fd);
  322. if(err < 0)
  323. {
  324. QL_SDMMC_DEMO_LOG("rewind file failed");
  325. ql_fclose(fd);
  326. goto exit;
  327. }
  328. err = ql_fread(buffer, ql_fsize(fd), 1, fd);
  329. if(err < 0)
  330. {
  331. QL_SDMMC_DEMO_LOG("read file failed");
  332. ql_fclose(fd);
  333. goto exit;
  334. }
  335. QL_SDMMC_DEMO_LOG("file read result is %s", buffer);
  336. ql_fclose(fd);
  337. exit:
  338. return err;
  339. }
  340. void ql_sdmmc_demo_fs_thread(void *ctx)
  341. {
  342. int64 err = 0;
  343. #if 0
  344. #if QL_SDMMC_MUTIL_PARTITION_TEST == 0
  345. //careful format sd, delete all files.
  346. if(QL_SDMMC_SUCCESS != ql_sdmmc_mkfs(QL_FM_FAT32))
  347. {
  348. QL_SDMMC_DEMO_LOG("mkfs failed");
  349. err = QL_SDMMC_MKFS_ERR;
  350. goto exit;
  351. }
  352. else
  353. {
  354. QL_SDMMC_DEMO_LOG("mkfs succeed");
  355. }
  356. //ql_rtos_task_sleep_s(2);
  357. #endif
  358. #endif
  359. #if QL_SDMMC_MUTIL_PARTITION_TEST
  360. if(!ql_sdmmc_is_fdisk_ex())
  361. {
  362. ql_sdmmc_part_info_t part_info[2] =
  363. {
  364. //如果分区总大小 > 容量,会分区失败
  365. //注意实际容量会比卡上标识的容量小一点点,所以最后一个分区可以填小一点,会自动调整为剩余容量
  366. //文件系统是有最小扇区数量要求的,最小为1024个扇区,所以分区容量不能太小。
  367. {QL_SDMMC_PARTITION_NUM_1,1000},//1000M
  368. {QL_SDMMC_PARTITION_NUM_2,8} //8M,实际值会根据容量自动调整为剩余容量
  369. };
  370. err = ql_sdmmc_fdisk_ex(part_info);
  371. if(err != QL_SDMMC_SUCCESS)
  372. {
  373. QL_SDMMC_DEMO_LOG("fdisk failed");
  374. goto exit;
  375. }
  376. }
  377. ql_sdmmc_mount_ex(QL_SDMMC_PARTITION_NUM_ALL);//挂载所有分区
  378. /*
  379. for(uint8_t i=QL_SDMMC_PARTITION_NUM_1;i<QL_SDMMC_PARTITION_NUM_MAX;i++)
  380. {
  381. err = ql_sdmmc_mount_ex(i);
  382. if(err != QL_SDMMC_SUCCESS)
  383. {
  384. if(!ql_sdmmc_is_format_ex(i))
  385. {
  386. err = ql_sdmmc_mkfs_ex(i,QL_FM_FAT32);
  387. if(err != QL_SDMMC_SUCCESS)
  388. {
  389. QL_SDMMC_DEMO_LOG("mkfs failed");
  390. goto exit;
  391. }
  392. }
  393. QL_SDMMC_DEMO_LOG("mount failed");
  394. goto exit;
  395. }
  396. }*/
  397. err = ql_sdmmc_fs_test(QL_SDMMC_FILE_PATH1);
  398. #endif
  399. err = ql_sdmmc_fs_test(QL_SDMMC_FILE_PATH);
  400. goto exit;//防止报错
  401. exit:
  402. if(err < 0)
  403. {
  404. QL_SDMMC_DEMO_LOG("errcode is %x", err);
  405. }
  406. QL_SDMMC_DEMO_LOG("exit ql_sdmmc_demo_fs_thread");
  407. ql_rtos_task_delete(NULL);
  408. }
  409. #endif
  410. #endif
  411. #endif
  412. void ql_sdmmc_app_init(void)
  413. {
  414. QlOSStatus err = QL_SDMMC_SUCCESS;
  415. /*sd pin init*/
  416. ql_sdmmc_pin_init();
  417. QL_SDMMC_DEMO_LOG("emmc pin init ok.");
  418. #if QL_SDMMC_ONLY_USE_DRIVER == 0
  419. #if QL_SDMMC_MUTIL_PARTITION_TEST == 0
  420. err = ql_sdmmc_mount_demo();
  421. if(err!= QL_SDMMC_SUCCESS)
  422. {
  423. QL_SDMMC_DEMO_LOG("sdmmc mount demo fail err = %d", err);
  424. }
  425. #endif
  426. #endif
  427. #if QL_SDMMC_DET_TEST
  428. err = ql_rtos_task_create(&ql_sdmmc_det_task, QL_SDMMC_TASK_STACK_SIZE, QL_SDMMC_TASK_PRIO, "sdDEMO_det", ql_sdmmc_demo_det_thread, NULL, QL_SDMMC_TASK_EVENT_CNT);
  429. if (err != QL_OSI_SUCCESS)
  430. {
  431. QL_SDMMC_DEMO_LOG("creat sd task fail err = %d", err);
  432. }
  433. err = ql_rtos_timer_create(&ql_sdmmc_det_debounce_timer, ql_sdmmc_det_task, ql_sdmmc_det_callback, NULL);
  434. if(err != QL_OSI_SUCCESS)
  435. {
  436. QL_SDMMC_DEMO_LOG("creat timer task fail err = %d", err);
  437. }
  438. #endif
  439. #if QL_SDMMC_ONLY_USE_DRIVER
  440. ql_task_t sdmmc_task = NULL;
  441. err = ql_rtos_task_create(&sdmmc_task, QL_SDMMC_TASK_STACK_SIZE, QL_SDMMC_TASK_PRIO, "sdDEMO", ql_sdmmc_demo_thread, NULL, QL_SDMMC_TASK_EVENT_CNT);
  442. if (err != QL_OSI_SUCCESS)
  443. {
  444. QL_SDMMC_DEMO_LOG("creat sd task failed err = %d", err);
  445. }
  446. #else
  447. #if QL_SDMMC_FS_TEST
  448. #ifdef CONFIG_QUEC_PROJECT_FEATURE_FILE
  449. ql_task_t sdmmc_task_fs = NULL;
  450. err = ql_rtos_task_create(&sdmmc_task_fs, QL_SDMMC_TASK_STACK_SIZE, QL_SDMMC_TASK_PRIO, "sdDEMO_fs", ql_sdmmc_demo_fs_thread, NULL, QL_SDMMC_TASK_EVENT_CNT);
  451. if(err != QL_OSI_SUCCESS)
  452. {
  453. QL_SDMMC_DEMO_LOG("creat sd task fs failed err = %d", err);
  454. }
  455. #endif
  456. #endif
  457. #endif
  458. }