fs_nand_flash_demo.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /**
  2. @file
  3. fs_nand_flash_demo.c
  4. @brief
  5. quectel nand flash demo.
  6. */
  7. /*================================================================
  8. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  9. Quectel Wireless Solution Proprietary and Confidential.
  10. =================================================================*/
  11. /*=================================================================
  12. EDIT HISTORY FOR MODULE
  13. This section contains comments describing changes made to the module.
  14. Notice that changes are listed in reverse chronological order.
  15. WHEN WHO WHAT, WHERE, WHY
  16. ------------ ------- -------------------------------------------------------------------------------
  17. 24/05/2021 Neo Init version
  18. =================================================================*/
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include "ql_gpio.h"
  23. #include "ql_api_osi.h"
  24. #include "ql_api_spi.h"
  25. #include "ql_api_spi_flash.h"
  26. #include "ql_api_spi_nand_flash.h"
  27. #include "ql_api_fs_nand_flash.h"
  28. #include "ql_log.h"
  29. #include "ql_fs.h"
  30. #include "fs_nand_flash_demo.h"
  31. #include "ql_app_feature_config.h"
  32. #include "quec_pin_index.h"
  33. #define QL_NAND_FLASH_LOG_LEVEL QL_LOG_LEVEL_INFO
  34. #define QL_NAND_FLASH_LOG(msg, ...) QL_LOG(QL_NAND_FLASH_LOG_LEVEL, "ql_FS_NAND_DEMO", msg, ##__VA_ARGS__)
  35. #define QL_NAND_FLASH_LOG_PUSH(msg, ...) QL_LOG_PUSH("ql_FS_NAND_DEMO", msg, ##__VA_ARGS__)
  36. #define QL_STANDARD_SPI 0 //Standard SPI: SCLK, CS#, SI, SO
  37. #define QL_QUAD_SPI 1 //Quad SPI: SCLK, CS#, SIO0, SIO1, SIO2, SIO3
  38. #define QL_DUAL_SPI 2 //Dual SPI: SCLK, CS#, SIO0, SIO1
  39. #define QL_SPI_TPYE QL_QUAD_SPI
  40. //If the total sector number is smaller than 66130, format it as FM_FAT.Otherwise, format it as FM_FAT32
  41. #define QL_FM_FAT 0x01
  42. #define QL_FM_FAT32 0x02
  43. ql_task_t fs_nand_flash_demo_task = NULL;
  44. //Standard SPI: SCLK, CS#, SI, SO
  45. #define QL_CUR_SPI_PORT QL_SPI_PORT1
  46. #define QL_CUR_SPI_CS_PIN QL_CUR_SPI1_CS_PIN
  47. #define QL_CUR_SPI_CS_FUNC QL_CUR_SPI1_CS_FUNC
  48. #define QL_CUR_SPI_CLK_PIN QL_CUR_SPI1_CLK_PIN
  49. #define QL_CUR_SPI_CLK_FUNC QL_CUR_SPI1_CLK_FUNC
  50. #define QL_CUR_SPI_DO_PIN QL_CUR_SPI1_DO_PIN
  51. #define QL_CUR_SPI_DO_FUNC QL_CUR_SPI1_DO_FUNC
  52. #define QL_CUR_SPI_DI_PIN QL_CUR_SPI1_DI_PIN
  53. #define QL_CUR_SPI_DI_FUNC QL_CUR_SPI1_DI_FUNC
  54. //Quad SPI: SCLK, CS#, SIO0, SIO1, SIO2, SIO3 //Dual SPI: SCLK, CS#, SIO0, SIO1
  55. #define QL_CUR_SPI6_PORT QL_SPI_PORT1
  56. #define QL_CUR_SPI6_CS_PIN QUEC_PIN_SPI6_CS_PIN
  57. #define QL_CUR_SPI6_CS_FUNC 0x01
  58. #define QL_CUR_SPI6_CLK_PIN QUEC_PIN_SPI6_CLK_PIN
  59. #define QL_CUR_SPI6_CLK_FUNC 0x01
  60. #define QL_CUR_SPI6_SIO0_PIN QUEC_PIN_SPI6_SIO0_PIN
  61. #define QL_CUR_SPI6_SIO0_FUNC 0x01
  62. #define QL_CUR_SPI6_SIO1_PIN QUEC_PIN_SPI6_SIO1_PIN
  63. #define QL_CUR_SPI6_SIO1_FUNC 0x01
  64. #define QL_CUR_SPI6_SIO2_PIN QUEC_PIN_SPI6_SIO2_PIN
  65. #define QL_CUR_SPI6_SIO2_FUNC 0x01
  66. #define QL_CUR_SPI6_SIO3_PIN QUEC_PIN_SPI6_SIO3_PIN
  67. #define QL_CUR_SPI6_SIO3_FUNC 0x01
  68. int ql_nand_flash_pin_init(void)
  69. {
  70. ql_errcode_gpio gpio_ret;
  71. if (QL_CUR_SPI_CS_PIN == QUEC_PIN_NONE || QL_CUR_SPI_CLK_PIN == QUEC_PIN_NONE || \
  72. QL_CUR_SPI_DO_PIN == QUEC_PIN_NONE || QL_CUR_SPI_DI_PIN == QUEC_PIN_NONE)
  73. {
  74. QL_NAND_FLASH_LOG("pin err");
  75. return -1;
  76. }
  77. gpio_ret = ql_pin_set_func(QL_CUR_SPI_CS_PIN, QL_CUR_SPI_CS_FUNC);
  78. if (gpio_ret != QL_GPIO_SUCCESS)
  79. {
  80. QL_NAND_FLASH_LOG("set pin err");
  81. return -1;
  82. }
  83. gpio_ret = ql_pin_set_func(QL_CUR_SPI_CLK_PIN, QL_CUR_SPI_CLK_FUNC);
  84. if (gpio_ret != QL_GPIO_SUCCESS)
  85. {
  86. QL_NAND_FLASH_LOG("set pin err");
  87. return -1;
  88. }
  89. gpio_ret = ql_pin_set_func(QL_CUR_SPI_DO_PIN, QL_CUR_SPI_DO_FUNC);
  90. if (gpio_ret != QL_GPIO_SUCCESS)
  91. {
  92. QL_NAND_FLASH_LOG("set pin err");
  93. return -1;
  94. }
  95. gpio_ret = ql_pin_set_func(QL_CUR_SPI_DI_PIN, QL_CUR_SPI_DI_FUNC);
  96. if (gpio_ret != QL_GPIO_SUCCESS)
  97. {
  98. QL_NAND_FLASH_LOG("set pin err");
  99. return -1;
  100. }
  101. return 0;
  102. }
  103. int ql_spi6_nand_flash_pin_init(void)
  104. {
  105. ql_errcode_gpio gpio_ret;
  106. if (QL_CUR_SPI6_CS_PIN == QUEC_PIN_NONE || QL_CUR_SPI6_CLK_PIN == QUEC_PIN_NONE || \
  107. QL_CUR_SPI6_SIO0_PIN == QUEC_PIN_NONE || QL_CUR_SPI6_SIO1_PIN == QUEC_PIN_NONE || \
  108. QL_CUR_SPI6_SIO2_PIN == QUEC_PIN_NONE || QL_CUR_SPI6_SIO3_PIN == QUEC_PIN_NONE)
  109. {
  110. QL_NAND_FLASH_LOG("pin err");
  111. return -1;
  112. }
  113. gpio_ret = ql_pin_set_func(QL_CUR_SPI6_CS_PIN, QL_CUR_SPI6_CS_FUNC);
  114. if (gpio_ret != QL_GPIO_SUCCESS)
  115. {
  116. QL_NAND_FLASH_LOG("set pin err");
  117. return -1;
  118. }
  119. gpio_ret = ql_pin_set_func(QL_CUR_SPI6_CLK_PIN, QL_CUR_SPI6_CLK_FUNC);
  120. if (gpio_ret != QL_GPIO_SUCCESS)
  121. {
  122. QL_NAND_FLASH_LOG("set pin err");
  123. return -1;
  124. }
  125. gpio_ret = ql_pin_set_func(QL_CUR_SPI6_SIO0_PIN, QL_CUR_SPI6_SIO0_FUNC);
  126. if (gpio_ret != QL_GPIO_SUCCESS)
  127. {
  128. QL_NAND_FLASH_LOG("set pin err");
  129. return -1;
  130. }
  131. gpio_ret = ql_pin_set_func(QL_CUR_SPI6_SIO1_PIN, QL_CUR_SPI6_SIO1_FUNC);
  132. if (gpio_ret != QL_GPIO_SUCCESS)
  133. {
  134. QL_NAND_FLASH_LOG("set pin err");
  135. return -1;
  136. }
  137. #if (QL_SPI_TPYE == QL_QUAD_SPI)
  138. gpio_ret = ql_pin_set_func(QL_CUR_SPI6_SIO2_PIN, QL_CUR_SPI6_SIO2_FUNC);
  139. if (gpio_ret != QL_GPIO_SUCCESS)
  140. {
  141. QL_NAND_FLASH_LOG("set pin err");
  142. return -1;
  143. }
  144. gpio_ret = ql_pin_set_func(QL_CUR_SPI6_SIO3_PIN, QL_CUR_SPI6_SIO3_FUNC);
  145. if (gpio_ret != QL_GPIO_SUCCESS)
  146. {
  147. QL_NAND_FLASH_LOG("set pin err");
  148. return -1;
  149. }
  150. #endif
  151. return 0;
  152. }
  153. static void ql_fs_nand_flash_demo_task_thread(void *ctx)
  154. {
  155. #if (defined QL_APP_FEATURE_SPI_NAND_FLASH || defined QL_APP_FEATURE_SPI6_NAND_FLASH)
  156. ql_errcode_spi_nand_e ret;
  157. #endif
  158. ql_errcode_nand_flash_e nand_ret;
  159. #if (defined QL_APP_FEATURE_SPI_NAND_FLASH && (QL_SPI_TPYE == QL_STANDARD_SPI))
  160. ql_spi_nand_config_s spi_nand_config = {0};
  161. #endif
  162. #if (defined QL_APP_FEATURE_SPI6_NAND_FLASH && (QL_SPI_TPYE != QL_STANDARD_SPI))
  163. ql_spi6_nand_config_s spi6_nand_config = {0};
  164. #endif
  165. int64 err = 0;
  166. uint8_t opt = QL_FM_FAT32;
  167. ql_nand_hw_info_t nand_info = {0};
  168. #ifdef QL_APP_FEATURE_FILE
  169. int fd = 0;
  170. char buffer[200] = { 0 };
  171. char *str = TEST_STR_NAND;
  172. #endif
  173. #if (QL_SPI_TPYE == QL_STANDARD_SPI)
  174. #ifdef QL_APP_FEATURE_SPI_NAND_FLASH
  175. //step1:pin init----customers can use the custom pin to initialize
  176. if (ql_nand_flash_pin_init())
  177. {
  178. QL_NAND_FLASH_LOG("pin err");
  179. goto QL_FTL_TASK_EXIT;
  180. }
  181. //step2:spi init
  182. //If you use the default parameters, you can initialize it with ql_spi_nand_init
  183. //ret = ql_spi_nand_init(QL_CUR_SPI_PORT, QL_SPI_CLK_25MHZ);
  184. spi_nand_config.port = QL_CUR_SPI_PORT;
  185. spi_nand_config.spiclk = QL_SPI_CLK_25MHZ;
  186. spi_nand_config.input_sel = QL_SPI_DI_1;
  187. spi_nand_config.transmode = QL_SPI_DIRECT_POLLING;
  188. spi_nand_config.cs = QL_SPI_CS0;
  189. ret = ql_spi_nand_init_ext(spi_nand_config);
  190. if (ret != QL_SPI_FLASH_SUCCESS)
  191. {
  192. QL_NAND_FLASH_LOG("init err");
  193. goto QL_FTL_NAND_EXIT;
  194. }
  195. #endif
  196. #else
  197. #ifdef QL_APP_FEATURE_SPI6_NAND_FLASH
  198. //step1:pin init----customers can use the custom pin to initialize
  199. if (ql_spi6_nand_flash_pin_init())
  200. {
  201. QL_NAND_FLASH_LOG("pin err");
  202. goto QL_FTL_TASK_EXIT;
  203. }
  204. /*
  205. 目前建议使用的值:如果需要使用其他的freq需要抓波形调整参数,尤其是sample_delay参数,
  206. 如果设置不对会导致读/写数据不正确。
  207. ----------------------------------------------------------------------------
  208. | 复用的pin脚--GPIO number:GPIO18-23 |
  209. ----------------------------------------------------------------------------
  210. | freq | clk | clk_div | drv | sample_delay |
  211. | 40M | SPI6_NAND_FLASH_CLK_200MHZ | 5 | 0x2 | 2/3 |
  212. | 50M | SPI6_NAND_FLASH_CLK_200MHZ | 4 | 0x2 | 2/3 |
  213. | 83.3M | SPI6_NAND_FLASH_CLK_500MHZ | 6 | 0x2 | 4/6 |
  214. ----------------------------------------------------------------------------
  215. ----------------------------------------------------------------------------
  216. | 复用的pin脚--SPI_LCD |
  217. ----------------------------------------------------------------------------
  218. | freq | clk | clk_div | drv | sample_delay |
  219. | 40M | SPI6_NAND_FLASH_CLK_200MHZ | 5 | 0x7 | 2/3 |
  220. | 50M | SPI6_NAND_FLASH_CLK_200MHZ | 4 | 0x7 | 2/3 |
  221. | 83.3M | SPI6_NAND_FLASH_CLK_500MHZ | 6 | 0x7 | 4/5 |
  222. ----------------------------------------------------------------------------
  223. ----------------------------------------------------------------------------
  224. | 复用的pin脚--SDMMC |
  225. ----------------------------------------------------------------------------
  226. | freq | clk | clk_div | drv | sample_delay |
  227. | 40M | SPI6_NAND_FLASH_CLK_200MHZ | 5 | 0x7 | 2/3 |
  228. | 50M | SPI6_NAND_FLASH_CLK_200MHZ | 4 | 0x7 | 2/3 |
  229. | 83.3M | SPI6_NAND_FLASH_CLK_500MHZ | 6 | 0x7 | 4/6 |
  230. ----------------------------------------------------------------------------
  231. */
  232. spi6_nand_config.port = QL_CUR_SPI_PORT;
  233. spi6_nand_config.clk = SPI6_NAND_FLASH_CLK_200MHZ;
  234. spi6_nand_config.clk_div = 5; //200M/5=40mHZ
  235. #if (QL_SPI_TPYE == QL_QUAD_SPI)
  236. spi6_nand_config.quad_mode = 1;
  237. #else
  238. spi6_nand_config.quad_mode = 0;
  239. #endif
  240. spi6_nand_config.sample_delay = 3;
  241. spi6_nand_config.isslow = 0; //此参数无意义
  242. ret = ql_spi6_nand_init_ext(spi6_nand_config);
  243. if (ret != QL_SPI_FLASH_SUCCESS)
  244. {
  245. QL_NAND_FLASH_LOG("init err");
  246. goto QL_FTL_NAND_EXIT;
  247. }
  248. #endif
  249. #endif
  250. //step3:mkfs nand flash----the first time using flash or the file system is damaged needs to format the file system and mount file system
  251. //mkfs operation can not be performed frequently. it will erase the whole block, which is very time-consuming
  252. #if 0
  253. //opt = QL_FM_FAT;//if sector number < 66130,format it as FM_FAT.Otherwise, format it as FM_FAT32
  254. //1G nand = 60928 sector numbers,so should format as FM_FAT.
  255. //2G nand > 66130 sector numbers,so should format as FM_FAT32.
  256. nand_ret = ql_nand_flash_mkfs(opt);
  257. if(nand_ret != QL_NAND_FLASH_SUCCESS)
  258. {
  259. QL_NAND_FLASH_LOG("nand flash mkfs err");
  260. goto QL_FTL_NAND_EXIT;
  261. }
  262. ql_rtos_task_sleep_ms(100);
  263. #else
  264. opt = opt;//only prevents compilation errors
  265. //step4:mount nand flash----mount file system
  266. nand_ret = ql_nand_flash_mount();
  267. if(nand_ret != QL_NAND_FLASH_SUCCESS)
  268. {
  269. QL_NAND_FLASH_LOG("nand flash mount err");
  270. goto QL_FTL_NAND_EXIT;
  271. }
  272. #endif
  273. //step5:read id & read total size
  274. ql_nand_get_hw_info(&nand_info);
  275. QL_NAND_FLASH_LOG("mid=%x, total_size = %d", nand_info.mid, nand_info.blknum * nand_info.blksize);
  276. //step6:using file system API to complete read, write ect.
  277. #ifdef QL_APP_FEATURE_FILE
  278. err = ql_mkdir(DIR_PATH_NAND, 0);
  279. if(err < 0)
  280. {
  281. if(err == QL_DIR_DIR_ALREADY_EXIST)
  282. {
  283. QL_NAND_FLASH_LOG("dir exist, not create");
  284. }
  285. else
  286. {
  287. QL_NAND_FLASH_LOG("make dir failed");
  288. goto QL_FTL_TASK_EXIT;
  289. }
  290. }
  291. fd = ql_fopen(FILE_PATH_NAND, "wb+");
  292. if(fd < 0)
  293. {
  294. QL_NAND_FLASH_LOG("open file failed");
  295. err = fd;
  296. goto QL_FTL_TASK_EXIT;
  297. }
  298. err = ql_fwrite(str, strlen(str) + 1, 1, fd); //strlen not include '\0'
  299. if(err < 0)
  300. {
  301. QL_NAND_FLASH_LOG("write file failed");
  302. ql_fclose(fd);
  303. goto QL_FTL_TASK_EXIT;
  304. }
  305. err = ql_frewind(fd);
  306. if(err < 0)
  307. {
  308. QL_NAND_FLASH_LOG("rewind file failed");
  309. ql_fclose(fd);
  310. goto QL_FTL_TASK_EXIT;
  311. }
  312. err = ql_fread(buffer, ql_fsize(fd), 1, fd);
  313. if(err < 0)
  314. {
  315. QL_NAND_FLASH_LOG("read file failed");
  316. ql_fclose(fd);
  317. goto QL_FTL_TASK_EXIT;
  318. }
  319. QL_NAND_FLASH_LOG("file read result is %s", buffer);
  320. ql_fclose(fd);
  321. #endif
  322. //step7:umount nand flash----umount file system
  323. nand_ret = ql_nand_flash_umount();
  324. if(nand_ret != QL_NAND_FLASH_SUCCESS)
  325. {
  326. QL_NAND_FLASH_LOG("nand flash umount err");
  327. goto QL_FTL_NAND_EXIT;
  328. }
  329. //err
  330. QL_FTL_NAND_EXIT:
  331. #if (QL_SPI_TPYE == QL_STANDARD_SPI)
  332. ql_spi_release(QL_CUR_SPI_PORT);
  333. #endif
  334. QL_FTL_TASK_EXIT:
  335. if(err < 0)
  336. {
  337. QL_NAND_FLASH_LOG("errcode is %x", err);
  338. }
  339. QL_NAND_FLASH_LOG("ql_rtos_task_delete");
  340. err = ql_rtos_task_delete(NULL);
  341. if(err != QL_OSI_SUCCESS)
  342. {
  343. QL_NAND_FLASH_LOG("task deleted failed");
  344. }
  345. }
  346. QlOSStatus ql_fs_nand_flash_demo_init(void)
  347. {
  348. QlOSStatus err = QL_OSI_SUCCESS;
  349. err = ql_rtos_task_create(&fs_nand_flash_demo_task, FS_NAND_FLASH_DEMO_TASK_STACK_SIZE, FS_NAND_FLASH_DEMO_TASK_PRIO, "ql_nand_flash", ql_fs_nand_flash_demo_task_thread, NULL, FS_NAND_FLASH_DEMO_TASK_EVENT_CNT);
  350. if(err != QL_OSI_SUCCESS)
  351. {
  352. QL_NAND_FLASH_LOG("demo_task created failed");
  353. return err;
  354. }
  355. return err;
  356. }