luat_lib_fatfs.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. #include "luat_base.h"
  2. #include "luat_spi.h"
  3. #include "luat_timer.h"
  4. #include "luat_gpio.h"
  5. #include "luat_malloc.h"
  6. #include "luat_fs.h"
  7. #include "ff.h" /* Obtains integer types */
  8. #include "diskio.h" /* Declarations of disk functions */
  9. #define LUAT_LOG_TAG "fatfs"
  10. #include "luat_log.h"
  11. static FATFS *fs = NULL; /* FatFs work area needed for each volume */
  12. extern BYTE FATFS_DEBUG; // debug log, 0 -- disable , 1 -- enable
  13. // extern BYTE FATFS_SPI_ID;
  14. // extern BYTE FATFS_SPI_TYPE;
  15. // extern BYTE FATFS_SPI_CS; // GPIO 3
  16. // extern luat_spi_device_t* fatfs_spi_device;
  17. // extern uint8_t fatfs_spi_port;
  18. DRESULT diskio_open_ramdisk(BYTE pdrv, size_t len);
  19. DRESULT diskio_open_spitf(BYTE pdrv, void* userdata);
  20. #ifdef LUAT_USE_FS_VFS
  21. extern const struct luat_vfs_filesystem vfs_fs_fatfs;
  22. #endif
  23. static int fatfs_mount(lua_State *L)
  24. {
  25. if (FATFS_DEBUG)
  26. LLOGD("fatfs_init>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
  27. if (fs == NULL) {
  28. fs = luat_heap_malloc(sizeof(FATFS));
  29. if (fs == NULL) {
  30. lua_pushboolean(L, 0);
  31. LLOGD("out of memory when malloc FATFS");
  32. lua_pushstring(L, "out of memory when malloc FATFS");
  33. return 2;
  34. }
  35. }
  36. // 挂载点
  37. const char *mount_point = luaL_optstring(L, 1, "");
  38. luat_fatfs_spi_t *spit = luat_heap_malloc(sizeof(luat_fatfs_spi_t));
  39. if (spit == NULL) {
  40. lua_pushboolean(L, 0);
  41. LLOGD("out of memory when malloc luat_fatfs_spi_t");
  42. lua_pushstring(L, "out of memory when malloc luat_fatfs_spi_t");
  43. return 2;
  44. }
  45. memset(spit, 0, sizeof(luat_fatfs_spi_t));
  46. if (lua_type(L, 2) == LUA_TUSERDATA){
  47. spit->spi_device = (luat_spi_device_t*)lua_touserdata(L, 2);
  48. spit->fast_speed = luaL_optinteger(L, 4, 10000000);
  49. spit->type = 1;
  50. diskio_open_spitf(0, (void*)spit);
  51. } else {
  52. spit->type = 0;
  53. spit->spi_id = luaL_optinteger(L, 2, 0); // SPI_1
  54. spit->spi_cs = luaL_optinteger(L, 3, 3); // GPIO_3
  55. spit->fast_speed = luaL_optinteger(L, 4, 10000000);
  56. if (!strcmp("ramdisk", mount_point) || !strcmp("ram", mount_point)) {
  57. LLOGD("init ramdisk at FatFS");
  58. diskio_open_ramdisk(0, luaL_optinteger(L, 2, 64*1024));
  59. } else {
  60. LLOGD("init sdcard at spi=%d cs=%d", spit->spi_id, spit->spi_cs);
  61. diskio_open_spitf(0, (void*)spit);
  62. }
  63. }
  64. FRESULT re = f_mount(fs, "/", 0);
  65. lua_pushboolean(L, re == 0);
  66. lua_pushinteger(L, re);
  67. if (re == FR_OK) {
  68. if (FATFS_DEBUG)
  69. LLOGD("[FatFS]fatfs_init success");
  70. #ifdef LUAT_USE_FS_VFS
  71. luat_fs_conf_t conf2 = {
  72. .busname = (char*)fs,
  73. .type = "fatfs",
  74. .filesystem = "fatfs",
  75. .mount_point = "/sd",
  76. };
  77. luat_fs_mount(&conf2);
  78. #endif
  79. }
  80. else {
  81. if (FATFS_DEBUG)
  82. LLOGD("[FatFS]fatfs_init FAIL!! re=%d", re);
  83. }
  84. if (FATFS_DEBUG)
  85. LLOGD("fatfs_init<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
  86. return 2;
  87. }
  88. static int fatfs_unmount(lua_State *L) {
  89. const char *mount_point = luaL_optstring(L, 1, "");
  90. FRESULT re = f_unmount(mount_point);
  91. lua_pushinteger(L, re);
  92. return 1;
  93. }
  94. static int fatfs_mkfs(lua_State *L) {
  95. const char *mount_point = luaL_optstring(L, 1, "");
  96. // BYTE sfd = luaL_optinteger(L, 2, 0);
  97. // DWORD au = luaL_optinteger(L, 3, 0);
  98. BYTE work[FF_MAX_SS] = {0};
  99. if (FATFS_DEBUG)
  100. LLOGI("mkfs GO %d");
  101. MKFS_PARM parm = {
  102. .fmt = FM_ANY, // 暂时应付一下ramdisk
  103. .au_size = 0,
  104. .align = 0,
  105. .n_fat = 0,
  106. .n_root = 0,
  107. };
  108. if (!strcmp("ramdisk", mount_point) || !strcmp("ram", mount_point)) {
  109. parm.fmt = FM_ANY | FM_SFD;
  110. }
  111. FRESULT re = f_mkfs(mount_point, &parm, work, FF_MAX_SS);
  112. lua_pushinteger(L, re);
  113. if (FATFS_DEBUG)
  114. LLOGI("mkfs ret %d", re);
  115. return 1;
  116. }
  117. static int fatfs_getfree(lua_State *L)
  118. {
  119. DWORD fre_clust, fre_sect, tot_sect;
  120. // 挂载点
  121. const char *mount_point = luaL_optstring(L, 1, "");
  122. FATFS *fs2;
  123. FRESULT re2 = f_getfree(mount_point, &fre_clust, &fs2);
  124. if (re2) {
  125. lua_pushnil(L);
  126. lua_pushinteger(L, re2);
  127. return 2;
  128. }
  129. /* Get total sectors and free sectors */
  130. tot_sect = (fs2->n_fatent - 2) * fs2->csize;
  131. fre_sect = fre_clust * fs2->csize;
  132. lua_newtable(L);
  133. lua_pushstring(L, "total_sectors");
  134. lua_pushinteger(L, tot_sect);
  135. lua_settable(L, -3);
  136. lua_pushstring(L, "free_sectors");
  137. lua_pushinteger(L, fre_sect);
  138. lua_settable(L, -3);
  139. lua_pushstring(L, "total_kb");
  140. lua_pushinteger(L, tot_sect / 2);
  141. lua_settable(L, -3);
  142. lua_pushstring(L, "free_kb");
  143. lua_pushinteger(L, fre_sect / 2);
  144. lua_settable(L, -3);
  145. return 1;
  146. }
  147. // ------------------------------------------------
  148. // ------------------------------------------------
  149. static int fatfs_mkdir(lua_State *L) {
  150. int luaType = lua_type( L, 1);
  151. if(luaType != LUA_TSTRING) {
  152. lua_pushinteger(L, -1);
  153. lua_pushstring(L, "file path must string");
  154. return 2;
  155. }
  156. FRESULT re = f_mkdir(lua_tostring(L, 1));
  157. lua_pushinteger(L, re);
  158. return 1;
  159. }
  160. static int fatfs_lsdir(lua_State *L)
  161. {
  162. //FIL Fil; /* File object needed for each open file */
  163. DIR dir;
  164. FILINFO fileinfo;
  165. int luaType = lua_type( L, 1);
  166. if(luaType != LUA_TSTRING) {
  167. lua_pushinteger(L, -1);
  168. lua_pushstring(L, "dir must string");
  169. return 2;
  170. }
  171. //u8 *buf;
  172. size_t len;
  173. const char *buf = lua_tolstring( L, 1, &len );
  174. char dirname[len+1];
  175. memcpy(dirname, buf, len);
  176. dirname[len] = 0x00;
  177. FRESULT re = f_opendir(&dir, dirname);
  178. if (re != FR_OK) {
  179. lua_pushinteger(L, re);
  180. return 1;
  181. }
  182. lua_pushinteger(L, 0);
  183. lua_newtable(L);
  184. while(f_readdir(&dir, &fileinfo) == FR_OK) {
  185. if(!fileinfo.fname[0]) break;
  186. lua_pushlstring(L, fileinfo.fname, strlen(fileinfo.fname));
  187. lua_newtable(L);
  188. lua_pushstring(L, "size");
  189. lua_pushinteger(L, fileinfo.fsize);
  190. lua_settable(L, -3);
  191. lua_pushstring(L, "date");
  192. lua_pushinteger(L, fileinfo.fdate);
  193. lua_settable(L, -3);
  194. lua_pushstring(L, "time");
  195. lua_pushinteger(L, fileinfo.ftime);
  196. lua_settable(L, -3);
  197. lua_pushstring(L, "attrib");
  198. lua_pushinteger(L, fileinfo.fattrib);
  199. lua_settable(L, -3);
  200. lua_pushstring(L, "isdir");
  201. lua_pushinteger(L, fileinfo.fattrib & AM_DIR);
  202. lua_settable(L, -3);
  203. lua_settable(L, -3);
  204. }
  205. f_closedir(&dir);
  206. //LLOGD("[FatFS] lua_gettop=%d", lua_gettop(L));
  207. return 2;
  208. }
  209. //-------------------------------------------------------------
  210. static int fatfs_stat(lua_State *L) {
  211. int luaType = lua_type(L, 1);
  212. if(luaType != LUA_TSTRING) {
  213. lua_pushinteger(L, -1);
  214. lua_pushstring(L, "file path must string");
  215. return 2;
  216. }
  217. FILINFO fileinfo;
  218. const char *path = lua_tostring(L, 1);
  219. FRESULT re = f_stat(path, &fileinfo);
  220. lua_pushinteger(L, re);
  221. if (re == FR_OK) {
  222. lua_newtable(L);
  223. lua_pushstring(L, "size");
  224. lua_pushinteger(L, fileinfo.fsize);
  225. lua_rawset(L, -3);
  226. lua_pushstring(L, "date");
  227. lua_pushinteger(L, fileinfo.fdate);
  228. lua_rawset(L, -3);
  229. lua_pushstring(L, "time");
  230. lua_pushinteger(L, fileinfo.ftime);
  231. lua_rawset(L, -3);
  232. lua_pushstring(L, "attrib");
  233. lua_pushinteger(L, fileinfo.fattrib);
  234. lua_rawset(L, -3);
  235. lua_pushstring(L, "isdir");
  236. lua_pushinteger(L, fileinfo.fattrib & AM_DIR);
  237. lua_rawset(L, -3);
  238. }
  239. else {
  240. lua_pushnil(L);
  241. }
  242. return 2;
  243. }
  244. /**
  245. * fatfs.open("adc.txt")
  246. * fatfs.open("adc.txt", 2)
  247. */
  248. static int fatfs_open(lua_State *L) {
  249. int luaType = lua_type( L, 1);
  250. if(luaType != LUA_TSTRING) {
  251. lua_pushnil(L);
  252. lua_pushinteger(L, -1);
  253. lua_pushstring(L, "file path must string");
  254. return 3;
  255. }
  256. const char *path = lua_tostring(L, 1);
  257. int flag = luaL_optinteger(L, 2, 1); // 第二个参数
  258. flag |= luaL_optinteger(L, 3, 0); // 第三个参数
  259. flag |= luaL_optinteger(L, 4, 0); // 第四个参数
  260. if (FATFS_DEBUG)
  261. LLOGD("[FatFS]open %s %0X", path, flag);
  262. FIL* fil = (FIL*)lua_newuserdata(L, sizeof(FIL));
  263. FRESULT re = f_open(fil, path, (BYTE)flag);
  264. if (re != FR_OK) {
  265. lua_remove(L, -1);
  266. lua_pushnil(L);
  267. lua_pushinteger(L, re);
  268. return 2;
  269. }
  270. return 1;
  271. }
  272. static int fatfs_close(lua_State *L) {
  273. int luaType = lua_type(L, 1);
  274. if(luaType != LUA_TUSERDATA) {
  275. lua_pushinteger(L, -1);
  276. lua_pushstring(L, "must be FIL*");
  277. return 2;
  278. }
  279. FIL* fil = (FIL*)lua_touserdata(L, 1);
  280. FRESULT re = f_close(fil);
  281. //free(fil);
  282. lua_pushinteger(L, re);
  283. return 1;
  284. }
  285. static int fatfs_seek(lua_State *L) {
  286. int luaType = lua_type( L, 1);
  287. if(luaType != LUA_TUSERDATA) {
  288. lua_pushinteger(L, -1);
  289. lua_pushstring(L, "must be FIL*");
  290. return 2;
  291. }
  292. UINT seek = luaL_optinteger(L, 2, 0);
  293. FRESULT re = f_lseek((FIL*)lua_touserdata(L, 1), seek);
  294. lua_pushinteger(L, re);
  295. return 1;
  296. }
  297. static int fatfs_truncate(lua_State *L) {
  298. int luaType = lua_type( L, 1);
  299. if(luaType != LUA_TUSERDATA) {
  300. lua_pushinteger(L, -1);
  301. lua_pushstring(L, "must be FIL*");
  302. return 2;
  303. }
  304. FRESULT re = f_truncate((FIL*)lua_touserdata(L, 1));
  305. lua_pushinteger(L, re);
  306. return 1;
  307. }
  308. static int fatfs_read(lua_State *L) {
  309. int luaType = lua_type( L, 1);
  310. if(luaType != LUA_TUSERDATA) {
  311. lua_pushinteger(L, -1);
  312. lua_pushstring(L, "must be FIL*");
  313. return 2;
  314. }
  315. UINT limit = luaL_optinteger(L, 2, 512);
  316. BYTE buf[limit];
  317. UINT len;
  318. if (FATFS_DEBUG)
  319. LLOGD("[FatFS]readfile limit=%d", limit);
  320. FRESULT re = f_read((FIL*)lua_touserdata(L, 1), buf, limit, &len);
  321. lua_pushinteger(L, re);
  322. if (re != FR_OK) {
  323. return 1;
  324. }
  325. lua_pushlstring(L, (const char*)buf, len);
  326. return 2;
  327. }
  328. static int fatfs_write(lua_State *L) {
  329. int luaType = lua_type( L, 1);
  330. if(luaType != LUA_TUSERDATA) {
  331. lua_pushinteger(L, -1);
  332. lua_pushstring(L, "must be FIL*");
  333. return 2;
  334. }
  335. FIL* fil = (FIL*)lua_touserdata(L, 1);
  336. luaType = lua_type( L, 2 );
  337. size_t len;
  338. char* buf;
  339. FRESULT re = FR_OK;
  340. if(luaType == LUA_TSTRING )
  341. {
  342. buf = (char*)lua_tolstring( L, 2, &len );
  343. re = f_write(fil, buf, len, &len);
  344. }
  345. else if(luaType == LUA_TLIGHTUSERDATA)
  346. {
  347. buf = lua_touserdata(L, 2);
  348. len = lua_tointeger( L, 3);
  349. re = f_write(fil, buf, len, &len);
  350. }
  351. if (FATFS_DEBUG)
  352. LLOGD("[FatFS]write re=%d len=%d", re, len);
  353. lua_pushinteger(L, re);
  354. lua_pushinteger(L, len);
  355. return 2;
  356. }
  357. static int fatfs_remove(lua_State *L) {
  358. int luaType = lua_type(L, 1);
  359. if(luaType != LUA_TSTRING) {
  360. lua_pushinteger(L, -1);
  361. lua_pushstring(L, "file path must string");
  362. return 2;
  363. }
  364. FRESULT re = f_unlink(lua_tostring(L, 1));
  365. lua_pushinteger(L, re);
  366. return 1;
  367. }
  368. static int fatfs_rename(lua_State *L) {
  369. int luaType = lua_type(L, 1);
  370. if(luaType != LUA_TSTRING) {
  371. lua_pushinteger(L, -1);
  372. lua_pushstring(L, "source file path must string");
  373. return 2;
  374. }
  375. luaType = lua_type(L, 2);
  376. if(luaType != LUA_TSTRING) {
  377. lua_pushinteger(L, -1);
  378. lua_pushstring(L, "dest file path must string");
  379. return 2;
  380. }
  381. FRESULT re = f_rename(lua_tostring(L, 1), lua_tostring(L, 2));
  382. lua_pushinteger(L, re);
  383. return 1;
  384. }
  385. /**
  386. * fatfs.readfile("adc.txt")
  387. * fatfs.readfile("adc.txt", 512, 0) 默认只读取512字节,从0字节开始读
  388. */
  389. static int fatfs_readfile(lua_State *L) {
  390. int luaType = lua_type( L, 1);
  391. if(luaType != LUA_TSTRING) {
  392. lua_pushinteger(L, -1);
  393. lua_pushstring(L, "file path must string");
  394. return 2;
  395. }
  396. FIL fil;
  397. FRESULT re = f_open(&fil, lua_tostring(L, 1), FA_READ);
  398. if (re != FR_OK) {
  399. lua_pushinteger(L, re);
  400. return 1;
  401. }
  402. DWORD limit = luaL_optinteger(L, 2, 512);
  403. DWORD seek = luaL_optinteger(L, 3, 0);
  404. if (seek > 0) {
  405. f_lseek(&fil, seek);
  406. }
  407. BYTE buf[limit];
  408. size_t len;
  409. if (FATFS_DEBUG)
  410. LLOGD("[FatFS]readfile seek=%d limit=%d", seek, limit);
  411. FRESULT fr = f_read(&fil, buf, limit, &len);
  412. if (fr != FR_OK) {
  413. lua_pushinteger(L, -3);
  414. lua_pushinteger(L, fr);
  415. return 2;
  416. }
  417. f_close(&fil);
  418. lua_pushinteger(L, 0);
  419. lua_pushlstring(L, (const char*)buf, len);
  420. if (FATFS_DEBUG)
  421. LLOGD("[FatFS]readfile seek=%d limit=%d len=%d", seek, limit, len);
  422. return 2;
  423. }
  424. // static int fatfs_playmp3(lua_State *L) {
  425. // int luaType = lua_type( L, 1);
  426. // if(luaType != LUA_TSTRING) {
  427. // lua_pushinteger(L, -1);
  428. // lua_pushstring(L, "file path must string");
  429. // return 2;
  430. // }
  431. // FILINFO fileinfo;
  432. // u8 *path = lua_tostring(L, 1);
  433. // FRESULT re = f_stat(path, &fileinfo);
  434. // if (re) {
  435. // lua_pushinteger(L, re);
  436. // return 1;
  437. // }
  438. // FIL fil;
  439. // re = f_open(&fil, path, FA_READ);
  440. // if (re != FR_OK) {
  441. // lua_pushinteger(L, re);
  442. // return 1;
  443. // }
  444. // u8 buf[fileinfo.fsize];
  445. // UINT len;
  446. // FRESULT fr = f_read(&fil, buf, fileinfo.fsize, &len);
  447. // if (fr) {
  448. // lua_pushinteger(L, fr);
  449. // return 1;
  450. // }
  451. // f_close(&fil);
  452. // AudioPlayParam param;
  453. // param.isBuffer = TRUE;
  454. // param.buffer.format = PLATFORM_AUD_MP3;
  455. // param.buffer.loop = 0;
  456. // param.buffer.data = buf;
  457. // param.buffer.len = len;
  458. // re = platform_audio_play(&param);
  459. // lua_pushinteger(L, re);
  460. // return 1;
  461. // }
  462. static int fatfs_debug_mode(lua_State *L) {
  463. FATFS_DEBUG = luaL_optinteger(L, 1, 1);
  464. return 0;
  465. }
  466. // Module function map
  467. #include "rotable2.h"
  468. static const rotable_Reg_t reg_fatfs[] =
  469. {
  470. { "init", ROREG_FUNC(fatfs_mount)}, //初始化,挂载, 别名方法
  471. { "mount", ROREG_FUNC(fatfs_mount)}, //初始化,挂载
  472. { "unmount", ROREG_FUNC(fatfs_unmount)}, // 取消挂载
  473. { "mkfs", ROREG_FUNC(fatfs_mkfs)}, // 格式化!!!
  474. //{ "test", fatfs_test)},
  475. { "getfree", ROREG_FUNC(fatfs_getfree)}, // 获取文件系统大小,剩余空间
  476. { "debug", ROREG_FUNC(fatfs_debug_mode)}, // 调试模式,打印更多日志
  477. { "lsdir", ROREG_FUNC(fatfs_lsdir)}, // 列举目录下的文件,名称,大小,日期,属性
  478. { "mkdir", ROREG_FUNC(fatfs_mkdir)}, // 列举目录下的文件,名称,大小,日期,属性
  479. { "stat", ROREG_FUNC(fatfs_stat)}, // 查询文件信息
  480. { "open", ROREG_FUNC(fatfs_open)}, // 打开一个文件句柄
  481. { "close", ROREG_FUNC(fatfs_close)}, // 关闭一个文件句柄
  482. { "seek", ROREG_FUNC(fatfs_seek)}, // 移动句柄的当前位置
  483. { "truncate", ROREG_FUNC(fatfs_truncate)}, // 缩减文件尺寸到当前seek位置
  484. { "read", ROREG_FUNC(fatfs_read)}, // 读取数据
  485. { "write", ROREG_FUNC(fatfs_write)}, // 写入数据
  486. { "remove", ROREG_FUNC(fatfs_remove)}, // 删除文件,别名方法
  487. { "unlink", ROREG_FUNC(fatfs_remove)}, // 删除文件
  488. { "rename", ROREG_FUNC(fatfs_rename)}, // 文件改名
  489. { "readfile", ROREG_FUNC(fatfs_readfile)}, // 读取文件的简易方法
  490. { NULL, {}}
  491. };
  492. int luaopen_fatfs( lua_State *L )
  493. {
  494. luat_newlib2(L, reg_fatfs);
  495. #ifdef LUAT_USE_FS_VFS
  496. luat_vfs_reg(&vfs_fs_fatfs);
  497. #endif
  498. return 1;
  499. }