tfcard_app.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. --[[
  2. @module tfcard_app
  3. @summary TF卡文件操作测试模块
  4. @version 1.0.0
  5. @date 2025.08.25
  6. @author 王棚嶙
  7. @usage
  8. 本文件为TF卡的文件操作测试流程:
  9. 1. 创建目录
  10. 2. 创建并写入文件
  11. 3. 检查文件是否存在
  12. 4. 获取文件大小
  13. 5. 读取文件内容
  14. 6. 启动计数文件操作
  15. 7. 文件追加测试
  16. 8. 按行读取测试
  17. 9. 读取后关闭文件
  18. 10. 文件重命名
  19. 11. 列举目录内容
  20. 12. 删除文件
  21. 13. 删除目录
  22. 本文件没有对外接口,直接在main.lua中require "tfcard_app"就可以加载运行
  23. ]]
  24. function tfcard_main_task() -- 开始进行主测试流程。
  25. -- ########## SPI初始化 ##########
  26. -- Air8000核心板上TF卡的的pin_cs为gpio12,spi_id为1.请根据实际硬件修改
  27. spi_id, pin_cs = 1, 12
  28. spi.setup(spi_id, nil, 0, 0, 400 * 1000)
  29. gpio.setup(pin_cs, 1)
  30. -- ########## 开始进行tf卡挂载 ##########
  31. --挂载失败默认格式化,
  32. -- 如无需格式化应改为fatfs.mount(fatfs.SPI, "/sd", spi_id, pin_cs, 24 * 1000 * 1000, nil, 1, false),
  33. -- 一般是在测试硬件是否有问题的时候把格式化取消掉
  34. mount_ok, mount_err = fatfs.mount(fatfs.SPI, "/sd", spi_id, pin_cs, 24 * 1000 * 1000)
  35. if mount_ok then
  36. log.info("fatfs.mount", "挂载成功", mount_err)
  37. else
  38. log.error("fatfs.mount", "挂载失败", mount_err)
  39. goto resource_cleanup
  40. end
  41. -- ########## 获取SD卡的可用空间信息并打印。 ##########
  42. data, err = fatfs.getfree("/sd")
  43. if data then
  44. --打印SD卡的可用空间信息
  45. log.info("fatfs", "getfree", json.encode(data))
  46. else
  47. --打印错误信息
  48. log.info("fatfs", "getfree", "err", err)
  49. goto resource_cleanup
  50. end
  51. -- 列出所有挂载点,如不需要,可注释掉。
  52. data = io.lsmount()
  53. log.info("fs", "lsmount", json.encode(data))
  54. -- ########## 功能: 启用fatfs调试模式 ##########
  55. -- fatfs.debug(1) -- 若挂载失败,可以尝试打开调试信息,查找原因.(设置调试模式)
  56. -- 执行tfcard文件操作演示
  57. log.info("文件操作", "===== 开始文件操作 =====")
  58. dir_path = "/sd/io_test"
  59. -- 1. 创建目录
  60. if io.mkdir(dir_path) then
  61. log.info("io.mkdir", "目录创建成功", "路径:" .. dir_path)
  62. else
  63. -- 检查是否目录已存在
  64. if io.exists(dir_path) then
  65. log.warn("io.mkdir", "目录已存在,跳过创建", "路径:" .. dir_path)
  66. else
  67. log.error("io.mkdir", "目录创建失败且目录不存在", "路径:" .. dir_path)
  68. goto resource_cleanup
  69. end
  70. end
  71. -- 2. 创建并写入文件
  72. file_path = dir_path .. "/boottime"
  73. file = io.open(file_path, "wb")
  74. if file then
  75. file:write("这是io库API文档示例的测试内容")
  76. file:close()
  77. --在LuatOS文件操作中,执行file:close()是必须且关键的操作,它用于关闭文件句柄,释放资源,并确保数据被正确写入磁盘。
  78. -- 如果不执行file:close(),可能会导致数据丢失、文件损坏或其他不可预测的问题。
  79. log.info("文件创建", "文件写入成功", "路径:" .. file_path)
  80. else
  81. log.error("文件创建", "文件创建失败", "路径:" .. file_path)
  82. goto resource_cleanup
  83. end
  84. -- 3. 检查文件是否存在
  85. if io.exists(file_path) then
  86. log.info("io.exists", "文件存在", "路径:" .. file_path)
  87. else
  88. log.error("io.exists", "文件不存在", "路径:" .. file_path)
  89. goto resource_cleanup
  90. end
  91. -- 4. 获取文件大小
  92. file_size = io.fileSize(file_path)
  93. if file_size then
  94. log.info("io.fileSize", "文件大小:" .. file_size .. "字节", "路径:" .. file_path)
  95. else
  96. log.error("io.fileSize", "获取文件大小失败", "路径:" .. file_path)
  97. goto resource_cleanup
  98. end
  99. -- 5. 读取文件内容
  100. file = io.open(file_path, "rb")
  101. if file then
  102. content = file:read("*a")
  103. log.info("文件读取", "路径:" .. file_path, "内容:" .. content)
  104. file:close()
  105. else
  106. log.error("文件操作", "无法打开文件读取内容", "路径:" .. file_path)
  107. goto resource_cleanup
  108. end
  109. -- 6. 启动计数文件操作
  110. count = 0
  111. --以只读模式打开文件
  112. file = io.open(file_path, "rb")
  113. if file then
  114. data = file:read("*a")
  115. log.info("启动计数", "文件内容:", data, "十六进制:", data:toHex())
  116. count = tonumber(data) or 0
  117. file:close()
  118. else
  119. log.warn("启动计数", "文件不存在或无法打开")
  120. end
  121. log.info("启动计数", "当前值:", count)
  122. count=count + 1
  123. log.info("启动计数", "更新值:", count)
  124. file = io.open(file_path, "wb")
  125. if file then
  126. file:write(tostring(count))
  127. file:close()
  128. log.info("文件写入", "路径:" .. file_path, "内容:", count)
  129. else
  130. log.error("文件写入", "无法打开文件", "路径:" .. file_path)
  131. goto resource_cleanup
  132. end
  133. -- 7. 文件追加测试
  134. append_file = dir_path .. "/test_a"
  135. -- 清理旧文件
  136. os.remove(append_file)
  137. -- 创建并写入初始内容
  138. file = io.open(append_file, "wb")
  139. if file then
  140. file:write("ABC")
  141. file:close()
  142. log.info("文件创建", "路径:" .. append_file, "初始内容:ABC")
  143. else
  144. log.error("文件创建", "无法创建文件", "路径:" .. append_file)
  145. goto resource_cleanup
  146. end
  147. -- 追加内容
  148. file = io.open(append_file, "a+")
  149. if file then
  150. file:write("def")
  151. file:close()
  152. log.info("文件追加", "路径:" .. append_file, "追加内容:def")
  153. else
  154. log.error("文件追加", "无法打开文件进行追加", "路径:" .. append_file)
  155. goto resource_cleanup
  156. end
  157. -- 验证追加结果
  158. file = io.open(append_file, "r")
  159. if file then
  160. data = file:read("*a")
  161. log.info("文件验证", "路径:" .. append_file, "内容:" .. data, "结果:",
  162. data == "ABCdef" and "成功" or "失败")
  163. file:close()
  164. else
  165. log.error("文件验证", "无法打开文件进行验证", "路径:" .. append_file)
  166. goto resource_cleanup
  167. end
  168. -- 8. 按行读取测试
  169. line_file = dir_path .. "/testline"
  170. file = io.open(line_file, "w")
  171. if file then
  172. file:write("abc\n")
  173. file:write("123\n")
  174. file:write("wendal\n")
  175. file:close()
  176. log.info("文件创建", "路径:" .. line_file, "写入3行文本")
  177. else
  178. log.error("文件创建", "无法创建文件", "路径:" .. line_file)
  179. goto resource_cleanup
  180. end
  181. -- 按行读取文件
  182. file = io.open(line_file, "r")
  183. if file then
  184. log.info("按行读取", "路径:" .. line_file, "第1行:", file:read("*l"))
  185. log.info("按行读取", "路径:" .. line_file, "第2行:", file:read("*l"))
  186. log.info("按行读取", "路径:" .. line_file, "第3行:", file:read("*l"))
  187. file:close()
  188. else
  189. log.error("按行读取", "无法打开文件", "路径:" .. line_file)
  190. goto resource_cleanup
  191. end
  192. -- 9. 文件重命名
  193. old_path = append_file
  194. new_path = dir_path .. "/renamed_file.txt"
  195. success, err = os.rename(old_path, new_path)
  196. if success then
  197. log.info("os.rename", "文件重命名成功", "原路径:" .. old_path, "新路径:" .. new_path)
  198. -- 验证重命名结果
  199. if io.exists(new_path) and not io.exists(old_path) then
  200. log.info("验证结果", "重命名验证成功", "新文件存在", "原文件不存在")
  201. else
  202. log.error("验证结果", "重命名验证失败")
  203. end
  204. else
  205. log.error("os.rename", "重命名失败", "错误:" .. tostring(err), "原路径:" .. old_path)
  206. goto resource_cleanup
  207. end
  208. -- 10. 列举目录内容
  209. log.info("目录操作", "===== 开始目录列举 =====")
  210. ret, data = io.lsdir(dir_path, 50, 0) -- 50表示最多返回50个文件,0表示从目录开头开始
  211. if ret then
  212. log.info("fs", "lsdir", json.encode(data))
  213. else
  214. log.info("fs", "lsdir", "fail", ret, data)
  215. goto resource_cleanup
  216. end
  217. -- 11. 删除文件测试
  218. -- 测试删除renamed_file.txt文件
  219. if os.remove(new_path) then
  220. log.info("os.remove", "文件删除成功", "路径:" .. new_path)
  221. -- 验证renamed_file.txt删除结果
  222. if not io.exists(new_path) then
  223. log.info("验证结果", "renamed_file.txt文件删除验证成功")
  224. else
  225. log.error("验证结果", "renamed_file.txt文件删除验证失败")
  226. end
  227. else
  228. log.error("io.remove", "renamed_file.txt文件删除失败", "路径:" .. new_path)
  229. goto resource_cleanup
  230. end
  231. -- 测试删除testline文件
  232. if os.remove(line_file) then
  233. log.info("os.remove", "testline文件删除成功", "路径:" .. line_file)
  234. -- 验证删除结果
  235. if not io.exists(line_file) then
  236. log.info("验证结果", "testline文件删除验证成功")
  237. else
  238. log.error("验证结果", "testline文件删除验证失败")
  239. end
  240. else
  241. log.error("io.remove", "testline文件删除失败", "路径:" .. line_file)
  242. goto resource_cleanup
  243. end
  244. if os.remove(file_path) then
  245. log.info("os.remove", "文件删除成功", "路径:" .. file_path)
  246. -- 验证删除结果
  247. if not io.exists(file_path) then
  248. log.info("验证结果", "boottime文件删除验证成功")
  249. else
  250. log.error("验证结果", "boottime文件删除验证失败")
  251. end
  252. else
  253. log.error("io.remove", "boottime文件删除失败", "路径:" .. file_path)
  254. goto resource_cleanup
  255. end
  256. -- 12. 删除目录(不能删除非空目录,所以在删除目录前要确保目录内没有文件或子目录)
  257. if io.rmdir(dir_path) then
  258. log.info("io.rmdir", "目录删除成功", "路径:" .. dir_path)
  259. -- 验证删除结果
  260. if not io.exists(dir_path) then
  261. log.info("验证结果", "目录删除验证成功")
  262. else
  263. log.error("验证结果", "目录删除验证失败")
  264. end
  265. else
  266. log.error("io.rmdir", "目录删除失败", "路径:" .. dir_path)
  267. goto resource_cleanup
  268. end
  269. log.info("文件操作", "===== 文件操作完成 =====")
  270. -- ########## 功能: 收尾功能演示##########
  271. -- 卸载文件系统和关闭SPI
  272. ::resource_cleanup::
  273. log.info("结束", "开始执行关闭操作...")
  274. -- 如已挂载需先卸载文件系统,未挂载直接关闭SPI
  275. if mount_ok then
  276. if fatfs.unmount("/sd") then
  277. log.info("文件系统", "卸载成功")
  278. else
  279. log.error("文件系统", "卸载失败")
  280. end
  281. end
  282. -- 2. 关闭SPI接口
  283. spi.close(spi_id)
  284. log.info("SPI接口", "已关闭")
  285. end
  286. sys.taskInit(tfcard_main_task)