LuatOS 是面向物联网设备的轻量级嵌入式 Lua 脚本运行框架与实时系统,基于 Lua 5.3 完成深度优化,主要适配 4G-Cat.1、MCU 这类物联网终端。从开发层面来看,LuatOS 采用 Lua 脚本开发模式,核心是协程多任务的设计思路,同时配套了 70 余个核心库、30 余个扩展库,还有 1000 多个应用 demo 示例,能覆盖物联网开发中的各类基础应用场景,开发层面的适配性也比较高。
一、概述
Xmodem是一种由Ward Christensen于1977年设计的异步文件传输协议,广泛应用于早期通过调制解调器或串行端口进行的计算机通信。该协议采用基于数据块的传输方式,其核心机制是发送方将数据分割成固定大小的块(通常为128字节),每个数据块都包含起始标志、块序号及其反码、数据区以及校验码。
接收方在收到每个数据块后,会进行校验和序号验证,并通过发送确认(ACK)或否认(NAK)信号来控制数据的继续传输或重发,从而在不可靠的信道上确保数据的完整性。Xmodem协议简单易实现,但其停止-等待的确认机制在高延迟环境中效率较低。
后来衍生出了多个改进版本,如使用循环冗余校验(CRC)提升可靠性的Xmodem-CRC、将数据块扩大至1024字节以提高效率的Xmodem-1K,以及支持批处理文件传输的YMODEM等。
尽管效率不如现代协议,因其实现简单、可靠性高,Xmodem至今仍在嵌入式系统固件升级、网络设备恢复等特定场景中发挥作用
LuatOS的xmodem扩展库,目前仅支持发送功能,不支持接收功能
二、核心示例
1、核心示例是指:使用本库文件提供的核心API,开发的基础业务逻辑的演示代码;
2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;
3、更加完整和详细的demo,请参考 LuatOS仓库 中各个产品目录下的demo/xmodem
lua
--[[
@module main
@summary xmodem 发送文件应用功能模块
@version 1.0
@date 2025.07.01
@author 李源龙
@usage
本文件为Air8000核心板演示xmodem功能的代码示例,本文档主要提供了两种方案:
1、把模块脚本区的文件利用xmodem协议通过uart发送到过去
2、进行http下载文件,利用xmodem协议通过uart发送到过去
]]
--加载xmodem模块
xmodem=require ("xmodem")
--设置默认filepath为脚本区的send.bin文件
local filepath="/luadb/send.bin"
local taskName = "xmodem_run"
local uart_id = 1 --串口号
local baudrate = 115200 --波特率
local file_path=filepath --文件路径
local send_type=true --true表示单次发送128字节,false表示单次发送1024字节
local inform_data="wait C" --发送前提示信息,告知对方要发送C字符来接收文件
-- 处理未识别的消息
local function xmodem_run_cb(msg)
log.info("xmodem_run_cb", msg[1], msg[2], msg[3], msg[4])
end
--http获取文件函数
local function http_recived_cb()
while not socket.adapter(socket.dft()) do
log.warn("httpplus_app_task_func", "wait IP_READY", socket.dft())
-- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
-- 或者等待1秒超时退出阻塞等待状态;
-- 注意:此处的1000毫秒超时不要修改的更长;
-- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
-- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
-- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
sys.waitUntil("IP_READY", 1000)
end
local path = "/send.bin"
-- 以下链接仅用于测试,禁止用于生产环境
local code, headers, body_size = http.request("GET", "http://airtest.openluat.com:2900/download/send.bin", nil, nil, {dst=path}).wait()
log.info("http", code==200 and "success" or "error", code)
if code==200 then
log.info("HTTP receive ok",body_size)
file = io.open(path, "rb")
if file then
content = file:read("*a")
log.info("文件读取", "路径:" .. path, "内容:" .. content)
file:close()
else
log.error("文件操作", "无法打开文件读取内容", "路径:" .. path)
end
file_path=path
end
end
-- 定义一个xmodem_run函数,用于用xmodem发送文件
local function xmodem_run()
--如果需要http下载文件,然后发送下载的文件,可以打开下面的http_recived_cb()函数
-- http_recived_cb()
--等待时间12秒,等待接收方发送C字符启动发送,发送结束后接收端发送ACK:0x06表示接收完成,
--文件全部传输完成之后模块发送EOT:0x04表示传输结束,接收端返回0x06表示确认结束
--启动xmodem发送
local result=xmodem.send(uart_id,baudrate,file_path,send_type,inform_data)
log.info("Xmodem", "start")
log.info("Xmodem", "send result", result)
--判断是否传输成功,传输是否成功,都需要关闭xmodem
if result then
log.info("Xmodem", "send success")
xmodem.close(uart_id)
else
log.info("Xmodem", "send failed")
xmodem.close(uart_id)
end
end
--创建并且启动一个task
--运行这个task的主函数xmodem_run
sys.taskInit(xmodem_run, taskName,xmodem_run_cb)
三、常量详解
xmodem扩展库没有常量。
四、函数详解
xmodem.send(uart_id,baudrate,file_path,send_type,inform_data)
功能
开启xmodem发送,该函数只能在task中运行
注意事项
发送会进入等待12秒,等待期间收到字符 'C'(ASCII 0x43)或者NAK:0x06则开始发送,否则超时退出, 成功返回true,失败返回false
模块端在接收到 'C'或 NAK后,才会发出第一个数据块。
接收方内容校验:计算数据区的校验和或CRC,并与数据包尾部的校验值对比。
只有当所有检查都通过时,接收方才会回复 ACK。发送方收到ACK后,才会继续发送下一个数据块。如果上述任何一项检查失败,接收方则会回复 NAK。发送方收到NAK后,不会前进到下一个数据块,而是重新发送刚才那个失败的数据块。这种机制称为"停止-等待"(Stop-and-Wait),确保了传输的可靠性
参数
uart_id
lua
含义说明:串口ID;
数据类型:number;
取值范围:1-3;
是否必选:是;
注意事项:无;
参数示例:xmodem.send(1, 115200, "/luadb/send.bin",true)
uart_br
lua
含义说明:串口波特率;
数据类型:number;
取值范围:可选择波特率表:{2000000,921600,460800,230400,115200,57600,38400,19200,9600,4800,2400};
是否必选:是;
注意事项:无;
参数示例:xmodem.send(1, 115200, "/luadb/send.bin",true)
file_path
lua
含义说明:发送文件路径;
数据类型:string;
取值范围:无特别限制;
是否必选:是;
注意事项:文件名必填,否则执行xmodem.send()会失败;
参数示例:xmodem.setup(1, 115200, "/luadb/send.bin",true)
send_type
lua
含义说明:发送类型选择;
数据类型:boolean;
取值范围:true/false,true代表单次传输128字节,false代表单次传输1k字节;
是否必选:否;
注意事项:默认发送1k字节;
参数示例:xmodem.setup(1, 115200, "/luadb/send.bin",true)
inform_data
lua
含义说明:发送前提示信息,告知对方要发送C字符来接收文件,通过串口把内容发给对方;
数据类型:string;
取值范围:无特别限制;
是否必选:否;
注意事项:填入该参数,发送文件之前,会先发该参数值给对方,对方收到该值判断模块准备好发送了;
参数示例:xmodem.setup(1, 115200, "/luadb/send.bin",true,"wait C")
返回值
local result = xmodem.send(uart_id,baudrate,file_path,send_type,inform_data)
result
lua
含义说明:发送成功/失败;
数据类型:boolean;
取值范围:true/false;
注意事项:无;
例子
lua
--设置默认filepath为脚本区的send.bin文件
local filepath="/luadb/send.bin"
local taskName = "xmodem_run"
local uart_id = 1 --串口号
local baudrate = 115200 --波特率
local file_path=filepath --文件路径
local send_type=true --true表示单次发送128字节,false表示单次发送1024字节
local inform_data="wait C" --发送前提示信息,告知对方要发送C字符来接收文件
-- 处理未识别的消息
local function xmodem_run_cb(msg)
log.info("xmodem_run_cb", msg[1], msg[2], msg[3], msg[4])
end
-- 定义一个xmodem_run函数,用于用xmodem发送文件
local function xmodem_run()
--等待时间12秒,等待接收方发送C字符启动发送,发送结束后接收端发送ACK:0x06表示接收完成,
--文件全部传输完成之后模块发送EOT:0x04表示传输结束,接收端返回0x06表示确认结束
--启动xmodem发送
local result=xmodem.send(uart_id,baudrate,file_path,send_type,inform_data)
log.info("Xmodem", "start")
log.info("Xmodem", "send result", result)
--判断是否传输成功,传输是否成功,都需要关闭xmodem
if result then
log.info("Xmodem", "send success")
xmodem.close(uart_id)
else
log.info("Xmodem", "send failed")
xmodem.close(uart_id)
end
end
--创建并且启动一个task
--运行这个task的主函数xmodem_run
sys.taskInit(xmodem_run, taskName,xmodem_run_cb)
xmodem.close(uart_id)
功能
关闭xmodem传输
注意事项
这个操作主要是把串口关闭,关闭后串口不可用,需要重新设置串口参数才能使用
参数
uart_id
lua
含义说明:串口ID;
数据类型:number;
取值范围:1-3;
是否必选:是;
注意事项:无;
参数示例:xmodem.close(1)
返回值
无
例子
lua
-- 执行xmodem传输后, 无论是否传输成功, 都建议关闭xmodem, 也会关闭uart
xmodem.close(1)
五、产品支持说明
支持 LuatOS 开发的所有产品都支持 xmodem 扩展库。