xmodem.lua 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. --[[
  2. @module xmodem
  3. @summary xmodem 驱动
  4. @version 1.0
  5. @date 2022.06.01
  6. @author Dozingfiretruck
  7. @usage
  8. --注意:因使用了sys.wait()所有api需要在协程中使用
  9. -- 用法实例
  10. local xmodem = require "xmodem"
  11. sys.taskInit(function()
  12. xmodem.send(2,115200,"/luadb/test.bin")
  13. while 1 do
  14. sys.wait(1000)
  15. end
  16. end)
  17. ]]
  18. local xmodem = {}
  19. local sys = require "sys"
  20. local HEAD
  21. local DATA_SIZE
  22. local SOH = 0x01 -- Modem数据头 128
  23. local STX = 0x02 -- Modem数据头 1K
  24. local EOT = 0x04 -- 发送结束
  25. local ACK = 0x06 -- 应答
  26. local NAK = 0x15 -- 非应答
  27. local CAN = 0x18 -- 取消发送
  28. local CTRLZ = 0x1A -- 填充
  29. local CRC_CHR = 0x43 -- C: ASCII字符C
  30. local CRC_SIZE = 2
  31. local FRAME_ID_SIZE = 2
  32. local DATA_SIZE_SOH = 128
  33. local DATA_SIZE_STX = 1024
  34. local function uart_cb(id, len)
  35. local data = uart.read(id, 1024)
  36. if #data == 0 then
  37. return
  38. end
  39. log.info("xmodem", "uart读取到数据:", data:toHex())
  40. data = data:byte(1)
  41. sys.publish("xmodem", data)
  42. end
  43. --[[
  44. xmodem 发送文件
  45. @api xmodem.send(uart_id, uart_br, file_path,type)
  46. @number uart_id uart端口号
  47. @number uart_br uart波特率
  48. @string file_path 文件路径
  49. @bool type 1k/128 默认1k
  50. @return bool 发送结果
  51. @usage
  52. xmodem.send(2,115200,"/luadb/test.bin")
  53. ]]
  54. function xmodem.send(uart_id, uart_br, file_path, type)
  55. local ret, flen, cnt, crc
  56. if type then
  57. HEAD = SOH
  58. DATA_SIZE = DATA_SIZE_SOH
  59. else
  60. HEAD = STX
  61. DATA_SIZE = DATA_SIZE_STX
  62. end
  63. local XMODEM_SIZE = 1+FRAME_ID_SIZE+DATA_SIZE+CRC_SIZE
  64. local packsn = 0
  65. local xmodem_buff = zbuff.create(XMODEM_SIZE)
  66. local data_buff = zbuff.create(DATA_SIZE)
  67. local fd = io.open(file_path, "rb")
  68. if fd then
  69. uart.setup(uart_id,uart_br)
  70. uart.on(uart_id, "receive", uart_cb)
  71. local result, data = sys.waitUntil("xmodem", 12000)
  72. if result and (data == CRC_CHR or data == NAK) then
  73. cnt = 1
  74. while true do
  75. data_buff:set(0, CTRLZ)
  76. ret, flen = fd:fill(data_buff,0,DATA_SIZE)
  77. log.info("xmodem", "发送第", cnt, "包")
  78. if flen > 0 then
  79. data_buff:seek(0)
  80. crc = crypto.crc16("XMODEM",data_buff)
  81. packsn = (packsn+1) & 0xff
  82. xmodem_buff[0] = 0x02
  83. xmodem_buff[1] = packsn
  84. xmodem_buff[2] = 0xff-xmodem_buff[1]
  85. data_buff:seek(DATA_SIZE)
  86. xmodem_buff:copy(3, data_buff)
  87. xmodem_buff[1027] = crc>>8
  88. xmodem_buff[1028] = crc&0xff
  89. xmodem_buff:seek(XMODEM_SIZE)
  90. -- log.info(xmodem_buff:used())
  91. :: RESEND ::
  92. uart.tx(uart_id, xmodem_buff)
  93. result, data = sys.waitUntil("xmodem", 10000)
  94. if result and data == ACK then
  95. cnt = cnt + 1
  96. elseif result and data == NAK then
  97. goto RESEND
  98. else
  99. log.info("xmodem", "发送失败")
  100. return false
  101. end
  102. if flen ~= DATA_SIZE then
  103. log.info("xmodem", "文件到头了")
  104. break
  105. end
  106. else
  107. log.info("xmodem", "文件到头了")
  108. break
  109. end
  110. end
  111. uart.write(uart_id, string.char(EOT))
  112. fd:close()
  113. return true
  114. else
  115. log.info("xmodem", "不支持的起始数据包",data)
  116. return false
  117. end
  118. else
  119. log.info("xmodem", "待传输的文件不存在")
  120. return false
  121. end
  122. end
  123. --[[
  124. 关闭xmodem
  125. @api xmodem.close(uart_id)
  126. @number uart_id uart端口号
  127. @usage
  128. -- 执行xmodem传输后, 无论是否传输成功, 都建议关闭xmodem上下文, 也会关闭uart
  129. xmodem.close(2)
  130. ]]
  131. function xmodem.close(uart_id)
  132. uart.on(uart_id, "receive")
  133. uart.close(uart_id)
  134. end
  135. return xmodem